Uprev to branch-heads/74

To commit
'Merge to M74: Revert "Remove rtc::TimeMillis() call from ALR detector."'

https://webrtc.googlesource.com/src/+/303fc7963064a46a27e8287e531ded8cec21ff77

Existing aec.ini config files should be modified base on the parameters
change as below:

Added:

AEC_DELAY_DELAY_HEADROOM_SAMPLES "delay:delay_headroom_samples"
AEC_DELAY_HYSTERESIS_LIMIT_BLOCKS "delay:hysteresis_limit_blocks"
AEC_EP_STRENGTH_DEFAULT_GAIN "ep_strength:default_gain"

Removed:

AEC_BUFFERING_USE_NEW_RENDER_BUFFERING "buffering:use_new_render_buffering"
AEC_DELAY_API_CALL_JITTER_BLOCKS "delay:api_call_jitter_blocks"
AEC_DELAY_MIN_ECHO_PATH_DELAY_BLOCKS "delay:min_echo_path_delay_blocks"
AEC_DELAY_DELAY_HEADROOM_BLOCKS "delay:delay_headroom_blocks"
AEC_DELAY_HYSTERESIS_LIMIT_1_BLOCKS "delay:hysteresis_limit_1_blocks"
AEC_DELAY_HYSTERESIS_LIMIT_2_BLOCKS "delay:hysteresis_limit_2_blocks"
AEC_DELAY_SKEW_HYSTERESIS_BLOCKS "delay:skew_hysteresis_blocks"
AEC_EP_STRENGTH_LF "ep_strength:lf"
AEC_EP_STRENGTH_MF "ep_strength:mf"
AEC_EP_STRENGTH_HF "ep_strength:hf"
AEC_ECHO_REMOVAL_CTL_INITIAL_GAIN "echo_removal_control:initial_gain"
AEC_ECHO_REMOVAL_CTL_FIRST_NON_ZERO_GAIN "echo_removal_control:first_non_zero_gain"
AEC_ECHO_REMOVAL_CTL_NON_ZERO_GAIN_BLOCKS "echo_removal_control:non_zero_gain_blocks"
AEC_ECHO_REMOVAL_CTL_FULL_GAIN_BLOCKS "echo_removal_control:full_gain_blocks"

BUG=chromium:947914
TEST=emerge-atlas webrtc-apm
CQ-DEPEND=CL:1545342

Change-Id: Ifb701bfc14844c32b8d7561c4b48fd61be3f7157
Reviewed-on: https://chromium-review.googlesource.com/1545814
Commit-Ready: ChromeOS CL Exonerator Bot <chromiumos-cl-exonerator@appspot.gserviceaccount.com>
Tested-by: Hsinyu Chao <hychao@chromium.org>
Reviewed-by: Hsinyu Chao <hychao@chromium.org>
Reviewed-by: Per Ã…hgren <peah@chromium.org>
diff --git a/absl/BUILD.bazel b/absl/BUILD.bazel
index edd0274..8e3c177 100644
--- a/absl/BUILD.bazel
+++ b/absl/BUILD.bazel
@@ -5,7 +5,7 @@
 # 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
+#      https://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,
diff --git a/absl/CMakeLists.txt b/absl/CMakeLists.txt
index 1d09b19..bba0f3e 100644
--- a/absl/CMakeLists.txt
+++ b/absl/CMakeLists.txt
@@ -5,7 +5,7 @@
 # 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
+#      https://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,
diff --git a/absl/algorithm/BUILD.bazel b/absl/algorithm/BUILD.bazel
index d04dc71..8d266db 100644
--- a/absl/algorithm/BUILD.bazel
+++ b/absl/algorithm/BUILD.bazel
@@ -5,7 +5,7 @@
 # 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
+#      https://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,
@@ -15,7 +15,7 @@
 #
 
 load(
-    "//absl:copts.bzl",
+    "//absl:copts/configure_copts.bzl",
     "ABSL_DEFAULT_COPTS",
     "ABSL_TEST_COPTS",
 )
diff --git a/absl/algorithm/CMakeLists.txt b/absl/algorithm/CMakeLists.txt
index fdf45c5..c51eb10 100644
--- a/absl/algorithm/CMakeLists.txt
+++ b/absl/algorithm/CMakeLists.txt
@@ -5,7 +5,7 @@
 # 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
+#      https://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,
@@ -14,50 +14,50 @@
 # limitations under the License.
 #
 
-list(APPEND ALGORITHM_PUBLIC_HEADERS
-  "algorithm.h"
-  "container.h"
-)
-
-
-#
-## TESTS
-#
-
-# test algorithm_test
-list(APPEND ALGORITHM_TEST_SRC
-  "algorithm_test.cc"
-  ${ALGORITHM_PUBLIC_HEADERS}
-  ${ALGORITHM_INTERNAL_HEADERS}
-)
-
-absl_header_library(
-  TARGET
-    absl_algorithm
-  EXPORT_NAME
+absl_cc_library(
+  NAME
     algorithm
+  HDRS
+    "algorithm.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  PUBLIC
 )
 
-absl_test(
-  TARGET
+absl_cc_test(
+  NAME
     algorithm_test
-  SOURCES
-    ${ALGORITHM_TEST_SRC}
-  PUBLIC_LIBRARIES
+  SRCS
+    "algorithm_test.cc"
+  DEPS
     absl::algorithm
+    gmock_main
 )
 
-
-
-
-# test container_test
-set(CONTAINER_TEST_SRC "container_test.cc")
-
-absl_test(
-  TARGET
-    container_test
-  SOURCES
-    ${CONTAINER_TEST_SRC}
-  PUBLIC_LIBRARIES
+absl_cc_library(
+  NAME
+    algorithm_container
+  HDRS
+    "container.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
     absl::algorithm
+    absl::core_headers
+    absl::meta
+  PUBLIC
+)
+
+absl_cc_test(
+  NAME
+    container_test
+  SRCS
+    "container_test.cc"
+  DEPS
+    absl::algorithm_container
+    absl::base
+    absl::core_headers
+    absl::memory
+    absl::span
+    gmock_main
 )
diff --git a/absl/algorithm/algorithm.h b/absl/algorithm/algorithm.h
index 3d65864..bb90215 100644
--- a/absl/algorithm/algorithm.h
+++ b/absl/algorithm/algorithm.h
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -94,7 +94,7 @@
 // then the predicate is never invoked and the function returns false.
 //
 // This is a C++11-compatible implementation of C++14 `std::equal`.  See
-// http://en.cppreference.com/w/cpp/algorithm/equal for more information.
+// https://en.cppreference.com/w/cpp/algorithm/equal for more information.
 template <typename InputIter1, typename InputIter2, typename Pred>
 bool equal(InputIter1 first1, InputIter1 last1, InputIter2 first2,
            InputIter2 last2, Pred&& pred) {
diff --git a/absl/algorithm/algorithm_test.cc b/absl/algorithm/algorithm_test.cc
index e4322bc..81fccb6 100644
--- a/absl/algorithm/algorithm_test.cc
+++ b/absl/algorithm/algorithm_test.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
diff --git a/absl/algorithm/container.h b/absl/algorithm/container.h
index 53ab156..752e47b 100644
--- a/absl/algorithm/container.h
+++ b/absl/algorithm/container.h
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -36,7 +36,6 @@
 // For template parameter and variable naming, `C` indicates the container type
 // to which the function is applied, `Pred` indicates the predicate object type
 // to be used by the function and `T` indicates the applicable element type.
-//
 
 #ifndef ABSL_ALGORITHM_CONTAINER_H_
 #define ABSL_ALGORITHM_CONTAINER_H_
@@ -46,6 +45,8 @@
 #include <iterator>
 #include <numeric>
 #include <type_traits>
+#include <unordered_map>
+#include <unordered_set>
 #include <utility>
 #include <vector>
 
@@ -54,7 +55,6 @@
 #include "absl/meta/type_traits.h"
 
 namespace absl {
-
 namespace container_algorithm_internal {
 
 // NOTE: it is important to defer to ADL lookup for building with C++ modules,
@@ -101,6 +101,17 @@
 template <typename C>
 ContainerIter<C> c_end(C& c) { return end(c); }
 
+template <typename T>
+struct IsUnorderedContainer : std::false_type {};
+
+template <class Key, class T, class Hash, class KeyEqual, class Allocator>
+struct IsUnorderedContainer<
+    std::unordered_map<Key, T, Hash, KeyEqual, Allocator>> : std::true_type {};
+
+template <class Key, class Hash, class KeyEqual, class Allocator>
+struct IsUnorderedContainer<std::unordered_set<Key, Hash, KeyEqual, Allocator>>
+    : std::true_type {};
+
 }  // namespace container_algorithm_internal
 
 // PUBLIC API
@@ -636,7 +647,6 @@
 // and `unique()` are omitted, because it's not clear whether or not such
 // functions should call erase on their supplied sequences afterwards. Either
 // behavior would be surprising for a different set of users.
-//
 
 // c_remove_copy()
 //
@@ -1154,7 +1164,13 @@
 // Container-based version of the <algorithm> `std::set_union()` function
 // to return an iterator containing the union of two containers; duplicate
 // values are not copied into the output.
-template <typename C1, typename C2, typename OutputIterator>
+template <typename C1, typename C2, typename OutputIterator,
+          typename = typename std::enable_if<
+              !container_algorithm_internal::IsUnorderedContainer<C1>::value,
+              void>::type,
+          typename = typename std::enable_if<
+              !container_algorithm_internal::IsUnorderedContainer<C2>::value,
+              void>::type>
 OutputIterator c_set_union(const C1& c1, const C2& c2, OutputIterator output) {
   return std::set_union(container_algorithm_internal::c_begin(c1),
                         container_algorithm_internal::c_end(c1),
@@ -1164,7 +1180,13 @@
 
 // Overload of c_set_union() for performing a merge using a `comp` other than
 // `operator<`.
-template <typename C1, typename C2, typename OutputIterator, typename Compare>
+template <typename C1, typename C2, typename OutputIterator, typename Compare,
+          typename = typename std::enable_if<
+              !container_algorithm_internal::IsUnorderedContainer<C1>::value,
+              void>::type,
+          typename = typename std::enable_if<
+              !container_algorithm_internal::IsUnorderedContainer<C2>::value,
+              void>::type>
 OutputIterator c_set_union(const C1& c1, const C2& c2, OutputIterator output,
                            Compare&& comp) {
   return std::set_union(container_algorithm_internal::c_begin(c1),
@@ -1178,7 +1200,13 @@
 //
 // Container-based version of the <algorithm> `std::set_intersection()` function
 // to return an iterator containing the intersection of two containers.
-template <typename C1, typename C2, typename OutputIterator>
+template <typename C1, typename C2, typename OutputIterator,
+          typename = typename std::enable_if<
+              !container_algorithm_internal::IsUnorderedContainer<C1>::value,
+              void>::type,
+          typename = typename std::enable_if<
+              !container_algorithm_internal::IsUnorderedContainer<C2>::value,
+              void>::type>
 OutputIterator c_set_intersection(const C1& c1, const C2& c2,
                                   OutputIterator output) {
   return std::set_intersection(container_algorithm_internal::c_begin(c1),
@@ -1189,7 +1217,13 @@
 
 // Overload of c_set_intersection() for performing a merge using a `comp` other
 // than `operator<`.
-template <typename C1, typename C2, typename OutputIterator, typename Compare>
+template <typename C1, typename C2, typename OutputIterator, typename Compare,
+          typename = typename std::enable_if<
+              !container_algorithm_internal::IsUnorderedContainer<C1>::value,
+              void>::type,
+          typename = typename std::enable_if<
+              !container_algorithm_internal::IsUnorderedContainer<C2>::value,
+              void>::type>
 OutputIterator c_set_intersection(const C1& c1, const C2& c2,
                                   OutputIterator output, Compare&& comp) {
   return std::set_intersection(container_algorithm_internal::c_begin(c1),
@@ -1204,7 +1238,13 @@
 // Container-based version of the <algorithm> `std::set_difference()` function
 // to return an iterator containing elements present in the first container but
 // not in the second.
-template <typename C1, typename C2, typename OutputIterator>
+template <typename C1, typename C2, typename OutputIterator,
+          typename = typename std::enable_if<
+              !container_algorithm_internal::IsUnorderedContainer<C1>::value,
+              void>::type,
+          typename = typename std::enable_if<
+              !container_algorithm_internal::IsUnorderedContainer<C2>::value,
+              void>::type>
 OutputIterator c_set_difference(const C1& c1, const C2& c2,
                                 OutputIterator output) {
   return std::set_difference(container_algorithm_internal::c_begin(c1),
@@ -1215,7 +1255,13 @@
 
 // Overload of c_set_difference() for performing a merge using a `comp` other
 // than `operator<`.
-template <typename C1, typename C2, typename OutputIterator, typename Compare>
+template <typename C1, typename C2, typename OutputIterator, typename Compare,
+          typename = typename std::enable_if<
+              !container_algorithm_internal::IsUnorderedContainer<C1>::value,
+              void>::type,
+          typename = typename std::enable_if<
+              !container_algorithm_internal::IsUnorderedContainer<C2>::value,
+              void>::type>
 OutputIterator c_set_difference(const C1& c1, const C2& c2,
                                 OutputIterator output, Compare&& comp) {
   return std::set_difference(container_algorithm_internal::c_begin(c1),
@@ -1230,7 +1276,13 @@
 // Container-based version of the <algorithm> `std::set_symmetric_difference()`
 // function to return an iterator containing elements present in either one
 // container or the other, but not both.
-template <typename C1, typename C2, typename OutputIterator>
+template <typename C1, typename C2, typename OutputIterator,
+          typename = typename std::enable_if<
+              !container_algorithm_internal::IsUnorderedContainer<C1>::value,
+              void>::type,
+          typename = typename std::enable_if<
+              !container_algorithm_internal::IsUnorderedContainer<C2>::value,
+              void>::type>
 OutputIterator c_set_symmetric_difference(const C1& c1, const C2& c2,
                                           OutputIterator output) {
   return std::set_symmetric_difference(
@@ -1242,7 +1294,13 @@
 
 // Overload of c_set_symmetric_difference() for performing a merge using a
 // `comp` other than `operator<`.
-template <typename C1, typename C2, typename OutputIterator, typename Compare>
+template <typename C1, typename C2, typename OutputIterator, typename Compare,
+          typename = typename std::enable_if<
+              !container_algorithm_internal::IsUnorderedContainer<C1>::value,
+              void>::type,
+          typename = typename std::enable_if<
+              !container_algorithm_internal::IsUnorderedContainer<C2>::value,
+              void>::type>
 OutputIterator c_set_symmetric_difference(const C1& c1, const C2& c2,
                                           OutputIterator output,
                                           Compare&& comp) {
diff --git a/absl/algorithm/container_test.cc b/absl/algorithm/container_test.cc
index 1502b17..04282b8 100644
--- a/absl/algorithm/container_test.cc
+++ b/absl/algorithm/container_test.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
diff --git a/absl/algorithm/equal_benchmark.cc b/absl/algorithm/equal_benchmark.cc
index 19c0780..7bf62c9 100644
--- a/absl/algorithm/equal_benchmark.cc
+++ b/absl/algorithm/equal_benchmark.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
diff --git a/absl/base/BUILD.bazel b/absl/base/BUILD.bazel
index f7d8101..804f62a 100644
--- a/absl/base/BUILD.bazel
+++ b/absl/base/BUILD.bazel
@@ -5,7 +5,7 @@
 # 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
+#      https://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,
@@ -15,7 +15,7 @@
 #
 
 load(
-    "//absl:copts.bzl",
+    "//absl:copts/configure_copts.bzl",
     "ABSL_DEFAULT_COPTS",
     "ABSL_TEST_COPTS",
     "ABSL_EXCEPTIONS_FLAG",
@@ -67,6 +67,7 @@
     name = "core_headers",
     hdrs = [
         "attributes.h",
+        "const_init.h",
         "macros.h",
         "optimization.h",
         "port.h",
@@ -75,7 +76,6 @@
     copts = ABSL_DEFAULT_COPTS,
     deps = [
         ":config",
-        ":dynamic_annotations",
     ],
 )
 
@@ -89,6 +89,10 @@
         "internal/low_level_alloc.h",
     ],
     copts = ABSL_DEFAULT_COPTS,
+    linkopts = select({
+        "//absl:windows": [],
+        "//conditions:default": ["-pthread"],
+    }),
     visibility = [
         "//absl:__subpackages__",
     ],
@@ -108,6 +112,7 @@
         "internal/identity.h",
         "internal/inline_variable.h",
         "internal/invoke.h",
+        "internal/scheduling_mode.h",
     ],
     copts = ABSL_DEFAULT_COPTS,
     visibility = [
@@ -141,6 +146,10 @@
         "log_severity.h",
     ],
     copts = ABSL_DEFAULT_COPTS,
+    linkopts = select({
+        "//absl:windows": [],
+        "//conditions:default": ["-pthread"],
+    }),
     deps = [
         ":base_internal",
         ":config",
@@ -188,7 +197,6 @@
     deps = [
         ":base",
         ":config",
-        ":core_headers",
     ],
 )
 
@@ -231,13 +239,12 @@
     copts = ABSL_TEST_COPTS + ABSL_EXCEPTIONS_FLAG,
     linkopts = ABSL_EXCEPTIONS_FLAG_LINKOPTS,
     deps = [
-        ":base",
         ":config",
         ":pretty_function",
         "//absl/memory",
         "//absl/meta:type_traits",
         "//absl/strings",
-        "//absl/types:optional",
+        "//absl/utility",
         "@com_google_googletest//:gtest",
     ],
 )
@@ -316,6 +323,33 @@
 )
 
 cc_library(
+    name = "spinlock_benchmark_common",
+    testonly = 1,
+    srcs = ["internal/spinlock_benchmark.cc"],
+    copts = ABSL_TEST_COPTS,
+    visibility = [
+        "//absl/base:__pkg__",
+    ],
+    deps = [
+        ":base",
+        ":base_internal",
+        "//absl/synchronization",
+        "@com_github_google_benchmark//:benchmark_main",
+    ],
+    alwayslink = 1,
+)
+
+cc_binary(
+    name = "spinlock_benchmark",
+    testonly = 1,
+    copts = ABSL_DEFAULT_COPTS,
+    visibility = ["//visibility:private"],
+    deps = [
+        ":spinlock_benchmark_common",
+    ],
+)
+
+cc_library(
     name = "endian",
     hdrs = [
         "internal/endian.h",
@@ -397,10 +431,6 @@
     size = "small",
     srcs = ["internal/low_level_alloc_test.cc"],
     copts = ABSL_TEST_COPTS,
-    linkopts = select({
-        "//absl:windows": [],
-        "//conditions:default": ["-pthread"],
-    }),
     tags = ["no_test_ios_x86_64"],
     deps = [":malloc_internal"],
 )
@@ -410,10 +440,6 @@
     size = "small",
     srcs = ["internal/thread_identity_test.cc"],
     copts = ABSL_TEST_COPTS,
-    linkopts = select({
-        "//absl:windows": [],
-        "//conditions:default": ["-pthread"],
-    }),
     tags = [
         "no_test_wasm",
     ],
@@ -457,3 +483,25 @@
         "@com_google_googletest//:gtest_main",
     ],
 )
+
+cc_library(
+    name = "scoped_set_env",
+    testonly = 1,
+    srcs = ["internal/scoped_set_env.cc"],
+    hdrs = ["internal/scoped_set_env.h"],
+    visibility = [
+        "//absl:__subpackages__",
+    ],
+    deps = [":base"],
+)
+
+cc_test(
+    name = "scoped_set_env_test",
+    size = "small",
+    srcs = ["internal/scoped_set_env_test.cc"],
+    copts = ABSL_TEST_COPTS,
+    deps = [
+        ":scoped_set_env",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
diff --git a/absl/base/BUILD.gn b/absl/base/BUILD.gn
index 6c540f3..c7fa3f3 100644
--- a/absl/base/BUILD.gn
+++ b/absl/base/BUILD.gn
@@ -88,6 +88,7 @@
   public_configs = [ "//third_party/abseil-cpp:absl_include_config" ]
   public = [
     "attributes.h",
+    "const_init.h",
     "macros.h",
     "optimization.h",
     "port.h",
@@ -95,7 +96,6 @@
   ]
   deps = [
     ":config",
-    ":dynamic_annotations",
   ]
 }
 
@@ -136,6 +136,7 @@
     "internal/identity.h",
     "internal/inline_variable.h",
     "internal/invoke.h",
+    "internal/scheduling_mode.h",
   ]
   visibility = []
   visibility += [ "../*" ]
@@ -196,7 +197,6 @@
   deps = [
     ":base",
     ":config",
-    ":core_headers",
   ]
   visibility = []
   visibility += [ "../*" ]
@@ -251,13 +251,12 @@
 #     "internal/exception_safety_testing.h",
 #   ]
 #   deps = [
-#     ":base",
 #     ":config",
 #     ":pretty_function",
 #     "../memory",
 #     "../meta:type_traits",
 #     "../strings",
-#     "../types:optional",
+#     "../utility",
 #     "//testing/gtest",
 #   ]
 # }
@@ -314,3 +313,23 @@
   visibility = []
   visibility += [ "../*" ]
 }
+
+source_set("scoped_set_env") {
+  testonly = true
+  configs -= [ "//build/config/compiler:chromium_code" ]
+  configs += [
+    "//build/config/compiler:no_chromium_code",
+    "//third_party/abseil-cpp:absl_default_cflags_cc",
+  ]
+  public = [
+    "internal/scoped_set_env.h",
+  ]
+  sources = [
+    "internal/scoped_set_env.cc",
+  ]
+  deps = [
+    ":base",
+  ]
+  visibility = []
+  visibility += [ "../*" ]
+}
diff --git a/absl/base/CMakeLists.txt b/absl/base/CMakeLists.txt
index 04a6eb3..d8a311c 100644
--- a/absl/base/CMakeLists.txt
+++ b/absl/base/CMakeLists.txt
@@ -5,7 +5,7 @@
 # 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
+#    https://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,
@@ -14,374 +14,427 @@
 # limitations under the License.
 #
 
-list(APPEND BASE_PUBLIC_HEADERS
-  "attributes.h"
-  "call_once.h"
-  "casts.h"
-  "config.h"
-  "dynamic_annotations.h"
-  "log_severity.h"
-  "macros.h"
-  "optimization.h"
-  "policy_checks.h"
-  "port.h"
-  "thread_annotations.h"
+absl_cc_library(
+  NAME
+    spinlock_wait
+  HDRS
+    "internal/scheduling_mode.h"
+    "internal/spinlock_wait.h"
+  SRCS
+    "internal/spinlock_akaros.inc"
+    "internal/spinlock_linux.inc"
+    "internal/spinlock_posix.inc"
+    "internal/spinlock_wait.cc"
+    "internal/spinlock_win32.inc"
+  DEPS
+    absl::core_headers
 )
 
-
-list(APPEND BASE_INTERNAL_HEADERS
-  "internal/atomic_hook.h"
-  "internal/bits.h"
-  "internal/cycleclock.h"
-  "internal/direct_mmap.h"
-  "internal/endian.h"
-  "internal/exception_testing.h"
-  "internal/exception_safety_testing.h"
-  "internal/hide_ptr.h"
-  "internal/identity.h"
-  "internal/invoke.h"
-  "internal/inline_variable.h"
-  "internal/low_level_alloc.h"
-  "internal/low_level_scheduling.h"
-  "internal/per_thread_tls.h"
-  "internal/pretty_function.h"
-  "internal/raw_logging.h"
-  "internal/scheduling_mode.h"
-  "internal/spinlock.h"
-  "internal/spinlock_wait.h"
-  "internal/sysinfo.h"
-  "internal/thread_identity.h"
-  "internal/throw_delegate.h"
-  "internal/tsan_mutex_interface.h"
-  "internal/unaligned_access.h"
-  "internal/unscaledcycleclock.h"
+absl_cc_library(
+  NAME
+    config
+  HDRS
+    "config.h"
+    "policy_checks.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  PUBLIC
 )
 
-
-# absl_base main library
-list(APPEND BASE_SRC
-  "internal/cycleclock.cc"
-  "internal/raw_logging.cc"
-  "internal/spinlock.cc"
-  "internal/sysinfo.cc"
-  "internal/thread_identity.cc"
-  "internal/unscaledcycleclock.cc"
-  "internal/low_level_alloc.cc"
-  ${BASE_PUBLIC_HEADERS}
-  ${BASE_INTERNAL_HEADERS}
+absl_cc_library(
+  NAME
+    dynamic_annotations
+  HDRS
+    "dynamic_annotations.h"
+  SRCS
+    "dynamic_annotations.cc"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEFINES
+    "__CLANG_SUPPORT_DYN_ANNOTATION__"
+  PUBLIC
 )
 
-absl_library(
-  TARGET
-    absl_base
-  SOURCES
-    ${BASE_SRC}
-  PUBLIC_LIBRARIES
-    absl_dynamic_annotations
-    absl_spinlock_wait
-  EXPORT_NAME
-    base
+absl_cc_library(
+  NAME
+    core_headers
+  HDRS
+    "attributes.h"
+    "const_init.h"
+    "macros.h"
+    "optimization.h"
+    "port.h"
+    "thread_annotations.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::config
+  PUBLIC
 )
 
-# throw delegate library
-set(THROW_DELEGATE_SRC "internal/throw_delegate.cc")
-
-absl_library(
-  TARGET
-    absl_throw_delegate
-  SOURCES
-    ${THROW_DELEGATE_SRC}
-  PUBLIC_LIBRARIES
-    ${THROW_DELEGATE_PUBLIC_LIBRARIES}
-  PRIVATE_COMPILE_FLAGS
-    ${ABSL_EXCEPTIONS_FLAG}
-  EXPORT_NAME
-    throw_delegate
-)
-
-if(BUILD_TESTING)
-  # exception-safety testing library
-  set(EXCEPTION_SAFETY_TESTING_SRC
-    "internal/exception_safety_testing.h"
-    "internal/exception_safety_testing.cc"
-  )
-  set(EXCEPTION_SAFETY_TESTING_PUBLIC_LIBRARIES
-    ${ABSL_TEST_COMMON_LIBRARIES}
+absl_cc_library(
+  NAME
+    malloc_internal
+  HDRS
+    "internal/direct_mmap.h"
+    "internal/low_level_alloc.h"
+  SRCS
+    "internal/low_level_alloc.cc"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
     absl::base
+    absl::config
+    absl::core_headers
+    absl::dynamic_annotations
+    absl::spinlock_wait
+)
+
+absl_cc_library(
+  NAME
+    base_internal
+  HDRS
+    "internal/hide_ptr.h"
+    "internal/identity.h"
+    "internal/inline_variable.h"
+    "internal/invoke.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+)
+
+absl_cc_library(
+  NAME
+    base
+  HDRS
+    "call_once.h"
+    "casts.h"
+    "internal/atomic_hook.h"
+    "internal/cycleclock.h"
+    "internal/low_level_scheduling.h"
+    "internal/per_thread_tls.h"
+    "internal/raw_logging.h"
+    "internal/spinlock.h"
+    "internal/sysinfo.h"
+    "internal/thread_identity.h"
+    "internal/tsan_mutex_interface.h"
+    "internal/unscaledcycleclock.h"
+    "log_severity.h"
+  SRCS
+    "internal/cycleclock.cc"
+    "internal/raw_logging.cc"
+    "internal/spinlock.cc"
+    "internal/sysinfo.cc"
+    "internal/thread_identity.cc"
+    "internal/unscaledcycleclock.cc"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::base_internal
+    absl::config
+    absl::core_headers
+    absl::dynamic_annotations
+    absl::spinlock_wait
+  PUBLIC
+)
+
+absl_cc_library(
+  NAME
+    throw_delegate
+  HDRS
+    "internal/throw_delegate.h"
+  SRCS
+    "internal/throw_delegate.cc"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+    ${ABSL_EXCEPTIONS_FLAG}
+  DEPS
+    absl::base
+)
+
+absl_cc_library(
+  NAME
+    exception_testing
+  HDRS
+    "internal/exception_testing.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::config
+    gtest
+  TESTONLY
+)
+
+absl_cc_library(
+  NAME
+    pretty_function
+  HDRS
+    "internal/pretty_function.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+)
+
+absl_cc_library(
+  NAME
+    exception_safety_testing
+  HDRS
+    "internal/exception_safety_testing.h"
+  SRCS
+    "internal/exception_safety_testing.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+    ${ABSL_EXCEPTIONS_FLAG}
+  LINKOPTS
+    ${ABSL_EXCEPTIONS_FLAG_LINKOPTS}
+  DEPS
+    absl::config
+    absl::pretty_function
     absl::memory
     absl::meta
     absl::strings
-    absl::optional
+    absl::utility
     gtest
-  )
-
-absl_library(
-  TARGET
-    absl_base_internal_exception_safety_testing
-  SOURCES
-    ${EXCEPTION_SAFETY_TESTING_SRC}
-  PUBLIC_LIBRARIES
-    ${EXCEPTION_SAFETY_TESTING_PUBLIC_LIBRARIES}
-  PRIVATE_COMPILE_FLAGS
-    ${ABSL_EXCEPTIONS_FLAG}
-)
-endif()
-
-
-# dynamic_annotations library
-set(DYNAMIC_ANNOTATIONS_SRC "dynamic_annotations.cc")
-
-absl_library(
-  TARGET
-    absl_dynamic_annotations
-  SOURCES
-    ${DYNAMIC_ANNOTATIONS_SRC}
+  TESTONLY
 )
 
-
-# spinlock_wait library
-set(SPINLOCK_WAIT_SRC "internal/spinlock_wait.cc")
-
-absl_library(
-  TARGET
-    absl_spinlock_wait
-  SOURCES
-    ${SPINLOCK_WAIT_SRC}
-)
-
-
-# malloc_internal library
-list(APPEND MALLOC_INTERNAL_SRC
-  "internal/low_level_alloc.cc"
-)
-
-absl_library(
-  TARGET
-    absl_malloc_internal
-  SOURCES
-    ${MALLOC_INTERNAL_SRC}
-  PUBLIC_LIBRARIES
-    absl_dynamic_annotations
-)
-
-
-
-#
-## TESTS
-#
-
-# call once test
-set(ATOMIC_HOOK_TEST_SRC "internal/atomic_hook_test.cc")
-set(ATOMIC_HOOK_TEST_PUBLIC_LIBRARIES absl::base)
-
-absl_test(
-  TARGET
-    atomic_hook_test
-  SOURCES
-    ${ATOMIC_HOOK_TEST_SRC}
-  PUBLIC_LIBRARIES
-    ${ATOMIC_HOOK_TEST_PUBLIC_LIBRARIES}
-)
-
-
-# call once test
-set(CALL_ONCE_TEST_SRC "call_once_test.cc")
-set(CALL_ONCE_TEST_PUBLIC_LIBRARIES absl::base absl::synchronization)
-
-absl_test(
-  TARGET
-    call_once_test
-  SOURCES
-    ${CALL_ONCE_TEST_SRC}
-  PUBLIC_LIBRARIES
-    ${CALL_ONCE_TEST_PUBLIC_LIBRARIES}
-)
-
-
-# test bit_cast_test
-set(BIT_CAST_TEST_SRC "bit_cast_test.cc")
-
-absl_test(
-  TARGET
-    bit_cast_test
-  SOURCES
-    ${BIT_CAST_TEST_SRC}
-)
-
-
-# test absl_throw_delegate_test
-set(THROW_DELEGATE_TEST_SRC "throw_delegate_test.cc")
-set(THROW_DELEGATE_TEST_PUBLIC_LIBRARIES absl::base absl_throw_delegate)
-
-absl_test(
-  TARGET
-    throw_delegate_test
-  SOURCES
-    ${THROW_DELEGATE_TEST_SRC}
-  PUBLIC_LIBRARIES
-    ${THROW_DELEGATE_TEST_PUBLIC_LIBRARIES}
-)
-
-
-# test invoke_test
-set(INVOKE_TEST_SRC "invoke_test.cc")
-set(INVOKE_TEST_PUBLIC_LIBRARIES absl::strings)
-
-absl_test(
-  TARGET
-    invoke_test
-  SOURCES
-    ${INVOKE_TEST_SRC}
-  PUBLIC_LIBRARIES
-    ${INVOKE_TEST_PUBLIC_LIBRARIES}
-)
-
-
-# test inline_variable_test
-list(APPEND INLINE_VARIABLE_TEST_SRC
-  "internal/inline_variable_testing.h"
-  "inline_variable_test.cc"
-  "inline_variable_test_a.cc"
-  "inline_variable_test_b.cc"
-)
-
-set(INLINE_VARIABLE_TEST_PUBLIC_LIBRARIES absl::base)
-
-absl_test(
-  TARGET
-    inline_variable_test
-  SOURCES
-    ${INLINE_VARIABLE_TEST_SRC}
-  PUBLIC_LIBRARIES
-    ${INLINE_VARIABLE_TEST_PUBLIC_LIBRARIES}
-)
-
-
-# test spinlock_test_common
-set(SPINLOCK_TEST_COMMON_SRC "spinlock_test_common.cc")
-set(SPINLOCK_TEST_COMMON_PUBLIC_LIBRARIES absl::base absl::synchronization)
-
-absl_test(
-  TARGET
-    spinlock_test_common
-  SOURCES
-    ${SPINLOCK_TEST_COMMON_SRC}
-  PUBLIC_LIBRARIES
-    ${SPINLOCK_TEST_COMMON_PUBLIC_LIBRARIES}
-)
-
-
-# test spinlock_test
-set(SPINLOCK_TEST_SRC "spinlock_test_common.cc")
-set(SPINLOCK_TEST_PUBLIC_LIBRARIES absl::base absl::synchronization)
-
-absl_test(
-  TARGET
-    spinlock_test
-  SOURCES
-    ${SPINLOCK_TEST_SRC}
-  PUBLIC_LIBRARIES
-    ${SPINLOCK_TEST_PUBLIC_LIBRARIES}
-)
-
-
-# test endian_test
-set(ENDIAN_TEST_SRC "internal/endian_test.cc")
-
-absl_test(
-  TARGET
-    endian_test
-  SOURCES
-    ${ENDIAN_TEST_SRC}
-)
-
-
-# test config_test
-set(CONFIG_TEST_SRC "config_test.cc")
-set(CONFIG_TEST_PUBLIC_LIBRARIES absl::base absl::synchronization)
-absl_test(
-  TARGET
-    config_test
-  SOURCES
-    ${CONFIG_TEST_SRC}
-  PUBLIC_LIBRARIES
-    ${CONFIG_TEST_PUBLIC_LIBRARIES}
-)
-
-
-# test raw_logging_test
-set(RAW_LOGGING_TEST_SRC "raw_logging_test.cc")
-set(RAW_LOGGING_TEST_PUBLIC_LIBRARIES absl::base absl::strings)
-
-absl_test(
-  TARGET
-    raw_logging_test
-  SOURCES
-    ${RAW_LOGGING_TEST_SRC}
-  PUBLIC_LIBRARIES
-    ${RAW_LOGGING_TEST_PUBLIC_LIBRARIES}
-)
-
-
-# test sysinfo_test
-set(SYSINFO_TEST_SRC "internal/sysinfo_test.cc")
-set(SYSINFO_TEST_PUBLIC_LIBRARIES absl::base absl::synchronization)
-
-absl_test(
-  TARGET
-    sysinfo_test
-  SOURCES
-    ${SYSINFO_TEST_SRC}
-  PUBLIC_LIBRARIES
-    ${SYSINFO_TEST_PUBLIC_LIBRARIES}
-)
-
-
-# test low_level_alloc_test
-set(LOW_LEVEL_ALLOC_TEST_SRC "internal/low_level_alloc_test.cc")
-set(LOW_LEVEL_ALLOC_TEST_PUBLIC_LIBRARIES absl::base)
-
-absl_test(
-  TARGET
-    low_level_alloc_test
-  SOURCES
-    ${LOW_LEVEL_ALLOC_TEST_SRC}
-  PUBLIC_LIBRARIES
-    ${LOW_LEVEL_ALLOC_TEST_PUBLIC_LIBRARIES}
-)
-
-
-# test thread_identity_test
-set(THREAD_IDENTITY_TEST_SRC "internal/thread_identity_test.cc")
-set(THREAD_IDENTITY_TEST_PUBLIC_LIBRARIES absl::base absl::synchronization)
-
-absl_test(
-  TARGET
-    thread_identity_test
-  SOURCES
-    ${THREAD_IDENTITY_TEST_SRC}
-  PUBLIC_LIBRARIES
-    ${THREAD_IDENTITY_TEST_PUBLIC_LIBRARIES}
-)
-
-#test exceptions_safety_testing_test
-set(EXCEPTION_SAFETY_TESTING_TEST_SRC "exception_safety_testing_test.cc")
-set(EXCEPTION_SAFETY_TESTING_TEST_PUBLIC_LIBRARIES
-  absl::base
-  absl_base_internal_exception_safety_testing
-  absl::memory
-  absl::meta
-  absl::strings
-  absl::optional
-)
-
-absl_test(
-  TARGET
+absl_cc_test(
+  NAME
     absl_exception_safety_testing_test
-  SOURCES
-    ${EXCEPTION_SAFETY_TESTING_TEST_SRC}
-  PUBLIC_LIBRARIES
-    ${EXCEPTION_SAFETY_TESTING_TEST_PUBLIC_LIBRARIES}
-  PRIVATE_COMPILE_FLAGS
+  SRCS
+    "exception_safety_testing_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
     ${ABSL_EXCEPTIONS_FLAG}
+  LINKOPTS
+    ${ABSL_EXCEPTIONS_FLAG_LINKOPTS}
+  DEPS
+    absl::exception_safety_testing
+    absl::memory
+    gtest_main
+)
+
+absl_cc_test(
+  NAME
+    atomic_hook_test
+  SRCS
+    "internal/atomic_hook_test.cc"
+  DEPS
+    absl::base
+    absl::core_headers
+    gtest_main
+)
+
+absl_cc_test(
+  NAME
+    bit_cast_test
+  SRCS
+    "bit_cast_test.cc"
+  DEPS
+    absl::base
+    absl::core_headers
+    gtest_main
+)
+
+absl_cc_test(
+  NAME
+    throw_delegate_test
+  SRCS
+    "throw_delegate_test.cc"
+  DEPS
+    absl::base
+    absl::throw_delegate
+    gtest_main
+)
+
+absl_cc_test(
+  NAME
+    inline_variable_test
+  SRCS
+    "internal/inline_variable_testing.h"
+    "inline_variable_test.cc"
+    "inline_variable_test_a.cc"
+    "inline_variable_test_b.cc"
+  DEPS
+    absl::base_internal
+    gtest_main
+)
+
+absl_cc_test(
+  NAME
+    invoke_test
+  SRCS
+    "invoke_test.cc"
+  DEPS
+    absl::base_internal
+    absl::memory
+    absl::strings
+    gmock
+    gtest_main
+)
+
+absl_cc_library(
+  NAME
+    spinlock_test_common
+  SRCS
+    "spinlock_test_common.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::base
+    absl::core_headers
+    absl::spinlock_wait
+    absl::synchronization
+    gtest
+  TESTONLY
+)
+
+# On bazel BUILD this target use "alwayslink = 1" which is not implemented here
+absl_cc_test(
+  NAME
+    spinlock_test
+  SRCS
+    "spinlock_test_common.cc"
+  DEPS
+    absl::base
+    absl::core_headers
+    absl::spinlock_wait
+    absl::synchronization
+    gtest_main
+)
+
+absl_cc_library(
+  NAME
+    endian
+  HDRS
+    "internal/endian.h"
+    "internal/unaligned_access.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::config
+    absl::core_headers
+  PUBLIC
+)
+
+absl_cc_test(
+  NAME
+    endian_test
+  SRCS
+    "internal/endian_test.cc"
+  DEPS
+    absl::base
+    absl::config
+    absl::endian
+    gtest_main
+)
+
+absl_cc_test(
+  NAME
+    config_test
+  SRCS
+    "config_test.cc"
+  DEPS
+    absl::config
+    absl::synchronization
+    gtest_main
+)
+
+absl_cc_test(
+  NAME
+    call_once_test
+  SRCS
+    "call_once_test.cc"
+  DEPS
+    absl::base
+    absl::core_headers
+    absl::synchronization
+    gtest_main
+)
+
+absl_cc_test(
+  NAME
+    raw_logging_test
+  SRCS
+    "raw_logging_test.cc"
+  DEPS
+    absl::base
+    absl::strings
+    gtest_main
+)
+
+absl_cc_test(
+  NAME
+    sysinfo_test
+  SRCS
+    "internal/sysinfo_test.cc"
+  DEPS
+    absl::base
+    absl::synchronization
+    gtest_main
+)
+
+absl_cc_test(
+  NAME
+    low_level_alloc_test
+  SRCS
+    "internal/low_level_alloc_test.cc"
+  DEPS
+    absl::malloc_internal
+    Threads::Threads
+)
+
+absl_cc_test(
+  NAME
+    thread_identity_test
+  SRCS
+    "internal/thread_identity_test.cc"
+  DEPS
+    absl::base
+    absl::core_headers
+    absl::synchronization
+    Threads::Threads
+    gtest_main
+)
+
+absl_cc_library(
+  NAME
+    bits
+  HDRS
+    "internal/bits.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::core_headers
+)
+
+absl_cc_test(
+  NAME
+    bits_test
+  SRCS
+    "internal/bits_test.cc"
+  DEPS
+    absl::bits
+    gtest_main
+)
+
+absl_cc_library(
+  NAME
+    scoped_set_env
+  SRCS
+    "internal/scoped_set_env.cc"
+  HDRS
+    "internal/scoped_set_env.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::base
+)
+
+absl_cc_test(
+  NAME
+    scoped_set_env_test
+  SRCS
+    "internal/scoped_set_env_test.cc"
+  DEPS
+    absl::scoped_set_env
+    gtest_main
 )
diff --git a/absl/base/attributes.h b/absl/base/attributes.h
index e850022..48195d6 100644
--- a/absl/base/attributes.h
+++ b/absl/base/attributes.h
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -80,7 +80,7 @@
 //
 // A function-like feature checking macro that accepts C++11 style attributes.
 // It's a wrapper around `__has_cpp_attribute`, defined by ISO C++ SD-6
-// (http://en.cppreference.com/w/cpp/experimental/feature_test). If we don't
+// (https://en.cppreference.com/w/cpp/experimental/feature_test). If we don't
 // find `__has_cpp_attribute`, will evaluate to 0.
 #if defined(__cplusplus) && defined(__has_cpp_attribute)
 // NOTE: requiring __cplusplus above should not be necessary, but
@@ -102,7 +102,7 @@
 //
 // Tells the compiler to perform `printf` format string checking if the
 // compiler supports it; see the 'format' attribute in
-// <http://gcc.gnu.org/onlinedocs/gcc-4.7.0/gcc/Function-Attributes.html>.
+// <https://gcc.gnu.org/onlinedocs/gcc-4.7.0/gcc/Function-Attributes.html>.
 //
 // Note: As the GCC manual states, "[s]ince non-static C++ methods
 // have an implicit 'this' argument, the arguments of such methods
@@ -155,7 +155,12 @@
 // ABSL_ATTRIBUTE_WEAK
 //
 // Tags a function as weak for the purposes of compilation and linking.
-#if ABSL_HAVE_ATTRIBUTE(weak) || (defined(__GNUC__) && !defined(__clang__))
+// Weak attributes currently do not work properly in LLVM's Windows backend,
+// so disable them there. See https://bugs.llvm.org/show_bug.cgi?id=37598
+// for futher information.
+#if (ABSL_HAVE_ATTRIBUTE(weak) || \
+     (defined(__GNUC__) && !defined(__clang__))) && \
+    !(defined(__llvm__) && defined(_WIN32))
 #undef ABSL_ATTRIBUTE_WEAK
 #define ABSL_ATTRIBUTE_WEAK __attribute__((weak))
 #define ABSL_HAVE_ATTRIBUTE_WEAK 1
@@ -282,6 +287,17 @@
 #define ABSL_ATTRIBUTE_NO_SANITIZE_CFI
 #endif
 
+// ABSL_ATTRIBUTE_NO_SANITIZE_SAFESTACK
+//
+// Tells the SafeStack to not instrument a given function.
+// See https://clang.llvm.org/docs/SafeStack.html for details.
+#if defined(__GNUC__) && defined(SAFESTACK_SANITIZER)
+#define ABSL_ATTRIBUTE_NO_SANITIZE_SAFESTACK \
+  __attribute__((no_sanitize("safe-stack")))
+#else
+#define ABSL_ATTRIBUTE_NO_SANITIZE_SAFESTACK
+#endif
+
 // ABSL_ATTRIBUTE_RETURNS_NONNULL
 //
 // Tells the compiler that a particular function never returns a null pointer.
@@ -296,13 +312,13 @@
 
 // ABSL_HAVE_ATTRIBUTE_SECTION
 //
-// Indicates whether labeled sections are supported. Labeled sections are not
-// supported on Darwin/iOS.
+// Indicates whether labeled sections are supported. Weak symbol support is
+// a prerequisite. Labeled sections are not supported on Darwin/iOS.
 #ifdef ABSL_HAVE_ATTRIBUTE_SECTION
 #error ABSL_HAVE_ATTRIBUTE_SECTION cannot be directly set
 #elif (ABSL_HAVE_ATTRIBUTE(section) ||                \
        (defined(__GNUC__) && !defined(__clang__))) && \
-    !defined(__APPLE__)
+    !defined(__APPLE__) && ABSL_HAVE_ATTRIBUTE_WEAK
 #define ABSL_HAVE_ATTRIBUTE_SECTION 1
 
 // ABSL_ATTRIBUTE_SECTION
@@ -397,17 +413,28 @@
 
 // ABSL_MUST_USE_RESULT
 //
-// Tells the compiler to warn about unused return values for functions declared
-// with this macro. The macro must appear as the very first part of a function
-// declaration or definition:
+// Tells the compiler to warn about unused results.
 //
-// Example:
+// When annotating a function, it must appear as the first part of the
+// declaration or definition. The compiler will warn if the return value from
+// such a function is unused:
 //
 //   ABSL_MUST_USE_RESULT Sprocket* AllocateSprocket();
+//   AllocateSprocket();  // Triggers a warning.
 //
-// This placement has the broadest compatibility with GCC, Clang, and MSVC, with
-// both defs and decls, and with GCC-style attributes, MSVC declspec, C++11
-// and C++17 attributes.
+// When annotating a class, it is equivalent to annotating every function which
+// returns an instance.
+//
+//   class ABSL_MUST_USE_RESULT Sprocket {};
+//   Sprocket();  // Triggers a warning.
+//
+//   Sprocket MakeSprocket();
+//   MakeSprocket();  // Triggers a warning.
+//
+// Note that references and pointers are not instances:
+//
+//   Sprocket* SprocketPointer();
+//   SprocketPointer();  // Does *not* trigger a warning.
 //
 // ABSL_MUST_USE_RESULT allows using cast-to-void to suppress the unused result
 // warning. For that, warn_unused_result is used only for clang but not for gcc.
diff --git a/absl/base/bit_cast_test.cc b/absl/base/bit_cast_test.cc
index 8cd878d..4846add 100644
--- a/absl/base/bit_cast_test.cc
+++ b/absl/base/bit_cast_test.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
diff --git a/absl/base/call_once.h b/absl/base/call_once.h
index 532ee2e..8c4f297 100644
--- a/absl/base/call_once.h
+++ b/absl/base/call_once.h
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -150,12 +150,8 @@
         old_control != kOnceRunning &&
         old_control != kOnceWaiter &&
         old_control != kOnceDone) {
-      ABSL_RAW_LOG(
-          FATAL,
-          "Unexpected value for control word: %lx. Either the control word "
-          "has non-static storage duration (where GoogleOnceDynamic might "
-          "be appropriate), or there's been a memory corruption.",
-          static_cast<unsigned long>(old_control)); // NOLINT
+      ABSL_RAW_LOG(FATAL, "Unexpected value for control word: 0x%lx",
+                   static_cast<unsigned long>(old_control));  // NOLINT
     }
   }
 #endif  // NDEBUG
diff --git a/absl/base/call_once_test.cc b/absl/base/call_once_test.cc
index cd58ee1..9c2a0c4 100644
--- a/absl/base/call_once_test.cc
+++ b/absl/base/call_once_test.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -18,6 +18,8 @@
 #include <vector>
 
 #include "gtest/gtest.h"
+#include "absl/base/attributes.h"
+#include "absl/base/const_init.h"
 #include "absl/base/thread_annotations.h"
 #include "absl/synchronization/mutex.h"
 
@@ -25,7 +27,8 @@
 namespace {
 
 absl::once_flag once;
-Mutex counters_mu;
+
+ABSL_CONST_INIT Mutex counters_mu(absl::kConstInit);
 
 int running_thread_count GUARDED_BY(counters_mu) = 0;
 int call_once_invoke_count GUARDED_BY(counters_mu) = 0;
diff --git a/absl/base/casts.h b/absl/base/casts.h
index 20fd34d..00196d2 100644
--- a/absl/base/casts.h
+++ b/absl/base/casts.h
@@ -5,7 +5,7 @@
 // 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
+//      https://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,
@@ -105,7 +105,7 @@
 //
 // Such implicit cast chaining may be useful within template logic.
 template <typename To>
-inline To implicit_cast(typename absl::internal::identity_t<To> to) {
+constexpr To implicit_cast(typename absl::internal::identity_t<To> to) {
   return to;
 }
 
diff --git a/absl/base/config.h b/absl/base/config.h
index d4eb7d0..3b81e26 100644
--- a/absl/base/config.h
+++ b/absl/base/config.h
@@ -5,7 +5,7 @@
 // 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
+//      https://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,
@@ -118,7 +118,7 @@
 // Checks whether `std::is_trivially_copy_assignable<T>` is supported.
 
 // Notes: Clang with libc++ supports these features, as does gcc >= 5.1 with
-// either libc++ or libstdc++, and Visual Studio.
+// either libc++ or libstdc++, and Visual Studio (but not NVCC).
 #if defined(ABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE)
 #error ABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE cannot be directly set
 #elif defined(ABSL_HAVE_STD_IS_TRIVIALLY_ASSIGNABLE)
@@ -127,7 +127,7 @@
     (!defined(__clang__) && defined(__GNUC__) &&                 \
      (__GNUC__ > 5 || (__GNUC__ == 5 && __GNUC_MINOR__ >= 1)) && \
      (defined(_LIBCPP_VERSION) || defined(__GLIBCXX__))) ||      \
-    defined(_MSC_VER)
+    (defined(_MSC_VER) && !defined(__NVCC__))
 #define ABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE 1
 #define ABSL_HAVE_STD_IS_TRIVIALLY_ASSIGNABLE 1
 #endif
@@ -139,12 +139,18 @@
 #ifdef ABSL_HAVE_THREAD_LOCAL
 #error ABSL_HAVE_THREAD_LOCAL cannot be directly set
 #elif defined(__APPLE__)
-// Notes: Xcode's clang did not support `thread_local` until version
-// 8, and even then not for all iOS < 9.0. Also, Xcode 9.3 started disallowing
-// `thread_local` for 32-bit iOS simulator targeting iOS 9.x.
-// `__has_feature` is only supported by Clang so it has be inside
+// Notes:
+// * Xcode's clang did not support `thread_local` until version 8, and
+//   even then not for all iOS < 9.0.
+// * Xcode 9.3 started disallowing `thread_local` for 32-bit iOS simulator
+//   targeting iOS 9.x.
+// * Xcode 10 moves the deployment target check for iOS < 9.0 to link time
+//   making __has_feature unreliable there.
+//
+// Otherwise, `__has_feature` is only supported by Clang so it has be inside
 // `defined(__APPLE__)` check.
-#if __has_feature(cxx_thread_local)
+#if __has_feature(cxx_thread_local) && \
+    !(TARGET_OS_IPHONE && __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_9_0)
 #define ABSL_HAVE_THREAD_LOCAL 1
 #endif
 #else  // !defined(__APPLE__)
@@ -268,7 +274,8 @@
 #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(__sun)
+    defined(__wasm__) || defined(__Fuchsia__) || defined(__sun) || \
+    defined(__ASYLO__)
 #define ABSL_HAVE_MMAP 1
 #endif
 
@@ -322,6 +329,8 @@
 #define ABSL_HAVE_ALARM 1
 #elif defined(_MSC_VER)
 // feature tests for Microsoft's library
+#elif defined(__EMSCRIPTEN__)
+// emscripten doesn't support signals
 #elif defined(__native_client__)
 #else
 // other standard libraries
@@ -356,6 +365,18 @@
 #error "absl endian detection needs to be set up for your compiler"
 #endif
 
+// MacOS 10.13 doesn't let you use <any>, <optional>, or <variant> even though
+// the headers exist and are publicly noted to work.  See
+// https://github.com/abseil/abseil-cpp/issues/207 and
+// https://developer.apple.com/documentation/xcode_release_notes/xcode_10_release_notes
+#if defined(__APPLE__) && defined(_LIBCPP_VERSION) && \
+    defined(__MAC_OS_X_VERSION_MIN_REQUIRED__) &&     \
+    __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 101400
+#define ABSL_INTERNAL_MACOS_CXX17_TYPES_UNAVAILABLE 1
+#else
+#define ABSL_INTERNAL_MACOS_CXX17_TYPES_UNAVAILABLE 0
+#endif
+
 // ABSL_HAVE_STD_ANY
 //
 // Checks whether C++17 std::any is available by checking whether <any> exists.
@@ -364,7 +385,8 @@
 #endif
 
 #ifdef __has_include
-#if __has_include(<any>) && __cplusplus >= 201703L
+#if __has_include(<any>) && __cplusplus >= 201703L && \
+    !ABSL_INTERNAL_MACOS_CXX17_TYPES_UNAVAILABLE
 #define ABSL_HAVE_STD_ANY 1
 #endif
 #endif
@@ -377,7 +399,8 @@
 #endif
 
 #ifdef __has_include
-#if __has_include(<optional>) && __cplusplus >= 201703L
+#if __has_include(<optional>) && __cplusplus >= 201703L && \
+    !ABSL_INTERNAL_MACOS_CXX17_TYPES_UNAVAILABLE
 #define ABSL_HAVE_STD_OPTIONAL 1
 #endif
 #endif
@@ -390,7 +413,8 @@
 #endif
 
 #ifdef __has_include
-#if __has_include(<variant>) && __cplusplus >= 201703L
+#if __has_include(<variant>) && __cplusplus >= 201703L && \
+    !ABSL_INTERNAL_MACOS_CXX17_TYPES_UNAVAILABLE
 #define ABSL_HAVE_STD_VARIANT 1
 #endif
 #endif
@@ -423,4 +447,12 @@
 #define ABSL_HAVE_STD_STRING_VIEW 1
 #endif
 
+// In debug mode, MSVC 2017's std::variant throws a EXCEPTION_ACCESS_VIOLATION
+// SEH exception from emplace for variant<SomeStruct> when constructing the
+// struct can throw. This defeats some of variant_test and
+// variant_exception_safety_test.
+#if defined(_MSC_VER) && _MSC_VER >= 1700 && defined(_DEBUG)
+#define ABSL_INTERNAL_MSVC_2017_DBG_MODE
+#endif
+
 #endif  // ABSL_BASE_CONFIG_H_
diff --git a/absl/base/config_test.cc b/absl/base/config_test.cc
index c839712..7e0c033 100644
--- a/absl/base/config_test.cc
+++ b/absl/base/config_test.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
diff --git a/absl/base/const_init.h b/absl/base/const_init.h
new file mode 100644
index 0000000..17858a7
--- /dev/null
+++ b/absl/base/const_init.h
@@ -0,0 +1,72 @@
+// Copyright 2017 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
+//
+//      https://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.
+//
+// -----------------------------------------------------------------------------
+// kConstInit
+// -----------------------------------------------------------------------------
+//
+// A constructor tag used to mark an object as safe for use as a global
+// variable, avoiding the usual lifetime issues that can affect globals.
+
+#ifndef ABSL_BASE_CONST_INIT_H_
+#define ABSL_BASE_CONST_INIT_H_
+
+// In general, objects with static storage duration (such as global variables)
+// can trigger tricky object lifetime situations.  Attempting to access them
+// from the constructors or destructors of other global objects can result in
+// undefined behavior, unless their constructors and destructors are designed
+// with this issue in mind.
+//
+// The normal way to deal with this issue in C++11 is to use constant
+// initialization and trivial destructors.
+//
+// Constant initialization is guaranteed to occur before any other code
+// executes.  Constructors that are declared 'constexpr' are eligible for
+// constant initialization.  You can annotate a variable declaration with the
+// ABSL_CONST_INIT macro to express this intent.  For compilers that support
+// it, this annotation will cause a compilation error for declarations that
+// aren't subject to constant initialization (perhaps because a runtime value
+// was passed as a constructor argument).
+//
+// On program shutdown, lifetime issues can be avoided on global objects by
+// ensuring that they contain  trivial destructors.  A class has a trivial
+// destructor unless it has a user-defined destructor, a virtual method or base
+// class, or a data member or base class with a non-trivial destructor of its
+// own.  Objects with static storage duration and a trivial destructor are not
+// cleaned up on program shutdown, and are thus safe to access from other code
+// running during shutdown.
+//
+// For a few core Abseil classes, we make a best effort to allow for safe global
+// instances, even though these classes have non-trivial destructors.  These
+// objects can be created with the absl::kConstInit tag.  For example:
+//   ABSL_CONST_INIT absl::Mutex global_mutex(absl::kConstInit);
+//
+// The line above declares a global variable of type absl::Mutex which can be
+// accessed at any point during startup or shutdown.  global_mutex's destructor
+// will still run, but will not invalidate the object.  Note that C++ specifies
+// that accessing an object after its destructor has run results in undefined
+// behavior, but this pattern works on the toolchains we support.
+//
+// The absl::kConstInit tag should only be used to define objects with static
+// or thread_local storage duration.
+
+namespace absl {
+
+enum ConstInitType {
+  kConstInit,
+};
+
+}  // namespace absl
+
+#endif  // ABSL_BASE_CONST_INIT_H_
diff --git a/absl/base/dynamic_annotations.cc b/absl/base/dynamic_annotations.cc
index b97fa3a..1411093 100644
--- a/absl/base/dynamic_annotations.cc
+++ b/absl/base/dynamic_annotations.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
diff --git a/absl/base/dynamic_annotations.h b/absl/base/dynamic_annotations.h
index 88048b0..8ac7498 100644
--- a/absl/base/dynamic_annotations.h
+++ b/absl/base/dynamic_annotations.h
@@ -5,7 +5,7 @@
  * 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
+ *      https://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,
@@ -139,6 +139,7 @@
   #define ABSL_ANNOTATE_MEMORY_IS_INITIALIZED(address, size) /* empty */
   #define ABSL_ANNOTATE_MEMORY_IS_UNINITIALIZED(address, size) /* empty */
 #endif  /* ABSL_DYNAMIC_ANNOTATIONS_ENABLED || MEMORY_SANITIZER */
+
 /* TODO(delesley) -- Replace __CLANG_SUPPORT_DYN_ANNOTATION__ with the
    appropriate feature ID. */
 #if defined(__clang__) && (!defined(SWIG)) \
diff --git a/absl/base/exception_safety_testing_test.cc b/absl/base/exception_safety_testing_test.cc
index 106bc34..2ed3860 100644
--- a/absl/base/exception_safety_testing_test.cc
+++ b/absl/base/exception_safety_testing_test.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -770,6 +770,18 @@
                   .Test(invoker));
 }
 
+TEST(ExceptionSafetyTesterTest, ResetsCountdown) {
+  auto test =
+      testing::MakeExceptionSafetyTester()
+          .WithInitialValue(ThrowingValue<>())
+          .WithContracts([](ThrowingValue<>*) { return AssertionSuccess(); })
+          .WithOperation([](ThrowingValue<>*) {});
+  ASSERT_TRUE(test.Test());
+  // If the countdown isn't reset because there were no exceptions thrown, then
+  // this will fail with a termination from an unhandled exception
+  EXPECT_TRUE(test.Test());
+}
+
 struct NonCopyable : public NonNegative {
   NonCopyable(const NonCopyable&) = delete;
   NonCopyable() : NonNegative{0} {}
diff --git a/absl/base/inline_variable_test.cc b/absl/base/inline_variable_test.cc
index 5499189..471f706 100644
--- a/absl/base/inline_variable_test.cc
+++ b/absl/base/inline_variable_test.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
diff --git a/absl/base/inline_variable_test_a.cc b/absl/base/inline_variable_test_a.cc
index a3bf3b6..d0b8e7d 100644
--- a/absl/base/inline_variable_test_a.cc
+++ b/absl/base/inline_variable_test_a.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
diff --git a/absl/base/inline_variable_test_b.cc b/absl/base/inline_variable_test_b.cc
index b4b9393..931d56d 100644
--- a/absl/base/inline_variable_test_b.cc
+++ b/absl/base/inline_variable_test_b.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
diff --git a/absl/base/internal/atomic_hook.h b/absl/base/internal/atomic_hook.h
index b458511..803e905 100644
--- a/absl/base/internal/atomic_hook.h
+++ b/absl/base/internal/atomic_hook.h
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
diff --git a/absl/base/internal/atomic_hook_test.cc b/absl/base/internal/atomic_hook_test.cc
index cf74075..ecc8040 100644
--- a/absl/base/internal/atomic_hook_test.cc
+++ b/absl/base/internal/atomic_hook_test.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
diff --git a/absl/base/internal/bits.h b/absl/base/internal/bits.h
index bc7faae..b0780f2 100644
--- a/absl/base/internal/bits.h
+++ b/absl/base/internal/bits.h
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
diff --git a/absl/base/internal/bits_test.cc b/absl/base/internal/bits_test.cc
index e5d991d..7855fa6 100644
--- a/absl/base/internal/bits_test.cc
+++ b/absl/base/internal/bits_test.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
diff --git a/absl/base/internal/cycleclock.cc b/absl/base/internal/cycleclock.cc
index a742df0..4b553c2 100644
--- a/absl/base/internal/cycleclock.cc
+++ b/absl/base/internal/cycleclock.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -22,6 +22,7 @@
 
 #include "absl/base/internal/cycleclock.h"
 
+#include <atomic>
 #include <chrono>  // NOLINT(build/c++11)
 
 #include "absl/base/internal/unscaledcycleclock.h"
@@ -52,17 +53,26 @@
 #endif
 
 static constexpr double kFrequencyScale = 1.0 / (1 << kShift);
+static std::atomic<CycleClockSourceFunc> cycle_clock_source;
 
 }  // namespace
 
 int64_t CycleClock::Now() {
-  return base_internal::UnscaledCycleClock::Now() >> kShift;
+  auto fn = cycle_clock_source.load(std::memory_order_relaxed);
+  if (fn == nullptr) {
+    return base_internal::UnscaledCycleClock::Now() >> kShift;
+  }
+  return fn() >> kShift;
 }
 
 double CycleClock::Frequency() {
   return kFrequencyScale * base_internal::UnscaledCycleClock::Frequency();
 }
 
+void CycleClockSource::Register(CycleClockSourceFunc source) {
+  cycle_clock_source.store(source, std::memory_order_relaxed);
+}
+
 #else
 
 int64_t CycleClock::Now() {
diff --git a/absl/base/internal/cycleclock.h b/absl/base/internal/cycleclock.h
index 60e9715..794564e 100644
--- a/absl/base/internal/cycleclock.h
+++ b/absl/base/internal/cycleclock.h
@@ -5,7 +5,7 @@
 // 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
+//      https://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,
@@ -28,7 +28,6 @@
 // not necessarily "CPU cycles" and code should not rely on that behavior, even
 // if experimentally observed.
 //
-//
 // An arbitrary offset may have been added to the counter at power on.
 //
 // On some platforms, the rate and offset of the counter may differ
@@ -71,6 +70,20 @@
   CycleClock& operator=(const CycleClock&) = delete;
 };
 
+using CycleClockSourceFunc = int64_t (*)();
+
+class CycleClockSource {
+ private:
+  // CycleClockSource::Register()
+  //
+  // Register a function that provides an alternate source for the unscaled CPU
+  // cycle count value. The source function must be async signal safe, must not
+  // call CycleClock::Now(), and must have a frequency that matches that of the
+  // unscaled clock used by CycleClock. A nullptr value resets CycleClock to use
+  // the default source.
+  static void Register(CycleClockSourceFunc source);
+};
+
 }  // namespace base_internal
 }  // namespace absl
 
diff --git a/absl/base/internal/direct_mmap.h b/absl/base/internal/direct_mmap.h
index 0426e11..0401ddf 100644
--- a/absl/base/internal/direct_mmap.h
+++ b/absl/base/internal/direct_mmap.h
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -75,7 +75,11 @@
   // On these architectures, implement mmap with mmap2.
   static int pagesize = 0;
   if (pagesize == 0) {
+#if defined(__wasm__) || defined(__asmjs__)
     pagesize = getpagesize();
+#else
+    pagesize = sysconf(_SC_PAGESIZE);
+#endif
   }
   if (offset < 0 || offset % pagesize != 0) {
     errno = EINVAL;
diff --git a/absl/base/internal/endian.h b/absl/base/internal/endian.h
index edc10f1..6b828b6 100644
--- a/absl/base/internal/endian.h
+++ b/absl/base/internal/endian.h
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -75,21 +75,21 @@
   if (__builtin_constant_p(host_int)) {
     return __bswap_constant_64(host_int);
   } else {
-    register uint64_t result;
+    uint64_t result;
     __asm__("bswap %0" : "=r"(result) : "0"(host_int));
     return result;
   }
 #elif defined(__GLIBC__)
   return bswap_64(host_int);
 #else
-  return (((x & uint64_t{(0xFF}) << 56) |
-          ((x & uint64_t{(0xFF00}) << 40) |
-          ((x & uint64_t{(0xFF0000}) << 24) |
-          ((x & uint64_t{(0xFF000000}) << 8) |
-          ((x & uint64_t{(0xFF00000000}) >> 8) |
-          ((x & uint64_t{(0xFF0000000000}) >> 24) |
-          ((x & uint64_t{(0xFF000000000000}) >> 40) |
-          ((x & uint64_t{(0xFF00000000000000}) >> 56));
+  return (((host_int & uint64_t{0xFF}) << 56) |
+          ((host_int & uint64_t{0xFF00}) << 40) |
+          ((host_int & uint64_t{0xFF0000}) << 24) |
+          ((host_int & uint64_t{0xFF000000}) << 8) |
+          ((host_int & uint64_t{0xFF00000000}) >> 8) |
+          ((host_int & uint64_t{0xFF0000000000}) >> 24) |
+          ((host_int & uint64_t{0xFF000000000000}) >> 40) |
+          ((host_int & uint64_t{0xFF00000000000000}) >> 56));
 #endif  // bswap_64
 }
 
@@ -97,8 +97,10 @@
 #if defined(__GLIBC__)
   return bswap_32(host_int);
 #else
-  return (((x & 0xFF) << 24) | ((x & 0xFF00) << 8) | ((x & 0xFF0000) >> 8) |
-          ((x & 0xFF000000) >> 24));
+  return (((host_int & uint32_t{0xFF}) << 24) |
+          ((host_int & uint32_t{0xFF00}) << 8) |
+          ((host_int & uint32_t{0xFF0000}) >> 8) |
+          ((host_int & uint32_t{0xFF000000}) >> 24));
 #endif
 }
 
@@ -106,7 +108,8 @@
 #if defined(__GLIBC__)
   return bswap_16(host_int);
 #else
-  return uint16_t{((x & 0xFF) << 8) | ((x & 0xFF00) >> 8)};
+  return (((host_int & uint16_t{0xFF}) << 8) |
+          ((host_int & uint16_t{0xFF00}) >> 8));
 #endif
 }
 
diff --git a/absl/base/internal/endian_test.cc b/absl/base/internal/endian_test.cc
index e276915..98a099e 100644
--- a/absl/base/internal/endian_test.cc
+++ b/absl/base/internal/endian_test.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
diff --git a/absl/base/internal/exception_safety_testing.cc b/absl/base/internal/exception_safety_testing.cc
index f1d081f..6ef4325 100644
--- a/absl/base/internal/exception_safety_testing.cc
+++ b/absl/base/internal/exception_safety_testing.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -23,6 +23,10 @@
 
 exceptions_internal::StrongGuaranteeTagType strong_guarantee;
 
+exceptions_internal::ExceptionSafetyTestBuilder<> MakeExceptionSafetyTester() {
+  return {};
+}
+
 namespace exceptions_internal {
 
 int countdown = -1;
diff --git a/absl/base/internal/exception_safety_testing.h b/absl/base/internal/exception_safety_testing.h
index 5665a1b..be38ba5 100644
--- a/absl/base/internal/exception_safety_testing.h
+++ b/absl/base/internal/exception_safety_testing.h
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -33,7 +33,7 @@
 #include "absl/meta/type_traits.h"
 #include "absl/strings/string_view.h"
 #include "absl/strings/substitute.h"
-#include "absl/types/optional.h"
+#include "absl/utility/utility.h"
 
 namespace testing {
 
@@ -127,10 +127,8 @@
       void* address = it.first;
       TrackedAddress& tracked_address = it.second;
       if (tracked_address.is_alive) {
-        ADD_FAILURE() << "Object at address " << address
-                      << " with countdown of " << countdown_
-                      << " was not destroyed [" << tracked_address.description
-                      << "]";
+        ADD_FAILURE() << ErrorMessage(address, tracked_address.description,
+                                      countdown_, "Object was not destroyed.");
       }
     }
   }
@@ -141,11 +139,11 @@
     TrackedAddress& tracked_address =
         current_tracker_instance_->address_map_[address];
     if (tracked_address.is_alive) {
-      ADD_FAILURE() << "Object at address " << address << " with countdown of "
-                    << current_tracker_instance_->countdown_
-                    << " was re-constructed. Previously: ["
-                    << tracked_address.description << "] Now: [" << description
-                    << "]";
+      ADD_FAILURE() << ErrorMessage(
+          address, tracked_address.description,
+          current_tracker_instance_->countdown_,
+          "Object was re-constructed. Current object was constructed by " +
+              description);
     }
     tracked_address = {true, std::move(description)};
   }
@@ -159,10 +157,9 @@
 
     TrackedAddress& tracked_address = it->second;
     if (!tracked_address.is_alive) {
-      ADD_FAILURE() << "Object at address " << address << " with countdown of "
-                    << current_tracker_instance_->countdown_
-                    << " was re-destroyed or created prior to construction "
-                    << "tracking [" << tracked_address.description << "]";
+      ADD_FAILURE() << ErrorMessage(address, tracked_address.description,
+                                    current_tracker_instance_->countdown_,
+                                    "Object was re-destroyed.");
     }
     tracked_address.is_alive = false;
   }
@@ -172,6 +169,18 @@
     return current_tracker_instance_ != nullptr;
   }
 
+  static std::string ErrorMessage(void* address,
+                                  const std::string& address_description,
+                                  int countdown,
+                                  const std::string& error_description) {
+    return absl::Substitute(
+        "With coundtown at $0:\n"
+        "  $1\n"
+        "  Object originally constructed by $2\n"
+        "  Object address: $3\n",
+        countdown, error_description, address_description, address);
+  }
+
   std::unordered_map<void*, TrackedAddress> address_map_;
   int countdown_;
 
@@ -190,70 +199,6 @@
 
   ~TrackedObject() noexcept { ConstructorTracker::ObjectDestructed(this); }
 };
-
-template <typename Factory, typename Operation, typename Contract>
-absl::optional<testing::AssertionResult> TestSingleContractAtCountdownImpl(
-    const Factory& factory, const Operation& operation, int count,
-    const Contract& contract) {
-  auto t_ptr = factory();
-  absl::optional<testing::AssertionResult> current_res;
-  SetCountdown(count);
-  try {
-    operation(t_ptr.get());
-  } catch (const exceptions_internal::TestException& e) {
-    current_res.emplace(contract(t_ptr.get()));
-    if (!current_res.value()) {
-      *current_res << e.what() << " failed contract check";
-    }
-  }
-  UnsetCountdown();
-  return current_res;
-}
-
-template <typename Factory, typename Operation>
-absl::optional<testing::AssertionResult> TestSingleContractAtCountdownImpl(
-    const Factory& factory, const Operation& operation, int count,
-    StrongGuaranteeTagType) {
-  using TPtr = typename decltype(factory())::pointer;
-  auto t_is_strong = [&](TPtr t) { return *t == *factory(); };
-  return TestSingleContractAtCountdownImpl(factory, operation, count,
-                                           t_is_strong);
-}
-
-template <typename Factory, typename Operation, typename Contract>
-int TestSingleContractAtCountdown(
-    const Factory& factory, const Operation& operation, int count,
-    const Contract& contract,
-    absl::optional<testing::AssertionResult>* reduced_res) {
-  // If reduced_res is empty, it means the current call to
-  // TestSingleContractAtCountdown(...) is the first test being run so we do
-  // want to run it. Alternatively, if it's not empty (meaning a previous test
-  // has run) we want to check if it passed. If the previous test did pass, we
-  // want to contine running tests so we do want to run the current one. If it
-  // failed, we want to short circuit so as not to overwrite the AssertionResult
-  // output. If that's the case, we do not run the current test and instead we
-  // simply return.
-  if (!reduced_res->has_value() || reduced_res->value()) {
-    *reduced_res =
-        TestSingleContractAtCountdownImpl(factory, operation, count, contract);
-  }
-  return 0;
-}
-
-template <typename Factory, typename Operation, typename... Contracts>
-inline absl::optional<testing::AssertionResult> TestAllContractsAtCountdown(
-    const Factory& factory, const Operation& operation, int count,
-    const Contracts&... contracts) {
-  absl::optional<testing::AssertionResult> reduced_res;
-
-  // Run each checker, short circuiting after the first failure
-  int dummy[] = {
-      0, (TestSingleContractAtCountdown(factory, operation, count, contracts,
-                                        &reduced_res))...};
-  static_cast<void>(dummy);
-  return reduced_res;
-}
-
 }  // namespace exceptions_internal
 
 extern exceptions_internal::NoThrowTag nothrow_ctor;
@@ -613,8 +558,8 @@
   // We provide both regular and templated operator delete because if only the
   // templated version is provided as we did with operator new, the compiler has
   // no way of knowing which overload of operator delete to call. See
-  // http://en.cppreference.com/w/cpp/memory/new/operator_delete and
-  // http://en.cppreference.com/w/cpp/language/delete for the gory details.
+  // https://en.cppreference.com/w/cpp/memory/new/operator_delete and
+  // https://en.cppreference.com/w/cpp/language/delete for the gory details.
   void operator delete(void* p) noexcept { ::operator delete(p); }
 
   template <typename... Args>
@@ -773,7 +718,7 @@
   }
 
   size_type max_size() const noexcept {
-    return std::numeric_limits<difference_type>::max() / sizeof(value_type);
+    return (std::numeric_limits<difference_type>::max)() / sizeof(value_type);
   }
 
   ThrowingAllocator select_on_container_copy_construction() noexcept(
@@ -871,7 +816,7 @@
 
 namespace exceptions_internal {
 
-// Dummy struct for ExceptionSafetyTester<> partial state.
+// Dummy struct for ExceptionSafetyTestBuilder<> partial state.
 struct UninitializedT {};
 
 template <typename T>
@@ -893,20 +838,97 @@
 
 template <typename Factory = UninitializedT,
           typename Operation = UninitializedT, typename... Contracts>
-class ExceptionSafetyTester;
+class ExceptionSafetyTestBuilder;
 
 }  // namespace exceptions_internal
 
-exceptions_internal::ExceptionSafetyTester<> MakeExceptionSafetyTester();
+/*
+ * Constructs an empty ExceptionSafetyTestBuilder. All
+ * ExceptionSafetyTestBuilder objects are immutable and all With[thing] mutation
+ * methods return new instances of ExceptionSafetyTestBuilder.
+ *
+ * In order to test a T for exception safety, a factory for that T, a testable
+ * operation, and at least one contract callback returning an assertion
+ * result must be applied using the respective methods.
+ */
+exceptions_internal::ExceptionSafetyTestBuilder<> MakeExceptionSafetyTester();
 
 namespace exceptions_internal {
+template <typename T>
+struct IsUniquePtr : std::false_type {};
+
+template <typename T, typename D>
+struct IsUniquePtr<std::unique_ptr<T, D>> : std::true_type {};
+
+template <typename Factory>
+struct FactoryPtrTypeHelper {
+  using type = decltype(std::declval<const Factory&>()());
+
+  static_assert(IsUniquePtr<type>::value, "Factories must return a unique_ptr");
+};
+
+template <typename Factory>
+using FactoryPtrType = typename FactoryPtrTypeHelper<Factory>::type;
+
+template <typename Factory>
+using FactoryElementType = typename FactoryPtrType<Factory>::element_type;
+
+template <typename T>
+class ExceptionSafetyTest {
+  using Factory = std::function<std::unique_ptr<T>()>;
+  using Operation = std::function<void(T*)>;
+  using Contract = std::function<AssertionResult(T*)>;
+
+ public:
+  template <typename... Contracts>
+  explicit ExceptionSafetyTest(const Factory& f, const Operation& op,
+                               const Contracts&... contracts)
+      : factory_(f), operation_(op), contracts_{WrapContract(contracts)...} {}
+
+  AssertionResult Test() const {
+    for (int count = 0;; ++count) {
+      exceptions_internal::ConstructorTracker ct(count);
+
+      for (const auto& contract : contracts_) {
+        auto t_ptr = factory_();
+        try {
+          SetCountdown(count);
+          operation_(t_ptr.get());
+          // Unset for the case that the operation throws no exceptions, which
+          // would leave the countdown set and break the *next* exception safety
+          // test after this one.
+          UnsetCountdown();
+          return AssertionSuccess();
+        } catch (const exceptions_internal::TestException& e) {
+          if (!contract(t_ptr.get())) {
+            return AssertionFailure() << e.what() << " failed contract check";
+          }
+        }
+      }
+    }
+  }
+
+ private:
+  template <typename ContractFn>
+  Contract WrapContract(const ContractFn& contract) {
+    return [contract](T* t_ptr) { return AssertionResult(contract(t_ptr)); };
+  }
+
+  Contract WrapContract(StrongGuaranteeTagType) {
+    return [this](T* t_ptr) { return AssertionResult(*factory_() == *t_ptr); };
+  }
+
+  Factory factory_;
+  Operation operation_;
+  std::vector<Contract> contracts_;
+};
 
 /*
  * Builds a tester object that tests if performing a operation on a T follows
  * exception safety guarantees. Verification is done via contract assertion
  * callbacks applied to T instances post-throw.
  *
- * Template parameters for ExceptionSafetyTester:
+ * Template parameters for ExceptionSafetyTestBuilder:
  *
  * - Factory: The factory object (passed in via tester.WithFactory(...) or
  *   tester.WithInitialValue(...)) must be invocable with the signature
@@ -933,13 +955,13 @@
  *   please.
  */
 template <typename Factory, typename Operation, typename... Contracts>
-class ExceptionSafetyTester {
+class ExceptionSafetyTestBuilder {
  public:
   /*
-   * Returns a new ExceptionSafetyTester with an included T factory based on the
-   * provided T instance. The existing factory will not be included in the newly
-   * created tester instance. The created factory returns a new T instance by
-   * copy-constructing the provided const T& t.
+   * Returns a new ExceptionSafetyTestBuilder with an included T factory based
+   * on the provided T instance. The existing factory will not be included in
+   * the newly created tester instance. The created factory returns a new T
+   * instance by copy-constructing the provided const T& t.
    *
    * Preconditions for tester.WithInitialValue(const T& t):
    *
@@ -948,41 +970,41 @@
    *   tester.WithFactory(...).
    */
   template <typename T>
-  ExceptionSafetyTester<DefaultFactory<T>, Operation, Contracts...>
+  ExceptionSafetyTestBuilder<DefaultFactory<T>, Operation, Contracts...>
   WithInitialValue(const T& t) const {
     return WithFactory(DefaultFactory<T>(t));
   }
 
   /*
-   * Returns a new ExceptionSafetyTester with the provided T factory included.
-   * The existing factory will not be included in the newly-created tester
-   * instance. This method is intended for use with types lacking a copy
+   * Returns a new ExceptionSafetyTestBuilder with the provided T factory
+   * included. The existing factory will not be included in the newly-created
+   * tester instance. This method is intended for use with types lacking a copy
    * constructor. Types that can be copy-constructed should instead use the
    * method tester.WithInitialValue(...).
    */
   template <typename NewFactory>
-  ExceptionSafetyTester<absl::decay_t<NewFactory>, Operation, Contracts...>
+  ExceptionSafetyTestBuilder<absl::decay_t<NewFactory>, Operation, Contracts...>
   WithFactory(const NewFactory& new_factory) const {
     return {new_factory, operation_, contracts_};
   }
 
   /*
-   * Returns a new ExceptionSafetyTester with the provided testable operation
-   * included. The existing operation will not be included in the newly created
-   * tester.
+   * Returns a new ExceptionSafetyTestBuilder with the provided testable
+   * operation included. The existing operation will not be included in the
+   * newly created tester.
    */
   template <typename NewOperation>
-  ExceptionSafetyTester<Factory, absl::decay_t<NewOperation>, Contracts...>
+  ExceptionSafetyTestBuilder<Factory, absl::decay_t<NewOperation>, Contracts...>
   WithOperation(const NewOperation& new_operation) const {
     return {factory_, new_operation, contracts_};
   }
 
   /*
-   * Returns a new ExceptionSafetyTester with the provided MoreContracts...
+   * Returns a new ExceptionSafetyTestBuilder with the provided MoreContracts...
    * combined with the Contracts... that were already included in the instance
    * on which the method was called. Contracts... cannot be removed or replaced
-   * once added to an ExceptionSafetyTester instance. A fresh object must be
-   * created in order to get an empty Contracts... list.
+   * once added to an ExceptionSafetyTestBuilder instance. A fresh object must
+   * be created in order to get an empty Contracts... list.
    *
    * In addition to passing in custom contract assertion callbacks, this method
    * accepts `testing::strong_guarantee` as an argument which checks T instances
@@ -991,8 +1013,8 @@
    * properly rolled back.
    */
   template <typename... MoreContracts>
-  ExceptionSafetyTester<Factory, Operation, Contracts...,
-                        absl::decay_t<MoreContracts>...>
+  ExceptionSafetyTestBuilder<Factory, Operation, Contracts...,
+                             absl::decay_t<MoreContracts>...>
   WithContracts(const MoreContracts&... more_contracts) const {
     return {
         factory_, operation_,
@@ -1039,48 +1061,27 @@
       typename LazyOperation = Operation,
       typename = EnableIfTestable<sizeof...(Contracts), Factory, LazyOperation>>
   testing::AssertionResult Test() const {
-    return TestImpl(operation_, absl::index_sequence_for<Contracts...>());
+    return Test(operation_);
   }
 
  private:
   template <typename, typename, typename...>
-  friend class ExceptionSafetyTester;
+  friend class ExceptionSafetyTestBuilder;
 
-  friend ExceptionSafetyTester<> testing::MakeExceptionSafetyTester();
+  friend ExceptionSafetyTestBuilder<> testing::MakeExceptionSafetyTester();
 
-  ExceptionSafetyTester() {}
+  ExceptionSafetyTestBuilder() {}
 
-  ExceptionSafetyTester(const Factory& f, const Operation& o,
-                        const std::tuple<Contracts...>& i)
+  ExceptionSafetyTestBuilder(const Factory& f, const Operation& o,
+                             const std::tuple<Contracts...>& i)
       : factory_(f), operation_(o), contracts_(i) {}
 
   template <typename SelectedOperation, size_t... Indices>
-  testing::AssertionResult TestImpl(const SelectedOperation& selected_operation,
+  testing::AssertionResult TestImpl(SelectedOperation selected_operation,
                                     absl::index_sequence<Indices...>) const {
-    // Starting from 0 and counting upwards until one of the exit conditions is
-    // hit...
-    for (int count = 0;; ++count) {
-      exceptions_internal::ConstructorTracker ct(count);
-
-      // Run the full exception safety test algorithm for the current countdown
-      auto reduced_res =
-          TestAllContractsAtCountdown(factory_, selected_operation, count,
-                                      std::get<Indices>(contracts_)...);
-      // If there is no value in the optional, no contracts were run because no
-      // exception was thrown. This means that the test is complete and the loop
-      // can exit successfully.
-      if (!reduced_res.has_value()) {
-        return testing::AssertionSuccess();
-      }
-      // If the optional is not empty and the value is falsy, an contract check
-      // failed so the test must exit to propegate the failure.
-      if (!reduced_res.value()) {
-        return reduced_res.value();
-      }
-      // If the optional is not empty and the value is not falsy, it means
-      // exceptions were thrown but the contracts passed so the test must
-      // continue to run.
-    }
+    return ExceptionSafetyTest<FactoryElementType<Factory>>(
+               factory_, selected_operation, std::get<Indices>(contracts_)...)
+        .Test();
   }
 
   Factory factory_;
@@ -1090,20 +1091,6 @@
 
 }  // namespace exceptions_internal
 
-/*
- * Constructs an empty ExceptionSafetyTester. All ExceptionSafetyTester
- * objects are immutable and all With[thing] mutation methods return new
- * instances of ExceptionSafetyTester.
- *
- * In order to test a T for exception safety, a factory for that T, a testable
- * operation, and at least one contract callback returning an assertion
- * result must be applied using the respective methods.
- */
-inline exceptions_internal::ExceptionSafetyTester<>
-MakeExceptionSafetyTester() {
-  return {};
-}
-
 }  // namespace testing
 
 #endif  // ABSL_BASE_INTERNAL_EXCEPTION_SAFETY_TESTING_H_
diff --git a/absl/base/internal/exception_testing.h b/absl/base/internal/exception_testing.h
index 0cf7918..01b5465 100644
--- a/absl/base/internal/exception_testing.h
+++ b/absl/base/internal/exception_testing.h
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
diff --git a/absl/base/internal/hide_ptr.h b/absl/base/internal/hide_ptr.h
index 45cf438..cf8f408 100644
--- a/absl/base/internal/hide_ptr.h
+++ b/absl/base/internal/hide_ptr.h
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
diff --git a/absl/base/internal/identity.h b/absl/base/internal/identity.h
index a1a5d70..086447c 100644
--- a/absl/base/internal/identity.h
+++ b/absl/base/internal/identity.h
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
diff --git a/absl/base/internal/inline_variable.h b/absl/base/internal/inline_variable.h
index f7bb8c5..130d8c2 100644
--- a/absl/base/internal/inline_variable.h
+++ b/absl/base/internal/inline_variable.h
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
diff --git a/absl/base/internal/inline_variable_testing.h b/absl/base/internal/inline_variable_testing.h
index a0dd2bb..15dc481 100644
--- a/absl/base/internal/inline_variable_testing.h
+++ b/absl/base/internal/inline_variable_testing.h
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
diff --git a/absl/base/internal/invoke.h b/absl/base/internal/invoke.h
index 8c3f4f6..8da2869 100644
--- a/absl/base/internal/invoke.h
+++ b/absl/base/internal/invoke.h
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
diff --git a/absl/base/internal/low_level_alloc.cc b/absl/base/internal/low_level_alloc.cc
index 159f945..e4030ed 100644
--- a/absl/base/internal/low_level_alloc.cc
+++ b/absl/base/internal/low_level_alloc.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -208,7 +208,7 @@
   int32_t allocation_count GUARDED_BY(mu);
   // flags passed to NewArena
   const uint32_t flags;
-  // Result of getpagesize()
+  // Result of sysconf(_SC_PAGESIZE)
   const size_t pagesize;
   // Lowest power of two >= max(16, sizeof(AllocList))
   const size_t roundup;
@@ -324,8 +324,10 @@
   SYSTEM_INFO system_info;
   GetSystemInfo(&system_info);
   return std::max(system_info.dwPageSize, system_info.dwAllocationGranularity);
-#else
+#elif defined(__wasm__) || defined(__asmjs__)
   return getpagesize();
+#else
+  return sysconf(_SC_PAGESIZE);
 #endif
 }
 
diff --git a/absl/base/internal/low_level_alloc.h b/absl/base/internal/low_level_alloc.h
index fba9466..b35673d 100644
--- a/absl/base/internal/low_level_alloc.h
+++ b/absl/base/internal/low_level_alloc.h
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -119,4 +119,5 @@
 
 }  // namespace base_internal
 }  // namespace absl
+
 #endif  // ABSL_BASE_INTERNAL_LOW_LEVEL_ALLOC_H_
diff --git a/absl/base/internal/low_level_alloc_test.cc b/absl/base/internal/low_level_alloc_test.cc
index cf2b363..34a080c 100644
--- a/absl/base/internal/low_level_alloc_test.cc
+++ b/absl/base/internal/low_level_alloc_test.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -137,6 +137,7 @@
     TEST_ASSERT(LowLevelAlloc::DeleteArena(arena));
   }
 }
+
 // LowLevelAlloc is designed to be safe to call before main().
 static struct BeforeMain {
   BeforeMain() {
diff --git a/absl/base/internal/low_level_scheduling.h b/absl/base/internal/low_level_scheduling.h
index e716f2b..0fcc8d3 100644
--- a/absl/base/internal/low_level_scheduling.h
+++ b/absl/base/internal/low_level_scheduling.h
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -86,6 +86,7 @@
 //------------------------------------------------------------------------------
 // End of public interfaces.
 //------------------------------------------------------------------------------
+
 inline bool SchedulingGuard::ReschedulingIsAllowed() {
   return false;
 }
@@ -98,7 +99,7 @@
   return;
 }
 
-
 }  // namespace base_internal
 }  // namespace absl
+
 #endif  // ABSL_BASE_INTERNAL_LOW_LEVEL_SCHEDULING_H_
diff --git a/absl/base/internal/per_thread_tls.h b/absl/base/internal/per_thread_tls.h
index 2428bdc..cf5e97a 100644
--- a/absl/base/internal/per_thread_tls.h
+++ b/absl/base/internal/per_thread_tls.h
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -16,13 +16,17 @@
 #define ABSL_BASE_INTERNAL_PER_THREAD_TLS_H_
 
 // This header defines two macros:
+//
 // If the platform supports thread-local storage:
-//   ABSL_PER_THREAD_TLS_KEYWORD is the C keyword needed to declare a
-//   thread-local variable ABSL_PER_THREAD_TLS is 1
+//
+// * ABSL_PER_THREAD_TLS_KEYWORD is the C keyword needed to declare a
+//   thread-local variable
+// * ABSL_PER_THREAD_TLS is 1
 //
 // Otherwise:
-//   ABSL_PER_THREAD_TLS_KEYWORD is empty
-//   ABSL_PER_THREAD_TLS is 0
+//
+// * ABSL_PER_THREAD_TLS_KEYWORD is empty
+// * ABSL_PER_THREAD_TLS is 0
 //
 // Microsoft C supports thread-local storage.
 // GCC supports it if the appropriate version of glibc is available,
diff --git a/absl/base/internal/pretty_function.h b/absl/base/internal/pretty_function.h
index 01b0547..35d5167 100644
--- a/absl/base/internal/pretty_function.h
+++ b/absl/base/internal/pretty_function.h
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
diff --git a/absl/base/internal/raw_logging.cc b/absl/base/internal/raw_logging.cc
index d9485a6..b5a05e8 100644
--- a/absl/base/internal/raw_logging.cc
+++ b/absl/base/internal/raw_logging.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
diff --git a/absl/base/internal/raw_logging.h b/absl/base/internal/raw_logging.h
index 79a7bb9..6a4c093 100644
--- a/absl/base/internal/raw_logging.h
+++ b/absl/base/internal/raw_logging.h
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -38,6 +38,7 @@
 //   ABSL_RAW_LOG(ERROR, "Failed foo with %i: %s", status, error);
 // This will print an almost standard log line like this to stderr only:
 //   E0821 211317 file.cc:123] RAW: Failed foo with 22: bad_file
+
 #define ABSL_RAW_LOG(severity, ...)                                            \
   do {                                                                         \
     constexpr const char* absl_raw_logging_internal_basename =                 \
@@ -79,13 +80,13 @@
         absl_raw_logging_internal_basename, __LINE__, message);       \
   } while (0)
 
-#define ABSL_INTERNAL_CHECK(condition, message)               \
-  do {                                                        \
-    if (ABSL_PREDICT_FALSE(!(condition))) {                   \
+#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);                \
-    }                                                         \
+      ABSL_INTERNAL_LOG(FATAL, death_message);                     \
+    }                                                              \
   } while (0)
 
 #define ABSL_RAW_LOGGING_INTERNAL_INFO ::absl::LogSeverity::kInfo
diff --git a/absl/base/internal/scheduling_mode.h b/absl/base/internal/scheduling_mode.h
index 1b6497a..d5b4b7f 100644
--- a/absl/base/internal/scheduling_mode.h
+++ b/absl/base/internal/scheduling_mode.h
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
diff --git a/absl/base/internal/scoped_set_env.cc b/absl/base/internal/scoped_set_env.cc
new file mode 100644
index 0000000..3ac3f68
--- /dev/null
+++ b/absl/base/internal/scoped_set_env.cc
@@ -0,0 +1,79 @@
+// Copyright 2019 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
+//
+//      https://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/base/internal/scoped_set_env.h"
+
+#ifdef _WIN32
+#include <windows.h>
+#endif
+
+#include <cstdlib>
+
+#include "absl/base/internal/raw_logging.h"
+
+namespace absl {
+namespace base_internal {
+
+namespace {
+
+#ifdef _WIN32
+const int kMaxEnvVarValueSize = 1024;
+#endif
+
+void SetEnvVar(const char* name, const char* value) {
+#ifdef _WIN32
+  SetEnvironmentVariableA(name, value);
+#else
+  if (value == nullptr) {
+    ::unsetenv(name);
+  } else {
+    ::setenv(name, value, 1);
+  }
+#endif
+}
+
+}  // namespace
+
+ScopedSetEnv::ScopedSetEnv(const char* var_name, const char* new_value)
+    : var_name_(var_name), was_unset_(false) {
+#ifdef _WIN32
+  char buf[kMaxEnvVarValueSize];
+  auto get_res = GetEnvironmentVariableA(var_name_.c_str(), buf, sizeof(buf));
+  ABSL_INTERNAL_CHECK(get_res < sizeof(buf), "value exceeds buffer size");
+
+  if (get_res == 0) {
+    was_unset_ = (GetLastError() == ERROR_ENVVAR_NOT_FOUND);
+  } else {
+    old_value_.assign(buf, get_res);
+  }
+
+  SetEnvironmentVariableA(var_name_.c_str(), new_value);
+#else
+  const char* val = ::getenv(var_name_.c_str());
+  if (val == nullptr) {
+    was_unset_ = true;
+  } else {
+    old_value_ = val;
+  }
+#endif
+
+  SetEnvVar(var_name_.c_str(), new_value);
+}
+
+ScopedSetEnv::~ScopedSetEnv() {
+  SetEnvVar(var_name_.c_str(), was_unset_ ? nullptr : old_value_.c_str());
+}
+
+}  // namespace base_internal
+}  // namespace absl
diff --git a/absl/base/internal/scoped_set_env.h b/absl/base/internal/scoped_set_env.h
new file mode 100644
index 0000000..855b22f
--- /dev/null
+++ b/absl/base/internal/scoped_set_env.h
@@ -0,0 +1,41 @@
+//
+// Copyright 2019 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
+//
+//      https://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.
+//
+
+#ifndef ABSL_BASE_INTERNAL_SCOPED_SET_ENV_H_
+#define ABSL_BASE_INTERNAL_SCOPED_SET_ENV_H_
+
+#include <string>
+
+namespace absl {
+namespace base_internal {
+
+class ScopedSetEnv {
+ public:
+  ScopedSetEnv(const char* var_name, const char* new_value);
+  ~ScopedSetEnv();
+
+ private:
+  std::string var_name_;
+  std::string old_value_;
+
+  // True if the environment variable was initially not set.
+  bool was_unset_;
+};
+
+}  // namespace base_internal
+}  // namespace absl
+
+#endif  // ABSL_BASE_INTERNAL_SCOPED_SET_ENV_H_
diff --git a/absl/base/internal/scoped_set_env_test.cc b/absl/base/internal/scoped_set_env_test.cc
new file mode 100644
index 0000000..5cbad24
--- /dev/null
+++ b/absl/base/internal/scoped_set_env_test.cc
@@ -0,0 +1,99 @@
+// Copyright 2019 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
+//
+//      https://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.
+
+#ifdef _WIN32
+#include <windows.h>
+#endif
+
+#include "gtest/gtest.h"
+#include "absl/base/internal/scoped_set_env.h"
+
+namespace {
+
+using absl::base_internal::ScopedSetEnv;
+
+std::string GetEnvVar(const char* name) {
+#ifdef _WIN32
+  char buf[1024];
+  auto get_res = GetEnvironmentVariableA(name, buf, sizeof(buf));
+  if (get_res >= sizeof(buf)) {
+    return "TOO_BIG";
+  }
+
+  if (get_res == 0) {
+    return "UNSET";
+  }
+
+  return std::string(buf, get_res);
+#else
+  const char* val = ::getenv(name);
+  if (val == nullptr) {
+    return "UNSET";
+  }
+
+  return val;
+#endif
+}
+
+TEST(ScopedSetEnvTest, SetNonExistingVarToString) {
+  EXPECT_EQ(GetEnvVar("SCOPED_SET_ENV_TEST_VAR"), "UNSET");
+
+  {
+    ScopedSetEnv scoped_set("SCOPED_SET_ENV_TEST_VAR", "value");
+
+    EXPECT_EQ(GetEnvVar("SCOPED_SET_ENV_TEST_VAR"), "value");
+  }
+
+  EXPECT_EQ(GetEnvVar("SCOPED_SET_ENV_TEST_VAR"), "UNSET");
+}
+
+TEST(ScopedSetEnvTest, SetNonExistingVarToNull) {
+  EXPECT_EQ(GetEnvVar("SCOPED_SET_ENV_TEST_VAR"), "UNSET");
+
+  {
+    ScopedSetEnv scoped_set("SCOPED_SET_ENV_TEST_VAR", nullptr);
+
+    EXPECT_EQ(GetEnvVar("SCOPED_SET_ENV_TEST_VAR"), "UNSET");
+  }
+
+  EXPECT_EQ(GetEnvVar("SCOPED_SET_ENV_TEST_VAR"), "UNSET");
+}
+
+TEST(ScopedSetEnvTest, SetExistingVarToString) {
+  ScopedSetEnv scoped_set("SCOPED_SET_ENV_TEST_VAR", "value");
+  EXPECT_EQ(GetEnvVar("SCOPED_SET_ENV_TEST_VAR"), "value");
+
+  {
+    ScopedSetEnv scoped_set("SCOPED_SET_ENV_TEST_VAR", "new_value");
+
+    EXPECT_EQ(GetEnvVar("SCOPED_SET_ENV_TEST_VAR"), "new_value");
+  }
+
+  EXPECT_EQ(GetEnvVar("SCOPED_SET_ENV_TEST_VAR"), "value");
+}
+
+TEST(ScopedSetEnvTest, SetExistingVarToNull) {
+  ScopedSetEnv scoped_set("SCOPED_SET_ENV_TEST_VAR", "value");
+  EXPECT_EQ(GetEnvVar("SCOPED_SET_ENV_TEST_VAR"), "value");
+
+  {
+    ScopedSetEnv scoped_set("SCOPED_SET_ENV_TEST_VAR", nullptr);
+
+    EXPECT_EQ(GetEnvVar("SCOPED_SET_ENV_TEST_VAR"), "UNSET");
+  }
+
+  EXPECT_EQ(GetEnvVar("SCOPED_SET_ENV_TEST_VAR"), "value");
+}
+
+}  // namespace
diff --git a/absl/base/internal/spinlock.cc b/absl/base/internal/spinlock.cc
index 1b97efb..7354438 100644
--- a/absl/base/internal/spinlock.cc
+++ b/absl/base/internal/spinlock.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -95,13 +95,9 @@
 }
 
 // Monitor the lock to see if its value changes within some time period
-// (adaptive_spin_count loop iterations).  A timestamp indicating
-// when the thread initially started waiting for the lock is passed in via
-// the initial_wait_timestamp value.  The total wait time in cycles for the
-// lock is returned in the wait_cycles parameter.  The last value read
-// from the lock is returned from the method.
-uint32_t SpinLock::SpinLoop(int64_t initial_wait_timestamp,
-                            uint32_t *wait_cycles) {
+// (adaptive_spin_count loop iterations). The last value read from the lock
+// is returned from the method.
+uint32_t SpinLock::SpinLoop() {
   // We are already in the slow path of SpinLock, initialize the
   // adaptive_spin_count here.
   ABSL_CONST_INIT static absl::once_flag init_adaptive_spin_count;
@@ -115,22 +111,21 @@
   do {
     lock_value = lockword_.load(std::memory_order_relaxed);
   } while ((lock_value & kSpinLockHeld) != 0 && --c > 0);
-  uint32_t spin_loop_wait_cycles =
-      EncodeWaitCycles(initial_wait_timestamp, CycleClock::Now());
-  *wait_cycles = spin_loop_wait_cycles;
-
-  return TryLockInternal(lock_value, spin_loop_wait_cycles);
+  return lock_value;
 }
 
 void SpinLock::SlowLock() {
+  uint32_t lock_value = SpinLoop();
+  lock_value = TryLockInternal(lock_value, 0);
+  if ((lock_value & kSpinLockHeld) == 0) {
+    return;
+  }
   // The lock was not obtained initially, so this thread needs to wait for
   // it.  Record the current timestamp in the local variable wait_start_time
   // so the total wait time can be stored in the lockword once this thread
   // obtains the lock.
   int64_t wait_start_time = CycleClock::Now();
-  uint32_t wait_cycles;
-  uint32_t lock_value = SpinLoop(wait_start_time, &wait_cycles);
-
+  uint32_t wait_cycles = 0;
   int lock_wait_call_count = 0;
   while ((lock_value & kSpinLockHeld) != 0) {
     // If the lock is currently held, but not marked as having a sleeper, mark
@@ -141,7 +136,7 @@
       // owner to think it experienced contention.
       if (lockword_.compare_exchange_strong(
               lock_value, lock_value | kSpinLockSleeper,
-              std::memory_order_acquire, std::memory_order_relaxed)) {
+              std::memory_order_relaxed, std::memory_order_relaxed)) {
         // Successfully transitioned to kSpinLockSleeper.  Pass
         // kSpinLockSleeper to the SpinLockWait routine to properly indicate
         // the last lock_value observed.
@@ -170,7 +165,9 @@
     ABSL_TSAN_MUTEX_POST_DIVERT(this, 0);
     // Spin again after returning from the wait routine to give this thread
     // some chance of obtaining the lock.
-    lock_value = SpinLoop(wait_start_time, &wait_cycles);
+    lock_value = SpinLoop();
+    wait_cycles = EncodeWaitCycles(wait_start_time, CycleClock::Now());
+    lock_value = TryLockInternal(lock_value, wait_cycles);
   }
 }
 
@@ -206,14 +203,20 @@
       (wait_end_time - wait_start_time) >> PROFILE_TIMESTAMP_SHIFT;
 
   // Return a representation of the time spent waiting that can be stored in
-  // the lock word's upper bits.  bit_cast is required as Atomic32 is signed.
-  const uint32_t clamped = static_cast<uint32_t>(
+  // the lock word's upper bits.
+  uint32_t clamped = static_cast<uint32_t>(
       std::min(scaled_wait_time, kMaxWaitTime) << LOCKWORD_RESERVED_SHIFT);
 
-  // bump up value if necessary to avoid returning kSpinLockSleeper.
-  const uint32_t after_spinlock_sleeper =
-     kSpinLockSleeper + (1 << LOCKWORD_RESERVED_SHIFT);
-  return clamped == kSpinLockSleeper ? after_spinlock_sleeper : clamped;
+  if (clamped == 0) {
+    return kSpinLockSleeper;  // Just wake waiters, but don't record contention.
+  }
+  // Bump up value if necessary to avoid returning kSpinLockSleeper.
+  const uint32_t kMinWaitTime =
+      kSpinLockSleeper + (1 << LOCKWORD_RESERVED_SHIFT);
+  if (clamped == kSpinLockSleeper) {
+    return kMinWaitTime;
+  }
+  return clamped;
 }
 
 uint64_t SpinLock::DecodeWaitCycles(uint32_t lock_value) {
diff --git a/absl/base/internal/spinlock.h b/absl/base/internal/spinlock.h
index 212abc6..4a31639 100644
--- a/absl/base/internal/spinlock.h
+++ b/absl/base/internal/spinlock.h
@@ -5,7 +5,7 @@
 // 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
+//      https://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,
@@ -101,8 +101,8 @@
   inline void Unlock() UNLOCK_FUNCTION() {
     ABSL_TSAN_MUTEX_PRE_UNLOCK(this, 0);
     uint32_t lock_value = lockword_.load(std::memory_order_relaxed);
-    lockword_.store(lock_value & kSpinLockCooperative,
-                    std::memory_order_release);
+    lock_value = lockword_.exchange(lock_value & kSpinLockCooperative,
+                                    std::memory_order_release);
 
     if ((lock_value & kSpinLockDisabledScheduling) != 0) {
       base_internal::SchedulingGuard::EnableRescheduling(true);
@@ -161,7 +161,7 @@
   void InitLinkerInitializedAndCooperative();
   void SlowLock() ABSL_ATTRIBUTE_COLD;
   void SlowUnlock(uint32_t lock_value) ABSL_ATTRIBUTE_COLD;
-  uint32_t SpinLoop(int64_t initial_wait_timestamp, uint32_t* wait_cycles);
+  uint32_t SpinLoop();
 
   inline bool TryLockImpl() {
     uint32_t lock_value = lockword_.load(std::memory_order_relaxed);
diff --git a/absl/base/internal/spinlock_akaros.inc b/absl/base/internal/spinlock_akaros.inc
index 051c8cf..bc46894 100644
--- a/absl/base/internal/spinlock_akaros.inc
+++ b/absl/base/internal/spinlock_akaros.inc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
diff --git a/absl/base/internal/spinlock_benchmark.cc b/absl/base/internal/spinlock_benchmark.cc
new file mode 100644
index 0000000..0451c65
--- /dev/null
+++ b/absl/base/internal/spinlock_benchmark.cc
@@ -0,0 +1,52 @@
+// 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
+//
+//      https://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.
+
+// See also //absl/synchronization:mutex_benchmark for a comparison of SpinLock
+// and Mutex performance under varying levels of contention.
+
+#include "absl/base/internal/raw_logging.h"
+#include "absl/base/internal/scheduling_mode.h"
+#include "absl/base/internal/spinlock.h"
+#include "absl/synchronization/internal/create_thread_identity.h"
+#include "benchmark/benchmark.h"
+
+namespace {
+
+template <absl::base_internal::SchedulingMode scheduling_mode>
+static void BM_SpinLock(benchmark::State& state) {
+  // Ensure a ThreadIdentity is installed.
+  ABSL_INTERNAL_CHECK(
+      absl::synchronization_internal::GetOrCreateCurrentThreadIdentity() !=
+          nullptr,
+      "GetOrCreateCurrentThreadIdentity() failed");
+
+  static auto* spinlock = new absl::base_internal::SpinLock(scheduling_mode);
+  for (auto _ : state) {
+    absl::base_internal::SpinLockHolder holder(spinlock);
+  }
+}
+
+BENCHMARK_TEMPLATE(BM_SpinLock,
+                   absl::base_internal::SCHEDULE_KERNEL_ONLY)
+    ->UseRealTime()
+    ->Threads(1)
+    ->ThreadPerCpu();
+
+BENCHMARK_TEMPLATE(BM_SpinLock,
+                   absl::base_internal::SCHEDULE_COOPERATIVE_AND_KERNEL)
+    ->UseRealTime()
+    ->Threads(1)
+    ->ThreadPerCpu();
+
+}  // namespace
diff --git a/absl/base/internal/spinlock_linux.inc b/absl/base/internal/spinlock_linux.inc
index 94c861d..28e29d1 100644
--- a/absl/base/internal/spinlock_linux.inc
+++ b/absl/base/internal/spinlock_linux.inc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -51,17 +51,12 @@
 ABSL_ATTRIBUTE_WEAK void AbslInternalSpinLockDelay(
     std::atomic<uint32_t> *w, uint32_t value, int loop,
     absl::base_internal::SchedulingMode) {
-  if (loop != 0) {
-    int save_errno = errno;
-    struct timespec tm;
-    tm.tv_sec = 0;
-    // Increase the delay; we expect (but do not rely on) explicit wakeups.
-    // We don't rely on explicit wakeups because we intentionally allow for
-    // a race on the kSpinLockSleeper bit.
-    tm.tv_nsec = 16 * absl::base_internal::SpinLockSuggestedDelayNS(loop);
-    syscall(SYS_futex, w, FUTEX_WAIT | FUTEX_PRIVATE_FLAG, value, &tm);
-    errno = save_errno;
-  }
+  int save_errno = errno;
+  struct timespec tm;
+  tm.tv_sec = 0;
+  tm.tv_nsec = absl::base_internal::SpinLockSuggestedDelayNS(loop);
+  syscall(SYS_futex, w, FUTEX_WAIT | FUTEX_PRIVATE_FLAG, value, &tm);
+  errno = save_errno;
 }
 
 ABSL_ATTRIBUTE_WEAK void AbslInternalSpinLockWake(std::atomic<uint32_t> *w,
diff --git a/absl/base/internal/spinlock_posix.inc b/absl/base/internal/spinlock_posix.inc
index 0098c1c..f025b5f 100644
--- a/absl/base/internal/spinlock_posix.inc
+++ b/absl/base/internal/spinlock_posix.inc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
diff --git a/absl/base/internal/spinlock_wait.cc b/absl/base/internal/spinlock_wait.cc
index 0fde9c0..fac8a21 100644
--- a/absl/base/internal/spinlock_wait.cc
+++ b/absl/base/internal/spinlock_wait.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -38,14 +38,15 @@
 uint32_t SpinLockWait(std::atomic<uint32_t> *w, int n,
                       const SpinLockWaitTransition trans[],
                       base_internal::SchedulingMode scheduling_mode) {
-  for (int loop = 0; ; loop++) {
+  int loop = 0;
+  for (;;) {
     uint32_t v = w->load(std::memory_order_acquire);
     int i;
     for (i = 0; i != n && v != trans[i].from; i++) {
     }
     if (i == n) {
-      SpinLockDelay(w, v, loop, scheduling_mode);  // no matching transition
-    } else if (trans[i].to == v ||                 // null transition
+      SpinLockDelay(w, v, ++loop, scheduling_mode);  // no matching transition
+    } else if (trans[i].to == v ||                   // null transition
                w->compare_exchange_strong(v, trans[i].to,
                                           std::memory_order_acquire,
                                           std::memory_order_relaxed)) {
@@ -64,17 +65,14 @@
   r = 0x5deece66dLL * r + 0xb;   // numbers from nrand48()
   delay_rand.store(r, std::memory_order_relaxed);
 
-  r <<= 16;   // 48-bit random number now in top 48-bits.
   if (loop < 0 || loop > 32) {   // limit loop to 0..32
     loop = 32;
   }
-  // loop>>3 cannot exceed 4 because loop cannot exceed 32.
-  // Select top 20..24 bits of lower 48 bits,
-  // giving approximately 0ms to 16ms.
-  // Mean is exponential in loop for first 32 iterations, then 8ms.
-  // The futex path multiplies this by 16, since we expect explicit wakeups
-  // almost always on that path.
-  return static_cast<int>(r >> (44 - (loop >> 3)));
+  const int kMinDelay = 128 << 10;  // 128us
+  // Double delay every 8 iterations, up to 16x (2ms).
+  int delay = kMinDelay << (loop / 8);
+  // Randomize in delay..2*delay range, for resulting 128us..4ms range.
+  return delay | ((delay - 1) & static_cast<int>(r));
 }
 
 }  // namespace base_internal
diff --git a/absl/base/internal/spinlock_wait.h b/absl/base/internal/spinlock_wait.h
index 5c6cc7f..6642ce1 100644
--- a/absl/base/internal/spinlock_wait.h
+++ b/absl/base/internal/spinlock_wait.h
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
diff --git a/absl/base/internal/spinlock_win32.inc b/absl/base/internal/spinlock_win32.inc
index 32c8fc0..78654b5 100644
--- a/absl/base/internal/spinlock_win32.inc
+++ b/absl/base/internal/spinlock_win32.inc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
diff --git a/absl/base/internal/sysinfo.cc b/absl/base/internal/sysinfo.cc
index db41bac..4dd3add 100644
--- a/absl/base/internal/sysinfo.cc
+++ b/absl/base/internal/sysinfo.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
diff --git a/absl/base/internal/sysinfo.h b/absl/base/internal/sysinfo.h
index 5bd1c50..b864a59 100644
--- a/absl/base/internal/sysinfo.h
+++ b/absl/base/internal/sysinfo.h
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
diff --git a/absl/base/internal/sysinfo_test.cc b/absl/base/internal/sysinfo_test.cc
index e0d9aab..247f3d8 100644
--- a/absl/base/internal/sysinfo_test.cc
+++ b/absl/base/internal/sysinfo_test.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
diff --git a/absl/base/internal/thread_identity.cc b/absl/base/internal/thread_identity.cc
index cff9c1b..91273a6 100644
--- a/absl/base/internal/thread_identity.cc
+++ b/absl/base/internal/thread_identity.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
diff --git a/absl/base/internal/thread_identity.h b/absl/base/internal/thread_identity.h
index a51722f..b34674a 100644
--- a/absl/base/internal/thread_identity.h
+++ b/absl/base/internal/thread_identity.h
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -42,9 +42,9 @@
 class SpinLock;
 struct ThreadIdentity;
 
-// Used by the implementation of base::Mutex and base::CondVar.
+// Used by the implementation of absl::Mutex and absl::CondVar.
 struct PerThreadSynch {
-  // The internal representation of base::Mutex and base::CondVar rely
+  // The internal representation of absl::Mutex and absl::CondVar rely
   // on the alignment of PerThreadSynch. Both store the address of the
   // PerThreadSynch in the high-order bits of their internal state,
   // which means the low kLowZeroBits of the address of PerThreadSynch
@@ -237,4 +237,5 @@
 
 }  // namespace base_internal
 }  // namespace absl
+
 #endif  // ABSL_BASE_INTERNAL_THREAD_IDENTITY_H_
diff --git a/absl/base/internal/thread_identity_benchmark.cc b/absl/base/internal/thread_identity_benchmark.cc
index 242522b..0ae10f2 100644
--- a/absl/base/internal/thread_identity_benchmark.cc
+++ b/absl/base/internal/thread_identity_benchmark.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
diff --git a/absl/base/internal/thread_identity_test.cc b/absl/base/internal/thread_identity_test.cc
index ecb8af6..13bfbe3 100644
--- a/absl/base/internal/thread_identity_test.cc
+++ b/absl/base/internal/thread_identity_test.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
diff --git a/absl/base/internal/throw_delegate.cc b/absl/base/internal/throw_delegate.cc
index 46dc573..8e928b8 100644
--- a/absl/base/internal/throw_delegate.cc
+++ b/absl/base/internal/throw_delegate.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -30,8 +30,8 @@
 #ifdef ABSL_HAVE_EXCEPTIONS
   throw error;
 #else
-  ABSL_RAW_LOG(ERROR, "%s", error.what());
-  abort();
+  ABSL_RAW_LOG(FATAL, "%s", error.what());
+  std::abort();
 #endif
 }
 }  // namespace
diff --git a/absl/base/internal/throw_delegate.h b/absl/base/internal/throw_delegate.h
index 70e2d77..03c700b 100644
--- a/absl/base/internal/throw_delegate.h
+++ b/absl/base/internal/throw_delegate.h
@@ -5,7 +5,7 @@
 // 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
+//      https://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,
diff --git a/absl/base/internal/tsan_mutex_interface.h b/absl/base/internal/tsan_mutex_interface.h
index 6bb4fae..2a51060 100644
--- a/absl/base/internal/tsan_mutex_interface.h
+++ b/absl/base/internal/tsan_mutex_interface.h
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
diff --git a/absl/base/internal/unaligned_access.h b/absl/base/internal/unaligned_access.h
index f9df3b7..2d66737 100644
--- a/absl/base/internal/unaligned_access.h
+++ b/absl/base/internal/unaligned_access.h
@@ -5,7 +5,7 @@
 // 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
+//      https://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,
diff --git a/absl/base/internal/unscaledcycleclock.cc b/absl/base/internal/unscaledcycleclock.cc
index a12d68b..593762b 100644
--- a/absl/base/internal/unscaledcycleclock.cc
+++ b/absl/base/internal/unscaledcycleclock.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
diff --git a/absl/base/internal/unscaledcycleclock.h b/absl/base/internal/unscaledcycleclock.h
index 049f1ca..58950cc 100644
--- a/absl/base/internal/unscaledcycleclock.h
+++ b/absl/base/internal/unscaledcycleclock.h
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -83,6 +83,7 @@
       defined(_M_IX86) || defined(_M_X64))
 #define ABSL_INTERNAL_UNSCALED_CYCLECLOCK_FREQUENCY_IS_CPU_FREQUENCY
 #endif
+
 namespace absl {
 namespace time_internal {
 class UnscaledCycleClockWrapperForGetCurrentTime;
@@ -114,6 +115,7 @@
 
 }  // namespace base_internal
 }  // namespace absl
+
 #endif  // ABSL_USE_UNSCALED_CYCLECLOCK
 
 #endif  // ABSL_BASE_INTERNAL_UNSCALEDCYCLECLOCK_H_
diff --git a/absl/base/invoke_test.cc b/absl/base/invoke_test.cc
index 466bf11..691f553 100644
--- a/absl/base/invoke_test.cc
+++ b/absl/base/invoke_test.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
diff --git a/absl/base/log_severity.h b/absl/base/log_severity.h
index 5770d36..b19a7ff 100644
--- a/absl/base/log_severity.h
+++ b/absl/base/log_severity.h
@@ -4,14 +4,13 @@
 // 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
+//      https://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.
-//
 
 #ifndef ABSL_BASE_INTERNAL_LOG_SEVERITY_H_
 #define ABSL_BASE_INTERNAL_LOG_SEVERITY_H_
diff --git a/absl/base/macros.h b/absl/base/macros.h
index ca3d5ed..5b43d7c 100644
--- a/absl/base/macros.h
+++ b/absl/base/macros.h
@@ -5,7 +5,7 @@
 // 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
+//      https://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,
@@ -24,7 +24,6 @@
 // This code is compiled directly on many platforms, including client
 // platforms like Windows, Mac, and embedded systems.  Before making
 // any changes here, make sure that you're not breaking any platforms.
-//
 
 #ifndef ABSL_BASE_MACROS_H_
 #define ABSL_BASE_MACROS_H_
@@ -199,4 +198,14 @@
                              : [] { assert(false && #expr); }())  // NOLINT
 #endif
 
+#ifdef ABSL_HAVE_EXCEPTIONS
+#define ABSL_INTERNAL_TRY try
+#define ABSL_INTERNAL_CATCH_ANY catch (...)
+#define ABSL_INTERNAL_RETHROW do { throw; } while (false)
+#else  // ABSL_HAVE_EXCEPTIONS
+#define ABSL_INTERNAL_TRY if (true)
+#define ABSL_INTERNAL_CATCH_ANY else if (false)
+#define ABSL_INTERNAL_RETHROW do {} while (false)
+#endif  // ABSL_HAVE_EXCEPTIONS
+
 #endif  // ABSL_BASE_MACROS_H_
diff --git a/absl/base/optimization.h b/absl/base/optimization.h
index 2fddfc8..6974f1f 100644
--- a/absl/base/optimization.h
+++ b/absl/base/optimization.h
@@ -5,7 +5,7 @@
 // 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
+//      https://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,
@@ -111,9 +111,9 @@
 // See http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0154r1.html
 // for more information.
 //
-// On some compilers, `ABSL_CACHELINE_ALIGNED` expands to
-// `__attribute__((aligned(ABSL_CACHELINE_SIZE)))`. For compilers where this is
-// not known to work, the macro expands to nothing.
+// On some compilers, `ABSL_CACHELINE_ALIGNED` expands to an `__attribute__`
+// or `__declspec` attribute. For compilers where this is not known to work,
+// the macro expands to nothing.
 //
 // No further guarantees are made here. The result of applying the macro
 // to variables and types is always implementation-defined.
@@ -122,6 +122,14 @@
 // of causing bugs that are difficult to diagnose, crash, etc. It does not
 // of itself guarantee that objects are aligned to a cache line.
 //
+// NOTE: Some compilers are picky about the locations of annotations such as
+// this attribute, so prefer to put it at the beginning of your declaration.
+// For example,
+//
+//   ABSL_CACHELINE_ALIGNED static Foo* foo = ...
+//
+//   class ABSL_CACHELINE_ALIGNED Bar { ...
+//
 // Recommendations:
 //
 // 1) Consult compiler documentation; this comment is not kept in sync as
@@ -131,8 +139,10 @@
 // 3) Prefer applying this attribute to individual variables. Avoid
 //    applying it to types. This tends to localize the effect.
 #define ABSL_CACHELINE_ALIGNED __attribute__((aligned(ABSL_CACHELINE_SIZE)))
-
-#else  // not GCC
+#elif defined(_MSC_VER)
+#define ABSL_CACHELINE_SIZE 64
+#define ABSL_CACHELINE_ALIGNED __declspec(align(ABSL_CACHELINE_SIZE))
+#else
 #define ABSL_CACHELINE_SIZE 64
 #define ABSL_CACHELINE_ALIGNED
 #endif
diff --git a/absl/base/policy_checks.h b/absl/base/policy_checks.h
index 0a07fc0..699fb1a 100644
--- a/absl/base/policy_checks.h
+++ b/absl/base/policy_checks.h
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
diff --git a/absl/base/port.h b/absl/base/port.h
index 1c67257..6c28068 100644
--- a/absl/base/port.h
+++ b/absl/base/port.h
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
diff --git a/absl/base/raw_logging_test.cc b/absl/base/raw_logging_test.cc
index b21cf65..3d30bd3 100644
--- a/absl/base/raw_logging_test.cc
+++ b/absl/base/raw_logging_test.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
diff --git a/absl/base/spinlock_test_common.cc b/absl/base/spinlock_test_common.cc
index 1b50884..e62b2ea 100644
--- a/absl/base/spinlock_test_common.cc
+++ b/absl/base/spinlock_test_common.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -54,6 +54,7 @@
 
 static constexpr int kArrayLength = 10;
 static uint32_t values[kArrayLength];
+
 static SpinLock static_spinlock(base_internal::kLinkerInitialized);
 static SpinLock static_cooperative_spinlock(
     base_internal::kLinkerInitialized,
@@ -155,7 +156,8 @@
 
   // Test corner cases
   int64_t start_time = time_distribution(generator);
-  EXPECT_EQ(0, SpinLockTest::EncodeWaitCycles(start_time, start_time));
+  EXPECT_EQ(kSpinLockSleeper,
+            SpinLockTest::EncodeWaitCycles(start_time, start_time));
   EXPECT_EQ(0, SpinLockTest::DecodeWaitCycles(0));
   EXPECT_EQ(0, SpinLockTest::DecodeWaitCycles(kLockwordReservedMask));
   EXPECT_EQ(kMaxCycles & ~kProfileTimestampMask,
@@ -188,6 +190,7 @@
     SpinLockTest::DecodeWaitCycles(before_max_value);
   EXPECT_GT(expected_max_value_decoded, before_max_value_decoded);
 }
+
 TEST(SpinLockWithThreads, StaticSpinLock) {
   ThreadedTest(&static_spinlock);
 }
diff --git a/absl/base/thread_annotations.h b/absl/base/thread_annotations.h
index fbb2797..0b2c306 100644
--- a/absl/base/thread_annotations.h
+++ b/absl/base/thread_annotations.h
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -21,7 +21,6 @@
 // code. The annotations can also help program analysis tools to identify
 // potential thread safety issues.
 //
-//
 // These annotations are implemented using compiler attributes. Using the macros
 // defined here instead of raw attributes allow for portability and future
 // compatibility.
@@ -34,6 +33,7 @@
 
 #ifndef ABSL_BASE_THREAD_ANNOTATIONS_H_
 #define ABSL_BASE_THREAD_ANNOTATIONS_H_
+
 #if defined(__clang__)
 #define THREAD_ANNOTATION_ATTRIBUTE__(x)   __attribute__((x))
 #else
@@ -108,13 +108,23 @@
 // The mutex is expected to be held both on entry to, and exit from, the
 // function.
 //
+// An exclusive lock allows read-write access to the guarded data member(s), and
+// only one thread can acquire a lock exclusively at any one time. A shared lock
+// allows read-only access, and any number of threads can acquire a shared lock
+// concurrently.
+//
+// Generally, non-const methods should be annotated with
+// EXCLUSIVE_LOCKS_REQUIRED, while const methods should be annotated with
+// SHARED_LOCKS_REQUIRED.
+//
 // Example:
 //
 //   Mutex mu1, mu2;
 //   int a GUARDED_BY(mu1);
 //   int b GUARDED_BY(mu2);
 //
-//   void foo() EXCLUSIVE_LOCKS_REQUIRED(mu1, mu2) { ... };
+//   void foo() EXCLUSIVE_LOCKS_REQUIRED(mu1, mu2) { ... }
+//   void bar() const SHARED_LOCKS_REQUIRED(mu1, mu2) { ... }
 #define EXCLUSIVE_LOCKS_REQUIRED(...) \
   THREAD_ANNOTATION_ATTRIBUTE__(exclusive_locks_required(__VA_ARGS__))
 
diff --git a/absl/base/throw_delegate_test.cc b/absl/base/throw_delegate_test.cc
index 0f15df0..a74dd3c 100644
--- a/absl/base/throw_delegate_test.cc
+++ b/absl/base/throw_delegate_test.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
diff --git a/absl/compiler_config_setting.bzl b/absl/compiler_config_setting.bzl
index b77c4f5..6696229 100644
--- a/absl/compiler_config_setting.bzl
+++ b/absl/compiler_config_setting.bzl
@@ -5,35 +5,34 @@
 # 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
+#      https://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,
-    )
+    # 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 f2210e3..cd914ba 100644
--- a/absl/container/BUILD.bazel
+++ b/absl/container/BUILD.bazel
@@ -5,7 +5,7 @@
 # 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
+#      https://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,
@@ -15,11 +15,11 @@
 #
 
 load(
-    "//absl:copts.bzl",
+    "//absl:copts/configure_copts.bzl",
     "ABSL_DEFAULT_COPTS",
-    "ABSL_TEST_COPTS",
     "ABSL_EXCEPTIONS_FLAG",
     "ABSL_EXCEPTIONS_FLAG_LINKOPTS",
+    "ABSL_TEST_COPTS",
 )
 
 package(default_visibility = ["//visibility:public"])
@@ -41,6 +41,8 @@
     copts = ABSL_TEST_COPTS,
     deps = [
         ":compressed_tuple",
+        "//absl/memory",
+        "//absl/utility",
         "@com_google_googletest//:gtest_main",
     ],
 )
@@ -110,10 +112,20 @@
 )
 
 cc_library(
+    name = "inlined_vector_internal",
+    hdrs = ["internal/inlined_vector.h"],
+    copts = ABSL_DEFAULT_COPTS,
+    deps = [
+        "//absl/meta:type_traits",
+    ],
+)
+
+cc_library(
     name = "inlined_vector",
     hdrs = ["inlined_vector.h"],
     copts = ABSL_DEFAULT_COPTS,
     deps = [
+        ":inlined_vector_internal",
         "//absl/algorithm",
         "//absl/base:core_headers",
         "//absl/base:throw_delegate",
@@ -121,12 +133,21 @@
     ],
 )
 
+cc_library(
+    name = "counting_allocator",
+    testonly = 1,
+    hdrs = ["internal/counting_allocator.h"],
+    copts = ABSL_DEFAULT_COPTS,
+    visibility = ["//visibility:private"],
+)
+
 cc_test(
     name = "inlined_vector_test",
     srcs = ["inlined_vector_test.cc"],
     copts = ABSL_TEST_COPTS + ABSL_EXCEPTIONS_FLAG,
     linkopts = ABSL_EXCEPTIONS_FLAG_LINKOPTS,
     deps = [
+        ":counting_allocator",
         ":inlined_vector",
         ":test_instance_tracker",
         "//absl/base",
@@ -144,6 +165,7 @@
     srcs = ["inlined_vector_test.cc"],
     copts = ABSL_TEST_COPTS,
     deps = [
+        ":counting_allocator",
         ":inlined_vector",
         ":test_instance_tracker",
         "//absl/base",
@@ -212,6 +234,7 @@
         ":container_memory",
         ":hash_function_defaults",
         ":raw_hash_map",
+        "//absl/algorithm:container",
         "//absl/memory",
     ],
 )
@@ -219,13 +242,14 @@
 cc_test(
     name = "flat_hash_map_test",
     srcs = ["flat_hash_map_test.cc"],
-    copts = ABSL_TEST_COPTS + ["-DUNORDERED_MAP_CXX17"],
+    copts = ABSL_TEST_COPTS,
     tags = NOTEST_TAGS_NONMOBILE,
     deps = [
         ":flat_hash_map",
         ":hash_generator_testing",
         ":unordered_map_constructor_test",
         ":unordered_map_lookup_test",
+        ":unordered_map_members_test",
         ":unordered_map_modifiers_test",
         "//absl/types:any",
         "@com_google_googletest//:gtest_main",
@@ -240,6 +264,7 @@
         ":container_memory",
         ":hash_function_defaults",
         ":raw_hash_set",
+        "//absl/algorithm:container",
         "//absl/base:core_headers",
         "//absl/memory",
     ],
@@ -255,6 +280,7 @@
         ":hash_generator_testing",
         ":unordered_set_constructor_test",
         ":unordered_set_lookup_test",
+        ":unordered_set_members_test",
         ":unordered_set_modifiers_test",
         "//absl/memory",
         "//absl/strings",
@@ -271,6 +297,7 @@
         ":hash_function_defaults",
         ":node_hash_policy",
         ":raw_hash_map",
+        "//absl/algorithm:container",
         "//absl/memory",
     ],
 )
@@ -278,7 +305,7 @@
 cc_test(
     name = "node_hash_map_test",
     srcs = ["node_hash_map_test.cc"],
-    copts = ABSL_TEST_COPTS + ["-DUNORDERED_MAP_CXX17"],
+    copts = ABSL_TEST_COPTS,
     tags = NOTEST_TAGS_NONMOBILE,
     deps = [
         ":hash_generator_testing",
@@ -286,6 +313,7 @@
         ":tracked",
         ":unordered_map_constructor_test",
         ":unordered_map_lookup_test",
+        ":unordered_map_members_test",
         ":unordered_map_modifiers_test",
         "@com_google_googletest//:gtest_main",
     ],
@@ -296,10 +324,10 @@
     hdrs = ["node_hash_set.h"],
     copts = ABSL_DEFAULT_COPTS,
     deps = [
-        ":container_memory",
         ":hash_function_defaults",
         ":node_hash_policy",
         ":raw_hash_set",
+        "//absl/algorithm:container",
         "//absl/memory",
     ],
 )
@@ -310,10 +338,10 @@
     copts = ABSL_TEST_COPTS + ["-DUNORDERED_SET_CXX17"],
     tags = NOTEST_TAGS_NONMOBILE,
     deps = [
-        ":hash_generator_testing",
         ":node_hash_set",
         ":unordered_set_constructor_test",
         ":unordered_set_lookup_test",
+        ":unordered_set_members_test",
         ":unordered_set_modifiers_test",
         "@com_google_googletest//:gtest_main",
     ],
@@ -432,6 +460,39 @@
 )
 
 cc_library(
+    name = "hashtablez_sampler",
+    srcs = [
+        "internal/hashtablez_sampler.cc",
+        "internal/hashtablez_sampler_force_weak_definition.cc",
+    ],
+    hdrs = ["internal/hashtablez_sampler.h"],
+    copts = ABSL_DEFAULT_COPTS,
+    deps = [
+        ":have_sse",
+        "//absl/base",
+        "//absl/base:core_headers",
+        "//absl/debugging:stacktrace",
+        "//absl/memory",
+        "//absl/synchronization",
+        "//absl/utility",
+    ],
+)
+
+cc_test(
+    name = "hashtablez_sampler_test",
+    srcs = ["internal/hashtablez_sampler_test.cc"],
+    deps = [
+        ":hashtablez_sampler",
+        ":have_sse",
+        "//absl/base:core_headers",
+        "//absl/synchronization",
+        "//absl/synchronization:thread_pool",
+        "//absl/time",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
+
+cc_library(
     name = "node_hash_policy",
     hdrs = ["internal/node_hash_policy.h"],
     copts = ABSL_DEFAULT_COPTS,
@@ -459,15 +520,35 @@
 )
 
 cc_library(
+    name = "have_sse",
+    hdrs = ["internal/have_sse.h"],
+    copts = ABSL_DEFAULT_COPTS,
+    visibility = ["//visibility:private"],
+)
+
+cc_library(
+    name = "common",
+    hdrs = ["internal/common.h"],
+    copts = ABSL_DEFAULT_COPTS,
+    deps = [
+        "//absl/meta:type_traits",
+        "//absl/types:optional",
+    ],
+)
+
+cc_library(
     name = "raw_hash_set",
     srcs = ["internal/raw_hash_set.cc"],
     hdrs = ["internal/raw_hash_set.h"],
     copts = ABSL_DEFAULT_COPTS,
     deps = [
+        ":common",
         ":compressed_tuple",
         ":container_memory",
         ":hash_policy_traits",
         ":hashtable_debug_hooks",
+        ":hashtablez_sampler",
+        ":have_sse",
         ":layout",
         "//absl/base:bits",
         "//absl/base:config",
@@ -475,7 +556,6 @@
         "//absl/base:endian",
         "//absl/memory",
         "//absl/meta:type_traits",
-        "//absl/types:optional",
         "//absl/utility",
     ],
 )
@@ -592,6 +672,29 @@
     deps = [
         ":hash_generator_testing",
         ":hash_policy_testing",
+        "//absl/meta:type_traits",
+        "@com_google_googletest//:gtest",
+    ],
+)
+
+cc_library(
+    name = "unordered_set_members_test",
+    testonly = 1,
+    hdrs = ["internal/unordered_set_members_test.h"],
+    copts = ABSL_TEST_COPTS,
+    deps = [
+        "//absl/meta:type_traits",
+        "@com_google_googletest//:gtest",
+    ],
+)
+
+cc_library(
+    name = "unordered_map_members_test",
+    testonly = 1,
+    hdrs = ["internal/unordered_map_members_test.h"],
+    copts = ABSL_TEST_COPTS,
+    deps = [
+        "//absl/meta:type_traits",
         "@com_google_googletest//:gtest",
     ],
 )
@@ -628,6 +731,7 @@
     deps = [
         ":unordered_set_constructor_test",
         ":unordered_set_lookup_test",
+        ":unordered_set_members_test",
         ":unordered_set_modifiers_test",
         "@com_google_googletest//:gtest_main",
     ],
@@ -641,6 +745,7 @@
     deps = [
         ":unordered_map_constructor_test",
         ":unordered_map_lookup_test",
+        ":unordered_map_members_test",
         ":unordered_map_modifiers_test",
         "@com_google_googletest//:gtest_main",
     ],
diff --git a/absl/container/BUILD.gn b/absl/container/BUILD.gn
index a2fbd54..3b8ece7 100644
--- a/absl/container/BUILD.gn
+++ b/absl/container/BUILD.gn
@@ -49,6 +49,21 @@
   ]
 }
 
+source_set("inlined_vector_internal") {
+  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/inlined_vector.h",
+  ]
+  deps = [
+    "../meta:type_traits",
+  ]
+}
+
 source_set("inlined_vector") {
   configs -= [ "//build/config/compiler:chromium_code" ]
   configs += [
@@ -60,6 +75,7 @@
     "inlined_vector.h",
   ]
   deps = [
+    ":inlined_vector_internal",
     "../algorithm",
     "../base:core_headers",
     "../base:throw_delegate",
@@ -67,6 +83,21 @@
   ]
 }
 
+source_set("counting_allocator") {
+  testonly = true
+  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/counting_allocator.h",
+  ]
+  visibility = []
+  visibility += [ ":*" ]
+}
+
 source_set("test_instance_tracker") {
   testonly = true
   configs -= [ "//build/config/compiler:chromium_code" ]
@@ -99,6 +130,7 @@
     ":container_memory",
     ":hash_function_defaults",
     ":raw_hash_map",
+    "../algorithm:container",
     "../memory",
   ]
 }
@@ -117,6 +149,7 @@
     ":container_memory",
     ":hash_function_defaults",
     ":raw_hash_set",
+    "../algorithm:container",
     "../base:core_headers",
     "../memory",
   ]
@@ -137,6 +170,7 @@
     ":hash_function_defaults",
     ":node_hash_policy",
     ":raw_hash_map",
+    "../algorithm:container",
     "../memory",
   ]
 }
@@ -156,6 +190,7 @@
     ":hash_function_defaults",
     ":node_hash_policy",
     ":raw_hash_set",
+    "../algorithm:container",
     "../memory",
   ]
 }
@@ -273,6 +308,31 @@
   ]
 }
 
+source_set("hashtablez_sampler") {
+  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/hashtablez_sampler.h",
+  ]
+  sources = [
+    "internal/hashtablez_sampler.cc",
+    "internal/hashtablez_sampler_force_weak_definition.cc",
+  ]
+  deps = [
+    ":have_sse",
+    "../base",
+    "../base:core_headers",
+    "../debugging:stacktrace",
+    "../memory",
+    "../synchronization",
+    "../utility",
+  ]
+}
+
 source_set("node_hash_policy") {
   configs -= [ "//build/config/compiler:chromium_code" ]
   configs += [
@@ -301,6 +361,36 @@
   ]
 }
 
+source_set("have_sse") {
+  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/have_sse.h",
+  ]
+  visibility = []
+  visibility += [ ":*" ]
+}
+
+source_set("common") {
+  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/common.h",
+  ]
+  deps = [
+    "../meta:type_traits",
+    "../types:optional",
+  ]
+}
+
 source_set("raw_hash_set") {
   configs -= [ "//build/config/compiler:chromium_code" ]
   configs += [
@@ -315,10 +405,13 @@
     "internal/raw_hash_set.h",
   ]
   deps = [
+    ":common",
     ":compressed_tuple",
     ":container_memory",
     ":hash_policy_traits",
     ":hashtable_debug_hooks",
+    ":hashtablez_sampler",
+    ":have_sse",
     ":layout",
     "../base:bits",
     "../base:config",
@@ -326,7 +419,6 @@
     "../base:endian",
     "../memory",
     "../meta:type_traits",
-    "../types:optional",
     "../utility",
   ]
 }
@@ -431,6 +523,41 @@
   deps = [
     ":hash_generator_testing",
     ":hash_policy_testing",
+    "../meta:type_traits",
+    "//testing/gtest",
+  ]
+}
+
+source_set("unordered_set_members_test") {
+  testonly = true
+  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/unordered_set_members_test.h",
+  ]
+  deps = [
+    "../meta:type_traits",
+    "//testing/gtest",
+  ]
+}
+
+source_set("unordered_map_members_test") {
+  testonly = true
+  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/unordered_map_members_test.h",
+  ]
+  deps = [
+    "../meta:type_traits",
     "//testing/gtest",
   ]
 }
diff --git a/absl/container/CMakeLists.txt b/absl/container/CMakeLists.txt
index 9e40690..292fea2 100644
--- a/absl/container/CMakeLists.txt
+++ b/absl/container/CMakeLists.txt
@@ -5,7 +5,7 @@
 # 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
+#      https://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,
@@ -14,163 +14,772 @@
 # limitations under the License.
 #
 
-
-list(APPEND CONTAINER_PUBLIC_HEADERS
-  "fixed_array.h"
-  "flat_hash_map.h"
-  "flat_hash_set.h"
-  "inlined_vector.h"
-  "node_hash_map.h"
-  "node_hash_set.h"
-)
-
-
-list(APPEND CONTAINER_INTERNAL_HEADERS
-  "internal/compressed_tuple.h"
-  "internal/container_memory.h"
-  "internal/hash_function_defaults.h"
-  "internal/hash_generator_testing.h"
-  "internal/hash_policy_testing.h"
-  "internal/hash_policy_traits.h"
-  "internal/hashtable_debug.h"
-  "internal/layout.h"
-  "internal/node_hash_policy.h"
-  "internal/raw_hash_map.h"
-  "internal/raw_hash_set.h"
-  "internal/test_instance_tracker.h"
-  "internal/tracked.h"
-  "internal/unordered_map_constructor_test.h"
-  "internal/unordered_map_lookup_test.h"
-  "internal/unordered_map_modifiers_test.h"
-  "internal/unordered_set_constructor_test.h"
-  "internal/unordered_set_lookup_test.h"
-  "internal/unordered_set_modifiers_test.h"
-)
-
-
-absl_library(
-  TARGET
-    absl_container
-  SOURCES
-    "internal/raw_hash_set.cc"
-  EXPORT_NAME
+# This is deprecated and will be removed in the future.  It also doesn't do
+# anything anyways.  Prefer to use the library associated with the API you are
+# using.
+absl_cc_library(
+  NAME
     container
+  PUBLIC
 )
 
-
-#
-## TESTS
-#
-
-list(APPEND TEST_INSTANCE_TRACKER_LIB_SRC
-  "internal/test_instance_tracker.cc"
-  ${CONTAINER_PUBLIC_HEADERS}
-  ${CONTAINER_INTERNAL_HEADERS}
+absl_cc_library(
+  NAME
+    compressed_tuple
+  HDRS
+   "internal/compressed_tuple.h"
+  DEPS
+    absl::utility
+  PUBLIC
 )
 
-
-absl_library(
-  TARGET
-    test_instance_tracker_lib
-  SOURCES
-    ${TEST_INSTANCE_TRACKER_LIB_SRC}
-  PUBLIC_LIBRARIES
-    absl::container
+absl_cc_test(
+  NAME
+    compressed_tuple_test
+  SRCS
+    "internal/compressed_tuple_test.cc"
+  DEPS
+    absl::compressed_tuple
+    absl::memory
+    absl::utility
+    gmock_main
 )
 
+absl_cc_library(
+  NAME
+    fixed_array
+  HDRS
+   "fixed_array.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::compressed_tuple
+    absl::algorithm
+    absl::core_headers
+    absl::dynamic_annotations
+    absl::throw_delegate
+    absl::memory
+  PUBLIC
+)
 
-
-# test fixed_array_test
-set(FIXED_ARRAY_TEST_SRC "fixed_array_test.cc")
-set(FIXED_ARRAY_TEST_PUBLIC_LIBRARIES absl::base absl_throw_delegate test_instance_tracker_lib)
-
-absl_test(
-  TARGET
+absl_cc_test(
+  NAME
     fixed_array_test
-  SOURCES
-    ${FIXED_ARRAY_TEST_SRC}
-  PUBLIC_LIBRARIES
-    ${FIXED_ARRAY_TEST_PUBLIC_LIBRARIES}
-  PRIVATE_COMPILE_FLAGS
+  SRCS
+    "fixed_array_test.cc"
+  COPTS
     ${ABSL_EXCEPTIONS_FLAG}
+  LINKOPTS
+    ${ABSL_EXCEPTIONS_FLAG_LINKOPTS}
+  DEPS
+    absl::fixed_array
+    absl::exception_testing
+    absl::hash_testing
+    absl::memory
+    gmock_main
 )
 
-
-
-absl_test(
-  TARGET
+absl_cc_test(
+  NAME
     fixed_array_test_noexceptions
-  SOURCES
-    ${FIXED_ARRAY_TEST_SRC}
-  PUBLIC_LIBRARIES
-    ${FIXED_ARRAY_TEST_PUBLIC_LIBRARIES}
+  SRCS
+    "fixed_array_test.cc"
+  DEPS
+    absl::fixed_array
+    absl::exception_testing
+    absl::hash_testing
+    absl::memory
+    gmock_main
 )
 
-
-# test fixed_array_exception_safety_test
-set(FIXED_ARRAY_EXCEPTION_SAFETY_TEST_SRC "fixed_array_exception_safety_test.cc")
-set(FIXED_ARRAY_EXCEPTION_SAFETY_TEST_PUBLIC_LIBRARIES
-  absl::container
-  absl_base_internal_exception_safety_testing
-)
-
-absl_test(
-  TARGET
+absl_cc_test(
+  NAME
     fixed_array_exception_safety_test
-  SOURCES
-    ${FIXED_ARRAY_EXCEPTION_SAFETY_TEST_SRC}
-  PUBLIC_LIBRARIES
-    ${FIXED_ARRAY_EXCEPTION_SAFETY_TEST_PUBLIC_LIBRARIES}
-  PRIVATE_COMPILE_FLAGS
+  SRCS
+    "fixed_array_exception_safety_test.cc"
+  COPTS
     ${ABSL_EXCEPTIONS_FLAG}
+  LINKOPTS
+    ${ABSL_EXCEPTIONS_FLAG_LINKOPTS}
+  DEPS
+    absl::fixed_array
+    absl::exception_safety_testing
+    gmock_main
 )
 
+absl_cc_library(
+  NAME
+    inlined_vector_internal
+  HDRS
+   "internal/inlined_vector.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::type_traits
+  PUBLIC
+)
 
-# test inlined_vector_test
-set(INLINED_VECTOR_TEST_SRC "inlined_vector_test.cc")
-set(INLINED_VECTOR_TEST_PUBLIC_LIBRARIES absl::base absl_throw_delegate test_instance_tracker_lib)
+absl_cc_library(
+  NAME
+    inlined_vector
+  HDRS
+   "inlined_vector.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::algorithm
+    absl::core_headers
+    absl::throw_delegate
+    absl::memory
+  PUBLIC
+)
 
-absl_test(
-  TARGET
+absl_cc_library(
+  NAME
+    counting_allocator
+  HDRS
+    "internal/counting_allocator.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+)
+
+absl_cc_test(
+  NAME
     inlined_vector_test
-  SOURCES
-    ${INLINED_VECTOR_TEST_SRC}
-  PUBLIC_LIBRARIES
-    ${INLINED_VECTOR_TEST_PUBLIC_LIBRARIES}
+  SRCS
+    "inlined_vector_test.cc"
+  COPTS
+    ${ABSL_EXCEPTIONS_FLAG}
+  LINKOPTS
+    ${ABSL_EXCEPTIONS_FLAG_LINKOPTS}
+  DEPS
+    absl::counting_allocator
+    absl::inlined_vector
+    absl::test_instance_tracker
+    absl::base
+    absl::core_headers
+    absl::exception_testing
+    absl::hash_testing
+    absl::memory
+    absl::strings
+    gmock_main
 )
 
-absl_test(
-  TARGET
+absl_cc_test(
+  NAME
     inlined_vector_test_noexceptions
-  SOURCES
-    ${INLINED_VECTOR_TEST_SRC}
-  PUBLIC_LIBRARIES
-    ${INLINED_VECTOR_TEST_PUBLIC_LIBRARIES}
-  PRIVATE_COMPILE_FLAGS
-    ${ABSL_NOEXCEPTION_CXXFLAGS}
+  SRCS
+    "inlined_vector_test.cc"
+  DEPS
+    absl::inlined_vector
+    absl::test_instance_tracker
+    absl::base
+    absl::core_headers
+    absl::exception_testing
+    absl::hash_testing
+    absl::memory
+    absl::strings
+    gmock_main
 )
 
+absl_cc_library(
+  NAME
+    test_instance_tracker
+  HDRS
+    "internal/test_instance_tracker.h"
+  SRCS
+    "internal/test_instance_tracker.cc"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  TESTONLY
+)
 
-# test test_instance_tracker_test
-set(TEST_INSTANCE_TRACKER_TEST_SRC "internal/test_instance_tracker_test.cc")
-set(TEST_INSTANCE_TRACKER_TEST_PUBLIC_LIBRARIES absl::base absl_throw_delegate test_instance_tracker_lib)
-
-
-absl_test(
-  TARGET
+absl_cc_test(
+  NAME
     test_instance_tracker_test
-  SOURCES
-    ${TEST_INSTANCE_TRACKER_TEST_SRC}
-  PUBLIC_LIBRARIES
-    ${TEST_INSTANCE_TRACKER_TEST_PUBLIC_LIBRARIES}
+  SRCS
+    "internal/test_instance_tracker_test.cc"
+  DEPS
+    absl::test_instance_tracker
+    gmock_main
 )
 
+absl_cc_library(
+  NAME
+    flat_hash_map
+  HDRS
+    "flat_hash_map.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::container_memory
+    absl::hash_function_defaults
+    absl::raw_hash_map
+    absl::algorithm_container
+    absl::memory
+  PUBLIC
+)
 
-absl_test(
-  TARGET
+absl_cc_test(
+  NAME
+    flat_hash_map_test
+  SRCS
+    "flat_hash_map_test.cc"
+  DEPS
+    absl::flat_hash_map
+    absl::hash_generator_testing
+    absl::unordered_map_constructor_test
+    absl::unordered_map_lookup_test
+    absl::unordered_map_members_test
+    absl::unordered_map_modifiers_test
+    absl::any
+    gmock_main
+)
+
+absl_cc_library(
+  NAME
+    flat_hash_set
+  HDRS
+    "flat_hash_set.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::container_memory
+    absl::hash_function_defaults
+    absl::raw_hash_set
+    absl::algorithm_container
+    absl::core_headers
+    absl::memory
+  PUBLIC
+)
+
+absl_cc_test(
+  NAME
+    flat_hash_set_test
+  SRCS
+    "flat_hash_set_test.cc"
+  COPTS
+    "-DUNORDERED_SET_CXX17"
+  DEPS
+    absl::flat_hash_set
+    absl::hash_generator_testing
+    absl::unordered_set_constructor_test
+    absl::unordered_set_lookup_test
+    absl::unordered_set_members_test
+    absl::unordered_set_modifiers_test
+    absl::memory
+    absl::strings
+    gmock_main
+)
+
+absl_cc_library(
+  NAME
+    node_hash_map
+  HDRS
+    "node_hash_map.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::container_memory
+    absl::hash_function_defaults
+    absl::node_hash_policy
+    absl::raw_hash_map
+    absl::algorithm_container
+    absl::memory
+  PUBLIC
+)
+
+absl_cc_test(
+  NAME
+    node_hash_map_test
+  SRCS
+    "node_hash_map_test.cc"
+  DEPS
+    absl::hash_generator_testing
+    absl::node_hash_map
+    absl::tracked
+    absl::unordered_map_constructor_test
+    absl::unordered_map_lookup_test
+    absl::unordered_map_members_test
+    absl::unordered_map_modifiers_test
+    gmock_main
+)
+
+absl_cc_library(
+  NAME
+    node_hash_set
+  HDRS
+    "node_hash_set.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::hash_function_defaults
+    absl::node_hash_policy
+    absl::raw_hash_set
+    absl::algorithm_container
+    absl::memory
+  PUBLIC
+)
+
+absl_cc_test(
+  NAME
+    node_hash_set_test
+  SRCS
+    "node_hash_set_test.cc"
+  COPTS
+    "-DUNORDERED_SET_CXX17"
+  DEPS
+    absl::hash_generator_testing
+    absl::node_hash_set
+    absl::unordered_set_constructor_test
+    absl::unordered_set_lookup_test
+    absl::unordered_set_members_test
+    absl::unordered_set_modifiers_test
+    gmock_main
+)
+
+absl_cc_library(
+  NAME
+    container_memory
+  HDRS
+    "internal/container_memory.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::memory
+    absl::utility
+  PUBLIC
+)
+
+absl_cc_test(
+  NAME
+    container_memory_test
+  SRCS
+    "internal/container_memory_test.cc"
+  DEPS
+    absl::container_memory
+    absl::strings
+    gmock_main
+)
+
+absl_cc_library(
+  NAME
+    hash_function_defaults
+  HDRS
+    "internal/hash_function_defaults.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::config
+    absl::hash
+    absl::strings
+  PUBLIC
+)
+
+absl_cc_test(
+  NAME
+    hash_function_defaults_test
+  SRCS
+    "internal/hash_function_defaults_test.cc"
+  DEPS
+    absl::hash_function_defaults
+    absl::hash
+    absl::strings
+    gmock_main
+)
+
+absl_cc_library(
+  NAME
+    hash_generator_testing
+  HDRS
+    "internal/hash_generator_testing.h"
+  SRCS
+    "internal/hash_generator_testing.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::hash_policy_testing
+    absl::meta
+    absl::strings
+  TESTONLY
+)
+
+absl_cc_library(
+  NAME
+    hash_policy_testing
+  HDRS
+    "internal/hash_policy_testing.h"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::hash
+    absl::strings
+  TESTONLY
+)
+
+absl_cc_test(
+  NAME
+    hash_policy_testing_test
+  SRCS
+    "internal/hash_policy_testing_test.cc"
+  DEPS
+    absl::hash_policy_testing
+    gmock_main
+)
+
+absl_cc_library(
+  NAME
+    hash_policy_traits
+  HDRS
+    "internal/hash_policy_traits.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::meta
+  PUBLIC
+)
+
+absl_cc_test(
+  NAME
+    hash_policy_traits_test
+  SRCS
+    "internal/hash_policy_traits_test.cc"
+  DEPS
+    absl::hash_policy_traits
+    gmock_main
+)
+
+absl_cc_library(
+  NAME
+    hashtablez_sampler
+  HDRS
+    "internal/hashtablez_sampler.h"
+  SRCS
+    "internal/hashtablez_sampler.cc"
+    "internal/hashtablez_sampler_force_weak_definition.cc"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::base
+    absl::have_sse
+    absl::synchronization
+)
+
+absl_cc_test(
+  NAME
+    hashtablez_sampler_test
+  SRCS
+    "internal/hashtablez_sampler_test.cc"
+  DEPS
+    absl::hashtablez_sampler
+    absl::have_sse
+    gmock_main
+)
+
+absl_cc_library(
+  NAME
+    hashtable_debug
+  HDRS
+    "internal/hashtable_debug.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::hashtable_debug_hooks
+)
+
+absl_cc_library(
+  NAME
+    hashtable_debug_hooks
+  HDRS
+    "internal/hashtable_debug_hooks.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  PUBLIC
+)
+
+absl_cc_library(
+  NAME
+    have_sse
+  HDRS
+    "internal/have_sse.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+)
+
+absl_cc_library(
+  NAME
+    node_hash_policy
+  HDRS
+    "internal/node_hash_policy.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  PUBLIC
+)
+
+absl_cc_test(
+  NAME
+    node_hash_policy_test
+  SRCS
+    "internal/node_hash_policy_test.cc"
+  DEPS
+    absl::hash_policy_traits
+    absl::node_hash_policy
+    gmock_main
+)
+
+absl_cc_library(
+  NAME
+    raw_hash_map
+  HDRS
+    "internal/raw_hash_map.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::container_memory
+    absl::raw_hash_set
+  PUBLIC
+)
+
+absl_cc_library(
+  NAME
+    container_common
+  HDRS
+    "internal/commom.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::type_traits
+)
+
+absl_cc_library(
+  NAME
+    raw_hash_set
+  HDRS
+    "internal/raw_hash_set.h"
+  SRCS
+    "internal/raw_hash_set.cc"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::bits
+    absl::compressed_tuple
+    absl::config
+    absl::container_common
+    absl::container_memory
+    absl::core_headers
+    absl::endian
+    absl::hash_policy_traits
+    absl::hashtable_debug_hooks
+    absl::have_sse
+    absl::layout
+    absl::memory
+    absl::meta
+    absl::optional
+    absl::utility
+    absl::hashtablez_sampler
+  PUBLIC
+)
+
+absl_cc_test(
+  NAME
     raw_hash_set_test
-  SOURCES
+  SRCS
     "internal/raw_hash_set_test.cc"
-  PUBLIC_LIBRARIES
-    absl::base absl::hash absl_throw_delegate test_instance_tracker_lib
+  DEPS
+    absl::container_memory
+    absl::hash_function_defaults
+    absl::hash_policy_testing
+    absl::hashtable_debug
+    absl::raw_hash_set
+    absl::base
+    absl::core_headers
+    absl::strings
+    gmock_main
+)
+
+absl_cc_test(
+  NAME
+    raw_hash_set_allocator_test
+  SRCS
+    "internal/raw_hash_set_allocator_test.cc"
+  DEPS
+    absl::raw_hash_set
+    absl::tracked
+    absl::core_headers
+    gmock_main
+)
+
+absl_cc_library(
+  NAME
+    layout
+  HDRS
+    "internal/layout.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::core_headers
+    absl::meta
+    absl::strings
+    absl::span
+    absl::utility
+  PUBLIC
+)
+
+absl_cc_test(
+  NAME
+    layout_test
+  SRCS
+    "internal/layout_test.cc"
+  DEPS
+    absl::layout
+    absl::base
+    absl::core_headers
+    absl::span
+    gmock_main
+)
+
+absl_cc_library(
+  NAME
+    tracked
+  HDRS
+    "internal/tracked.h"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  TESTONLY
+)
+
+absl_cc_library(
+  NAME
+    unordered_map_constructor_test
+  HDRS
+    "internal/unordered_map_constructor_test.h"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::hash_generator_testing
+    absl::hash_policy_testing
+    gmock
+  TESTONLY
+)
+
+absl_cc_library(
+  NAME
+    unordered_map_lookup_test
+  HDRS
+    "internal/unordered_map_lookup_test.h"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::hash_generator_testing
+    absl::hash_policy_testing
+    gmock
+  TESTONLY
+)
+
+absl_cc_library(
+  NAME
+    unordered_map_members_test
+  HDRS
+    "internal/unordered_map_members_test.h"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::type_traits
+    gmock
+  TESTONLY
+)
+
+absl_cc_library(
+  NAME
+    unordered_map_modifiers_test
+  HDRS
+    "internal/unordered_map_modifiers_test.h"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::hash_generator_testing
+    absl::hash_policy_testing
+    gmock
+  TESTONLY
+)
+
+absl_cc_library(
+  NAME
+    unordered_set_constructor_test
+  HDRS
+    "internal/unordered_set_constructor_test.h"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::hash_generator_testing
+    absl::hash_policy_testing
+    gmock
+  TESTONLY
+)
+
+absl_cc_library(
+  NAME
+    unordered_set_lookup_test
+  HDRS
+    "internal/unordered_set_lookup_test.h"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::hash_generator_testing
+    absl::hash_policy_testing
+    gmock
+  TESTONLY
+)
+
+absl_cc_library(
+  NAME
+    unordered_set_members_test
+  HDRS
+    "internal/unordered_set_members_test.h"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::type_traits
+    gmock
+  TESTONLY
+)
+
+absl_cc_library(
+  NAME
+    unordered_set_modifiers_test
+  HDRS
+    "internal/unordered_set_modifiers_test.h"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::hash_generator_testing
+    absl::hash_policy_testing
+    gmock
+  TESTONLY
+)
+
+absl_cc_test(
+  NAME
+    unordered_set_test
+  SRCS
+    "internal/unordered_set_test.cc"
+  DEPS
+    absl::unordered_set_constructor_test
+    absl::unordered_set_lookup_test
+    absl::unordered_set_members_test
+    absl::unordered_set_modifiers_test
+    gmock_main
+)
+
+absl_cc_test(
+  NAME
+    unordered_map_test
+  SRCS
+    "internal/unordered_map_test.cc"
+  DEPS
+    absl::unordered_map_constructor_test
+    absl::unordered_map_lookup_test
+    absl::unordered_map_members_test
+    absl::unordered_map_modifiers_test
+    gmock_main
 )
diff --git a/absl/container/fixed_array.h b/absl/container/fixed_array.h
index 6d9fa5f..60da048 100644
--- a/absl/container/fixed_array.h
+++ b/absl/container/fixed_array.h
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -188,7 +188,7 @@
   // `FixedArray<T>`. This is equivalent to the most possible addressable bytes
   // over the number of bytes taken by T.
   constexpr size_type max_size() const {
-    return std::numeric_limits<difference_type>::max() / sizeof(value_type);
+    return (std::numeric_limits<difference_type>::max)() / sizeof(value_type);
   }
 
   // FixedArray::empty()
@@ -515,4 +515,5 @@
   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_benchmark.cc b/absl/container/fixed_array_benchmark.cc
index b4f0cf2..ff56f46 100644
--- a/absl/container/fixed_array_benchmark.cc
+++ b/absl/container/fixed_array_benchmark.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
diff --git a/absl/container/fixed_array_exception_safety_test.cc b/absl/container/fixed_array_exception_safety_test.cc
index da63dbf..826eca6 100644
--- a/absl/container/fixed_array_exception_safety_test.cc
+++ b/absl/container/fixed_array_exception_safety_test.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
diff --git a/absl/container/fixed_array_test.cc b/absl/container/fixed_array_test.cc
index 205ff41..a4f2498 100644
--- a/absl/container/fixed_array_test.cc
+++ b/absl/container/fixed_array_test.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -150,7 +150,7 @@
   }
 
   {
-    // Arrays of > default size should be on the stack
+    // Arrays of > default size should be on the heap
     absl::FixedArray<int, 100> array(101);
     EXPECT_FALSE(IsOnStack(array));
   }
@@ -365,7 +365,8 @@
 TEST(IteratorConstructorTest, NonPod) {
   char const* kInput[] =
       { "red", "orange", "yellow", "green", "blue", "indigo", "violet" };
-  absl::FixedArray<std::string> const fixed(kInput, kInput + ABSL_ARRAYSIZE(kInput));
+  absl::FixedArray<std::string> const fixed(kInput,
+                                            kInput + ABSL_ARRAYSIZE(kInput));
   ASSERT_EQ(ABSL_ARRAYSIZE(kInput), fixed.size());
   for (size_t i = 0; i < ABSL_ARRAYSIZE(kInput); ++i) {
     ASSERT_EQ(kInput[i], fixed[i]);
@@ -869,4 +870,21 @@
 }
 #endif  // ADDRESS_SANITIZER
 
+TEST(FixedArrayTest, AbslHashValueWorks) {
+  using V = absl::FixedArray<int>;
+  std::vector<V> cases;
+
+  // Generate a variety of vectors some of these are small enough for the inline
+  // space but are stored out of line.
+  for (int i = 0; i < 10; ++i) {
+    V v(i);
+    for (int j = 0; j < i; ++j) {
+      v[j] = j;
+    }
+    cases.push_back(v);
+  }
+
+  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(cases));
+}
+
 }  // namespace
diff --git a/absl/container/flat_hash_map.h b/absl/container/flat_hash_map.h
index e5570d1..00cc4dc 100644
--- a/absl/container/flat_hash_map.h
+++ b/absl/container/flat_hash_map.h
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -35,6 +35,7 @@
 #include <type_traits>
 #include <utility>
 
+#include "absl/algorithm/container.h"
 #include "absl/container/internal/container_memory.h"
 #include "absl/container/internal/hash_function_defaults.h"  // IWYU pragma: export
 #include "absl/container/internal/raw_hash_map.h"  // IWYU pragma: export
@@ -69,7 +70,7 @@
 // By default, `flat_hash_map` uses the `absl::Hash` hashing framework.
 // All fundamental and Abseil types that support the `absl::Hash` framework have
 // a compatible equality operator for comparing insertions into `flat_hash_map`.
-// If your type is not yet supported by the `asbl::Hash` framework, see
+// If your type is not yet supported by the `absl::Hash` framework, see
 // absl/hash/hash.h for information on extending Abseil hashing to user-defined
 // types.
 //
@@ -109,6 +110,46 @@
   using Base = typename flat_hash_map::raw_hash_map;
 
  public:
+  // Constructors and Assignment Operators
+  //
+  // A flat_hash_map supports the same overload set as `std::unordered_map`
+  // for construction and assignment:
+  //
+  // *  Default constructor
+  //
+  //    // No allocation for the table's elements is made.
+  //    absl::flat_hash_map<int, std::string> map1;
+  //
+  // * Initializer List constructor
+  //
+  //   absl::flat_hash_map<int, std::string> map2 =
+  //       {{1, "huey"}, {2, "dewey"}, {3, "louie"},};
+  //
+  // * Copy constructor
+  //
+  //   absl::flat_hash_map<int, std::string> map3(map2);
+  //
+  // * Copy assignment operator
+  //
+  //  // Hash functor and Comparator are copied as well
+  //  absl::flat_hash_map<int, std::string> map4;
+  //  map4 = map3;
+  //
+  // * Move constructor
+  //
+  //   // Move is guaranteed efficient
+  //   absl::flat_hash_map<int, std::string> map5(std::move(map4));
+  //
+  // * Move assignment operator
+  //
+  //   // May be efficient if allocators are compatible
+  //   absl::flat_hash_map<int, std::string> map6;
+  //   map6 = std::move(map5);
+  //
+  // * Range constructor
+  //
+  //   std::vector<std::pair<int, std::string>> v = {{1, "a"}, {2, "b"}};
+  //   absl::flat_hash_map<int, std::string> map7(v.begin(), v.end());
   flat_hash_map() {}
   using Base::Base;
 
@@ -178,8 +219,12 @@
   //   Erases the element at `position` of the `flat_hash_map`, returning
   //   `void`.
   //
-  //   NOTE: this return behavior is different than that of STL containers in
-  //   general and `std::unordered_map` in particular.
+  //   NOTE: returning `void` in this case is different than that of STL
+  //   containers in general and `std::unordered_map` in particular (which
+  //   return an iterator to the element following the erased element). If that
+  //   iterator is needed, simply post increment the iterator:
+  //
+  //     map.erase(it++);
   //
   // iterator erase(const_iterator first, const_iterator last):
   //
@@ -486,25 +531,26 @@
 
 template <class K, class V>
 struct FlatHashMapPolicy {
-  using slot_type = container_internal::slot_type<K, V>;
+  using slot_policy = container_internal::map_slot_policy<K, V>;
+  using slot_type = typename slot_policy::slot_type;
   using key_type = K;
   using mapped_type = V;
   using init_type = std::pair</*non const*/ key_type, mapped_type>;
 
   template <class Allocator, class... Args>
   static void construct(Allocator* alloc, slot_type* slot, Args&&... args) {
-    slot_type::construct(alloc, slot, std::forward<Args>(args)...);
+    slot_policy::construct(alloc, slot, std::forward<Args>(args)...);
   }
 
   template <class Allocator>
   static void destroy(Allocator* alloc, slot_type* slot) {
-    slot_type::destroy(alloc, slot);
+    slot_policy::destroy(alloc, slot);
   }
 
   template <class Allocator>
   static void transfer(Allocator* alloc, slot_type* new_slot,
                        slot_type* old_slot) {
-    slot_type::transfer(alloc, new_slot, old_slot);
+    slot_policy::transfer(alloc, new_slot, old_slot);
   }
 
   template <class F, class... Args>
@@ -524,5 +570,16 @@
 };
 
 }  // namespace container_internal
+
+namespace container_algorithm_internal {
+
+// Specialization of trait in absl/algorithm/container.h
+template <class Key, class T, class Hash, class KeyEqual, class Allocator>
+struct IsUnorderedContainer<
+    absl::flat_hash_map<Key, T, Hash, KeyEqual, Allocator>> : std::true_type {};
+
+}  // namespace container_algorithm_internal
+
 }  // namespace absl
+
 #endif  // ABSL_CONTAINER_FLAT_HASH_MAP_H_
diff --git a/absl/container/flat_hash_map_test.cc b/absl/container/flat_hash_map_test.cc
index 10a781f..ebcb560 100644
--- a/absl/container/flat_hash_map_test.cc
+++ b/absl/container/flat_hash_map_test.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -17,6 +17,7 @@
 #include "absl/container/internal/hash_generator_testing.h"
 #include "absl/container/internal/unordered_map_constructor_test.h"
 #include "absl/container/internal/unordered_map_lookup_test.h"
+#include "absl/container/internal/unordered_map_members_test.h"
 #include "absl/container/internal/unordered_map_modifiers_test.h"
 #include "absl/types/any.h"
 
@@ -30,19 +31,20 @@
 using ::testing::UnorderedElementsAre;
 
 template <class K, class V>
-using Map =
-    flat_hash_map<K, V, StatefulTestingHash, StatefulTestingEqual, Alloc<>>;
+using Map = flat_hash_map<K, V, StatefulTestingHash, StatefulTestingEqual,
+                          Alloc<std::pair<const K, V>>>;
 
 static_assert(!std::is_standard_layout<NonStandardLayout>(), "");
 
 using MapTypes =
-    ::testing::Types<Map<int, int>, Map<std::string, int>, Map<Enum, std::string>,
-                     Map<EnumClass, int>, Map<int, NonStandardLayout>,
-                     Map<NonStandardLayout, int>>;
+    ::testing::Types<Map<int, int>, Map<std::string, int>,
+                     Map<Enum, std::string>, Map<EnumClass, int>,
+                     Map<int, NonStandardLayout>, Map<NonStandardLayout, int>>;
 
-INSTANTIATE_TYPED_TEST_CASE_P(FlatHashMap, ConstructorTest, MapTypes);
-INSTANTIATE_TYPED_TEST_CASE_P(FlatHashMap, LookupTest, MapTypes);
-INSTANTIATE_TYPED_TEST_CASE_P(FlatHashMap, ModifiersTest, MapTypes);
+INSTANTIATE_TYPED_TEST_SUITE_P(FlatHashMap, ConstructorTest, MapTypes);
+INSTANTIATE_TYPED_TEST_SUITE_P(FlatHashMap, LookupTest, MapTypes);
+INSTANTIATE_TYPED_TEST_SUITE_P(FlatHashMap, MembersTest, MapTypes);
+INSTANTIATE_TYPED_TEST_SUITE_P(FlatHashMap, ModifiersTest, MapTypes);
 
 TEST(FlatHashMap, StandardLayout) {
   struct Int {
@@ -94,7 +96,7 @@
   }
 }
 
-// Demonstration of the "Lazy Key" pattern.  This uses heterogenous insert to
+// Demonstration of the "Lazy Key" pattern.  This uses heterogeneous insert to
 // avoid creating expensive key elements when the item is already present in the
 // map.
 struct LazyInt {
@@ -139,6 +141,7 @@
   int conversions = 0;
   int hashes = 0;
   flat_hash_map<size_t, size_t, Hash, Eq> m(0, Hash{&hashes});
+  m.reserve(3);
 
   m[LazyInt(1, &conversions)] = 1;
   EXPECT_THAT(m, UnorderedElementsAre(Pair(1, 1)));
@@ -203,7 +206,9 @@
   m.insert(std::move(node));
   EXPECT_THAT(m, UnorderedElementsAre(Pair(1, 17), Pair(2, 9)));
 }
-#if !defined(__ANDROID__) && !defined(__APPLE__) && !defined(__EMSCRIPTEN__)
+
+#if (defined(ABSL_HAVE_STD_ANY) || !defined(_LIBCPP_VERSION)) && \
+    !defined(__EMSCRIPTEN__)
 TEST(FlatHashMap, Any) {
   absl::flat_hash_map<int, absl::any> m;
   m.emplace(1, 7);
@@ -234,7 +239,8 @@
   ASSERT_NE(it2, m2.end());
   EXPECT_EQ(7, it2->second);
 }
-#endif  // __ANDROID__
+#endif  // (defined(ABSL_HAVE_STD_ANY) || !defined(_LIBCPP_VERSION)) &&
+        // !defined(__EMSCRIPTEN__)
 
 }  // namespace
 }  // namespace container_internal
diff --git a/absl/container/flat_hash_set.h b/absl/container/flat_hash_set.h
index 98aead1..6bf5183 100644
--- a/absl/container/flat_hash_set.h
+++ b/absl/container/flat_hash_set.h
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -32,6 +32,7 @@
 #include <type_traits>
 #include <utility>
 
+#include "absl/algorithm/container.h"
 #include "absl/base/macros.h"
 #include "absl/container/internal/container_memory.h"
 #include "absl/container/internal/hash_function_defaults.h"  // IWYU pragma: export
@@ -66,7 +67,7 @@
 // By default, `flat_hash_set` uses the `absl::Hash` hashing framework. All
 // fundamental and Abseil types that support the `absl::Hash` framework have a
 // compatible equality operator for comparing insertions into `flat_hash_map`.
-// If your type is not yet supported by the `asbl::Hash` framework, see
+// If your type is not yet supported by the `absl::Hash` framework, see
 // absl/hash/hash.h for information on extending Abseil hashing to user-defined
 // types.
 //
@@ -84,7 +85,7 @@
 //     {"huey", "dewey", "louie"};
 //
 //  // Insert a new element into the flat hash set
-//  ducks.insert("donald"};
+//  ducks.insert("donald");
 //
 //  // Force a rehash of the flat hash set
 //  ducks.rehash(0);
@@ -102,6 +103,46 @@
   using Base = typename flat_hash_set::raw_hash_set;
 
  public:
+  // Constructors and Assignment Operators
+  //
+  // A flat_hash_set supports the same overload set as `std::unordered_map`
+  // for construction and assignment:
+  //
+  // *  Default constructor
+  //
+  //    // No allocation for the table's elements is made.
+  //    absl::flat_hash_set<std::string> set1;
+  //
+  // * Initializer List constructor
+  //
+  //   absl::flat_hash_set<std::string> set2 =
+  //       {{"huey"}, {"dewey"}, {"louie"},};
+  //
+  // * Copy constructor
+  //
+  //   absl::flat_hash_set<std::string> set3(set2);
+  //
+  // * Copy assignment operator
+  //
+  //  // Hash functor and Comparator are copied as well
+  //  absl::flat_hash_set<std::string> set4;
+  //  set4 = set3;
+  //
+  // * Move constructor
+  //
+  //   // Move is guaranteed efficient
+  //   absl::flat_hash_set<std::string> set5(std::move(set4));
+  //
+  // * Move assignment operator
+  //
+  //   // May be efficient if allocators are compatible
+  //   absl::flat_hash_set<std::string> set6;
+  //   set6 = std::move(set5);
+  //
+  // * Range constructor
+  //
+  //   std::vector<std::string> v = {"a", "b"};
+  //   absl::flat_hash_set<std::string> set7(v.begin(), v.end());
   flat_hash_set() {}
   using Base::Base;
 
@@ -171,8 +212,12 @@
   //   Erases the element at `position` of the `flat_hash_set`, returning
   //   `void`.
   //
-  //   NOTE: this return behavior is different than that of STL containers in
-  //   general and `std::unordered_map` in particular.
+  //   NOTE: returning `void` in this case is different than that of STL
+  //   containers in general and `std::unordered_set` in particular (which
+  //   return an iterator to the element following the erased element). If that
+  //   iterator is needed, simply post increment the iterator:
+  //
+  //     set.erase(it++);
   //
   // iterator erase(const_iterator first, const_iterator last):
   //
@@ -238,8 +283,7 @@
   //
   // The element may be constructed even if there already is an element with the
   // key in the container, in which case the newly constructed element will be
-  // destroyed immediately. Prefer `try_emplace()` unless your key is not
-  // copyable or moveable.
+  // destroyed immediately.
   //
   // If rehashing occurs due to the insertion, all iterators are invalidated.
   using Base::emplace;
@@ -253,8 +297,7 @@
   //
   // The element may be constructed even if there already is an element with the
   // key in the container, in which case the newly constructed element will be
-  // destroyed immediately. Prefer `try_emplace()` unless your key is not
-  // copyable or moveable.
+  // destroyed immediately.
   //
   // If rehashing occurs due to the insertion, all iterators are invalidated.
   using Base::emplace_hint;
@@ -435,5 +478,16 @@
   static size_t space_used(const T*) { return 0; }
 };
 }  // namespace container_internal
+
+namespace container_algorithm_internal {
+
+// Specialization of trait in absl/algorithm/container.h
+template <class Key, class Hash, class KeyEqual, class Allocator>
+struct IsUnorderedContainer<absl::flat_hash_set<Key, Hash, KeyEqual, Allocator>>
+    : std::true_type {};
+
+}  // namespace container_algorithm_internal
+
 }  // namespace absl
+
 #endif  // ABSL_CONTAINER_FLAT_HASH_SET_H_
diff --git a/absl/container/flat_hash_set_test.cc b/absl/container/flat_hash_set_test.cc
index e52fd53..b55be59 100644
--- a/absl/container/flat_hash_set_test.cc
+++ b/absl/container/flat_hash_set_test.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -19,6 +19,7 @@
 #include "absl/container/internal/hash_generator_testing.h"
 #include "absl/container/internal/unordered_set_constructor_test.h"
 #include "absl/container/internal/unordered_set_lookup_test.h"
+#include "absl/container/internal/unordered_set_members_test.h"
 #include "absl/container/internal/unordered_set_modifiers_test.h"
 #include "absl/memory/memory.h"
 #include "absl/strings/string_view.h"
@@ -40,9 +41,10 @@
 using SetTypes =
     ::testing::Types<Set<int>, Set<std::string>, Set<Enum>, Set<EnumClass>>;
 
-INSTANTIATE_TYPED_TEST_CASE_P(FlatHashSet, ConstructorTest, SetTypes);
-INSTANTIATE_TYPED_TEST_CASE_P(FlatHashSet, LookupTest, SetTypes);
-INSTANTIATE_TYPED_TEST_CASE_P(FlatHashSet, ModifiersTest, SetTypes);
+INSTANTIATE_TYPED_TEST_SUITE_P(FlatHashSet, ConstructorTest, SetTypes);
+INSTANTIATE_TYPED_TEST_SUITE_P(FlatHashSet, LookupTest, SetTypes);
+INSTANTIATE_TYPED_TEST_SUITE_P(FlatHashSet, MembersTest, SetTypes);
+INSTANTIATE_TYPED_TEST_SUITE_P(FlatHashSet, ModifiersTest, SetTypes);
 
 TEST(FlatHashSet, EmplaceString) {
   std::vector<std::string> v = {"a", "b"};
diff --git a/absl/container/inlined_vector.h b/absl/container/inlined_vector.h
index 12756bb..7798805 100644
--- a/absl/container/inlined_vector.h
+++ b/absl/container/inlined_vector.h
@@ -1,10 +1,10 @@
-// Copyright 2017 The Abseil Authors.
+// Copyright 2019 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
+//      https://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,
@@ -20,17 +20,17 @@
 // vector" which behaves in an equivalent fashion to a `std::vector`, except
 // that storage for small sequences of the vector are provided inline without
 // requiring any heap allocation.
-
-// An `absl::InlinedVector<T,N>` specifies the size N at which to inline as one
-// of its template parameters. Vectors of length <= N are provided inline.
-// Typically N is very small (e.g., 4) so that sequences that are expected to be
-// short do not require allocations.
-
-// An `absl::InlinedVector` does not usually require a specific allocator; if
+//
+// An `absl::InlinedVector<T, N>` specifies the default capacity `N` as one of
+// its template parameters. Instances where `size() <= N` hold contained
+// elements in inline space. Typically `N` is very small so that sequences that
+// are expected to be short do not require allocations.
+//
+// An `absl::InlinedVector` does not usually require a specific allocator. If
 // the inlined vector grows beyond its initial constraints, it will need to
-// allocate (as any normal `std::vector` would) and it will generally use the
-// default allocator in that case; optionally, a custom allocator may be
-// specified using an `absl::InlinedVector<T,N,A>` construction.
+// allocate (as any normal `std::vector` would). This is usually performed with
+// the default allocator (defined as `std::allocator<T>`). Optionally, a custom
+// allocator type may be specified as `A` in `absl::InlinedVector<T, N, A>`.
 
 #ifndef ABSL_CONTAINER_INLINED_VECTOR_H_
 #define ABSL_CONTAINER_INLINED_VECTOR_H_
@@ -50,10 +50,10 @@
 #include "absl/base/internal/throw_delegate.h"
 #include "absl/base/optimization.h"
 #include "absl/base/port.h"
+#include "absl/container/internal/inlined_vector.h"
 #include "absl/memory/memory.h"
 
 namespace absl {
-
 // -----------------------------------------------------------------------------
 // InlinedVector
 // -----------------------------------------------------------------------------
@@ -61,323 +61,633 @@
 // An `absl::InlinedVector` is designed to be a drop-in replacement for
 // `std::vector` for use cases where the vector's size is sufficiently small
 // that it can be inlined. If the inlined vector does grow beyond its estimated
-// size, it will trigger an initial allocation on the heap, and will behave as a
-// `std:vector`. The API of the `absl::InlinedVector` within this file is
+// capacity, it will trigger an initial allocation on the heap, and will behave
+// as a `std:vector`. The API of the `absl::InlinedVector` within this file is
 // designed to cover the same API footprint as covered by `std::vector`.
-template <typename T, size_t N, typename A = std::allocator<T> >
+template <typename T, size_t N, typename A = std::allocator<T>>
 class InlinedVector {
-  using AllocatorTraits = std::allocator_traits<A>;
+  static_assert(
+      N > 0, "InlinedVector cannot be instantiated with `0` inlined elements.");
+
+  using Storage = inlined_vector_internal::Storage<InlinedVector>;
+  using Tag = typename Storage::Tag;
+  using AllocatorAndTag = typename Storage::AllocatorAndTag;
+  using Allocation = typename Storage::Allocation;
+
+  template <typename Iterator>
+  using IsAtLeastForwardIterator = std::is_convertible<
+      typename std::iterator_traits<Iterator>::iterator_category,
+      std::forward_iterator_tag>;
+
+  template <typename Iterator>
+  using EnableIfAtLeastForwardIterator =
+      absl::enable_if_t<IsAtLeastForwardIterator<Iterator>::value>;
+
+  template <typename Iterator>
+  using DisableIfAtLeastForwardIterator =
+      absl::enable_if_t<!IsAtLeastForwardIterator<Iterator>::value>;
+
+  using rvalue_reference = typename Storage::rvalue_reference;
 
  public:
-  using allocator_type = A;
-  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 allocator_type = typename Storage::allocator_type;
+  using value_type = typename Storage::value_type;
+  using pointer = typename Storage::pointer;
+  using const_pointer = typename Storage::const_pointer;
+  using reference = typename Storage::reference;
+  using const_reference = typename Storage::const_reference;
+  using size_type = typename Storage::size_type;
+  using difference_type = typename Storage::difference_type;
+  using iterator = typename Storage::iterator;
+  using const_iterator = typename Storage::const_iterator;
+  using reverse_iterator = typename Storage::reverse_iterator;
+  using const_reverse_iterator = typename Storage::const_reverse_iterator;
 
+  // ---------------------------------------------------------------------------
+  // InlinedVector Constructors and Destructor
+  // ---------------------------------------------------------------------------
+
+  // Creates an empty inlined vector with a default initialized allocator.
   InlinedVector() noexcept(noexcept(allocator_type()))
-      : allocator_and_tag_(allocator_type()) {}
+      : storage_(allocator_type()) {}
 
+  // Creates an empty inlined vector with a specified allocator.
   explicit InlinedVector(const allocator_type& alloc) noexcept
-      : allocator_and_tag_(alloc) {}
+      : storage_(alloc) {}
 
-  // Create a vector with n copies of value_type().
+  // Creates an inlined vector with `n` copies of `value_type()`.
   explicit InlinedVector(size_type n,
                          const allocator_type& alloc = allocator_type())
-      : allocator_and_tag_(alloc) {
+      : storage_(alloc) {
     InitAssign(n);
   }
 
-  // Create a vector with n copies of elem
-  InlinedVector(size_type n, const value_type& elem,
+  // Creates an inlined vector with `n` copies of `v`.
+  InlinedVector(size_type n, const_reference v,
                 const allocator_type& alloc = allocator_type())
-      : allocator_and_tag_(alloc) {
-    InitAssign(n, elem);
+      : storage_(alloc) {
+    InitAssign(n, v);
   }
 
-  // Create and initialize with the elements [first .. last).
-  // The unused enable_if argument restricts this constructor so that it is
-  // elided when value_type is an integral type.  This prevents ambiguous
-  // interpretation between a call to this constructor with two integral
-  // arguments and a call to the preceding (n, elem) constructor.
-  template <typename InputIterator>
-  InlinedVector(
-      InputIterator first, InputIterator last,
-      const allocator_type& alloc = allocator_type(),
-      typename std::enable_if<!std::is_integral<InputIterator>::value>::type* =
-          nullptr)
-      : allocator_and_tag_(alloc) {
-    AppendRange(first, last);
-  }
-
-  InlinedVector(std::initializer_list<value_type> init,
+  // Creates an inlined vector of copies of the values in `list`.
+  InlinedVector(std::initializer_list<value_type> list,
                 const allocator_type& alloc = allocator_type())
-      : allocator_and_tag_(alloc) {
-    AppendRange(init.begin(), init.end());
+      : storage_(alloc) {
+    AppendForwardRange(list.begin(), list.end());
   }
 
-  InlinedVector(const InlinedVector& v);
-  InlinedVector(const InlinedVector& v, const allocator_type& alloc);
+  // Creates an inlined vector with elements constructed from the provided
+  // forward iterator range [`first`, `last`).
+  //
+  // NOTE: The `enable_if` prevents ambiguous interpretation between a call to
+  // this constructor with two integral arguments and a call to the above
+  // `InlinedVector(size_type, const_reference)` constructor.
+  template <typename ForwardIterator,
+            EnableIfAtLeastForwardIterator<ForwardIterator>* = nullptr>
+  InlinedVector(ForwardIterator first, ForwardIterator last,
+                const allocator_type& alloc = allocator_type())
+      : storage_(alloc) {
+    AppendForwardRange(first, last);
+  }
 
-  // This move constructor does not allocate and only moves the underlying
-  // objects, so its `noexcept` specification depends on whether moving the
-  // underlying objects can throw or not. We assume
-  //  a) move constructors should only throw due to allocation failure and
-  //  b) if `value_type`'s move constructor allocates, it uses the same
-  //     allocation function as the `InlinedVector`'s allocator, so the move
+  // Creates an inlined vector with elements constructed from the provided input
+  // iterator range [`first`, `last`).
+  template <typename InputIterator,
+            DisableIfAtLeastForwardIterator<InputIterator>* = nullptr>
+  InlinedVector(InputIterator first, InputIterator last,
+                const allocator_type& alloc = allocator_type())
+      : storage_(alloc) {
+    std::copy(first, last, std::back_inserter(*this));
+  }
+
+  // Creates a copy of an `other` inlined vector using `other`'s allocator.
+  InlinedVector(const InlinedVector& other)
+      : InlinedVector(other, other.allocator()) {}
+
+  // Creates a copy of an `other` inlined vector using a specified allocator.
+  InlinedVector(const InlinedVector& other, const allocator_type& alloc)
+      : storage_(alloc) {
+    reserve(other.size());
+    if (allocated()) {
+      UninitializedCopy(other.begin(), other.end(), allocated_space());
+      tag().set_allocated_size(other.size());
+    } else {
+      UninitializedCopy(other.begin(), other.end(), inlined_space());
+      tag().set_inline_size(other.size());
+    }
+  }
+
+  // Creates an inlined vector by moving in the contents of an `other` inlined
+  // vector without performing any allocations. If `other` contains allocated
+  // memory, the newly-created instance will take ownership of that memory
+  // (leaving `other` itself empty). However, if `other` does not contain any
+  // allocated memory, the new inlined vector will  will perform element-wise
+  // move construction of `other`s elements.
+  //
+  // NOTE: since no allocation is performed for the inlined vector in either
+  // case, the `noexcept(...)` specification depends on whether moving the
+  // underlying objects can throw. We assume:
+  //  a) Move constructors should only throw due to allocation failure.
+  //  b) If `value_type`'s move constructor allocates, it uses the same
+  //     allocation function as the `InlinedVector`'s allocator. Thus, the move
   //     constructor is non-throwing if the allocator is non-throwing or
   //     `value_type`'s move constructor is specified as `noexcept`.
-  InlinedVector(InlinedVector&& v) noexcept(
+  InlinedVector(InlinedVector&& other) noexcept(
       absl::allocator_is_nothrow<allocator_type>::value ||
-      std::is_nothrow_move_constructible<value_type>::value);
+      std::is_nothrow_move_constructible<value_type>::value)
+      : storage_(other.allocator()) {
+    if (other.allocated()) {
+      // We can just steal the underlying buffer from the source.
+      // That leaves the source empty, so we clear its size.
+      init_allocation(other.allocation());
+      tag().set_allocated_size(other.size());
+      other.tag() = Tag();
+    } else {
+      UninitializedCopy(
+          std::make_move_iterator(other.inlined_space()),
+          std::make_move_iterator(other.inlined_space() + other.size()),
+          inlined_space());
+      tag().set_inline_size(other.size());
+    }
+  }
 
-  // This move constructor allocates and also moves the underlying objects, so
-  // its `noexcept` specification depends on whether the allocation can throw
-  // and whether moving the underlying objects can throw. Based on the same
-  // assumptions above, the `noexcept` specification is dominated by whether the
-  // allocation can throw regardless of whether `value_type`'s move constructor
-  // is specified as `noexcept`.
-  InlinedVector(InlinedVector&& v, const allocator_type& alloc) noexcept(
-      absl::allocator_is_nothrow<allocator_type>::value);
+  // Creates an inlined vector by moving in the contents of an `other` inlined
+  // vector, performing allocations with the specified `alloc` allocator. If
+  // `other`'s allocator is not equal to `alloc` and `other` contains allocated
+  // memory, this move constructor will create a new allocation.
+  //
+  // NOTE: since allocation is performed in this case, this constructor can
+  // only be `noexcept` if the specified allocator is also `noexcept`. If this
+  // is the case, or if `other` contains allocated memory, this constructor
+  // performs element-wise move construction of its contents.
+  //
+  // Only in the case where `other`'s allocator is equal to `alloc` and `other`
+  // contains allocated memory will the newly created inlined vector take
+  // ownership of `other`'s allocated memory.
+  InlinedVector(InlinedVector&& other, const allocator_type& alloc) noexcept(
+      absl::allocator_is_nothrow<allocator_type>::value)
+      : storage_(alloc) {
+    if (other.allocated()) {
+      if (alloc == other.allocator()) {
+        // We can just steal the allocation from the source.
+        tag() = other.tag();
+        init_allocation(other.allocation());
+        other.tag() = Tag();
+      } else {
+        // We need to use our own allocator
+        reserve(other.size());
+        UninitializedCopy(std::make_move_iterator(other.begin()),
+                          std::make_move_iterator(other.end()),
+                          allocated_space());
+        tag().set_allocated_size(other.size());
+      }
+    } else {
+      UninitializedCopy(
+          std::make_move_iterator(other.inlined_space()),
+          std::make_move_iterator(other.inlined_space() + other.size()),
+          inlined_space());
+      tag().set_inline_size(other.size());
+    }
+  }
 
   ~InlinedVector() { clear(); }
 
-  InlinedVector& operator=(const InlinedVector& v) {
-    if (this == &v) {
-      return *this;
+  // ---------------------------------------------------------------------------
+  // InlinedVector Member Accessors
+  // ---------------------------------------------------------------------------
+
+  // `InlinedVector::empty()`
+  //
+  // Checks if the inlined vector has no elements.
+  bool empty() const noexcept { return !size(); }
+
+  // `InlinedVector::size()`
+  //
+  // Returns the number of elements in the inlined vector.
+  size_type size() const noexcept { return tag().size(); }
+
+  // `InlinedVector::max_size()`
+  //
+  // Returns the maximum number of elements the vector can hold.
+  size_type max_size() const noexcept {
+    // One bit of the size storage is used to indicate whether the inlined
+    // vector is allocated. As a result, the maximum size of the container that
+    // we can express is half of the max for `size_type`.
+    return (std::numeric_limits<size_type>::max)() / 2;
+  }
+
+  // `InlinedVector::capacity()`
+  //
+  // Returns the number of elements that can be stored in the inlined vector
+  // without requiring a reallocation of underlying memory.
+  //
+  // NOTE: For most inlined vectors, `capacity()` should equal the template
+  // parameter `N`. For inlined vectors which exceed this capacity, they
+  // will no longer be inlined and `capacity()` will equal its capacity on the
+  // allocated heap.
+  size_type capacity() const noexcept {
+    return allocated() ? allocation().capacity() : static_cast<size_type>(N);
+  }
+
+  // `InlinedVector::data()`
+  //
+  // Returns a `pointer` to elements of the inlined vector. This pointer can be
+  // used to access and modify the contained elements.
+  // Only results within the range [`0`, `size()`) are defined.
+  pointer data() noexcept {
+    return allocated() ? allocated_space() : inlined_space();
+  }
+
+  // Overload of `InlinedVector::data()` to return a `const_pointer` to elements
+  // of the inlined vector. This pointer can be used to access (but not modify)
+  // the contained elements.
+  const_pointer data() const noexcept {
+    return allocated() ? allocated_space() : inlined_space();
+  }
+
+  // `InlinedVector::operator[]()`
+  //
+  // Returns a `reference` to the `i`th element of the inlined vector using the
+  // array operator.
+  reference operator[](size_type i) {
+    assert(i < size());
+    return data()[i];
+  }
+
+  // Overload of `InlinedVector::operator[]()` to return a `const_reference` to
+  // the `i`th element of the inlined vector.
+  const_reference operator[](size_type i) const {
+    assert(i < size());
+    return data()[i];
+  }
+
+  // `InlinedVector::at()`
+  //
+  // Returns a `reference` to the `i`th element of the inlined vector.
+  reference at(size_type i) {
+    if (ABSL_PREDICT_FALSE(i >= size())) {
+      base_internal::ThrowStdOutOfRange(
+          "`InlinedVector::at(size_type)` failed bounds check");
     }
+    return data()[i];
+  }
+
+  // Overload of `InlinedVector::at()` to return a `const_reference` to the
+  // `i`th element of the inlined vector.
+  const_reference at(size_type i) const {
+    if (ABSL_PREDICT_FALSE(i >= size())) {
+      base_internal::ThrowStdOutOfRange(
+          "`InlinedVector::at(size_type) const` failed bounds check");
+    }
+    return data()[i];
+  }
+
+  // `InlinedVector::front()`
+  //
+  // Returns a `reference` to the first element of the inlined vector.
+  reference front() {
+    assert(!empty());
+    return at(0);
+  }
+
+  // Overload of `InlinedVector::front()` returns a `const_reference` to the
+  // first element of the inlined vector.
+  const_reference front() const {
+    assert(!empty());
+    return at(0);
+  }
+
+  // `InlinedVector::back()`
+  //
+  // Returns a `reference` to the last element of the inlined vector.
+  reference back() {
+    assert(!empty());
+    return at(size() - 1);
+  }
+
+  // Overload of `InlinedVector::back()` to return a `const_reference` to the
+  // last element of the inlined vector.
+  const_reference back() const {
+    assert(!empty());
+    return at(size() - 1);
+  }
+
+  // `InlinedVector::begin()`
+  //
+  // Returns an `iterator` to the beginning of the inlined vector.
+  iterator begin() noexcept { return data(); }
+
+  // Overload of `InlinedVector::begin()` to return a `const_iterator` to
+  // the beginning of the inlined vector.
+  const_iterator begin() const noexcept { return data(); }
+
+  // `InlinedVector::end()`
+  //
+  // Returns an `iterator` to the end of the inlined vector.
+  iterator end() noexcept { return data() + size(); }
+
+  // Overload of `InlinedVector::end()` to return a `const_iterator` to the
+  // end of the inlined vector.
+  const_iterator end() const noexcept { return data() + size(); }
+
+  // `InlinedVector::cbegin()`
+  //
+  // Returns a `const_iterator` to the beginning of the inlined vector.
+  const_iterator cbegin() const noexcept { return begin(); }
+
+  // `InlinedVector::cend()`
+  //
+  // Returns a `const_iterator` to the end of the inlined vector.
+  const_iterator cend() const noexcept { return end(); }
+
+  // `InlinedVector::rbegin()`
+  //
+  // Returns a `reverse_iterator` from the end of the inlined vector.
+  reverse_iterator rbegin() noexcept { return reverse_iterator(end()); }
+
+  // Overload of `InlinedVector::rbegin()` to return a
+  // `const_reverse_iterator` from the end of the inlined vector.
+  const_reverse_iterator rbegin() const noexcept {
+    return const_reverse_iterator(end());
+  }
+
+  // `InlinedVector::rend()`
+  //
+  // Returns a `reverse_iterator` from the beginning of the inlined vector.
+  reverse_iterator rend() noexcept { return reverse_iterator(begin()); }
+
+  // Overload of `InlinedVector::rend()` to return a `const_reverse_iterator`
+  // from the beginning of the inlined vector.
+  const_reverse_iterator rend() const noexcept {
+    return const_reverse_iterator(begin());
+  }
+
+  // `InlinedVector::crbegin()`
+  //
+  // Returns a `const_reverse_iterator` from the end of the inlined vector.
+  const_reverse_iterator crbegin() const noexcept { return rbegin(); }
+
+  // `InlinedVector::crend()`
+  //
+  // Returns a `const_reverse_iterator` from the beginning of the inlined
+  // vector.
+  const_reverse_iterator crend() const noexcept { return rend(); }
+
+  // `InlinedVector::get_allocator()`
+  //
+  // Returns a copy of the allocator of the inlined vector.
+  allocator_type get_allocator() const { return allocator(); }
+
+  // ---------------------------------------------------------------------------
+  // InlinedVector Member Mutators
+  // ---------------------------------------------------------------------------
+
+  // `InlinedVector::operator=()`
+  //
+  // Replaces the contents of the inlined vector with copies of the elements in
+  // the provided `std::initializer_list`.
+  InlinedVector& operator=(std::initializer_list<value_type> list) {
+    AssignForwardRange(list.begin(), list.end());
+    return *this;
+  }
+
+  // Overload of `InlinedVector::operator=()` to replace the contents of the
+  // inlined vector with the contents of `other`.
+  InlinedVector& operator=(const InlinedVector& other) {
+    if (ABSL_PREDICT_FALSE(this == &other)) return *this;
+
     // Optimized to avoid reallocation.
     // Prefer reassignment to copy construction for elements.
-    if (size() < v.size()) {  // grow
-      reserve(v.size());
-      std::copy(v.begin(), v.begin() + size(), begin());
-      std::copy(v.begin() + size(), v.end(), std::back_inserter(*this));
+    if (size() < other.size()) {  // grow
+      reserve(other.size());
+      std::copy(other.begin(), other.begin() + size(), begin());
+      std::copy(other.begin() + size(), other.end(), std::back_inserter(*this));
     } else {  // maybe shrink
-      erase(begin() + v.size(), end());
-      std::copy(v.begin(), v.end(), begin());
+      erase(begin() + other.size(), end());
+      std::copy(other.begin(), other.end(), begin());
     }
     return *this;
   }
 
-  InlinedVector& operator=(InlinedVector&& v) {
-    if (this == &v) {
-      return *this;
-    }
-    if (v.allocated()) {
+  // Overload of `InlinedVector::operator=()` to replace the contents of the
+  // inlined vector with the contents of `other`.
+  //
+  // NOTE: As a result of calling this overload, `other` may be empty or it's
+  // contents may be left in a moved-from state.
+  InlinedVector& operator=(InlinedVector&& other) {
+    if (ABSL_PREDICT_FALSE(this == &other)) return *this;
+
+    if (other.allocated()) {
       clear();
-      tag().set_allocated_size(v.size());
-      init_allocation(v.allocation());
-      v.tag() = Tag();
+      tag().set_allocated_size(other.size());
+      init_allocation(other.allocation());
+      other.tag() = Tag();
     } else {
       if (allocated()) clear();
       // Both are inlined now.
-      if (size() < v.size()) {
-        auto mid = std::make_move_iterator(v.begin() + size());
-        std::copy(std::make_move_iterator(v.begin()), mid, begin());
-        UninitializedCopy(mid, std::make_move_iterator(v.end()), end());
+      if (size() < other.size()) {
+        auto mid = std::make_move_iterator(other.begin() + size());
+        std::copy(std::make_move_iterator(other.begin()), mid, begin());
+        UninitializedCopy(mid, std::make_move_iterator(other.end()), end());
       } else {
-        auto new_end = std::copy(std::make_move_iterator(v.begin()),
-                                 std::make_move_iterator(v.end()), begin());
+        auto new_end = std::copy(std::make_move_iterator(other.begin()),
+                                 std::make_move_iterator(other.end()), begin());
         Destroy(new_end, end());
       }
-      tag().set_inline_size(v.size());
+      tag().set_inline_size(other.size());
     }
     return *this;
   }
 
-  InlinedVector& operator=(std::initializer_list<value_type> init) {
-    AssignRange(init.begin(), init.end());
-    return *this;
-  }
-
-  // InlinedVector::assign()
+  // `InlinedVector::assign()`
   //
-  // Replaces the contents of the inlined vector with copies of those in the
-  // iterator range [first, last).
-  template <typename InputIterator>
-  void assign(
-      InputIterator first, InputIterator last,
-      typename std::enable_if<!std::is_integral<InputIterator>::value>::type* =
-          nullptr) {
-    AssignRange(first, last);
-  }
-
-  // Overload of `InlinedVector::assign()` to take values from elements of an
-  // initializer list
-  void assign(std::initializer_list<value_type> init) {
-    AssignRange(init.begin(), init.end());
-  }
-
-  // Overload of `InlinedVector::assign()` to replace the first `n` elements of
-  // the inlined vector with `elem` values.
-  void assign(size_type n, const value_type& elem) {
+  // Replaces the contents of the inlined vector with `n` copies of `v`.
+  void assign(size_type n, const_reference v) {
     if (n <= size()) {  // Possibly shrink
-      std::fill_n(begin(), n, elem);
+      std::fill_n(begin(), n, v);
       erase(begin() + n, end());
       return;
     }
     // Grow
     reserve(n);
-    std::fill_n(begin(), size(), elem);
+    std::fill_n(begin(), size(), v);
     if (allocated()) {
-      UninitializedFill(allocated_space() + size(), allocated_space() + n,
-                        elem);
+      UninitializedFill(allocated_space() + size(), allocated_space() + n, v);
       tag().set_allocated_size(n);
     } else {
-      UninitializedFill(inlined_space() + size(), inlined_space() + n, elem);
+      UninitializedFill(inlined_space() + size(), inlined_space() + n, v);
       tag().set_inline_size(n);
     }
   }
 
-  // InlinedVector::size()
-  //
-  // Returns the number of elements in the inlined vector.
-  size_type size() const noexcept { return tag().size(); }
-
-  // InlinedVector::empty()
-  //
-  // Checks if the inlined vector has no elements.
-  bool empty() const noexcept { return (size() == 0); }
-
-  // InlinedVector::capacity()
-  //
-  // Returns the number of elements that can be stored in an inlined vector
-  // without requiring a reallocation of underlying memory. Note that for
-  // most inlined vectors, `capacity()` should equal its initial size `N`; for
-  // inlined vectors which exceed this capacity, they will no longer be inlined,
-  // and `capacity()` will equal its capacity on the allocated heap.
-  size_type capacity() const noexcept {
-    return allocated() ? allocation().capacity() : N;
+  // Overload of `InlinedVector::assign()` to replace the contents of the
+  // inlined vector with copies of the values in the provided
+  // `std::initializer_list`.
+  void assign(std::initializer_list<value_type> list) {
+    AssignForwardRange(list.begin(), list.end());
   }
 
-  // InlinedVector::max_size()
-  //
-  // Returns the maximum number of elements the vector can hold.
-  size_type max_size() const noexcept {
-    // One bit of the size storage is used to indicate whether the inlined
-    // vector is allocated; as a result, the maximum size of the container that
-    // we can express is half of the max for our size type.
-    return std::numeric_limits<size_type>::max() / 2;
+  // Overload of `InlinedVector::assign()` to replace the contents of the
+  // inlined vector with the forward iterator range [`first`, `last`).
+  template <typename ForwardIterator,
+            EnableIfAtLeastForwardIterator<ForwardIterator>* = nullptr>
+  void assign(ForwardIterator first, ForwardIterator last) {
+    AssignForwardRange(first, last);
   }
 
-  // InlinedVector::data()
-  //
-  // Returns a const T* pointer to elements of the inlined vector. This pointer
-  // can be used to access (but not modify) the contained elements.
-  // Only results within the range `[0,size())` are defined.
-  const_pointer data() const noexcept {
-    return allocated() ? allocated_space() : inlined_space();
+  // Overload of `InlinedVector::assign()` to replace the contents of the
+  // inlined vector with the input iterator range [`first`, `last`).
+  template <typename InputIterator,
+            DisableIfAtLeastForwardIterator<InputIterator>* = nullptr>
+  void assign(InputIterator first, InputIterator last) {
+    size_type assign_index = 0;
+    for (; (assign_index < size()) && (first != last);
+         static_cast<void>(++assign_index), static_cast<void>(++first)) {
+      *(data() + assign_index) = *first;
+    }
+    erase(data() + assign_index, data() + size());
+    std::copy(first, last, std::back_inserter(*this));
   }
 
-  // Overload of InlinedVector::data() to return a T* pointer to elements of the
-  // inlined vector. This pointer can be used to access and modify the contained
-  // elements.
-  pointer data() noexcept {
-    return allocated() ? allocated_space() : inlined_space();
-  }
-
-  // InlinedVector::clear()
+  // `InlinedVector::resize()`
   //
-  // Removes all elements from the inlined vector.
-  void clear() noexcept {
+  // Resizes the inlined vector to contain `n` elements. If `n` is smaller than
+  // the inlined vector's current size, extra elements are destroyed. If `n` is
+  // larger than the initial size, new elements are value-initialized.
+  void resize(size_type n) {
     size_type s = size();
+    if (n < s) {
+      erase(begin() + n, end());
+      return;
+    }
+    reserve(n);
+    assert(capacity() >= n);
+
+    // Fill new space with elements constructed in-place.
     if (allocated()) {
-      Destroy(allocated_space(), allocated_space() + s);
-      allocation().Dealloc(allocator());
-    } else if (s != 0) {  // do nothing for empty vectors
-      Destroy(inlined_space(), inlined_space() + s);
+      UninitializedFill(allocated_space() + s, allocated_space() + n);
+      tag().set_allocated_size(n);
+    } else {
+      UninitializedFill(inlined_space() + s, inlined_space() + n);
+      tag().set_inline_size(n);
     }
-    tag() = Tag();
   }
 
-  // InlinedVector::at()
-  //
-  // Returns the ith element of an inlined vector.
-  const value_type& at(size_type i) const {
-    if (ABSL_PREDICT_FALSE(i >= size())) {
-      base_internal::ThrowStdOutOfRange(
-          "InlinedVector::at failed bounds check");
-    }
-    return data()[i];
-  }
-
-  // InlinedVector::operator[]
-  //
-  // Returns the ith element of an inlined vector using the array operator.
-  const value_type& operator[](size_type i) const {
-    assert(i < size());
-    return data()[i];
-  }
-
-  // Overload of InlinedVector::at() to return the ith element of an inlined
-  // vector.
-  value_type& at(size_type i) {
-    if (i >= size()) {
-      base_internal::ThrowStdOutOfRange(
-          "InlinedVector::at failed bounds check");
-    }
-    return data()[i];
-  }
-
-  // Overload of InlinedVector::operator[] to return the ith element of an
-  // inlined vector.
-  value_type& operator[](size_type i) {
-    assert(i < size());
-    return data()[i];
-  }
-
-  // InlinedVector::back()
-  //
-  // Returns a reference to the last element of an inlined vector.
-  value_type& back() {
-    assert(!empty());
-    return at(size() - 1);
-  }
-
-  // Overload of InlinedVector::back() returns a reference to the last element
-  // of an inlined vector of const values.
-  const value_type& back() const {
-    assert(!empty());
-    return at(size() - 1);
-  }
-
-  // InlinedVector::front()
-  //
-  // Returns a reference to the first element of an inlined vector.
-  value_type& front() {
-    assert(!empty());
-    return at(0);
-  }
-
-  // Overload of InlinedVector::front() returns a reference to the first element
-  // of an inlined vector of const values.
-  const value_type& front() const {
-    assert(!empty());
-    return at(0);
-  }
-
-  // InlinedVector::emplace_back()
-  //
-  // Constructs and appends an object to the inlined vector.
-  //
-  // Returns a reference to the inserted element.
-  template <typename... Args>
-  value_type& emplace_back(Args&&... args) {
+  // Overload of `InlinedVector::resize()` to resize the inlined vector to
+  // contain `n` elements where, if `n` is larger than `size()`, the new values
+  // will be copy-constructed from `v`.
+  void resize(size_type n, const_reference v) {
     size_type s = size();
-    assert(s <= capacity());
+    if (n < s) {
+      erase(begin() + n, end());
+      return;
+    }
+    reserve(n);
+    assert(capacity() >= n);
+
+    // Fill new space with copies of `v`.
+    if (allocated()) {
+      UninitializedFill(allocated_space() + s, allocated_space() + n, v);
+      tag().set_allocated_size(n);
+    } else {
+      UninitializedFill(inlined_space() + s, inlined_space() + n, v);
+      tag().set_inline_size(n);
+    }
+  }
+
+  // `InlinedVector::insert()`
+  //
+  // Copies `v` into `pos`, returning an `iterator` pointing to the newly
+  // inserted element.
+  iterator insert(const_iterator pos, const_reference v) {
+    return emplace(pos, v);
+  }
+
+  // Overload of `InlinedVector::insert()` for moving `v` into `pos`, returning
+  // an iterator pointing to the newly inserted element.
+  iterator insert(const_iterator pos, rvalue_reference v) {
+    return emplace(pos, std::move(v));
+  }
+
+  // Overload of `InlinedVector::insert()` for inserting `n` contiguous copies
+  // of `v` starting at `pos`. Returns an `iterator` pointing to the first of
+  // the newly inserted elements.
+  iterator insert(const_iterator pos, size_type n, const_reference v) {
+    return InsertWithCount(pos, n, v);
+  }
+
+  // Overload of `InlinedVector::insert()` for copying the contents of the
+  // `std::initializer_list` into the vector starting at `pos`. Returns an
+  // `iterator` pointing to the first of the newly inserted elements.
+  iterator insert(const_iterator pos, std::initializer_list<value_type> list) {
+    return insert(pos, list.begin(), list.end());
+  }
+
+  // Overload of `InlinedVector::insert()` for inserting elements constructed
+  // from the forward iterator range [`first`, `last`). Returns an `iterator`
+  // pointing to the first of the newly inserted elements.
+  //
+  // NOTE: The `enable_if` is intended to disambiguate the two three-argument
+  // overloads of `insert()`.
+  template <typename ForwardIterator,
+            EnableIfAtLeastForwardIterator<ForwardIterator>* = nullptr>
+  iterator insert(const_iterator pos, ForwardIterator first,
+                  ForwardIterator last) {
+    return InsertWithForwardRange(pos, first, last);
+  }
+
+  // Overload of `InlinedVector::insert()` for inserting elements constructed
+  // from the input iterator range [`first`, `last`). Returns an `iterator`
+  // pointing to the first of the newly inserted elements.
+  template <typename InputIterator,
+            DisableIfAtLeastForwardIterator<InputIterator>* = nullptr>
+  iterator insert(const_iterator pos, InputIterator first, InputIterator last) {
+    size_type initial_insert_index = std::distance(cbegin(), pos);
+    for (size_type insert_index = initial_insert_index; first != last;
+         static_cast<void>(++insert_index), static_cast<void>(++first)) {
+      insert(data() + insert_index, *first);
+    }
+    return iterator(data() + initial_insert_index);
+  }
+
+  // `InlinedVector::emplace()`
+  //
+  // Constructs and inserts an object in the inlined vector at the given `pos`,
+  // returning an `iterator` pointing to the newly emplaced element.
+  template <typename... Args>
+  iterator emplace(const_iterator pos, Args&&... args) {
+    assert(pos >= begin());
+    assert(pos <= end());
+    if (ABSL_PREDICT_FALSE(pos == end())) {
+      emplace_back(std::forward<Args>(args)...);
+      return end() - 1;
+    }
+
+    T new_t = T(std::forward<Args>(args)...);
+
+    auto range = ShiftRight(pos, 1);
+    if (range.first == range.second) {
+      // constructing into uninitialized memory
+      Construct(range.first, std::move(new_t));
+    } else {
+      // assigning into moved-from object
+      *range.first = T(std::move(new_t));
+    }
+
+    return range.first;
+  }
+
+  // `InlinedVector::emplace_back()`
+  //
+  // Constructs and appends a new element to the end of the inlined vector,
+  // returning a `reference` to the emplaced element.
+  template <typename... Args>
+  reference emplace_back(Args&&... args) {
+    size_type s = size();
     if (ABSL_PREDICT_FALSE(s == capacity())) {
       return GrowAndEmplaceBack(std::forward<Args>(args)...);
     }
-    assert(s < capacity());
-
-    value_type* space;
+    pointer space;
     if (allocated()) {
       tag().set_allocated_size(s + 1);
       space = allocated_space();
@@ -388,19 +698,22 @@
     return Construct(space + s, std::forward<Args>(args)...);
   }
 
-  // InlinedVector::push_back()
+  // `InlinedVector::push_back()`
   //
-  // Appends a const element to the inlined vector.
-  void push_back(const value_type& t) { emplace_back(t); }
+  // Appends a copy of `v` to the end of the inlined vector.
+  void push_back(const_reference v) { static_cast<void>(emplace_back(v)); }
 
-  // Overload of InlinedVector::push_back() to append a move-only element to the
-  // inlined vector.
-  void push_back(value_type&& t) { emplace_back(std::move(t)); }
+  // Overload of `InlinedVector::push_back()` for moving `v` into a newly
+  // appended element.
+  void push_back(rvalue_reference v) {
+    static_cast<void>(emplace_back(std::move(v)));
+  }
 
-  // InlinedVector::pop_back()
+  // `InlinedVector::pop_back()`
   //
-  // Removes the last element (which is destroyed) in the inlined vector.
-  void pop_back() {
+  // Destroys the element at the end of the inlined vector and shrinks the size
+  // by `1` (unless the inlined vector is empty, in which case this is a no-op).
+  void pop_back() noexcept {
     assert(!empty());
     size_type s = size();
     if (allocated()) {
@@ -412,161 +725,75 @@
     }
   }
 
-  // InlinedVector::resize()
+  // `InlinedVector::erase()`
   //
-  // Resizes the inlined vector to contain `n` elements. If `n` is smaller than
-  // the inlined vector's current size, extra elements are destroyed. If `n` is
-  // larger than the initial size, new elements are value-initialized.
-  void resize(size_type n);
-
-  // Overload of InlinedVector::resize() to resize the inlined vector to contain
-  // `n` elements. If `n` is larger than the current size, enough copies of
-  // `elem` are appended to increase its size to `n`.
-  void resize(size_type n, const value_type& elem);
-
-  // InlinedVector::begin()
+  // Erases the element at `pos` of the inlined vector, returning an `iterator`
+  // pointing to the first element following the erased element.
   //
-  // Returns an iterator to the beginning of the inlined vector.
-  iterator begin() noexcept { return data(); }
+  // NOTE: May return the end iterator, which is not dereferencable.
+  iterator erase(const_iterator pos) {
+    assert(pos >= begin());
+    assert(pos < end());
 
-  // Overload of InlinedVector::begin() for returning a const iterator to the
-  // beginning of the inlined vector.
-  const_iterator begin() const noexcept { return data(); }
-
-  // InlinedVector::cbegin()
-  //
-  // Returns a const iterator to the beginning of the inlined vector.
-  const_iterator cbegin() const noexcept { return begin(); }
-
-  // InlinedVector::end()
-  //
-  // Returns an iterator to the end of the inlined vector.
-  iterator end() noexcept { return data() + size(); }
-
-  // Overload of InlinedVector::end() for returning a const iterator to the end
-  // of the inlined vector.
-  const_iterator end() const noexcept { return data() + size(); }
-
-  // InlinedVector::cend()
-  //
-  // Returns a const iterator to the end of the inlined vector.
-  const_iterator cend() const noexcept { return end(); }
-
-  // InlinedVector::rbegin()
-  //
-  // Returns a reverse iterator from the end of the inlined vector.
-  reverse_iterator rbegin() noexcept { return reverse_iterator(end()); }
-
-  // Overload of InlinedVector::rbegin() for returning a const reverse iterator
-  // from the end of the inlined vector.
-  const_reverse_iterator rbegin() const noexcept {
-    return const_reverse_iterator(end());
-  }
-
-  // InlinedVector::crbegin()
-  //
-  // Returns a const reverse iterator from the end of the inlined vector.
-  const_reverse_iterator crbegin() const noexcept { return rbegin(); }
-
-  // InlinedVector::rend()
-  //
-  // Returns a reverse iterator from the beginning of the inlined vector.
-  reverse_iterator rend() noexcept { return reverse_iterator(begin()); }
-
-  // Overload of InlinedVector::rend() for returning a const reverse iterator
-  // from the beginning of the inlined vector.
-  const_reverse_iterator rend() const noexcept {
-    return const_reverse_iterator(begin());
-  }
-
-  // InlinedVector::crend()
-  //
-  // Returns a reverse iterator from the beginning of the inlined vector.
-  const_reverse_iterator crend() const noexcept { return rend(); }
-
-  // InlinedVector::emplace()
-  //
-  // Constructs and inserts an object to the inlined vector at the given
-  // `position`, returning an iterator pointing to the newly emplaced element.
-  template <typename... Args>
-  iterator emplace(const_iterator position, Args&&... args);
-
-  // InlinedVector::insert()
-  //
-  // Inserts an element of the specified value at `position`, returning an
-  // iterator pointing to the newly inserted element.
-  iterator insert(const_iterator position, const value_type& v) {
-    return emplace(position, v);
-  }
-
-  // Overload of InlinedVector::insert() for inserting an element of the
-  // specified rvalue, returning an iterator pointing to the newly inserted
-  // element.
-  iterator insert(const_iterator position, value_type&& v) {
-    return emplace(position, std::move(v));
-  }
-
-  // Overload of InlinedVector::insert() for inserting `n` elements of the
-  // specified value at `position`, returning an iterator pointing to the first
-  // of the newly inserted elements.
-  iterator insert(const_iterator position, size_type n, const value_type& v) {
-    return InsertWithCount(position, n, v);
-  }
-
-  // Overload of `InlinedVector::insert()` to disambiguate the two
-  // three-argument overloads of `insert()`, returning an iterator pointing to
-  // the first of the newly inserted elements.
-  template <typename InputIterator,
-            typename = typename std::enable_if<std::is_convertible<
-                typename std::iterator_traits<InputIterator>::iterator_category,
-                std::input_iterator_tag>::value>::type>
-  iterator insert(const_iterator position, InputIterator first,
-                  InputIterator last) {
-    using IterType =
-        typename std::iterator_traits<InputIterator>::iterator_category;
-    return InsertWithRange(position, first, last, IterType());
-  }
-
-  // Overload of InlinedVector::insert() for inserting a list of elements at
-  // `position`, returning an iterator pointing to the first of the newly
-  // inserted elements.
-  iterator insert(const_iterator position,
-                  std::initializer_list<value_type> init) {
-    return insert(position, init.begin(), init.end());
-  }
-
-  // InlinedVector::erase()
-  //
-  // Erases the element at `position` of the inlined vector, returning an
-  // iterator pointing to the following element or the container's end if the
-  // last element was erased.
-  iterator erase(const_iterator position) {
-    assert(position >= begin());
-    assert(position < end());
-
-    iterator pos = const_cast<iterator>(position);
-    std::move(pos + 1, end(), pos);
+    iterator position = const_cast<iterator>(pos);
+    std::move(position + 1, end(), position);
     pop_back();
-    return pos;
+    return position;
   }
 
-  // Overload of InlinedVector::erase() for erasing all elements in the
-  // iterator range [first, last) in the inlined vector, returning an iterator
-  // pointing to the first element following the range erased, or the
-  // container's end if range included the container's last element.
-  iterator erase(const_iterator first, const_iterator last);
+  // Overload of `InlinedVector::erase()` for erasing all elements in the
+  // range [`from`, `to`) in the inlined vector. Returns an `iterator` pointing
+  // to the first element following the range erased or the end iterator if `to`
+  // was the end iterator.
+  iterator erase(const_iterator from, const_iterator to) {
+    assert(begin() <= from);
+    assert(from <= to);
+    assert(to <= end());
 
-  // InlinedVector::reserve()
+    iterator range_start = const_cast<iterator>(from);
+    iterator range_end = const_cast<iterator>(to);
+
+    size_type s = size();
+    ptrdiff_t erase_gap = std::distance(range_start, range_end);
+    if (erase_gap > 0) {
+      pointer space;
+      if (allocated()) {
+        space = allocated_space();
+        tag().set_allocated_size(s - erase_gap);
+      } else {
+        space = inlined_space();
+        tag().set_inline_size(s - erase_gap);
+      }
+      std::move(range_end, space + s, range_start);
+      Destroy(space + s - erase_gap, space + s);
+    }
+    return range_start;
+  }
+
+  // `InlinedVector::clear()`
+  //
+  // Destroys all elements in the inlined vector, sets the size of `0` and
+  // deallocates the heap allocation if the inlined vector was allocated.
+  void clear() noexcept {
+    size_type s = size();
+    if (allocated()) {
+      Destroy(allocated_space(), allocated_space() + s);
+      allocation().Dealloc(allocator());
+    } else if (s != 0) {  // do nothing for empty vectors
+      Destroy(inlined_space(), inlined_space() + s);
+    }
+    tag() = Tag();
+  }
+
+  // `InlinedVector::reserve()`
   //
   // Enlarges the underlying representation of the inlined vector so it can hold
   // at least `n` elements. This method does not change `size()` or the actual
   // contents of the vector.
   //
-  // Note that if `n` does not exceed the inlined vector's initial size `N`,
-  // `reserve()` will have no effect; if it does exceed its initial size,
-  // `reserve()` will trigger an initial allocation and move the inlined vector
-  // onto the heap. If the vector already exists on the heap and the requested
-  // size exceeds it, a reallocation will be performed.
+  // NOTE: If `n` does not exceed `capacity()`, `reserve()` will have no
+  // effects. Otherwise, `reserve()` will reallocate, performing an n-time
+  // element-wise move of everything contained.
   void reserve(size_type n) {
     if (n > capacity()) {
       // Make room for new elements
@@ -574,26 +801,25 @@
     }
   }
 
-  // InlinedVector::shrink_to_fit()
+  // `InlinedVector::shrink_to_fit()`
   //
-  // Reduces memory usage by freeing unused memory.
-  // After this call `capacity()` will be equal to `max(N, size())`.
+  // Reduces memory usage by freeing unused memory. After this call, calls to
+  // `capacity()` will be equal to `max(N, size())`.
   //
   // If `size() <= N` and the elements are currently stored on the heap, they
-  // will be moved to the inlined storage and the heap memory deallocated.
-  // If `size() > N` and `size() < capacity()` the elements will be moved to
-  // a reallocated storage on heap.
+  // will be moved to the inlined storage and the heap memory will be
+  // deallocated.
+  //
+  // If `size() > N` and `size() < capacity()` the elements will be moved to a
+  // smaller heap allocation.
   void shrink_to_fit() {
     const auto s = size();
-    if (!allocated() || s == capacity()) {
-      // There's nothing to deallocate.
-      return;
-    }
+    if (ABSL_PREDICT_FALSE(!allocated() || s == capacity())) return;
 
     if (s <= N) {
       // Move the elements to the inlined storage.
-      // We have to do this using a temporary, because inlined_storage and
-      // allocation_storage are in a union field.
+      // We have to do this using a temporary, because `inlined_storage` and
+      // `allocation_storage` are in a union field.
       auto temp = std::move(*this);
       assign(std::make_move_iterator(temp.begin()),
              std::make_move_iterator(temp.end()));
@@ -601,8 +827,8 @@
     }
 
     // Reallocate storage and move elements.
-    // We can't simply use the same approach as above, because assign() would
-    // call into reserve() internally and reserve larger capacity than we need.
+    // We can't simply use the same approach as above, because `assign()` would
+    // call into `reserve()` internally and reserve larger capacity than we need
     Allocation new_allocation(allocator(), s);
     UninitializedCopy(std::make_move_iterator(allocated_space()),
                       std::make_move_iterator(allocated_space() + s),
@@ -610,129 +836,62 @@
     ResetAllocation(new_allocation, s);
   }
 
-  // InlinedVector::swap()
+  // `InlinedVector::swap()`
   //
   // Swaps the contents of this inlined vector with the contents of `other`.
-  void swap(InlinedVector& other);
+  void swap(InlinedVector& other) {
+    if (ABSL_PREDICT_FALSE(this == &other)) return;
 
-  // InlinedVector::get_allocator()
-  //
-  // Returns the allocator of this inlined vector.
-  allocator_type get_allocator() const { return allocator(); }
-
-  template <typename H>
-  friend H AbslHashValue(H h, const InlinedVector& v) {
-    return H::combine(H::combine_contiguous(std::move(h), v.data(), v.size()),
-                      v.size());
+    SwapImpl(other);
   }
 
  private:
-  static_assert(N > 0, "inlined vector with nonpositive size");
+  template <typename H, typename TheT, size_t TheN, typename TheA>
+  friend auto AbslHashValue(H h, const InlinedVector<TheT, TheN, TheA>& v) -> H;
 
-  // 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_ / 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; }
+  const Tag& tag() const { return storage_.allocator_and_tag_.tag(); }
 
-   private:
-    size_type size_;
-  };
-
-  // Derives from allocator_type to use the empty base class optimization.
-  // If the allocator_type is stateless, we can 'store'
-  // our instance of it for free.
-  class AllocatorAndTag : private allocator_type {
-   public:
-    explicit AllocatorAndTag(const allocator_type& a) : allocator_type(a) {}
-    Tag& tag() { return tag_; }
-    const Tag& tag() const { return tag_; }
-    allocator_type& allocator() { return *this; }
-    const allocator_type& allocator() const { return *this; }
-
-   private:
-    Tag tag_;
-  };
-
-  class Allocation {
-   public:
-    Allocation(allocator_type& a,  // NOLINT(runtime/references)
-               size_type capacity)
-        : capacity_(capacity),
-          buffer_(AllocatorTraits::allocate(a, capacity_)) {}
-
-    void Dealloc(allocator_type& a) {  // NOLINT(runtime/references)
-      AllocatorTraits::deallocate(a, buffer(), capacity());
-    }
-
-    size_type capacity() const { return capacity_; }
-    const value_type* buffer() const { return buffer_; }
-    value_type* buffer() { return buffer_; }
-
-   private:
-    size_type capacity_;
-    value_type* buffer_;
-  };
-
-  const Tag& tag() const { return allocator_and_tag_.tag(); }
-  Tag& tag() { return allocator_and_tag_.tag(); }
+  Tag& tag() { return storage_.allocator_and_tag_.tag(); }
 
   Allocation& allocation() {
-    return reinterpret_cast<Allocation&>(rep_.allocation_storage.allocation);
+    return reinterpret_cast<Allocation&>(
+        storage_.rep_.allocation_storage.allocation);
   }
+
   const Allocation& allocation() const {
     return reinterpret_cast<const Allocation&>(
-        rep_.allocation_storage.allocation);
+        storage_.rep_.allocation_storage.allocation);
   }
+
   void init_allocation(const Allocation& allocation) {
-    new (&rep_.allocation_storage.allocation) Allocation(allocation);
+    new (&storage_.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*>(
-        std::addressof(rep_.inlined_storage.inlined[0]));
-  }
-  const value_type* inlined_space() const {
-    return reinterpret_cast<const value_type*>(
-        std::addressof(rep_.inlined_storage.inlined[0]));
+  pointer inlined_space() {
+    return reinterpret_cast<pointer>(
+        std::addressof(storage_.rep_.inlined_storage.inlined[0]));
   }
 
-  value_type* allocated_space() { return allocation().buffer(); }
-  const value_type* allocated_space() const { return allocation().buffer(); }
+  const_pointer inlined_space() const {
+    return reinterpret_cast<const_pointer>(
+        std::addressof(storage_.rep_.inlined_storage.inlined[0]));
+  }
+
+  pointer allocated_space() { return allocation().buffer(); }
+
+  const_pointer allocated_space() const { return allocation().buffer(); }
 
   const allocator_type& allocator() const {
-    return allocator_and_tag_.allocator();
+    return storage_.allocator_and_tag_.allocator();
   }
-  allocator_type& allocator() { return allocator_and_tag_.allocator(); }
+
+  allocator_type& allocator() {
+    return storage_.allocator_and_tag_.allocator();
+  }
 
   bool allocated() const { return tag().allocated(); }
 
-  // Enlarge the underlying representation so we can store size_ + delta elems.
-  // The size is not changed, and any newly added memory is not initialized.
-  void EnlargeBy(size_type delta);
-
-  // Shift all elements from position to end() n places to the right.
-  // If the vector needs to be enlarged, memory will be allocated.
-  // Returns iterators pointing to the start of the previously-initialized
-  // portion and the start of the uninitialized portion of the created gap.
-  // The number of initialized spots is pair.second - pair.first;
-  // the number of raw spots is n - (pair.second - pair.first).
-  //
-  // Updates the size of the InlinedVector internally.
-  std::pair<iterator, iterator> ShiftRight(const_iterator position,
-                                           size_type n);
-
   void ResetAllocation(Allocation new_allocation, size_type new_size) {
     if (allocated()) {
       Destroy(allocated_space(), allocated_space() + size());
@@ -747,13 +906,137 @@
   }
 
   template <typename... Args>
-  value_type& GrowAndEmplaceBack(Args&&... args) {
+  reference Construct(pointer p, Args&&... args) {
+    std::allocator_traits<allocator_type>::construct(
+        allocator(), p, std::forward<Args>(args)...);
+    return *p;
+  }
+
+  template <typename Iterator>
+  void UninitializedCopy(Iterator src, Iterator src_last, pointer dst) {
+    for (; src != src_last; ++dst, ++src) Construct(dst, *src);
+  }
+
+  template <typename... Args>
+  void UninitializedFill(pointer dst, pointer dst_last, const Args&... args) {
+    for (; dst != dst_last; ++dst) Construct(dst, args...);
+  }
+
+  // Destroy [`from`, `to`) in place.
+  void Destroy(pointer from, pointer to) {
+    for (pointer cur = from; cur != to; ++cur) {
+      std::allocator_traits<allocator_type>::destroy(allocator(), cur);
+    }
+#if !defined(NDEBUG)
+    // Overwrite unused memory with `0xab` so we can catch uninitialized usage.
+    // Cast to `void*` to tell the compiler that we don't care that we might be
+    // scribbling on a vtable pointer.
+    if (from != to) {
+      auto len = sizeof(value_type) * std::distance(from, to);
+      std::memset(reinterpret_cast<void*>(from), 0xab, len);
+    }
+#endif  // !defined(NDEBUG)
+  }
+
+  // Enlarge the underlying representation so we can store `size_ + delta` elems
+  // in allocated space. The size is not changed, and any newly added memory is
+  // not initialized.
+  void EnlargeBy(size_type delta) {
+    const size_type s = size();
+    assert(s <= capacity());
+
+    size_type target = (std::max)(N, s + delta);
+
+    // Compute new capacity by repeatedly doubling current capacity
+    // TODO(psrc): Check and avoid overflow?
+    size_type new_capacity = capacity();
+    while (new_capacity < target) {
+      new_capacity <<= 1;
+    }
+
+    Allocation new_allocation(allocator(), new_capacity);
+
+    UninitializedCopy(std::make_move_iterator(data()),
+                      std::make_move_iterator(data() + s),
+                      new_allocation.buffer());
+
+    ResetAllocation(new_allocation, s);
+  }
+
+  // Shift all elements from `position` to `end()` by `n` places to the right.
+  // If the vector needs to be enlarged, memory will be allocated.
+  // Returns `iterator`s pointing to the start of the previously-initialized
+  // portion and the start of the uninitialized portion of the created gap.
+  // The number of initialized spots is `pair.second - pair.first`. The number
+  // of raw spots is `n - (pair.second - pair.first)`.
+  //
+  // Updates the size of the InlinedVector internally.
+  std::pair<iterator, iterator> ShiftRight(const_iterator position,
+                                           size_type n) {
+    iterator start_used = const_cast<iterator>(position);
+    iterator start_raw = const_cast<iterator>(position);
+    size_type s = size();
+    size_type required_size = s + n;
+
+    if (required_size > capacity()) {
+      // Compute new capacity by repeatedly doubling current capacity
+      size_type new_capacity = capacity();
+      while (new_capacity < required_size) {
+        new_capacity <<= 1;
+      }
+      // Move everyone into the new allocation, leaving a gap of `n` for the
+      // requested shift.
+      Allocation new_allocation(allocator(), new_capacity);
+      size_type index = position - begin();
+      UninitializedCopy(std::make_move_iterator(data()),
+                        std::make_move_iterator(data() + index),
+                        new_allocation.buffer());
+      UninitializedCopy(std::make_move_iterator(data() + index),
+                        std::make_move_iterator(data() + s),
+                        new_allocation.buffer() + index + n);
+      ResetAllocation(new_allocation, s);
+
+      // New allocation means our iterator is invalid, so we'll recalculate.
+      // Since the entire gap is in new space, there's no used space to reuse.
+      start_raw = begin() + index;
+      start_used = start_raw;
+    } else {
+      // If we had enough space, it's a two-part move. Elements going into
+      // previously-unoccupied space need an `UninitializedCopy()`. Elements
+      // going into a previously-occupied space are just a `std::move()`.
+      iterator pos = const_cast<iterator>(position);
+      iterator raw_space = end();
+      size_type slots_in_used_space = raw_space - pos;
+      size_type new_elements_in_used_space = (std::min)(n, slots_in_used_space);
+      size_type new_elements_in_raw_space = n - new_elements_in_used_space;
+      size_type old_elements_in_used_space =
+          slots_in_used_space - new_elements_in_used_space;
+
+      UninitializedCopy(
+          std::make_move_iterator(pos + old_elements_in_used_space),
+          std::make_move_iterator(raw_space),
+          raw_space + new_elements_in_raw_space);
+      std::move_backward(pos, pos + old_elements_in_used_space, raw_space);
+
+      // If the gap is entirely in raw space, the used space starts where the
+      // raw space starts, leaving no elements in used space. If the gap is
+      // entirely in used space, the raw space starts at the end of the gap,
+      // leaving all elements accounted for within the used space.
+      start_used = pos;
+      start_raw = pos + new_elements_in_used_space;
+    }
+    tag().add_size(n);
+    return std::make_pair(start_used, start_raw);
+  }
+
+  template <typename... Args>
+  reference GrowAndEmplaceBack(Args&&... args) {
     assert(size() == capacity());
     const size_type s = size();
 
     Allocation new_allocation(allocator(), 2 * capacity());
 
-    value_type& new_element =
+    reference new_element =
         Construct(new_allocation.buffer() + s, std::forward<Args>(args)...);
     UninitializedCopy(std::make_move_iterator(data()),
                       std::make_move_iterator(data() + s),
@@ -764,628 +1047,268 @@
     return new_element;
   }
 
-  void InitAssign(size_type n);
-  void InitAssign(size_type n, const value_type& t);
-
-  template <typename... Args>
-  value_type& Construct(pointer p, Args&&... args) {
-    AllocatorTraits::construct(allocator(), p, std::forward<Args>(args)...);
-    return *p;
+  void InitAssign(size_type n) {
+    if (n > N) {
+      Allocation new_allocation(allocator(), n);
+      init_allocation(new_allocation);
+      UninitializedFill(allocated_space(), allocated_space() + n);
+      tag().set_allocated_size(n);
+    } else {
+      UninitializedFill(inlined_space(), inlined_space() + n);
+      tag().set_inline_size(n);
+    }
   }
 
-  template <typename Iter>
-  void UninitializedCopy(Iter src, Iter src_last, value_type* dst) {
-    for (; src != src_last; ++dst, ++src) Construct(dst, *src);
+  void InitAssign(size_type n, const_reference v) {
+    if (n > N) {
+      Allocation new_allocation(allocator(), n);
+      init_allocation(new_allocation);
+      UninitializedFill(allocated_space(), allocated_space() + n, v);
+      tag().set_allocated_size(n);
+    } else {
+      UninitializedFill(inlined_space(), inlined_space() + n, v);
+      tag().set_inline_size(n);
+    }
   }
 
-  template <typename... Args>
-  void UninitializedFill(value_type* dst, value_type* dst_last,
-                         const Args&... args) {
-    for (; dst != dst_last; ++dst) Construct(dst, args...);
+  template <typename ForwardIt>
+  void AssignForwardRange(ForwardIt first, ForwardIt last) {
+    static_assert(IsAtLeastForwardIterator<ForwardIt>::value, "");
+
+    auto length = std::distance(first, last);
+
+    // Prefer reassignment to copy construction for elements.
+    if (static_cast<size_type>(length) <= size()) {
+      erase(std::copy(first, last, begin()), end());
+      return;
+    }
+
+    reserve(length);
+    iterator out = begin();
+    for (; out != end(); ++first, ++out) *out = *first;
+    if (allocated()) {
+      UninitializedCopy(first, last, out);
+      tag().set_allocated_size(length);
+    } else {
+      UninitializedCopy(first, last, out);
+      tag().set_inline_size(length);
+    }
   }
 
-  // Destroy [ptr, ptr_last) in place.
-  void Destroy(value_type* ptr, value_type* ptr_last);
+  template <typename ForwardIt>
+  void AppendForwardRange(ForwardIt first, ForwardIt last) {
+    static_assert(IsAtLeastForwardIterator<ForwardIt>::value, "");
 
-  template <typename Iter>
-  void AppendRange(Iter first, Iter last, std::input_iterator_tag) {
-    std::copy(first, last, std::back_inserter(*this));
-  }
-
-  // Faster path for forward iterators.
-  template <typename Iter>
-  void AppendRange(Iter first, Iter last, std::forward_iterator_tag);
-
-  template <typename Iter>
-  void AppendRange(Iter first, Iter last) {
-    using IterTag = typename std::iterator_traits<Iter>::iterator_category;
-    AppendRange(first, last, IterTag());
-  }
-
-  template <typename Iter>
-  void AssignRange(Iter first, Iter last, std::input_iterator_tag);
-
-  // Faster path for forward iterators.
-  template <typename Iter>
-  void AssignRange(Iter first, Iter last, std::forward_iterator_tag);
-
-  template <typename Iter>
-  void AssignRange(Iter first, Iter last) {
-    using IterTag = typename std::iterator_traits<Iter>::iterator_category;
-    AssignRange(first, last, IterTag());
+    auto length = std::distance(first, last);
+    reserve(size() + length);
+    if (allocated()) {
+      UninitializedCopy(first, last, allocated_space() + size());
+      tag().set_allocated_size(size() + length);
+    } else {
+      UninitializedCopy(first, last, inlined_space() + size());
+      tag().set_inline_size(size() + length);
+    }
   }
 
   iterator InsertWithCount(const_iterator position, size_type n,
-                           const value_type& v);
+                           const_reference v) {
+    assert(position >= begin() && position <= end());
+    if (ABSL_PREDICT_FALSE(n == 0)) return const_cast<iterator>(position);
 
-  template <typename InputIter>
-  iterator InsertWithRange(const_iterator position, InputIter first,
-                           InputIter last, std::input_iterator_tag);
-  template <typename ForwardIter>
-  iterator InsertWithRange(const_iterator position, ForwardIter first,
-                           ForwardIter last, std::forward_iterator_tag);
+    value_type copy = v;
+    std::pair<iterator, iterator> it_pair = ShiftRight(position, n);
+    std::fill(it_pair.first, it_pair.second, copy);
+    UninitializedFill(it_pair.second, it_pair.first + n, copy);
 
-  AllocatorAndTag allocator_and_tag_;
+    return it_pair.first;
+  }
 
-  // Either the inlined or allocated representation
-  union Rep {
-    // Use struct to perform indirection that solves a bizarre compilation
-    // error on Visual Studio (all known versions).
-    struct {
-      typename std::aligned_storage<sizeof(value_type),
-                                    alignof(value_type)>::type inlined[N];
-    } inlined_storage;
-    struct {
-      typename std::aligned_storage<sizeof(Allocation),
-                                    alignof(Allocation)>::type allocation;
-    } allocation_storage;
-  } rep_;
+  template <typename ForwardIt>
+  iterator InsertWithForwardRange(const_iterator position, ForwardIt first,
+                                  ForwardIt last) {
+    static_assert(IsAtLeastForwardIterator<ForwardIt>::value, "");
+    assert(position >= begin() && position <= end());
+
+    if (ABSL_PREDICT_FALSE(first == last))
+      return const_cast<iterator>(position);
+
+    auto n = std::distance(first, last);
+    std::pair<iterator, iterator> it_pair = ShiftRight(position, n);
+    size_type used_spots = it_pair.second - it_pair.first;
+    auto open_spot = std::next(first, used_spots);
+    std::copy(first, open_spot, it_pair.first);
+    UninitializedCopy(open_spot, last, it_pair.second);
+    return it_pair.first;
+  }
+
+  void SwapImpl(InlinedVector& other) {
+    using std::swap;  // Augment ADL with `std::swap`.
+
+    if (allocated() && other.allocated()) {
+      // Both out of line, so just swap the tag, allocation, and allocator.
+      swap(tag(), other.tag());
+      swap(allocation(), other.allocation());
+      swap(allocator(), other.allocator());
+      return;
+    }
+    if (!allocated() && !other.allocated()) {
+      // Both inlined: swap up to smaller size, then move remaining elements.
+      InlinedVector* a = this;
+      InlinedVector* b = &other;
+      if (size() < other.size()) {
+        swap(a, b);
+      }
+
+      const size_type a_size = a->size();
+      const size_type b_size = b->size();
+      assert(a_size >= b_size);
+      // `a` is larger. Swap the elements up to the smaller array size.
+      std::swap_ranges(a->inlined_space(), a->inlined_space() + b_size,
+                       b->inlined_space());
+
+      // Move the remaining elements:
+      //   [`b_size`, `a_size`) from `a` -> [`b_size`, `a_size`) from `b`
+      b->UninitializedCopy(a->inlined_space() + b_size,
+                           a->inlined_space() + a_size,
+                           b->inlined_space() + b_size);
+      a->Destroy(a->inlined_space() + b_size, a->inlined_space() + a_size);
+
+      swap(a->tag(), b->tag());
+      swap(a->allocator(), b->allocator());
+      assert(b->size() == a_size);
+      assert(a->size() == b_size);
+      return;
+    }
+
+    // One is out of line, one is inline.
+    // We first move the elements from the inlined vector into the
+    // inlined space in the other vector.  We then put the other vector's
+    // pointer/capacity into the originally inlined vector and swap
+    // the tags.
+    InlinedVector* a = this;
+    InlinedVector* b = &other;
+    if (a->allocated()) {
+      swap(a, b);
+    }
+    assert(!a->allocated());
+    assert(b->allocated());
+    const size_type a_size = a->size();
+    const size_type b_size = b->size();
+    // In an optimized build, `b_size` would be unused.
+    static_cast<void>(b_size);
+
+    // Made Local copies of `size()`, don't need `tag()` accurate anymore
+    swap(a->tag(), b->tag());
+
+    // Copy `b_allocation` out before `b`'s union gets clobbered by
+    // `inline_space`
+    Allocation b_allocation = b->allocation();
+
+    b->UninitializedCopy(a->inlined_space(), a->inlined_space() + a_size,
+                         b->inlined_space());
+    a->Destroy(a->inlined_space(), a->inlined_space() + a_size);
+
+    a->allocation() = b_allocation;
+
+    if (a->allocator() != b->allocator()) {
+      swap(a->allocator(), b->allocator());
+    }
+
+    assert(b->size() == a_size);
+    assert(a->size() == b_size);
+  }
+
+  Storage storage_;
 };
 
 // -----------------------------------------------------------------------------
 // InlinedVector Non-Member Functions
 // -----------------------------------------------------------------------------
 
-// swap()
+// `swap()`
 //
 // Swaps the contents of two inlined vectors. This convenience function
-// simply calls InlinedVector::swap(other_inlined_vector).
+// simply calls `InlinedVector::swap()`.
 template <typename T, size_t N, typename A>
-void swap(InlinedVector<T, N, A>& a,
-          InlinedVector<T, N, A>& b) noexcept(noexcept(a.swap(b))) {
+auto swap(InlinedVector<T, N, A>& a,
+          InlinedVector<T, N, A>& b) noexcept(noexcept(a.swap(b))) -> void {
   a.swap(b);
 }
 
-// operator==()
+// `operator==()`
 //
 // Tests the equivalency of the contents of two inlined vectors.
 template <typename T, size_t N, typename A>
-bool operator==(const InlinedVector<T, N, A>& a,
-                const InlinedVector<T, N, A>& b) {
+auto operator==(const InlinedVector<T, N, A>& a,
+                const InlinedVector<T, N, A>& b) -> bool {
   return absl::equal(a.begin(), a.end(), b.begin(), b.end());
 }
 
-// operator!=()
+// `operator!=()`
 //
 // Tests the inequality of the contents of two inlined vectors.
 template <typename T, size_t N, typename A>
-bool operator!=(const InlinedVector<T, N, A>& a,
-                const InlinedVector<T, N, A>& b) {
+auto operator!=(const InlinedVector<T, N, A>& a,
+                const InlinedVector<T, N, A>& b) -> bool {
   return !(a == b);
 }
 
-// operator<()
+// `operator<()`
 //
 // Tests whether the contents of one inlined vector are less than the contents
 // of another through a lexicographical comparison operation.
 template <typename T, size_t N, typename A>
-bool operator<(const InlinedVector<T, N, A>& a,
-               const InlinedVector<T, N, A>& b) {
+auto operator<(const InlinedVector<T, N, A>& a, const InlinedVector<T, N, A>& b)
+    -> bool {
   return std::lexicographical_compare(a.begin(), a.end(), b.begin(), b.end());
 }
 
-// operator>()
+// `operator>()`
 //
 // Tests whether the contents of one inlined vector are greater than the
 // contents of another through a lexicographical comparison operation.
 template <typename T, size_t N, typename A>
-bool operator>(const InlinedVector<T, N, A>& a,
-               const InlinedVector<T, N, A>& b) {
+auto operator>(const InlinedVector<T, N, A>& a, const InlinedVector<T, N, A>& b)
+    -> bool {
   return b < a;
 }
 
-// operator<=()
+// `operator<=()`
 //
 // Tests whether the contents of one inlined vector are less than or equal to
 // the contents of another through a lexicographical comparison operation.
 template <typename T, size_t N, typename A>
-bool operator<=(const InlinedVector<T, N, A>& a,
-                const InlinedVector<T, N, A>& b) {
+auto operator<=(const InlinedVector<T, N, A>& a,
+                const InlinedVector<T, N, A>& b) -> bool {
   return !(b < a);
 }
 
-// operator>=()
+// `operator>=()`
 //
 // Tests whether the contents of one inlined vector are greater than or equal to
 // the contents of another through a lexicographical comparison operation.
 template <typename T, size_t N, typename A>
-bool operator>=(const InlinedVector<T, N, A>& a,
-                const InlinedVector<T, N, A>& b) {
+auto operator>=(const InlinedVector<T, N, A>& a,
+                const InlinedVector<T, N, A>& b) -> bool {
   return !(a < b);
 }
 
+// AbslHashValue()
+//
+// Provides `absl::Hash` support for inlined vectors. You do not normally call
+// this function directly.
+template <typename H, typename TheT, size_t TheN, typename TheA>
+auto AbslHashValue(H h, const InlinedVector<TheT, TheN, TheA>& v) -> H {
+  auto p = v.data();
+  auto n = v.size();
+  return H::combine(H::combine_contiguous(std::move(h), p, n), n);
+}
+}  // namespace absl
+
 // -----------------------------------------------------------------------------
 // Implementation of InlinedVector
-// -----------------------------------------------------------------------------
 //
-// Do not depend on any implementation details below this line.
-
-template <typename T, size_t N, typename A>
-InlinedVector<T, N, A>::InlinedVector(const InlinedVector& v)
-    : allocator_and_tag_(v.allocator()) {
-  reserve(v.size());
-  if (allocated()) {
-    UninitializedCopy(v.begin(), v.end(), allocated_space());
-    tag().set_allocated_size(v.size());
-  } else {
-    UninitializedCopy(v.begin(), v.end(), inlined_space());
-    tag().set_inline_size(v.size());
-  }
-}
-
-template <typename T, size_t N, typename A>
-InlinedVector<T, N, A>::InlinedVector(const InlinedVector& v,
-                                      const allocator_type& alloc)
-    : allocator_and_tag_(alloc) {
-  reserve(v.size());
-  if (allocated()) {
-    UninitializedCopy(v.begin(), v.end(), allocated_space());
-    tag().set_allocated_size(v.size());
-  } else {
-    UninitializedCopy(v.begin(), v.end(), inlined_space());
-    tag().set_inline_size(v.size());
-  }
-}
-
-template <typename T, size_t N, typename A>
-InlinedVector<T, N, A>::InlinedVector(InlinedVector&& v) noexcept(
-    absl::allocator_is_nothrow<allocator_type>::value ||
-    std::is_nothrow_move_constructible<value_type>::value)
-    : allocator_and_tag_(v.allocator_and_tag_) {
-  if (v.allocated()) {
-    // We can just steal the underlying buffer from the source.
-    // That leaves the source empty, so we clear its size.
-    init_allocation(v.allocation());
-    v.tag() = Tag();
-  } else {
-    UninitializedCopy(std::make_move_iterator(v.inlined_space()),
-                      std::make_move_iterator(v.inlined_space() + v.size()),
-                      inlined_space());
-  }
-}
-
-template <typename T, size_t N, typename A>
-InlinedVector<T, N, A>::InlinedVector(
-    InlinedVector&& v,
-    const allocator_type&
-        alloc) noexcept(absl::allocator_is_nothrow<allocator_type>::value)
-    : allocator_and_tag_(alloc) {
-  if (v.allocated()) {
-    if (alloc == v.allocator()) {
-      // We can just steal the allocation from the source.
-      tag() = v.tag();
-      init_allocation(v.allocation());
-      v.tag() = Tag();
-    } else {
-      // We need to use our own allocator
-      reserve(v.size());
-      UninitializedCopy(std::make_move_iterator(v.begin()),
-                        std::make_move_iterator(v.end()), allocated_space());
-      tag().set_allocated_size(v.size());
-    }
-  } else {
-    UninitializedCopy(std::make_move_iterator(v.inlined_space()),
-                      std::make_move_iterator(v.inlined_space() + v.size()),
-                      inlined_space());
-    tag().set_inline_size(v.size());
-  }
-}
-
-template <typename T, size_t N, typename A>
-void InlinedVector<T, N, A>::InitAssign(size_type n, const value_type& t) {
-  if (n > static_cast<size_type>(N)) {
-    Allocation new_allocation(allocator(), n);
-    init_allocation(new_allocation);
-    UninitializedFill(allocated_space(), allocated_space() + n, t);
-    tag().set_allocated_size(n);
-  } else {
-    UninitializedFill(inlined_space(), inlined_space() + n, t);
-    tag().set_inline_size(n);
-  }
-}
-
-template <typename T, size_t N, typename A>
-void InlinedVector<T, N, A>::InitAssign(size_type n) {
-  if (n > static_cast<size_type>(N)) {
-    Allocation new_allocation(allocator(), n);
-    init_allocation(new_allocation);
-    UninitializedFill(allocated_space(), allocated_space() + n);
-    tag().set_allocated_size(n);
-  } else {
-    UninitializedFill(inlined_space(), inlined_space() + n);
-    tag().set_inline_size(n);
-  }
-}
-
-template <typename T, size_t N, typename A>
-void InlinedVector<T, N, A>::resize(size_type n) {
-  size_type s = size();
-  if (n < s) {
-    erase(begin() + n, end());
-    return;
-  }
-  reserve(n);
-  assert(capacity() >= n);
-
-  // Fill new space with elements constructed in-place.
-  if (allocated()) {
-    UninitializedFill(allocated_space() + s, allocated_space() + n);
-    tag().set_allocated_size(n);
-  } else {
-    UninitializedFill(inlined_space() + s, inlined_space() + n);
-    tag().set_inline_size(n);
-  }
-}
-
-template <typename T, size_t N, typename A>
-void InlinedVector<T, N, A>::resize(size_type n, const value_type& elem) {
-  size_type s = size();
-  if (n < s) {
-    erase(begin() + n, end());
-    return;
-  }
-  reserve(n);
-  assert(capacity() >= n);
-
-  // Fill new space with copies of 'elem'.
-  if (allocated()) {
-    UninitializedFill(allocated_space() + s, allocated_space() + n, elem);
-    tag().set_allocated_size(n);
-  } else {
-    UninitializedFill(inlined_space() + s, inlined_space() + n, elem);
-    tag().set_inline_size(n);
-  }
-}
-
-template <typename T, size_t N, typename A>
-template <typename... Args>
-typename InlinedVector<T, N, A>::iterator InlinedVector<T, N, A>::emplace(
-    const_iterator position, Args&&... args) {
-  assert(position >= begin());
-  assert(position <= end());
-  if (position == end()) {
-    emplace_back(std::forward<Args>(args)...);
-    return end() - 1;
-  }
-
-  T new_t = T(std::forward<Args>(args)...);
-
-  auto range = ShiftRight(position, 1);
-  if (range.first == range.second) {
-    // constructing into uninitialized memory
-    Construct(range.first, std::move(new_t));
-  } else {
-    // assigning into moved-from object
-    *range.first = T(std::move(new_t));
-  }
-
-  return range.first;
-}
-
-template <typename T, size_t N, typename A>
-typename InlinedVector<T, N, A>::iterator InlinedVector<T, N, A>::erase(
-    const_iterator first, const_iterator last) {
-  assert(begin() <= first);
-  assert(first <= last);
-  assert(last <= end());
-
-  iterator range_start = const_cast<iterator>(first);
-  iterator range_end = const_cast<iterator>(last);
-
-  size_type s = size();
-  ptrdiff_t erase_gap = std::distance(range_start, range_end);
-  if (erase_gap > 0) {
-    pointer space;
-    if (allocated()) {
-      space = allocated_space();
-      tag().set_allocated_size(s - erase_gap);
-    } else {
-      space = inlined_space();
-      tag().set_inline_size(s - erase_gap);
-    }
-    std::move(range_end, space + s, range_start);
-    Destroy(space + s - erase_gap, space + s);
-  }
-  return range_start;
-}
-
-template <typename T, size_t N, typename A>
-void InlinedVector<T, N, A>::swap(InlinedVector& other) {
-  using std::swap;  // Augment ADL with std::swap.
-  if (&other == this) {
-    return;
-  }
-  if (allocated() && other.allocated()) {
-    // Both out of line, so just swap the tag, allocation, and allocator.
-    swap(tag(), other.tag());
-    swap(allocation(), other.allocation());
-    swap(allocator(), other.allocator());
-    return;
-  }
-  if (!allocated() && !other.allocated()) {
-    // Both inlined: swap up to smaller size, then move remaining elements.
-    InlinedVector* a = this;
-    InlinedVector* b = &other;
-    if (size() < other.size()) {
-      swap(a, b);
-    }
-
-    const size_type a_size = a->size();
-    const size_type b_size = b->size();
-    assert(a_size >= b_size);
-    // 'a' is larger. Swap the elements up to the smaller array size.
-    std::swap_ranges(a->inlined_space(), a->inlined_space() + b_size,
-                     b->inlined_space());
-
-    // Move the remaining elements: A[b_size,a_size) -> B[b_size,a_size)
-    b->UninitializedCopy(a->inlined_space() + b_size,
-                         a->inlined_space() + a_size,
-                         b->inlined_space() + b_size);
-    a->Destroy(a->inlined_space() + b_size, a->inlined_space() + a_size);
-
-    swap(a->tag(), b->tag());
-    swap(a->allocator(), b->allocator());
-    assert(b->size() == a_size);
-    assert(a->size() == b_size);
-    return;
-  }
-  // One is out of line, one is inline.
-  // We first move the elements from the inlined vector into the
-  // inlined space in the other vector.  We then put the other vector's
-  // pointer/capacity into the originally inlined vector and swap
-  // the tags.
-  InlinedVector* a = this;
-  InlinedVector* b = &other;
-  if (a->allocated()) {
-    swap(a, b);
-  }
-  assert(!a->allocated());
-  assert(b->allocated());
-  const size_type a_size = a->size();
-  const size_type b_size = b->size();
-  // In an optimized build, b_size would be unused.
-  (void)b_size;
-
-  // Made Local copies of size(), don't need tag() accurate anymore
-  swap(a->tag(), b->tag());
-
-  // Copy b_allocation out before b's union gets clobbered by inline_space.
-  Allocation b_allocation = b->allocation();
-
-  b->UninitializedCopy(a->inlined_space(), a->inlined_space() + a_size,
-                       b->inlined_space());
-  a->Destroy(a->inlined_space(), a->inlined_space() + a_size);
-
-  a->allocation() = b_allocation;
-
-  if (a->allocator() != b->allocator()) {
-    swap(a->allocator(), b->allocator());
-  }
-
-  assert(b->size() == a_size);
-  assert(a->size() == b_size);
-}
-
-template <typename T, size_t N, typename A>
-void InlinedVector<T, N, A>::EnlargeBy(size_type delta) {
-  const size_type s = size();
-  assert(s <= capacity());
-
-  size_type target = std::max(static_cast<size_type>(N), s + delta);
-
-  // Compute new capacity by repeatedly doubling current capacity
-  // TODO(psrc): Check and avoid overflow?
-  size_type new_capacity = capacity();
-  while (new_capacity < target) {
-    new_capacity <<= 1;
-  }
-
-  Allocation new_allocation(allocator(), new_capacity);
-
-  UninitializedCopy(std::make_move_iterator(data()),
-                    std::make_move_iterator(data() + s),
-                    new_allocation.buffer());
-
-  ResetAllocation(new_allocation, s);
-}
-
-template <typename T, size_t N, typename A>
-auto InlinedVector<T, N, A>::ShiftRight(const_iterator position, size_type n)
-    -> std::pair<iterator, iterator> {
-  iterator start_used = const_cast<iterator>(position);
-  iterator start_raw = const_cast<iterator>(position);
-  size_type s = size();
-  size_type required_size = s + n;
-
-  if (required_size > capacity()) {
-    // Compute new capacity by repeatedly doubling current capacity
-    size_type new_capacity = capacity();
-    while (new_capacity < required_size) {
-      new_capacity <<= 1;
-    }
-    // Move everyone into the new allocation, leaving a gap of n for the
-    // requested shift.
-    Allocation new_allocation(allocator(), new_capacity);
-    size_type index = position - begin();
-    UninitializedCopy(std::make_move_iterator(data()),
-                      std::make_move_iterator(data() + index),
-                      new_allocation.buffer());
-    UninitializedCopy(std::make_move_iterator(data() + index),
-                      std::make_move_iterator(data() + s),
-                      new_allocation.buffer() + index + n);
-    ResetAllocation(new_allocation, s);
-
-    // New allocation means our iterator is invalid, so we'll recalculate.
-    // Since the entire gap is in new space, there's no used space to reuse.
-    start_raw = begin() + index;
-    start_used = start_raw;
-  } else {
-    // If we had enough space, it's a two-part move. Elements going into
-    // previously-unoccupied space need an UninitializedCopy. Elements
-    // going into a previously-occupied space are just a move.
-    iterator pos = const_cast<iterator>(position);
-    iterator raw_space = end();
-    size_type slots_in_used_space = raw_space - pos;
-    size_type new_elements_in_used_space = std::min(n, slots_in_used_space);
-    size_type new_elements_in_raw_space = n - new_elements_in_used_space;
-    size_type old_elements_in_used_space =
-        slots_in_used_space - new_elements_in_used_space;
-
-    UninitializedCopy(std::make_move_iterator(pos + old_elements_in_used_space),
-                      std::make_move_iterator(raw_space),
-                      raw_space + new_elements_in_raw_space);
-    std::move_backward(pos, pos + old_elements_in_used_space, raw_space);
-
-    // If the gap is entirely in raw space, the used space starts where the raw
-    // space starts, leaving no elements in used space. If the gap is entirely
-    // in used space, the raw space starts at the end of the gap, leaving all
-    // elements accounted for within the used space.
-    start_used = pos;
-    start_raw = pos + new_elements_in_used_space;
-  }
-  tag().add_size(n);
-  return std::make_pair(start_used, start_raw);
-}
-
-template <typename T, size_t N, typename A>
-void InlinedVector<T, N, A>::Destroy(value_type* ptr, value_type* ptr_last) {
-  for (value_type* p = ptr; p != ptr_last; ++p) {
-    AllocatorTraits::destroy(allocator(), p);
-  }
-
-  // Overwrite unused memory with 0xab so we can catch uninitialized usage.
-  // Cast to void* to tell the compiler that we don't care that we might be
-  // scribbling on a vtable pointer.
-#ifndef NDEBUG
-  if (ptr != ptr_last) {
-    memset(reinterpret_cast<void*>(ptr), 0xab, sizeof(*ptr) * (ptr_last - ptr));
-  }
-#endif
-}
-
-template <typename T, size_t N, typename A>
-template <typename Iter>
-void InlinedVector<T, N, A>::AppendRange(Iter first, Iter last,
-                                         std::forward_iterator_tag) {
-  using Length = typename std::iterator_traits<Iter>::difference_type;
-  Length length = std::distance(first, last);
-  reserve(size() + length);
-  if (allocated()) {
-    UninitializedCopy(first, last, allocated_space() + size());
-    tag().set_allocated_size(size() + length);
-  } else {
-    UninitializedCopy(first, last, inlined_space() + size());
-    tag().set_inline_size(size() + length);
-  }
-}
-
-template <typename T, size_t N, typename A>
-template <typename Iter>
-void InlinedVector<T, N, A>::AssignRange(Iter first, Iter last,
-                                         std::input_iterator_tag) {
-  // Optimized to avoid reallocation.
-  // Prefer reassignment to copy construction for elements.
-  iterator out = begin();
-  for (; first != last && out != end(); ++first, ++out) {
-    *out = *first;
-  }
-  erase(out, end());
-  std::copy(first, last, std::back_inserter(*this));
-}
-
-template <typename T, size_t N, typename A>
-template <typename Iter>
-void InlinedVector<T, N, A>::AssignRange(Iter first, Iter last,
-                                         std::forward_iterator_tag) {
-  using Length = typename std::iterator_traits<Iter>::difference_type;
-  Length length = std::distance(first, last);
-  // Prefer reassignment to copy construction for elements.
-  if (static_cast<size_type>(length) <= size()) {
-    erase(std::copy(first, last, begin()), end());
-    return;
-  }
-  reserve(length);
-  iterator out = begin();
-  for (; out != end(); ++first, ++out) *out = *first;
-  if (allocated()) {
-    UninitializedCopy(first, last, out);
-    tag().set_allocated_size(length);
-  } else {
-    UninitializedCopy(first, last, out);
-    tag().set_inline_size(length);
-  }
-}
-
-template <typename T, size_t N, typename A>
-auto InlinedVector<T, N, A>::InsertWithCount(const_iterator position,
-                                             size_type n, const value_type& v)
-    -> iterator {
-  assert(position >= begin() && position <= end());
-  if (n == 0) return const_cast<iterator>(position);
-
-  value_type copy = v;
-  std::pair<iterator, iterator> it_pair = ShiftRight(position, n);
-  std::fill(it_pair.first, it_pair.second, copy);
-  UninitializedFill(it_pair.second, it_pair.first + n, copy);
-
-  return it_pair.first;
-}
-
-template <typename T, size_t N, typename A>
-template <typename InputIter>
-auto InlinedVector<T, N, A>::InsertWithRange(const_iterator position,
-                                             InputIter first, InputIter last,
-                                             std::input_iterator_tag)
-    -> iterator {
-  assert(position >= begin() && position <= end());
-  size_type index = position - cbegin();
-  size_type i = index;
-  while (first != last) insert(begin() + i++, *first++);
-  return begin() + index;
-}
-
-// Overload of InlinedVector::InsertWithRange()
-template <typename T, size_t N, typename A>
-template <typename ForwardIter>
-auto InlinedVector<T, N, A>::InsertWithRange(const_iterator position,
-                                             ForwardIter first,
-                                             ForwardIter last,
-                                             std::forward_iterator_tag)
-    -> iterator {
-  assert(position >= begin() && position <= end());
-  if (first == last) {
-    return const_cast<iterator>(position);
-  }
-  using Length = typename std::iterator_traits<ForwardIter>::difference_type;
-  Length n = std::distance(first, last);
-  std::pair<iterator, iterator> it_pair = ShiftRight(position, n);
-  size_type used_spots = it_pair.second - it_pair.first;
-  ForwardIter open_spot = std::next(first, used_spots);
-  std::copy(first, open_spot, it_pair.first);
-  UninitializedCopy(open_spot, last, it_pair.second);
-  return it_pair.first;
-}
-
-}  // namespace absl
+// Do not depend on any below implementation details!
+// -----------------------------------------------------------------------------
 
 #endif  // ABSL_CONTAINER_INLINED_VECTOR_H_
diff --git a/absl/container/inlined_vector_benchmark.cc b/absl/container/inlined_vector_benchmark.cc
index a3ad0f8..867a29e 100644
--- a/absl/container/inlined_vector_benchmark.cc
+++ b/absl/container/inlined_vector_benchmark.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -23,17 +23,13 @@
 
 namespace {
 
-using IntVec = absl::InlinedVector<int, 8>;
-
 void BM_InlinedVectorFill(benchmark::State& state) {
-  const int len = state.range(0);
+  absl::InlinedVector<int, 8> v;
+  int val = 10;
   for (auto _ : state) {
-    IntVec v;
-    for (int i = 0; i < len; i++) {
-      v.push_back(i);
-    }
+    benchmark::DoNotOptimize(v);
+    v.push_back(val);
   }
-  state.SetItemsProcessed(static_cast<int64_t>(state.iterations()) * len);
 }
 BENCHMARK(BM_InlinedVectorFill)->Range(0, 1024);
 
@@ -43,23 +39,25 @@
   for (int i = 0; i < len; i++) {
     ia[i] = i;
   }
+  auto* from = ia.get();
+  auto* to = from + len;
   for (auto _ : state) {
-    IntVec v(ia.get(), ia.get() + len);
+    benchmark::DoNotOptimize(from);
+    benchmark::DoNotOptimize(to);
+    absl::InlinedVector<int, 8> v(from, to);
     benchmark::DoNotOptimize(v);
   }
-  state.SetItemsProcessed(static_cast<int64_t>(state.iterations()) * len);
 }
 BENCHMARK(BM_InlinedVectorFillRange)->Range(0, 1024);
 
 void BM_StdVectorFill(benchmark::State& state) {
-  const int len = state.range(0);
+  std::vector<int> v;
+  int val = 10;
   for (auto _ : state) {
-    std::vector<int> v;
-    for (int i = 0; i < len; i++) {
-      v.push_back(i);
-    }
+    benchmark::DoNotOptimize(v);
+    benchmark::DoNotOptimize(val);
+    v.push_back(val);
   }
-  state.SetItemsProcessed(static_cast<int64_t>(state.iterations()) * len);
 }
 BENCHMARK(BM_StdVectorFill)->Range(0, 1024);
 
@@ -89,7 +87,7 @@
   const int len = state.range(0);
   const int no_sso = GetNonShortStringOptimizationSize();
   std::string strings[4] = {std::string(no_sso, 'A'), std::string(no_sso, 'B'),
-                       std::string(no_sso, 'C'), std::string(no_sso, 'D')};
+                            std::string(no_sso, 'C'), std::string(no_sso, 'D')};
 
   for (auto _ : state) {
     absl::InlinedVector<std::string, 8> v;
@@ -105,7 +103,7 @@
   const int len = state.range(0);
   const int no_sso = GetNonShortStringOptimizationSize();
   std::string strings[4] = {std::string(no_sso, 'A'), std::string(no_sso, 'B'),
-                       std::string(no_sso, 'C'), std::string(no_sso, 'D')};
+                            std::string(no_sso, 'C'), std::string(no_sso, 'D')};
 
   for (auto _ : state) {
     std::vector<std::string> v;
@@ -124,7 +122,7 @@
   void* user_data;
 };
 
-void BM_InlinedVectorTenAssignments(benchmark::State& state) {
+void BM_InlinedVectorAssignments(benchmark::State& state) {
   const int len = state.range(0);
   using BufferVec = absl::InlinedVector<Buffer, 2>;
 
@@ -133,18 +131,25 @@
 
   BufferVec dst;
   for (auto _ : state) {
-    for (int i = 0; i < 10; ++i) {
-      dst = src;
-    }
+    benchmark::DoNotOptimize(dst);
+    benchmark::DoNotOptimize(src);
+    dst = src;
   }
 }
-BENCHMARK(BM_InlinedVectorTenAssignments)
-    ->Arg(0)->Arg(1)->Arg(2)->Arg(3)->Arg(4)->Arg(20);
+BENCHMARK(BM_InlinedVectorAssignments)
+    ->Arg(0)
+    ->Arg(1)
+    ->Arg(2)
+    ->Arg(3)
+    ->Arg(4)
+    ->Arg(20);
 
 void BM_CreateFromContainer(benchmark::State& state) {
   for (auto _ : state) {
-    absl::InlinedVector<int, 4> x(absl::InlinedVector<int, 4>{1, 2, 3});
-    benchmark::DoNotOptimize(x);
+    absl::InlinedVector<int, 4> src{1, 2, 3};
+    benchmark::DoNotOptimize(src);
+    absl::InlinedVector<int, 4> dst(std::move(src));
+    benchmark::DoNotOptimize(dst);
   }
 }
 BENCHMARK(BM_CreateFromContainer);
@@ -159,15 +164,14 @@
 
 struct LargeCopyableSwappable {
   LargeCopyableSwappable() : d(1024, 17) {}
+
   LargeCopyableSwappable(const LargeCopyableSwappable& o) = default;
-  LargeCopyableSwappable(LargeCopyableSwappable&& o) = delete;
 
   LargeCopyableSwappable& operator=(LargeCopyableSwappable o) {
     using std::swap;
     swap(*this, o);
     return *this;
   }
-  LargeCopyableSwappable& operator=(LargeCopyableSwappable&& o) = delete;
 
   friend void swap(LargeCopyableSwappable& a, LargeCopyableSwappable& b) {
     using std::swap;
@@ -215,6 +219,8 @@
   Vec b;
   for (auto _ : state) {
     using std::swap;
+    benchmark::DoNotOptimize(a);
+    benchmark::DoNotOptimize(b);
     swap(a, b);
   }
 }
@@ -260,60 +266,44 @@
 void BM_InlinedVectorIndexInlined(benchmark::State& state) {
   absl::InlinedVector<int, 8> v = {1, 2, 3, 4, 5, 6, 7};
   for (auto _ : state) {
-    for (int i = 0; i < 1000; ++i) {
-      benchmark::DoNotOptimize(v);
-      benchmark::DoNotOptimize(v[4]);
-    }
+    benchmark::DoNotOptimize(v);
+    benchmark::DoNotOptimize(v[4]);
   }
-  state.SetItemsProcessed(1000 * static_cast<int64_t>(state.iterations()));
 }
 BENCHMARK(BM_InlinedVectorIndexInlined);
 
 void BM_InlinedVectorIndexExternal(benchmark::State& state) {
   absl::InlinedVector<int, 8> v = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
   for (auto _ : state) {
-    for (int i = 0; i < 1000; ++i) {
-      benchmark::DoNotOptimize(v);
-      benchmark::DoNotOptimize(v[4]);
-    }
+    benchmark::DoNotOptimize(v);
+    benchmark::DoNotOptimize(v[4]);
   }
-  state.SetItemsProcessed(1000 * static_cast<int64_t>(state.iterations()));
 }
 BENCHMARK(BM_InlinedVectorIndexExternal);
 
 void BM_StdVectorIndex(benchmark::State& state) {
   std::vector<int> v = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
   for (auto _ : state) {
-    for (int i = 0; i < 1000; ++i) {
-      benchmark::DoNotOptimize(v);
-      benchmark::DoNotOptimize(v[4]);
-    }
+    benchmark::DoNotOptimize(v);
+    benchmark::DoNotOptimize(v[4]);
   }
-  state.SetItemsProcessed(1000 * static_cast<int64_t>(state.iterations()));
 }
 BENCHMARK(BM_StdVectorIndex);
 
-#define UNROLL_2(x)            \
-  benchmark::DoNotOptimize(x); \
-  benchmark::DoNotOptimize(x);
-
-#define UNROLL_4(x) UNROLL_2(x) UNROLL_2(x)
-#define UNROLL_8(x) UNROLL_4(x) UNROLL_4(x)
-#define UNROLL_16(x) UNROLL_8(x) UNROLL_8(x);
-
 void BM_InlinedVectorDataInlined(benchmark::State& state) {
   absl::InlinedVector<int, 8> v = {1, 2, 3, 4, 5, 6, 7};
   for (auto _ : state) {
-    UNROLL_16(v.data());
+    benchmark::DoNotOptimize(v);
+    benchmark::DoNotOptimize(v.data());
   }
-  state.SetItemsProcessed(16 * static_cast<int64_t>(state.iterations()));
 }
 BENCHMARK(BM_InlinedVectorDataInlined);
 
 void BM_InlinedVectorDataExternal(benchmark::State& state) {
   absl::InlinedVector<int, 8> v = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
   for (auto _ : state) {
-    UNROLL_16(v.data());
+    benchmark::DoNotOptimize(v);
+    benchmark::DoNotOptimize(v.data());
   }
   state.SetItemsProcessed(16 * static_cast<int64_t>(state.iterations()));
 }
@@ -322,7 +312,8 @@
 void BM_StdVectorData(benchmark::State& state) {
   std::vector<int> v = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
   for (auto _ : state) {
-    UNROLL_16(v.data());
+    benchmark::DoNotOptimize(v);
+    benchmark::DoNotOptimize(v.data());
   }
   state.SetItemsProcessed(16 * static_cast<int64_t>(state.iterations()));
 }
@@ -331,54 +322,54 @@
 void BM_InlinedVectorSizeInlined(benchmark::State& state) {
   absl::InlinedVector<int, 8> v = {1, 2, 3, 4, 5, 6, 7};
   for (auto _ : state) {
-    UNROLL_16(v.size());
+    benchmark::DoNotOptimize(v);
+    benchmark::DoNotOptimize(v.size());
   }
-  state.SetItemsProcessed(16 * static_cast<int64_t>(state.iterations()));
 }
 BENCHMARK(BM_InlinedVectorSizeInlined);
 
 void BM_InlinedVectorSizeExternal(benchmark::State& state) {
   absl::InlinedVector<int, 8> v = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
   for (auto _ : state) {
-    UNROLL_16(v.size());
+    benchmark::DoNotOptimize(v);
+    benchmark::DoNotOptimize(v.size());
   }
-  state.SetItemsProcessed(16 * static_cast<int64_t>(state.iterations()));
 }
 BENCHMARK(BM_InlinedVectorSizeExternal);
 
 void BM_StdVectorSize(benchmark::State& state) {
   std::vector<int> v = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
   for (auto _ : state) {
-    UNROLL_16(v.size());
+    benchmark::DoNotOptimize(v);
+    benchmark::DoNotOptimize(v.size());
   }
-  state.SetItemsProcessed(16 * static_cast<int64_t>(state.iterations()));
 }
 BENCHMARK(BM_StdVectorSize);
 
 void BM_InlinedVectorEmptyInlined(benchmark::State& state) {
   absl::InlinedVector<int, 8> v = {1, 2, 3, 4, 5, 6, 7};
   for (auto _ : state) {
-    UNROLL_16(v.empty());
+    benchmark::DoNotOptimize(v);
+    benchmark::DoNotOptimize(v.empty());
   }
-  state.SetItemsProcessed(16 * static_cast<int64_t>(state.iterations()));
 }
 BENCHMARK(BM_InlinedVectorEmptyInlined);
 
 void BM_InlinedVectorEmptyExternal(benchmark::State& state) {
   absl::InlinedVector<int, 8> v = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
   for (auto _ : state) {
-    UNROLL_16(v.empty());
+    benchmark::DoNotOptimize(v);
+    benchmark::DoNotOptimize(v.empty());
   }
-  state.SetItemsProcessed(16 * static_cast<int64_t>(state.iterations()));
 }
 BENCHMARK(BM_InlinedVectorEmptyExternal);
 
 void BM_StdVectorEmpty(benchmark::State& state) {
   std::vector<int> v = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
   for (auto _ : state) {
-    UNROLL_16(v.empty());
+    benchmark::DoNotOptimize(v);
+    benchmark::DoNotOptimize(v.empty());
   }
-  state.SetItemsProcessed(16 * static_cast<int64_t>(state.iterations()));
 }
 BENCHMARK(BM_StdVectorEmpty);
 
diff --git a/absl/container/inlined_vector_test.cc b/absl/container/inlined_vector_test.cc
index 08dcd3e..6037001 100644
--- a/absl/container/inlined_vector_test.cc
+++ b/absl/container/inlined_vector_test.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -30,6 +30,7 @@
 #include "absl/base/internal/exception_testing.h"
 #include "absl/base/internal/raw_logging.h"
 #include "absl/base/macros.h"
+#include "absl/container/internal/counting_allocator.h"
 #include "absl/container/internal/test_instance_tracker.h"
 #include "absl/hash/hash_testing.h"
 #include "absl/memory/memory.h"
@@ -37,6 +38,7 @@
 
 namespace {
 
+using absl::container_internal::CountingAllocator;
 using absl::test_internal::CopyableMovableInstance;
 using absl::test_internal::CopyableOnlyInstance;
 using absl::test_internal::InstanceTracker;
@@ -68,7 +70,7 @@
 // test_instance_tracker.h.
 template <typename T>
 class InstanceTest : public ::testing::Test {};
-TYPED_TEST_CASE_P(InstanceTest);
+TYPED_TEST_SUITE_P(InstanceTest);
 
 // A simple reference counted class to make sure that the proper elements are
 // destroyed in the erase(begin, end) test.
@@ -138,57 +140,6 @@
   return v;
 }
 
-// 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) {}
-  explicit CountingAllocator(int64_t* b) : bytes_used_(b) {}
-
-  template <typename U>
-  CountingAllocator(const CountingAllocator<U>& x)
-      : Alloc(x), bytes_used_(x.bytes_used_) {}
-
-  pointer allocate(size_type n,
-                   std::allocator<void>::const_pointer 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 U>
-  class rebind {
-   public:
-    using other = CountingAllocator<U>;
-  };
-
-  friend bool operator==(const CountingAllocator& a,
-                         const CountingAllocator& b) {
-    return a.bytes_used_ == b.bytes_used_;
-  }
-
-  friend bool operator!=(const CountingAllocator& a,
-                         const CountingAllocator& b) {
-    return !(a == b);
-  }
-
-  int64_t* bytes_used_;
-};
-
 TEST(IntVec, SimpleOps) {
   for (int len = 0; len < 20; len++) {
     IntVec v;
@@ -906,6 +857,8 @@
       InstanceTracker tracker;
       InstanceVec a, b;
       const size_t inlined_capacity = a.capacity();
+      auto min_len = std::min(l1, l2);
+      auto max_len = std::max(l1, l2);
       for (int i = 0; i < l1; i++) a.push_back(Instance(i));
       for (int i = 0; i < l2; i++) b.push_back(Instance(100+i));
       EXPECT_EQ(tracker.instances(), l1 + l2);
@@ -919,15 +872,15 @@
         EXPECT_EQ(tracker.swaps(), 0);  // Allocations are swapped.
         EXPECT_EQ(tracker.moves(), 0);
       } else if (a.size() <= inlined_capacity && b.size() <= inlined_capacity) {
-        EXPECT_EQ(tracker.swaps(), std::min(l1, l2));
-        // TODO(bsamwel): This should use moves when the type is movable.
-        EXPECT_EQ(tracker.copies(), std::max(l1, l2) - std::min(l1, l2));
+        EXPECT_EQ(tracker.swaps(), min_len);
+        EXPECT_EQ((tracker.moves() ? tracker.moves() : tracker.copies()),
+                  max_len - min_len);
       } else {
         // One is allocated and the other isn't. The allocation is transferred
         // without copying elements, and the inlined instances are copied/moved.
         EXPECT_EQ(tracker.swaps(), 0);
-        // TODO(bsamwel): This should use moves when the type is movable.
-        EXPECT_EQ(tracker.copies(), std::min(l1, l2));
+        EXPECT_EQ((tracker.moves() ? tracker.moves() : tracker.copies()),
+                  min_len);
       }
 
       EXPECT_EQ(l1, b.size());
@@ -1726,39 +1679,58 @@
       std::scoped_allocator_adaptor<CountingAllocator<StdVector>>;
   using AllocVec = absl::InlinedVector<StdVector, 4, MyAlloc>;
 
+  // MSVC 2017's std::vector allocates different amounts of memory in debug
+  // versus opt mode.
+  int64_t test_allocated = 0;
+  StdVector v(CountingAllocator<int>{&test_allocated});
+  // The amount of memory allocated by a default constructed vector<int>
+  auto default_std_vec_allocated = test_allocated;
+  v.push_back(1);
+  // The amound of memory allocated by a copy-constructed vector<int> with one
+  // element.
+  int64_t one_element_std_vec_copy_allocated = test_allocated;
+
   int64_t allocated = 0;
   AllocVec vec(MyAlloc{CountingAllocator<StdVector>{&allocated}});
   EXPECT_EQ(allocated, 0);
 
   // This default constructs a vector<int>, but the allocator should pass itself
-  // into the vector<int>.
+  // into the vector<int>, so check allocation compared to that.
   // The absl::InlinedVector does not allocate any memory.
-  // The vector<int> does not allocate any memory.
+  // The vector<int> may allocate any memory.
+  auto expected = default_std_vec_allocated;
   vec.resize(1);
-  EXPECT_EQ(allocated, 0);
+  EXPECT_EQ(allocated, expected);
 
   // We make vector<int> allocate memory.
   // It must go through the allocator even though we didn't construct the
-  // vector directly.
+  // vector directly.  This assumes that vec[0] doesn't need to grow its
+  // allocation.
+  expected += sizeof(int);
   vec[0].push_back(1);
-  EXPECT_EQ(allocated, sizeof(int) * 1);
+  EXPECT_EQ(allocated, expected);
 
   // Another allocating vector.
+  expected += one_element_std_vec_copy_allocated;
   vec.push_back(vec[0]);
-  EXPECT_EQ(allocated, sizeof(int) * 2);
+  EXPECT_EQ(allocated, expected);
 
   // Overflow the inlined memory.
   // The absl::InlinedVector will now allocate.
+  expected += sizeof(StdVector) * 8 + default_std_vec_allocated * 3;
   vec.resize(5);
-  EXPECT_EQ(allocated, sizeof(int) * 2 + sizeof(StdVector) * 8);
+  EXPECT_EQ(allocated, expected);
 
   // Adding one more in external mode should also work.
+  expected += one_element_std_vec_copy_allocated;
   vec.push_back(vec[0]);
-  EXPECT_EQ(allocated, sizeof(int) * 3 + sizeof(StdVector) * 8);
+  EXPECT_EQ(allocated, expected);
 
-  // And extending these should still work.
+  // And extending these should still work.  This assumes that vec[0] does not
+  // need to grow its allocation.
+  expected += sizeof(int);
   vec[0].push_back(1);
-  EXPECT_EQ(allocated, sizeof(int) * 4 + sizeof(StdVector) * 8);
+  EXPECT_EQ(allocated, expected);
 
   vec.clear();
   EXPECT_EQ(allocated, 0);
@@ -1790,4 +1762,23 @@
   }
 }
 
+TEST(InlinedVectorTest, AbslHashValueWorks) {
+  using V = absl::InlinedVector<int, 4>;
+  std::vector<V> cases;
+
+  // Generate a variety of vectors some of these are small enough for the inline
+  // space but are stored out of line.
+  for (int i = 0; i < 10; ++i) {
+    V v;
+    for (int j = 0; j < i; ++j) {
+      v.push_back(j);
+    }
+    cases.push_back(v);
+    v.resize(i % 4);
+    cases.push_back(v);
+  }
+
+  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(cases));
+}
+
 }  // anonymous namespace
diff --git a/absl/container/internal/common.h b/absl/container/internal/common.h
new file mode 100644
index 0000000..b06e711
--- /dev/null
+++ b/absl/container/internal/common.h
@@ -0,0 +1,183 @@
+// 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
+//
+//      https://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.
+
+#ifndef ABSL_CONTAINER_INTERNAL_CONTAINER_H_
+#define ABSL_CONTAINER_INTERNAL_CONTAINER_H_
+
+#include <cassert>
+#include <type_traits>
+
+#include "absl/meta/type_traits.h"
+#include "absl/types/optional.h"
+
+namespace absl {
+namespace container_internal {
+
+template <class, class = void>
+struct IsTransparent : std::false_type {};
+template <class T>
+struct IsTransparent<T, absl::void_t<typename T::is_transparent>>
+    : std::true_type {};
+
+template <bool is_transparent>
+struct KeyArg {
+  // Transparent. Forward `K`.
+  template <typename K, typename key_type>
+  using type = K;
+};
+
+template <>
+struct KeyArg<false> {
+  // Not transparent. Always use `key_type`.
+  template <typename K, typename key_type>
+  using type = key_type;
+};
+
+// The node_handle concept from C++17.
+// We specialize node_handle for sets and maps. node_handle_base holds the
+// common API of both.
+template <typename PolicyTraits, typename Alloc>
+class node_handle_base {
+ protected:
+  using slot_type = typename PolicyTraits::slot_type;
+
+ public:
+  using allocator_type = Alloc;
+
+  constexpr node_handle_base() {}
+  node_handle_base(node_handle_base&& other) noexcept {
+    *this = std::move(other);
+  }
+  ~node_handle_base() { destroy(); }
+  node_handle_base& operator=(node_handle_base&& other) noexcept {
+    destroy();
+    if (!other.empty()) {
+      alloc_ = other.alloc_;
+      PolicyTraits::transfer(alloc(), slot(), other.slot());
+      other.reset();
+    }
+    return *this;
+  }
+
+  bool empty() const noexcept { return !alloc_; }
+  explicit operator bool() const noexcept { return !empty(); }
+  allocator_type get_allocator() const { return *alloc_; }
+
+ protected:
+  friend struct CommonAccess;
+
+  node_handle_base(const allocator_type& a, slot_type* s) : alloc_(a) {
+    PolicyTraits::transfer(alloc(), slot(), s);
+  }
+
+  void destroy() {
+    if (!empty()) {
+      PolicyTraits::destroy(alloc(), slot());
+      reset();
+    }
+  }
+
+  void reset() {
+    assert(alloc_.has_value());
+    alloc_ = absl::nullopt;
+  }
+
+  slot_type* slot() const {
+    assert(!empty());
+    return reinterpret_cast<slot_type*>(std::addressof(slot_space_));
+  }
+  allocator_type* alloc() { return std::addressof(*alloc_); }
+
+ private:
+  absl::optional<allocator_type> alloc_;
+  mutable absl::aligned_storage_t<sizeof(slot_type), alignof(slot_type)>
+      slot_space_;
+};
+
+// For sets.
+template <typename Policy, typename PolicyTraits, typename Alloc,
+          typename = void>
+class node_handle : public node_handle_base<PolicyTraits, Alloc> {
+  using Base = typename node_handle::node_handle_base;
+
+ public:
+  using value_type = typename PolicyTraits::value_type;
+
+  constexpr node_handle() {}
+
+  value_type& value() const { return PolicyTraits::element(this->slot()); }
+
+ private:
+  friend struct CommonAccess;
+
+  node_handle(const Alloc& a, typename Base::slot_type* s) : Base(a, s) {}
+};
+
+// For maps.
+template <typename Policy, typename PolicyTraits, typename Alloc>
+class node_handle<Policy, PolicyTraits, Alloc,
+                  absl::void_t<typename Policy::mapped_type>>
+    : public node_handle_base<PolicyTraits, Alloc> {
+  using Base = typename node_handle::node_handle_base;
+
+ public:
+  using key_type = typename Policy::key_type;
+  using mapped_type = typename Policy::mapped_type;
+
+  constexpr node_handle() {}
+
+  auto key() const -> decltype(PolicyTraits::key(this->slot())) {
+    return PolicyTraits::key(this->slot());
+  }
+
+  mapped_type& mapped() const {
+    return PolicyTraits::value(&PolicyTraits::element(this->slot()));
+  }
+
+ private:
+  friend struct CommonAccess;
+
+  node_handle(const Alloc& a, typename Base::slot_type* s) : Base(a, s) {}
+};
+
+// Provide access to non-public node-handle functions.
+struct CommonAccess {
+  template <typename Node>
+  static auto GetSlot(const Node& node) -> decltype(node.slot()) {
+    return node.slot();
+  }
+
+  template <typename Node>
+  static void Reset(Node* node) {
+    node->reset();
+  }
+
+  template <typename T, typename... Args>
+  static T Make(Args&&... args) {
+    return T(std::forward<Args>(args)...);
+  }
+};
+
+// Implement the insert_return_type<> concept of C++17.
+template <class Iterator, class NodeType>
+struct InsertReturnType {
+  Iterator position;
+  bool inserted;
+  NodeType node;
+};
+
+}  // namespace container_internal
+}  // namespace absl
+
+#endif  // ABSL_CONTAINER_INTERNAL_CONTAINER_H_
diff --git a/absl/container/internal/compressed_tuple.h b/absl/container/internal/compressed_tuple.h
index cc52614..b9bd91a 100644
--- a/absl/container/internal/compressed_tuple.h
+++ b/absl/container/internal/compressed_tuple.h
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -27,7 +27,7 @@
 //   const T2& t2 = value.get<2>();
 //   ...
 //
-// http://en.cppreference.com/w/cpp/language/ebo
+// https://en.cppreference.com/w/cpp/language/ebo
 
 #ifndef ABSL_CONTAINER_INTERNAL_COMPRESSED_TUPLE_H_
 #define ABSL_CONTAINER_INTERNAL_COMPRESSED_TUPLE_H_
@@ -89,8 +89,10 @@
   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; }
+  constexpr const T& get() const& { return value; }
+  T& get() & { return value; }
+  constexpr const T&& get() const&& { return absl::move(*this).value; }
+  T&& get() && { return std::move(*this).value; }
 };
 
 template <typename D, size_t I>
@@ -99,8 +101,10 @@
   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; }
+  constexpr const T& get() const& { return *this; }
+  T& get() & { return *this; }
+  constexpr const T&& get() const&& { return absl::move(*this); }
+  T&& get() && { return std::move(*this); }
 };
 
 template <typename D, typename I>
@@ -137,7 +141,7 @@
 //   const T2& t2 = value.get<2>();
 //   ...
 //
-// http://en.cppreference.com/w/cpp/language/ebo
+// https://en.cppreference.com/w/cpp/language/ebo
 template <typename... Ts>
 class ABSL_INTERNAL_COMPRESSED_TUPLE_DECLSPEC CompressedTuple
     : private internal_compressed_tuple::CompressedTupleImpl<
@@ -152,14 +156,26 @@
       : CompressedTuple::CompressedTupleImpl(absl::forward<Ts>(base)...) {}
 
   template <int I>
-  ElemT<I>& get() {
+  ElemT<I>& get() & {
     return internal_compressed_tuple::Storage<CompressedTuple, I>::get();
   }
 
   template <int I>
-  constexpr const ElemT<I>& get() const {
+  constexpr const ElemT<I>& get() const& {
     return internal_compressed_tuple::Storage<CompressedTuple, I>::get();
   }
+
+  template <int I>
+  ElemT<I>&& get() && {
+    return std::move(*this)
+        .internal_compressed_tuple::template Storage<CompressedTuple, I>::get();
+  }
+
+  template <int I>
+  constexpr const ElemT<I>&& get() const&& {
+    return absl::move(*this)
+        .internal_compressed_tuple::template Storage<CompressedTuple, I>::get();
+  }
 };
 
 // Explicit specialization for a zero-element tuple
diff --git a/absl/container/internal/compressed_tuple_test.cc b/absl/container/internal/compressed_tuple_test.cc
index 45030c6..28e7741 100644
--- a/absl/container/internal/compressed_tuple_test.cc
+++ b/absl/container/internal/compressed_tuple_test.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -14,17 +14,25 @@
 
 #include "absl/container/internal/compressed_tuple.h"
 
+#include <memory>
 #include <string>
 
 #include "gmock/gmock.h"
 #include "gtest/gtest.h"
+#include "absl/memory/memory.h"
+#include "absl/utility/utility.h"
 
 namespace absl {
 namespace container_internal {
 namespace {
 
+enum class CallType { kConstRef, kConstMove };
+
 template <int>
-struct Empty {};
+struct Empty {
+  constexpr CallType value() const& { return CallType::kConstRef; }
+  constexpr CallType value() const&& { return CallType::kConstMove; }
+};
 
 template <typename T>
 struct NotEmpty {
@@ -140,15 +148,44 @@
   EXPECT_TRUE(std::is_empty<CompressedTuple<>>::value);
 }
 
+TEST(CompressedTupleTest, MoveOnlyElements) {
+  CompressedTuple<std::unique_ptr<std::string>> str_tup(
+      absl::make_unique<std::string>("str"));
+
+  CompressedTuple<CompressedTuple<std::unique_ptr<std::string>>,
+                  std::unique_ptr<int>>
+  x(std::move(str_tup), absl::make_unique<int>(5));
+
+  EXPECT_EQ(*x.get<0>().get<0>(), "str");
+  EXPECT_EQ(*x.get<1>(), 5);
+
+  std::unique_ptr<std::string> x0 = std::move(x.get<0>()).get<0>();
+  std::unique_ptr<int> x1 = std::move(x).get<1>();
+
+  EXPECT_EQ(*x0, "str");
+  EXPECT_EQ(*x1, 5);
+}
+
 TEST(CompressedTupleTest, Constexpr) {
-  constexpr CompressedTuple<int, double, CompressedTuple<int>> x(
-      7, 1.25, CompressedTuple<int>(5));
+  constexpr CompressedTuple<int, double, CompressedTuple<int>, Empty<0>> 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>();
+  constexpr CallType x3 = x.get<3>().value();
+
   EXPECT_EQ(x0, 7);
   EXPECT_EQ(x1, 1.25);
   EXPECT_EQ(x2, 5);
+  EXPECT_EQ(x3, CallType::kConstRef);
+
+#if defined(__clang__)
+  // An apparent bug in earlier versions of gcc claims these are ambiguous.
+  constexpr int x2m = absl::move(x.get<2>()).get<0>();
+  constexpr CallType x3m = absl::move(x).get<3>().value();
+  EXPECT_EQ(x2m, 5);
+  EXPECT_EQ(x3m, CallType::kConstMove);
+#endif
 }
 
 #if defined(__clang__) || defined(__GNUC__)
diff --git a/absl/container/internal/container_memory.h b/absl/container/internal/container_memory.h
index 56c5d2d..e5bb977 100644
--- a/absl/container/internal/container_memory.h
+++ b/absl/container/internal/container_memory.h
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -286,13 +286,48 @@
 
 }  // namespace memory_internal
 
-// If kMutableKeys is false, only the value member is accessed.
+// The internal storage type for key-value containers like flat_hash_map.
 //
-// If kMutableKeys is true, key is accessed through all slots while value and
-// mutable_value are accessed only via INITIALIZED slots. Slots are created and
-// destroyed via mutable_value so that the key can be moved later.
+// It is convenient for the value_type of a flat_hash_map<K, V> to be
+// pair<const K, V>; the "const K" prevents accidental modification of the key
+// when dealing with the reference returned from find() and similar methods.
+// However, this creates other problems; we want to be able to emplace(K, V)
+// efficiently with move operations, and similarly be able to move a
+// pair<K, V> in insert().
+//
+// The solution is this union, which aliases the const and non-const versions
+// of the pair. This also allows flat_hash_map<const K, V> to work, even though
+// that has the same efficiency issues with move in emplace() and insert() -
+// but people do it anyway.
+//
+// If kMutableKeys is false, only the value member can be accessed.
+//
+// If kMutableKeys is true, key can be accessed through all slots while value
+// and mutable_value must be accessed only via INITIALIZED slots. Slots are
+// created and destroyed via mutable_value so that the key can be moved later.
+//
+// Accessing one of the union fields while the other is active is safe as
+// long as they are layout-compatible, which is guaranteed by the definition of
+// kMutableKeys. For C++11, the relevant section of the standard is
+// https://timsong-cpp.github.io/cppwp/n3337/class.mem#19 (9.2.19)
 template <class K, class V>
-union slot_type {
+union map_slot_type {
+  map_slot_type() {}
+  ~map_slot_type() = delete;
+  using value_type = std::pair<const K, V>;
+  using mutable_value_type = std::pair<K, V>;
+
+  value_type value;
+  mutable_value_type mutable_value;
+  K key;
+};
+
+template <class K, class V>
+struct map_slot_policy {
+  using slot_type = map_slot_type<K, V>;
+  using value_type = std::pair<const K, V>;
+  using mutable_value_type = std::pair<K, V>;
+
  private:
   static void emplace(slot_type* slot) {
     // The construction of union doesn't do anything at runtime but it allows us
@@ -302,19 +337,17 @@
   // If pair<const K, V> and pair<K, V> are layout-compatible, we can accept one
   // or the other via slot_type. We are also free to access the key via
   // slot_type::key in this case.
-  using kMutableKeys =
-      std::integral_constant<bool,
-                             memory_internal::IsLayoutCompatible<K, V>::value>;
+  using kMutableKeys = memory_internal::IsLayoutCompatible<K, V>;
 
  public:
-  slot_type() {}
-  ~slot_type() = delete;
-  using value_type = std::pair<const K, V>;
-  using mutable_value_type = std::pair<K, V>;
+  static value_type& element(slot_type* slot) { return slot->value; }
+  static const value_type& element(const slot_type* slot) {
+    return slot->value;
+  }
 
-  value_type value;
-  mutable_value_type mutable_value;
-  K key;
+  static const K& key(const slot_type* slot) {
+    return kMutableKeys::value ? slot->key : slot->value.first;
+  }
 
   template <class Allocator, class... Args>
   static void construct(Allocator* alloc, slot_type* slot, Args&&... args) {
diff --git a/absl/container/internal/container_memory_test.cc b/absl/container/internal/container_memory_test.cc
index f1c4058..d6b0495 100644
--- a/absl/container/internal/container_memory_test.cc
+++ b/absl/container/internal/container_memory_test.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
diff --git a/absl/container/internal/counting_allocator.h b/absl/container/internal/counting_allocator.h
new file mode 100644
index 0000000..4e717be
--- /dev/null
+++ b/absl/container/internal/counting_allocator.h
@@ -0,0 +1,79 @@
+// 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
+//
+//      https://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.
+
+#ifndef ABSL_CONTAINER_INTERNAL_COUNTING_ALLOCATOR_H_
+#define ABSL_CONTAINER_INTERNAL_COUNTING_ALLOCATOR_H_
+
+#include <cassert>
+#include <cstdint>
+#include <memory>
+
+namespace absl {
+namespace container_internal {
+
+// 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) {}
+  explicit CountingAllocator(int64_t* b) : bytes_used_(b) {}
+
+  template <typename U>
+  CountingAllocator(const CountingAllocator<U>& x)
+      : Alloc(x), bytes_used_(x.bytes_used_) {}
+
+  pointer allocate(size_type n,
+                   std::allocator<void>::const_pointer 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 U>
+  class rebind {
+   public:
+    using other = CountingAllocator<U>;
+  };
+
+  friend bool operator==(const CountingAllocator& a,
+                         const CountingAllocator& b) {
+    return a.bytes_used_ == b.bytes_used_;
+  }
+
+  friend bool operator!=(const CountingAllocator& a,
+                         const CountingAllocator& b) {
+    return !(a == b);
+  }
+
+  int64_t* bytes_used_;
+};
+
+}  // namespace container_internal
+}  // namespace absl
+
+#endif  // ABSL_CONTAINER_INTERNAL_COUNTING_ALLOCATOR_H_
diff --git a/absl/container/internal/hash_function_defaults.h b/absl/container/internal/hash_function_defaults.h
index 1f0d794..cb8f03c 100644
--- a/absl/container/internal/hash_function_defaults.h
+++ b/absl/container/internal/hash_function_defaults.h
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -39,8 +39,8 @@
 // equal functions are still bound to T. This is important because some type U
 // can be hashed by/tested for equality differently depending on T. A notable
 // example is `const char*`. `const char*` is treated as a c-style string when
-// the hash function is hash<string> but as a pointer when the hash function is
-// hash<void*>.
+// the hash function is hash<std::string> but as a pointer when the hash
+// function is hash<void*>.
 //
 #ifndef ABSL_CONTAINER_INTERNAL_HASH_FUNCTION_DEFAULTS_H_
 #define ABSL_CONTAINER_INTERNAL_HASH_FUNCTION_DEFAULTS_H_
@@ -83,6 +83,7 @@
     }
   };
 };
+
 template <>
 struct HashEq<std::string> : StringHashEq {};
 template <>
diff --git a/absl/container/internal/hash_function_defaults_test.cc b/absl/container/internal/hash_function_defaults_test.cc
index 464baae..82708db 100644
--- a/absl/container/internal/hash_function_defaults_test.cc
+++ b/absl/container/internal/hash_function_defaults_test.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -77,14 +77,14 @@
   hash_default_eq<T> key_eq;
 };
 
-TYPED_TEST_CASE(EqString, StringTypes);
+TYPED_TEST_SUITE(EqString, StringTypes);
 
 template <class T>
 struct HashString : ::testing::Test {
   hash_default_hash<T> hasher;
 };
 
-TYPED_TEST_CASE(HashString, StringTypes);
+TYPED_TEST_SUITE(HashString, StringTypes);
 
 TYPED_TEST(EqString, Works) {
   auto eq = this->key_eq;
@@ -121,14 +121,14 @@
   hash_default_eq<T> key_eq;
 };
 
-TYPED_TEST_CASE(EqPointer, PointerTypes);
+TYPED_TEST_SUITE(EqPointer, PointerTypes);
 
 template <class T>
 struct HashPointer : ::testing::Test {
   hash_default_hash<T> hasher;
 };
 
-TYPED_TEST_CASE(HashPointer, PointerTypes);
+TYPED_TEST_SUITE(HashPointer, PointerTypes);
 
 TYPED_TEST(EqPointer, Works) {
   int dummy;
@@ -202,15 +202,11 @@
   EXPECT_NE(hash(&dummy), hash(cuptr));
 }
 
-// Cartesian product of (string, std::string, absl::string_view)
-// with (string, std::string, absl::string_view, const char*).
+// Cartesian product of (std::string, absl::string_view)
+// with (std::string, absl::string_view, const char*).
 using StringTypesCartesianProduct = Types<
     // clang-format off
 
-    std::pair<std::string, std::string>,
-    std::pair<std::string, absl::string_view>,
-    std::pair<std::string, const char*>,
-
     std::pair<absl::string_view, std::string>,
     std::pair<absl::string_view, absl::string_view>,
     std::pair<absl::string_view, const char*>>;
@@ -248,7 +244,7 @@
   EXPECT_NE(this->hash(this->a1), this->hash(this->b2));
 }
 
-TYPED_TEST_CASE(StringLikeTest, StringTypesCartesianProduct);
+TYPED_TEST_SUITE(StringLikeTest, StringTypesCartesianProduct);
 
 }  // namespace
 }  // namespace container_internal
diff --git a/absl/container/internal/hash_generator_testing.cc b/absl/container/internal/hash_generator_testing.cc
index 0d6a9df..37a23d6 100644
--- a/absl/container/internal/hash_generator_testing.cc
+++ b/absl/container/internal/hash_generator_testing.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -39,9 +39,9 @@
 
 }  // namespace
 
-std::mt19937_64* GetThreadLocalRng() {
+std::mt19937_64* GetSharedRng() {
   RandomDeviceSeedSeq seed_seq;
-  thread_local auto* rng = new std::mt19937_64(seed_seq);
+  static auto* rng = new std::mt19937_64(seed_seq);
   return rng;
 }
 
@@ -51,7 +51,7 @@
   std::string res;
   res.resize(32);
   std::generate(res.begin(), res.end(),
-                [&]() { return chars(*GetThreadLocalRng()); });
+                [&]() { return chars(*GetSharedRng()); });
   return res;
 }
 
@@ -63,7 +63,7 @@
   auto& res = arena->back();
   res.resize(32);
   std::generate(res.begin(), res.end(),
-                [&]() { return chars(*GetThreadLocalRng()); });
+                [&]() { return chars(*GetSharedRng()); });
   return res;
 }
 
diff --git a/absl/container/internal/hash_generator_testing.h b/absl/container/internal/hash_generator_testing.h
index 50d7710..27fb84f 100644
--- a/absl/container/internal/hash_generator_testing.h
+++ b/absl/container/internal/hash_generator_testing.h
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -43,7 +43,7 @@
 
 }  // namespace generator_internal
 
-std::mt19937_64* GetThreadLocalRng();
+std::mt19937_64* GetSharedRng();
 
 enum Enum {
   kEnumEmpty,
@@ -66,7 +66,7 @@
 struct Generator<T, typename std::enable_if<std::is_integral<T>::value>::type> {
   T operator()() const {
     std::uniform_int_distribution<T> dist;
-    return dist(*GetThreadLocalRng());
+    return dist(*GetSharedRng());
   }
 };
 
@@ -76,7 +76,7 @@
     std::uniform_int_distribution<typename std::underlying_type<Enum>::type>
         dist;
     while (true) {
-      auto variate = dist(*GetThreadLocalRng());
+      auto variate = dist(*GetSharedRng());
       if (variate != kEnumEmpty && variate != kEnumDeleted)
         return static_cast<Enum>(variate);
     }
@@ -90,7 +90,7 @@
         typename std::underlying_type<EnumClass>::type>
         dist;
     while (true) {
-      EnumClass variate = static_cast<EnumClass>(dist(*GetThreadLocalRng()));
+      EnumClass variate = static_cast<EnumClass>(dist(*GetSharedRng()));
       if (variate != EnumClass::kEmpty && variate != EnumClass::kDeleted)
         return static_cast<EnumClass>(variate);
     }
diff --git a/absl/container/internal/hash_policy_testing.h b/absl/container/internal/hash_policy_testing.h
index ffc76ea..c57407a 100644
--- a/absl/container/internal/hash_policy_testing.h
+++ b/absl/container/internal/hash_policy_testing.h
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -139,7 +139,7 @@
   friend bool operator!=(const Alloc& a, const Alloc& b) { return !(a == b); }
 
  private:
-  size_t id_ = std::numeric_limits<size_t>::max();
+  size_t id_ = (std::numeric_limits<size_t>::max)();
 };
 
 template <class Map>
@@ -169,7 +169,11 @@
 // take allocator arguments. This test is defined ad-hoc for the platforms
 // we care about (notably Crosstool 17) because libstdcxx's useless
 // versioning scheme precludes a more principled solution.
-#if defined(__GLIBCXX__) && __GLIBCXX__ <= 20140425
+// From GCC-4.9 Changelog: (src: https://gcc.gnu.org/gcc-4.9/changes.html)
+// "the unordered associative containers in <unordered_map> and <unordered_set>
+// meet the allocator-aware container requirements;"
+#if (defined(__GLIBCXX__) && __GLIBCXX__ <= 20140425 ) || \
+( __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 9 ))
 #define ABSL_UNORDERED_SUPPORTS_ALLOC_CTORS 0
 #else
 #define ABSL_UNORDERED_SUPPORTS_ALLOC_CTORS 1
diff --git a/absl/container/internal/hash_policy_testing_test.cc b/absl/container/internal/hash_policy_testing_test.cc
index c215c42..0c95eb5 100644
--- a/absl/container/internal/hash_policy_testing_test.cc
+++ b/absl/container/internal/hash_policy_testing_test.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
diff --git a/absl/container/internal/hash_policy_traits.h b/absl/container/internal/hash_policy_traits.h
index 029e47e..fd007de 100644
--- a/absl/container/internal/hash_policy_traits.h
+++ b/absl/container/internal/hash_policy_traits.h
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -84,7 +84,7 @@
   }
 
   // Transfers the `old_slot` to `new_slot`. Any memory allocated by the
-  // allocator inside `old_slot` to `new_slot` can be transfered.
+  // allocator inside `old_slot` to `new_slot` can be transferred.
   //
   // OPTIONAL: defaults to:
   //
diff --git a/absl/container/internal/hash_policy_traits_test.cc b/absl/container/internal/hash_policy_traits_test.cc
index 423f154..e643d18 100644
--- a/absl/container/internal/hash_policy_traits_test.cc
+++ b/absl/container/internal/hash_policy_traits_test.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
diff --git a/absl/container/internal/hashtable_debug.h b/absl/container/internal/hashtable_debug.h
index c3bd65c..7193000 100644
--- a/absl/container/internal/hashtable_debug.h
+++ b/absl/container/internal/hashtable_debug.h
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -60,7 +60,7 @@
     size_t num_probes = GetHashtableDebugNumProbes(
         container,
         absl::container_internal::hashtable_debug_internal::GetKey<C>(*it, 0));
-    v.resize(std::max(v.size(), num_probes + 1));
+    v.resize((std::max)(v.size(), num_probes + 1));
     v[num_probes]++;
   }
   return v;
diff --git a/absl/container/internal/hashtable_debug_hooks.h b/absl/container/internal/hashtable_debug_hooks.h
index 8f21972..371ce81 100644
--- a/absl/container/internal/hashtable_debug_hooks.h
+++ b/absl/container/internal/hashtable_debug_hooks.h
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
diff --git a/absl/container/internal/hashtablez_sampler.cc b/absl/container/internal/hashtablez_sampler.cc
new file mode 100644
index 0000000..6667d3a
--- /dev/null
+++ b/absl/container/internal/hashtablez_sampler.cc
@@ -0,0 +1,308 @@
+// 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
+//
+//      https://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/hashtablez_sampler.h"
+
+#include <atomic>
+#include <cassert>
+#include <cmath>
+#include <functional>
+#include <limits>
+
+#include "absl/base/attributes.h"
+#include "absl/container/internal/have_sse.h"
+#include "absl/debugging/stacktrace.h"
+#include "absl/memory/memory.h"
+#include "absl/synchronization/mutex.h"
+
+namespace absl {
+namespace container_internal {
+constexpr int HashtablezInfo::kMaxStackDepth;
+
+namespace {
+ABSL_CONST_INIT std::atomic<bool> g_hashtablez_enabled{
+   false
+};
+ABSL_CONST_INIT std::atomic<int32_t> g_hashtablez_sample_parameter{1 << 10};
+ABSL_CONST_INIT std::atomic<int32_t> g_hashtablez_max_samples{1 << 20};
+
+// Returns the next pseudo-random value.
+// pRNG is: aX+b mod c with a = 0x5DEECE66D, b =  0xB, c = 1<<48
+// This is the lrand64 generator.
+uint64_t NextRandom(uint64_t rnd) {
+  const uint64_t prng_mult = uint64_t{0x5DEECE66D};
+  const uint64_t prng_add = 0xB;
+  const uint64_t prng_mod_power = 48;
+  const uint64_t prng_mod_mask = ~(~uint64_t{0} << prng_mod_power);
+  return (prng_mult * rnd + prng_add) & prng_mod_mask;
+}
+
+// Generates a geometric variable with the specified mean.
+// This is done by generating a random number between 0 and 1 and applying
+// the inverse cumulative distribution function for an exponential.
+// Specifically: Let m be the inverse of the sample period, then
+// the probability distribution function is m*exp(-mx) so the CDF is
+// p = 1 - exp(-mx), so
+// q = 1 - p = exp(-mx)
+// log_e(q) = -mx
+// -log_e(q)/m = x
+// log_2(q) * (-log_e(2) * 1/m) = x
+// In the code, q is actually in the range 1 to 2**26, hence the -26 below
+//
+int64_t GetGeometricVariable(int64_t mean) {
+#if ABSL_HAVE_THREAD_LOCAL
+  thread_local
+#else   // ABSL_HAVE_THREAD_LOCAL
+  // SampleSlow and hence GetGeometricVariable is guarded by a single mutex when
+  // there are not thread locals.  Thus, a single global rng is acceptable for
+  // that case.
+  static
+#endif  // ABSL_HAVE_THREAD_LOCAL
+      uint64_t rng = []() {
+        // We don't get well distributed numbers from this so we call
+        // NextRandom() a bunch to mush the bits around.  We use a global_rand
+        // to handle the case where the same thread (by memory address) gets
+        // created and destroyed repeatedly.
+        ABSL_CONST_INIT static std::atomic<uint32_t> global_rand(0);
+        uint64_t r = reinterpret_cast<uint64_t>(&rng) +
+                   global_rand.fetch_add(1, std::memory_order_relaxed);
+        for (int i = 0; i < 20; ++i) {
+          r = NextRandom(r);
+        }
+        return r;
+      }();
+
+  rng = NextRandom(rng);
+
+  // Take the top 26 bits as the random number
+  // (This plus the 1<<58 sampling bound give a max possible step of
+  // 5194297183973780480 bytes.)
+  const uint64_t prng_mod_power = 48;  // Number of bits in prng
+  // The uint32_t cast is to prevent a (hard-to-reproduce) NAN
+  // under piii debug for some binaries.
+  double q = static_cast<uint32_t>(rng >> (prng_mod_power - 26)) + 1.0;
+  // Put the computed p-value through the CDF of a geometric.
+  double interval = (log2(q) - 26) * (-std::log(2.0) * mean);
+
+  // Very large values of interval overflow int64_t. If we happen to
+  // hit such improbable condition, we simply cheat and clamp interval
+  // to largest supported value.
+  if (interval > static_cast<double>(std::numeric_limits<int64_t>::max() / 2)) {
+    return std::numeric_limits<int64_t>::max() / 2;
+  }
+
+  // Small values of interval are equivalent to just sampling next time.
+  if (interval < 1) {
+    return 1;
+  }
+  return static_cast<int64_t>(interval);
+}
+
+}  // namespace
+
+HashtablezSampler& HashtablezSampler::Global() {
+  static auto* sampler = new HashtablezSampler();
+  return *sampler;
+}
+
+HashtablezSampler::DisposeCallback HashtablezSampler::SetDisposeCallback(
+    DisposeCallback f) {
+  return dispose_.exchange(f, std::memory_order_relaxed);
+}
+
+HashtablezInfo::HashtablezInfo() { PrepareForSampling(); }
+HashtablezInfo::~HashtablezInfo() = default;
+
+void HashtablezInfo::PrepareForSampling() {
+  capacity.store(0, std::memory_order_relaxed);
+  size.store(0, std::memory_order_relaxed);
+  num_erases.store(0, std::memory_order_relaxed);
+  max_probe_length.store(0, std::memory_order_relaxed);
+  total_probe_length.store(0, std::memory_order_relaxed);
+  hashes_bitwise_or.store(0, std::memory_order_relaxed);
+  hashes_bitwise_and.store(~size_t{}, std::memory_order_relaxed);
+
+  create_time = absl::Now();
+  // The inliner makes hardcoded skip_count difficult (especially when combined
+  // with LTO).  We use the ability to exclude stacks by regex when encoding
+  // instead.
+  depth = absl::GetStackTrace(stack, HashtablezInfo::kMaxStackDepth,
+                              /* skip_count= */ 0);
+  dead = nullptr;
+}
+
+HashtablezSampler::HashtablezSampler()
+    : dropped_samples_(0), size_estimate_(0), all_(nullptr), dispose_(nullptr) {
+  absl::MutexLock l(&graveyard_.init_mu);
+  graveyard_.dead = &graveyard_;
+}
+
+HashtablezSampler::~HashtablezSampler() {
+  HashtablezInfo* s = all_.load(std::memory_order_acquire);
+  while (s != nullptr) {
+    HashtablezInfo* next = s->next;
+    delete s;
+    s = next;
+  }
+}
+
+void HashtablezSampler::PushNew(HashtablezInfo* sample) {
+  sample->next = all_.load(std::memory_order_relaxed);
+  while (!all_.compare_exchange_weak(sample->next, sample,
+                                     std::memory_order_release,
+                                     std::memory_order_relaxed)) {
+  }
+}
+
+void HashtablezSampler::PushDead(HashtablezInfo* sample) {
+  if (auto* dispose = dispose_.load(std::memory_order_relaxed)) {
+    dispose(*sample);
+  }
+
+  absl::MutexLock graveyard_lock(&graveyard_.init_mu);
+  absl::MutexLock sample_lock(&sample->init_mu);
+  sample->dead = graveyard_.dead;
+  graveyard_.dead = sample;
+}
+
+HashtablezInfo* HashtablezSampler::PopDead() {
+  absl::MutexLock graveyard_lock(&graveyard_.init_mu);
+
+  // The list is circular, so eventually it collapses down to
+  //   graveyard_.dead == &graveyard_
+  // when it is empty.
+  HashtablezInfo* sample = graveyard_.dead;
+  if (sample == &graveyard_) return nullptr;
+
+  absl::MutexLock sample_lock(&sample->init_mu);
+  graveyard_.dead = sample->dead;
+  sample->PrepareForSampling();
+  return sample;
+}
+
+HashtablezInfo* HashtablezSampler::Register() {
+  int64_t size = size_estimate_.fetch_add(1, std::memory_order_relaxed);
+  if (size > g_hashtablez_max_samples.load(std::memory_order_relaxed)) {
+    size_estimate_.fetch_sub(1, std::memory_order_relaxed);
+    dropped_samples_.fetch_add(1, std::memory_order_relaxed);
+    return nullptr;
+  }
+
+  HashtablezInfo* sample = PopDead();
+  if (sample == nullptr) {
+    // Resurrection failed.  Hire a new warlock.
+    sample = new HashtablezInfo();
+    PushNew(sample);
+  }
+
+  return sample;
+}
+
+void HashtablezSampler::Unregister(HashtablezInfo* sample) {
+  PushDead(sample);
+  size_estimate_.fetch_sub(1, std::memory_order_relaxed);
+}
+
+int64_t HashtablezSampler::Iterate(
+    const std::function<void(const HashtablezInfo& stack)>& f) {
+  HashtablezInfo* s = all_.load(std::memory_order_acquire);
+  while (s != nullptr) {
+    absl::MutexLock l(&s->init_mu);
+    if (s->dead == nullptr) {
+      f(*s);
+    }
+    s = s->next;
+  }
+
+  return dropped_samples_.load(std::memory_order_relaxed);
+}
+
+HashtablezInfo* SampleSlow(int64_t* next_sample) {
+  if (kAbslContainerInternalSampleEverything) {
+    *next_sample = 1;
+    return HashtablezSampler::Global().Register();
+  }
+
+  bool first = *next_sample < 0;
+  *next_sample = GetGeometricVariable(
+      g_hashtablez_sample_parameter.load(std::memory_order_relaxed));
+
+  // g_hashtablez_enabled can be dynamically flipped, we need to set a threshold
+  // low enough that we will start sampling in a reasonable time, so we just use
+  // the default sampling rate.
+  if (!g_hashtablez_enabled.load(std::memory_order_relaxed)) return nullptr;
+
+  // We will only be negative on our first count, so we should just retry in
+  // that case.
+  if (first) {
+    if (ABSL_PREDICT_TRUE(--*next_sample > 0)) return nullptr;
+    return SampleSlow(next_sample);
+  }
+
+  return HashtablezSampler::Global().Register();
+}
+
+#if ABSL_PER_THREAD_TLS == 1
+ABSL_PER_THREAD_TLS_KEYWORD int64_t global_next_sample = 0;
+#endif  // ABSL_PER_THREAD_TLS == 1
+
+void UnsampleSlow(HashtablezInfo* info) {
+  HashtablezSampler::Global().Unregister(info);
+}
+
+void RecordInsertSlow(HashtablezInfo* info, size_t hash,
+                      size_t distance_from_desired) {
+  // SwissTables probe in groups of 16, so scale this to count items probes and
+  // not offset from desired.
+  size_t probe_length = distance_from_desired;
+#if SWISSTABLE_HAVE_SSE2
+  probe_length /= 16;
+#else
+  probe_length /= 8;
+#endif
+
+  info->hashes_bitwise_and.fetch_and(hash, std::memory_order_relaxed);
+  info->hashes_bitwise_or.fetch_or(hash, std::memory_order_relaxed);
+  info->max_probe_length.store(
+      std::max(info->max_probe_length.load(std::memory_order_relaxed),
+               probe_length),
+      std::memory_order_relaxed);
+  info->total_probe_length.fetch_add(probe_length, std::memory_order_relaxed);
+  info->size.fetch_add(1, std::memory_order_relaxed);
+}
+
+void SetHashtablezEnabled(bool enabled) {
+  g_hashtablez_enabled.store(enabled, std::memory_order_release);
+}
+
+void SetHashtablezSampleParameter(int32_t rate) {
+  if (rate > 0) {
+    g_hashtablez_sample_parameter.store(rate, std::memory_order_release);
+  } else {
+    ABSL_RAW_LOG(ERROR, "Invalid hashtablez sample rate: %lld",
+                 static_cast<long long>(rate));  // NOLINT(runtime/int)
+  }
+}
+
+void SetHashtablezMaxSamples(int32_t max) {
+  if (max > 0) {
+    g_hashtablez_max_samples.store(max, std::memory_order_release);
+  } else {
+    ABSL_RAW_LOG(ERROR, "Invalid hashtablez max samples: %lld",
+                 static_cast<long long>(max));  // NOLINT(runtime/int)
+  }
+}
+
+}  // namespace container_internal
+}  // namespace absl
diff --git a/absl/container/internal/hashtablez_sampler.h b/absl/container/internal/hashtablez_sampler.h
new file mode 100644
index 0000000..a308e78
--- /dev/null
+++ b/absl/container/internal/hashtablez_sampler.h
@@ -0,0 +1,288 @@
+// 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
+//
+//      https://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.
+//
+// -----------------------------------------------------------------------------
+// File: hashtablez_sampler.h
+// -----------------------------------------------------------------------------
+//
+// This header file defines the API for a low level library to sample hashtables
+// and collect runtime statistics about them.
+//
+// `HashtablezSampler` controls the lifecycle of `HashtablezInfo` objects which
+// store information about a single sample.
+//
+// `Record*` methods store information into samples.
+// `Sample()` and `Unsample()` make use of a single global sampler with
+// properties controlled by the flags hashtablez_enabled,
+// hashtablez_sample_rate, and hashtablez_max_samples.
+//
+// WARNING
+//
+// Using this sampling API may cause sampled Swiss tables to use the global
+// allocator (operator `new`) in addition to any custom allocator.  If you
+// are using a table in an unusual circumstance where allocation or calling a
+// linux syscall is unacceptable, this could interfere.
+//
+// This utility is internal-only. Use at your own risk.
+
+#ifndef ABSL_CONTAINER_INTERNAL_HASHTABLEZ_SAMPLER_H_
+#define ABSL_CONTAINER_INTERNAL_HASHTABLEZ_SAMPLER_H_
+
+#include <atomic>
+#include <functional>
+#include <memory>
+#include <vector>
+
+#include "absl/base/internal/per_thread_tls.h"
+#include "absl/base/optimization.h"
+#include "absl/container/internal/have_sse.h"
+#include "absl/synchronization/mutex.h"
+#include "absl/utility/utility.h"
+
+namespace absl {
+namespace container_internal {
+
+// Stores information about a sampled hashtable.  All mutations to this *must*
+// be made through `Record*` functions below.  All reads from this *must* only
+// occur in the callback to `HashtablezSampler::Iterate`.
+struct HashtablezInfo {
+  // Constructs the object but does not fill in any fields.
+  HashtablezInfo();
+  ~HashtablezInfo();
+  HashtablezInfo(const HashtablezInfo&) = delete;
+  HashtablezInfo& operator=(const HashtablezInfo&) = delete;
+
+  // Puts the object into a clean state, fills in the logically `const` members,
+  // blocking for any readers that are currently sampling the object.
+  void PrepareForSampling() EXCLUSIVE_LOCKS_REQUIRED(init_mu);
+
+  // These fields are mutated by the various Record* APIs and need to be
+  // thread-safe.
+  std::atomic<size_t> capacity;
+  std::atomic<size_t> size;
+  std::atomic<size_t> num_erases;
+  std::atomic<size_t> max_probe_length;
+  std::atomic<size_t> total_probe_length;
+  std::atomic<size_t> hashes_bitwise_or;
+  std::atomic<size_t> hashes_bitwise_and;
+
+  // `HashtablezSampler` maintains intrusive linked lists for all samples.  See
+  // comments on `HashtablezSampler::all_` for details on these.  `init_mu`
+  // guards the ability to restore the sample to a pristine state.  This
+  // prevents races with sampling and resurrecting an object.
+  absl::Mutex init_mu;
+  HashtablezInfo* next;
+  HashtablezInfo* dead GUARDED_BY(init_mu);
+
+  // All of the fields below are set by `PrepareForSampling`, they must not be
+  // mutated in `Record*` functions.  They are logically `const` in that sense.
+  // These are guarded by init_mu, but that is not externalized to clients, who
+  // can only read them during `HashtablezSampler::Iterate` which will hold the
+  // lock.
+  static constexpr int kMaxStackDepth = 64;
+  absl::Time create_time;
+  int32_t depth;
+  void* stack[kMaxStackDepth];
+};
+
+inline void RecordRehashSlow(HashtablezInfo* info, size_t total_probe_length) {
+#if SWISSTABLE_HAVE_SSE2
+  total_probe_length /= 16;
+#else
+  total_probe_length /= 8;
+#endif
+  info->total_probe_length.store(total_probe_length, std::memory_order_relaxed);
+  info->num_erases.store(0, std::memory_order_relaxed);
+}
+
+inline void RecordStorageChangedSlow(HashtablezInfo* info, size_t size,
+                                     size_t capacity) {
+  info->size.store(size, std::memory_order_relaxed);
+  info->capacity.store(capacity, std::memory_order_relaxed);
+  if (size == 0) {
+    // This is a clear, reset the total/num_erases too.
+    RecordRehashSlow(info, 0);
+  }
+}
+
+void RecordInsertSlow(HashtablezInfo* info, size_t hash,
+                      size_t distance_from_desired);
+
+inline void RecordEraseSlow(HashtablezInfo* info) {
+  info->size.fetch_sub(1, std::memory_order_relaxed);
+  info->num_erases.fetch_add(1, std::memory_order_relaxed);
+}
+
+HashtablezInfo* SampleSlow(int64_t* next_sample);
+void UnsampleSlow(HashtablezInfo* info);
+
+class HashtablezInfoHandle {
+ public:
+  explicit HashtablezInfoHandle() : info_(nullptr) {}
+  explicit HashtablezInfoHandle(HashtablezInfo* info) : info_(info) {}
+  ~HashtablezInfoHandle() {
+    if (ABSL_PREDICT_TRUE(info_ == nullptr)) return;
+    UnsampleSlow(info_);
+  }
+
+  HashtablezInfoHandle(const HashtablezInfoHandle&) = delete;
+  HashtablezInfoHandle& operator=(const HashtablezInfoHandle&) = delete;
+
+  HashtablezInfoHandle(HashtablezInfoHandle&& o) noexcept
+      : info_(absl::exchange(o.info_, nullptr)) {}
+  HashtablezInfoHandle& operator=(HashtablezInfoHandle&& o) noexcept {
+    if (ABSL_PREDICT_FALSE(info_ != nullptr)) {
+      UnsampleSlow(info_);
+    }
+    info_ = absl::exchange(o.info_, nullptr);
+    return *this;
+  }
+
+  inline void RecordStorageChanged(size_t size, size_t capacity) {
+    if (ABSL_PREDICT_TRUE(info_ == nullptr)) return;
+    RecordStorageChangedSlow(info_, size, capacity);
+  }
+
+  inline void RecordRehash(size_t total_probe_length) {
+    if (ABSL_PREDICT_TRUE(info_ == nullptr)) return;
+    RecordRehashSlow(info_, total_probe_length);
+  }
+
+  inline void RecordInsert(size_t hash, size_t distance_from_desired) {
+    if (ABSL_PREDICT_TRUE(info_ == nullptr)) return;
+    RecordInsertSlow(info_, hash, distance_from_desired);
+  }
+
+  inline void RecordErase() {
+    if (ABSL_PREDICT_TRUE(info_ == nullptr)) return;
+    RecordEraseSlow(info_);
+  }
+
+  friend inline void swap(HashtablezInfoHandle& lhs,
+                          HashtablezInfoHandle& rhs) {
+    std::swap(lhs.info_, rhs.info_);
+  }
+
+ private:
+  friend class HashtablezInfoHandlePeer;
+  HashtablezInfo* info_;
+};
+
+#if ABSL_PER_THREAD_TLS == 1
+extern ABSL_PER_THREAD_TLS_KEYWORD int64_t global_next_sample;
+#endif  // ABSL_PER_THREAD_TLS
+
+// Returns an RAII sampling handle that manages registration and unregistation
+// with the global sampler.
+inline HashtablezInfoHandle Sample() {
+#if ABSL_PER_THREAD_TLS == 0
+  static auto* mu = new absl::Mutex;
+  static int64_t global_next_sample = 0;
+  absl::MutexLock l(mu);
+#endif  // !ABSL_HAVE_THREAD_LOCAL
+
+  if (ABSL_PREDICT_TRUE(--global_next_sample > 0)) {
+    return HashtablezInfoHandle(nullptr);
+  }
+  return HashtablezInfoHandle(SampleSlow(&global_next_sample));
+}
+
+// Holds samples and their associated stack traces with a soft limit of
+// `SetHashtablezMaxSamples()`.
+//
+// Thread safe.
+class HashtablezSampler {
+ public:
+  // Returns a global Sampler.
+  static HashtablezSampler& Global();
+
+  HashtablezSampler();
+  ~HashtablezSampler();
+
+  // Registers for sampling.  Returns an opaque registration info.
+  HashtablezInfo* Register();
+
+  // Unregisters the sample.
+  void Unregister(HashtablezInfo* sample);
+
+  // The dispose callback will be called on all samples the moment they are
+  // being unregistered. Only affects samples that are unregistered after the
+  // callback has been set.
+  // Returns the previous callback.
+  using DisposeCallback = void (*)(const HashtablezInfo&);
+  DisposeCallback SetDisposeCallback(DisposeCallback f);
+
+  // Iterates over all the registered `StackInfo`s.  Returning the number of
+  // samples that have been dropped.
+  int64_t Iterate(const std::function<void(const HashtablezInfo& stack)>& f);
+
+ private:
+  void PushNew(HashtablezInfo* sample);
+  void PushDead(HashtablezInfo* sample);
+  HashtablezInfo* PopDead();
+
+  std::atomic<size_t> dropped_samples_;
+  std::atomic<size_t> size_estimate_;
+
+  // Intrusive lock free linked lists for tracking samples.
+  //
+  // `all_` records all samples (they are never removed from this list) and is
+  // terminated with a `nullptr`.
+  //
+  // `graveyard_.dead` is a circular linked list.  When it is empty,
+  // `graveyard_.dead == &graveyard`.  The list is circular so that
+  // every item on it (even the last) has a non-null dead pointer.  This allows
+  // `Iterate` to determine if a given sample is live or dead using only
+  // information on the sample itself.
+  //
+  // For example, nodes [A, B, C, D, E] with [A, C, E] alive and [B, D] dead
+  // looks like this (G is the Graveyard):
+  //
+  //           +---+    +---+    +---+    +---+    +---+
+  //    all -->| A |--->| B |--->| C |--->| D |--->| E |
+  //           |   |    |   |    |   |    |   |    |   |
+  //   +---+   |   | +->|   |-+  |   | +->|   |-+  |   |
+  //   | G |   +---+ |  +---+ |  +---+ |  +---+ |  +---+
+  //   |   |         |        |        |        |
+  //   |   | --------+        +--------+        |
+  //   +---+                                    |
+  //     ^                                      |
+  //     +--------------------------------------+
+  //
+  std::atomic<HashtablezInfo*> all_;
+  HashtablezInfo graveyard_;
+
+  std::atomic<DisposeCallback> dispose_;
+};
+
+// Enables or disables sampling for Swiss tables.
+void SetHashtablezEnabled(bool enabled);
+
+// Sets the rate at which Swiss tables will be sampled.
+void SetHashtablezSampleParameter(int32_t rate);
+
+// Sets a soft max for the number of samples that will be kept.
+void SetHashtablezMaxSamples(int32_t max);
+
+// Configuration override.
+// This allows process-wide sampling without depending on order of
+// initialization of static storage duration objects.
+// The definition of this constant is weak, which allows us to inject a
+// different value for it at link time.
+extern "C" const bool kAbslContainerInternalSampleEverything;
+
+}  // namespace container_internal
+}  // namespace absl
+
+#endif  // ABSL_CONTAINER_INTERNAL_HASHTABLEZ_SAMPLER_H_
diff --git a/absl/container/internal/hashtablez_sampler_force_weak_definition.cc b/absl/container/internal/hashtablez_sampler_force_weak_definition.cc
new file mode 100644
index 0000000..4ca6ffd
--- /dev/null
+++ b/absl/container/internal/hashtablez_sampler_force_weak_definition.cc
@@ -0,0 +1,27 @@
+// 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
+//
+//      https://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/hashtablez_sampler.h"
+
+#include "absl/base/attributes.h"
+
+namespace absl {
+namespace container_internal {
+
+// See hashtablez_sampler.h for details.
+extern "C" ABSL_ATTRIBUTE_WEAK const bool
+    kAbslContainerInternalSampleEverything = false;
+
+}  // namespace container_internal
+}  // namespace absl
diff --git a/absl/container/internal/hashtablez_sampler_test.cc b/absl/container/internal/hashtablez_sampler_test.cc
new file mode 100644
index 0000000..d2435ed
--- /dev/null
+++ b/absl/container/internal/hashtablez_sampler_test.cc
@@ -0,0 +1,355 @@
+// 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
+//
+//      https://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/hashtablez_sampler.h"
+
+#include <atomic>
+#include <limits>
+#include <random>
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "absl/base/attributes.h"
+#include "absl/container/internal/have_sse.h"
+#include "absl/synchronization/blocking_counter.h"
+#include "absl/synchronization/internal/thread_pool.h"
+#include "absl/synchronization/mutex.h"
+#include "absl/synchronization/notification.h"
+#include "absl/time/clock.h"
+#include "absl/time/time.h"
+
+#if SWISSTABLE_HAVE_SSE2
+constexpr int kProbeLength = 16;
+#else
+constexpr int kProbeLength = 8;
+#endif
+
+namespace absl {
+namespace container_internal {
+class HashtablezInfoHandlePeer {
+ public:
+  static bool IsSampled(const HashtablezInfoHandle& h) {
+    return h.info_ != nullptr;
+  }
+
+  static HashtablezInfo* GetInfo(HashtablezInfoHandle* h) { return h->info_; }
+};
+
+namespace {
+using ::absl::synchronization_internal::ThreadPool;
+using ::testing::IsEmpty;
+using ::testing::UnorderedElementsAre;
+
+std::vector<size_t> GetSizes(HashtablezSampler* s) {
+  std::vector<size_t> res;
+  s->Iterate([&](const HashtablezInfo& info) {
+    res.push_back(info.size.load(std::memory_order_acquire));
+  });
+  return res;
+}
+
+HashtablezInfo* Register(HashtablezSampler* s, size_t size) {
+  auto* info = s->Register();
+  assert(info != nullptr);
+  info->size.store(size);
+  return info;
+}
+
+TEST(HashtablezInfoTest, PrepareForSampling) {
+  absl::Time test_start = absl::Now();
+  HashtablezInfo info;
+  absl::MutexLock l(&info.init_mu);
+  info.PrepareForSampling();
+
+  EXPECT_EQ(info.capacity.load(), 0);
+  EXPECT_EQ(info.size.load(), 0);
+  EXPECT_EQ(info.num_erases.load(), 0);
+  EXPECT_EQ(info.max_probe_length.load(), 0);
+  EXPECT_EQ(info.total_probe_length.load(), 0);
+  EXPECT_EQ(info.hashes_bitwise_or.load(), 0);
+  EXPECT_EQ(info.hashes_bitwise_and.load(), ~size_t{});
+  EXPECT_GE(info.create_time, test_start);
+
+  info.capacity.store(1, std::memory_order_relaxed);
+  info.size.store(1, std::memory_order_relaxed);
+  info.num_erases.store(1, std::memory_order_relaxed);
+  info.max_probe_length.store(1, std::memory_order_relaxed);
+  info.total_probe_length.store(1, std::memory_order_relaxed);
+  info.hashes_bitwise_or.store(1, std::memory_order_relaxed);
+  info.hashes_bitwise_and.store(1, std::memory_order_relaxed);
+  info.create_time = test_start - absl::Hours(20);
+
+  info.PrepareForSampling();
+  EXPECT_EQ(info.capacity.load(), 0);
+  EXPECT_EQ(info.size.load(), 0);
+  EXPECT_EQ(info.num_erases.load(), 0);
+  EXPECT_EQ(info.max_probe_length.load(), 0);
+  EXPECT_EQ(info.total_probe_length.load(), 0);
+  EXPECT_EQ(info.hashes_bitwise_or.load(), 0);
+  EXPECT_EQ(info.hashes_bitwise_and.load(), ~size_t{});
+  EXPECT_GE(info.create_time, test_start);
+}
+
+TEST(HashtablezInfoTest, RecordStorageChanged) {
+  HashtablezInfo info;
+  absl::MutexLock l(&info.init_mu);
+  info.PrepareForSampling();
+  RecordStorageChangedSlow(&info, 17, 47);
+  EXPECT_EQ(info.size.load(), 17);
+  EXPECT_EQ(info.capacity.load(), 47);
+  RecordStorageChangedSlow(&info, 20, 20);
+  EXPECT_EQ(info.size.load(), 20);
+  EXPECT_EQ(info.capacity.load(), 20);
+}
+
+TEST(HashtablezInfoTest, RecordInsert) {
+  HashtablezInfo info;
+  absl::MutexLock l(&info.init_mu);
+  info.PrepareForSampling();
+  EXPECT_EQ(info.max_probe_length.load(), 0);
+  RecordInsertSlow(&info, 0x0000FF00, 6 * kProbeLength);
+  EXPECT_EQ(info.max_probe_length.load(), 6);
+  EXPECT_EQ(info.hashes_bitwise_and.load(), 0x0000FF00);
+  EXPECT_EQ(info.hashes_bitwise_or.load(), 0x0000FF00);
+  RecordInsertSlow(&info, 0x000FF000, 4 * kProbeLength);
+  EXPECT_EQ(info.max_probe_length.load(), 6);
+  EXPECT_EQ(info.hashes_bitwise_and.load(), 0x0000F000);
+  EXPECT_EQ(info.hashes_bitwise_or.load(), 0x000FFF00);
+  RecordInsertSlow(&info, 0x00FF0000, 12 * kProbeLength);
+  EXPECT_EQ(info.max_probe_length.load(), 12);
+  EXPECT_EQ(info.hashes_bitwise_and.load(), 0x00000000);
+  EXPECT_EQ(info.hashes_bitwise_or.load(), 0x00FFFF00);
+}
+
+TEST(HashtablezInfoTest, RecordErase) {
+  HashtablezInfo info;
+  absl::MutexLock l(&info.init_mu);
+  info.PrepareForSampling();
+  EXPECT_EQ(info.num_erases.load(), 0);
+  EXPECT_EQ(info.size.load(), 0);
+  RecordInsertSlow(&info, 0x0000FF00, 6 * kProbeLength);
+  EXPECT_EQ(info.size.load(), 1);
+  RecordEraseSlow(&info);
+  EXPECT_EQ(info.size.load(), 0);
+  EXPECT_EQ(info.num_erases.load(), 1);
+}
+
+TEST(HashtablezInfoTest, RecordRehash) {
+  HashtablezInfo info;
+  absl::MutexLock l(&info.init_mu);
+  info.PrepareForSampling();
+  RecordInsertSlow(&info, 0x1, 0);
+  RecordInsertSlow(&info, 0x2, kProbeLength);
+  RecordInsertSlow(&info, 0x4, kProbeLength);
+  RecordInsertSlow(&info, 0x8, 2 * kProbeLength);
+  EXPECT_EQ(info.size.load(), 4);
+  EXPECT_EQ(info.total_probe_length.load(), 4);
+
+  RecordEraseSlow(&info);
+  RecordEraseSlow(&info);
+  EXPECT_EQ(info.size.load(), 2);
+  EXPECT_EQ(info.total_probe_length.load(), 4);
+  EXPECT_EQ(info.num_erases.load(), 2);
+
+  RecordRehashSlow(&info, 3 * kProbeLength);
+  EXPECT_EQ(info.size.load(), 2);
+  EXPECT_EQ(info.total_probe_length.load(), 3);
+  EXPECT_EQ(info.num_erases.load(), 0);
+}
+
+TEST(HashtablezSamplerTest, SmallSampleParameter) {
+  SetHashtablezEnabled(true);
+  SetHashtablezSampleParameter(100);
+
+  for (int i = 0; i < 1000; ++i) {
+    int64_t next_sample = 0;
+    HashtablezInfo* sample = SampleSlow(&next_sample);
+    EXPECT_GT(next_sample, 0);
+    EXPECT_NE(sample, nullptr);
+    UnsampleSlow(sample);
+  }
+}
+
+TEST(HashtablezSamplerTest, LargeSampleParameter) {
+  SetHashtablezEnabled(true);
+  SetHashtablezSampleParameter(std::numeric_limits<int32_t>::max());
+
+  for (int i = 0; i < 1000; ++i) {
+    int64_t next_sample = 0;
+    HashtablezInfo* sample = SampleSlow(&next_sample);
+    EXPECT_GT(next_sample, 0);
+    EXPECT_NE(sample, nullptr);
+    UnsampleSlow(sample);
+  }
+}
+
+TEST(HashtablezSamplerTest, Sample) {
+  SetHashtablezEnabled(true);
+  SetHashtablezSampleParameter(100);
+  int64_t num_sampled = 0;
+  int64_t total = 0;
+  double sample_rate;
+  for (int i = 0; i < 1000000; ++i) {
+    HashtablezInfoHandle h = Sample();
+    ++total;
+    if (HashtablezInfoHandlePeer::IsSampled(h)) {
+      ++num_sampled;
+    }
+    sample_rate = static_cast<double>(num_sampled) / total;
+    if (0.005 < sample_rate && sample_rate < 0.015) break;
+  }
+  EXPECT_NEAR(sample_rate, 0.01, 0.005);
+}
+
+TEST(HashtablezSamplerTest, Handle) {
+  auto& sampler = HashtablezSampler::Global();
+  HashtablezInfoHandle h(sampler.Register());
+  auto* info = HashtablezInfoHandlePeer::GetInfo(&h);
+  info->hashes_bitwise_and.store(0x12345678, std::memory_order_relaxed);
+
+  bool found = false;
+  sampler.Iterate([&](const HashtablezInfo& h) {
+    if (&h == info) {
+      EXPECT_EQ(h.hashes_bitwise_and.load(), 0x12345678);
+      found = true;
+    }
+  });
+  EXPECT_TRUE(found);
+
+  h = HashtablezInfoHandle();
+  found = false;
+  sampler.Iterate([&](const HashtablezInfo& h) {
+    if (&h == info) {
+      // this will only happen if some other thread has resurrected the info
+      // the old handle was using.
+      if (h.hashes_bitwise_and.load() == 0x12345678) {
+        found = true;
+      }
+    }
+  });
+  EXPECT_FALSE(found);
+}
+
+TEST(HashtablezSamplerTest, Registration) {
+  HashtablezSampler sampler;
+  auto* info1 = Register(&sampler, 1);
+  EXPECT_THAT(GetSizes(&sampler), UnorderedElementsAre(1));
+
+  auto* info2 = Register(&sampler, 2);
+  EXPECT_THAT(GetSizes(&sampler), UnorderedElementsAre(1, 2));
+  info1->size.store(3);
+  EXPECT_THAT(GetSizes(&sampler), UnorderedElementsAre(3, 2));
+
+  sampler.Unregister(info1);
+  sampler.Unregister(info2);
+}
+
+TEST(HashtablezSamplerTest, Unregistration) {
+  HashtablezSampler sampler;
+  std::vector<HashtablezInfo*> infos;
+  for (size_t i = 0; i < 3; ++i) {
+    infos.push_back(Register(&sampler, i));
+  }
+  EXPECT_THAT(GetSizes(&sampler), UnorderedElementsAre(0, 1, 2));
+
+  sampler.Unregister(infos[1]);
+  EXPECT_THAT(GetSizes(&sampler), UnorderedElementsAre(0, 2));
+
+  infos.push_back(Register(&sampler, 3));
+  infos.push_back(Register(&sampler, 4));
+  EXPECT_THAT(GetSizes(&sampler), UnorderedElementsAre(0, 2, 3, 4));
+  sampler.Unregister(infos[3]);
+  EXPECT_THAT(GetSizes(&sampler), UnorderedElementsAre(0, 2, 4));
+
+  sampler.Unregister(infos[0]);
+  sampler.Unregister(infos[2]);
+  sampler.Unregister(infos[4]);
+  EXPECT_THAT(GetSizes(&sampler), IsEmpty());
+}
+
+TEST(HashtablezSamplerTest, MultiThreaded) {
+  HashtablezSampler sampler;
+  Notification stop;
+  ThreadPool pool(10);
+
+  for (int i = 0; i < 10; ++i) {
+    pool.Schedule([&sampler, &stop]() {
+      std::random_device rd;
+      std::mt19937 gen(rd());
+
+      std::vector<HashtablezInfo*> infoz;
+      while (!stop.HasBeenNotified()) {
+        if (infoz.empty()) {
+          infoz.push_back(sampler.Register());
+        }
+        switch (std::uniform_int_distribution<>(0, 2)(gen)) {
+          case 0: {
+            infoz.push_back(sampler.Register());
+            break;
+          }
+          case 1: {
+            size_t p =
+                std::uniform_int_distribution<>(0, infoz.size() - 1)(gen);
+            HashtablezInfo* info = infoz[p];
+            infoz[p] = infoz.back();
+            infoz.pop_back();
+            sampler.Unregister(info);
+            break;
+          }
+          case 2: {
+            absl::Duration oldest = absl::ZeroDuration();
+            sampler.Iterate([&](const HashtablezInfo& info) {
+              oldest = std::max(oldest, absl::Now() - info.create_time);
+            });
+            ASSERT_GE(oldest, absl::ZeroDuration());
+            break;
+          }
+        }
+      }
+    });
+  }
+  // The threads will hammer away.  Give it a little bit of time for tsan to
+  // spot errors.
+  absl::SleepFor(absl::Seconds(3));
+  stop.Notify();
+}
+
+TEST(HashtablezSamplerTest, Callback) {
+  HashtablezSampler sampler;
+
+  auto* info1 = Register(&sampler, 1);
+  auto* info2 = Register(&sampler, 2);
+
+  static const HashtablezInfo* expected;
+
+  auto callback = [](const HashtablezInfo& info) {
+    // We can't use `info` outside of this callback because the object will be
+    // disposed as soon as we return from here.
+    EXPECT_EQ(&info, expected);
+  };
+
+  // Set the callback.
+  EXPECT_EQ(sampler.SetDisposeCallback(callback), nullptr);
+  expected = info1;
+  sampler.Unregister(info1);
+
+  // Unset the callback.
+  EXPECT_EQ(callback, sampler.SetDisposeCallback(nullptr));
+  expected = nullptr;  // no more calls.
+  sampler.Unregister(info2);
+}
+
+}  // namespace
+}  // namespace container_internal
+}  // namespace absl
diff --git a/absl/container/internal/have_sse.h b/absl/container/internal/have_sse.h
new file mode 100644
index 0000000..4341441
--- /dev/null
+++ b/absl/container/internal/have_sse.h
@@ -0,0 +1,49 @@
+// 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
+//
+//      https://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.
+//
+// Shared config probing for SSE instructions used in Swiss tables.
+#ifndef ABSL_CONTAINER_INTERNAL_HAVE_SSE_H_
+#define ABSL_CONTAINER_INTERNAL_HAVE_SSE_H_
+
+#ifndef SWISSTABLE_HAVE_SSE2
+#if defined(__SSE2__) ||  \
+    (defined(_MSC_VER) && \
+     (defined(_M_X64) || (defined(_M_IX86) && _M_IX86_FP >= 2)))
+#define SWISSTABLE_HAVE_SSE2 1
+#else
+#define SWISSTABLE_HAVE_SSE2 0
+#endif
+#endif
+
+#ifndef SWISSTABLE_HAVE_SSSE3
+#ifdef __SSSE3__
+#define SWISSTABLE_HAVE_SSSE3 1
+#else
+#define SWISSTABLE_HAVE_SSSE3 0
+#endif
+#endif
+
+#if SWISSTABLE_HAVE_SSSE3 && !SWISSTABLE_HAVE_SSE2
+#error "Bad configuration!"
+#endif
+
+#if SWISSTABLE_HAVE_SSE2
+#include <emmintrin.h>
+#endif
+
+#if SWISSTABLE_HAVE_SSSE3
+#include <tmmintrin.h>
+#endif
+
+#endif  // ABSL_CONTAINER_INTERNAL_HAVE_SSE_H_
diff --git a/absl/container/internal/inlined_vector.h b/absl/container/internal/inlined_vector.h
new file mode 100644
index 0000000..24059d9
--- /dev/null
+++ b/absl/container/internal/inlined_vector.h
@@ -0,0 +1,126 @@
+// Copyright 2019 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
+//
+//      https://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.
+
+#ifndef ABSL_CONTAINER_INTERNAL_INLINED_VECTOR_INTERNAL_H_
+#define ABSL_CONTAINER_INTERNAL_INLINED_VECTOR_INTERNAL_H_
+
+#include <cstddef>
+#include <iterator>
+#include <memory>
+
+#include "absl/meta/type_traits.h"
+
+namespace absl {
+namespace inlined_vector_internal {
+
+template <typename InlinedVector>
+class Storage;
+
+template <template <typename, size_t, typename> class InlinedVector, typename T,
+          size_t N, typename A>
+class Storage<InlinedVector<T, N, A>> {
+ public:
+  using allocator_type = A;
+  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 rvalue_reference = typename allocator_type::value_type&&;
+  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>;
+
+  explicit Storage(const allocator_type& a) : allocator_and_tag_(a) {}
+
+  // TODO(johnsoncj): Make the below types and members private after migration
+
+  // Holds whether the vector is allocated or not in the lowest bit and the size
+  // in the high bits:
+  //   `size_ = (size << 1) | is_allocated;`
+  class Tag {
+    size_type size_;
+
+   public:
+    Tag() : size_(0) {}
+    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; }
+  };
+
+  // Derives from `allocator_type` to use the empty base class optimization.
+  // If the `allocator_type` is stateless, we can store our instance for free.
+  class AllocatorAndTag : private allocator_type {
+    Tag tag_;
+
+   public:
+    explicit AllocatorAndTag(const allocator_type& a) : allocator_type(a) {}
+    Tag& tag() { return tag_; }
+    const Tag& tag() const { return tag_; }
+    allocator_type& allocator() { return *this; }
+    const allocator_type& allocator() const { return *this; }
+  };
+
+  class Allocation {
+    size_type capacity_;
+    pointer buffer_;
+
+   public:
+    Allocation(allocator_type& a, size_type capacity)
+        : capacity_(capacity), buffer_(Create(a, capacity)) {}
+    void Dealloc(allocator_type& a) {
+      std::allocator_traits<allocator_type>::deallocate(a, buffer_, capacity_);
+    }
+    size_type capacity() const { return capacity_; }
+    const_pointer buffer() const { return buffer_; }
+    pointer buffer() { return buffer_; }
+    static pointer Create(allocator_type& a, size_type n) {
+      return std::allocator_traits<allocator_type>::allocate(a, n);
+    }
+  };
+
+  // Stores either the inlined or allocated representation
+  union Rep {
+    using ValueTypeBuffer =
+        absl::aligned_storage_t<sizeof(value_type), alignof(value_type)>;
+    using AllocationBuffer =
+        absl::aligned_storage_t<sizeof(Allocation), alignof(Allocation)>;
+
+    // Structs wrap the buffers to perform indirection that solves a bizarre
+    // compilation error on Visual Studio (all known versions).
+    struct InlinedRep {
+      ValueTypeBuffer inlined[N];
+    };
+
+    struct AllocatedRep {
+      AllocationBuffer allocation;
+    };
+
+    InlinedRep inlined_storage;
+    AllocatedRep allocation_storage;
+  };
+
+  AllocatorAndTag allocator_and_tag_;
+  Rep rep_;
+};
+
+}  // namespace inlined_vector_internal
+}  // namespace absl
+
+#endif  // ABSL_CONTAINER_INTERNAL_INLINED_VECTOR_INTERNAL_H_
diff --git a/absl/container/internal/layout.h b/absl/container/internal/layout.h
index 676c7d6..bbdde50 100644
--- a/absl/container/internal/layout.h
+++ b/absl/container/internal/layout.h
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -232,13 +232,17 @@
 template <class T, size_t N>
 struct SizeOf<Aligned<T, N>> : std::integral_constant<size_t, sizeof(T)> {};
 
+// Note: workaround for https://gcc.gnu.org/PR88115
 template <class T>
-struct AlignOf : NotAligned<T>, std::integral_constant<size_t, alignof(T)> {};
+struct AlignOf : NotAligned<T> {
+  static constexpr size_t value = alignof(T);
+};
 
 template <class T, size_t N>
-struct AlignOf<Aligned<T, N>> : std::integral_constant<size_t, N> {
+struct AlignOf<Aligned<T, N>> {
   static_assert(N % alignof(T) == 0,
                 "Custom alignment can't be lower than the type's alignment");
+  static constexpr size_t value = N;
 };
 
 // Does `Ts...` contain `T`?
@@ -249,8 +253,10 @@
 using CopyConst =
     typename std::conditional<std::is_const<From>::value, const To, To>::type;
 
+// Note: We're not qualifying this with absl:: because it doesn't compile under
+// MSVC.
 template <class T>
-using SliceType = absl::Span<T>;
+using SliceType = Span<T>;
 
 // This namespace contains no types. It prevents functions defined in it from
 // being found by ADL.
@@ -290,7 +296,7 @@
 #ifdef ABSL_INTERNAL_HAS_CXA_DEMANGLE
   demangled = abi::__cxa_demangle(typeid(T).name(), nullptr, nullptr, &status);
 #endif
-  if (status == 0 && demangled != nullptr) {  // Demangling succeeeded.
+  if (status == 0 && demangled != nullptr) {  // Demangling succeeded.
     absl::StrAppend(&out, "<", demangled, ">");
     free(demangled);
   } else {
@@ -396,7 +402,7 @@
     static_assert(N < NumOffsets, "Index out of bounds");
     return adl_barrier::Align(
         Offset<N - 1>() + SizeOf<ElementType<N - 1>>() * size_[N - 1],
-        ElementAlignment<N>());
+        ElementAlignment<N>::value);
   }
 
   // Offset in bytes of the array with the specified element type. There must
@@ -445,7 +451,7 @@
     return Size<ElementIndex<T>()>();
   }
 
-    // The number of elements of all arrays for which they are known.
+  // The number of elements of all arrays for which they are known.
   constexpr std::array<size_t, NumSizes> Sizes() const {
     return {{Size<SizeSeq>()...}};
   }
@@ -610,7 +616,7 @@
 #ifdef ADDRESS_SANITIZER
     PoisonPadding<Char, N - 1>(p);
     // The `if` is an optimization. It doesn't affect the observable behaviour.
-    if (ElementAlignment<N - 1>() % ElementAlignment<N>()) {
+    if (ElementAlignment<N - 1>::value % ElementAlignment<N>::value) {
       size_t start =
           Offset<N - 1>() + SizeOf<ElementType<N - 1>>() * size_[N - 1];
       ASAN_POISON_MEMORY_REGION(p + start, Offset<N>() - start);
@@ -637,7 +643,8 @@
   std::string DebugString() const {
     const auto offsets = Offsets();
     const size_t sizes[] = {SizeOf<ElementType<OffsetSeq>>()...};
-    const std::string types[] = {adl_barrier::TypeName<ElementType<OffsetSeq>>()...};
+    const std::string types[] = {
+        adl_barrier::TypeName<ElementType<OffsetSeq>>()...};
     std::string res = absl::StrCat("@0", types[0], "(", sizes[0], ")");
     for (size_t i = 0; i != NumOffsets - 1; ++i) {
       absl::StrAppend(&res, "[", size_[i], "]; @", offsets[i + 1], types[i + 1],
@@ -690,7 +697,7 @@
   //
   // It's allowed to pass fewer array sizes than the number of arrays. E.g.,
   // if all you need is to the offset of the second array, you only need to
-  // pass one argument -- the number of elements in the first arrays.
+  // pass one argument -- the number of elements in the first array.
   //
   //   // int[3] followed by 4 bytes of padding and an unknown number of
   //   // doubles.
diff --git a/absl/container/internal/layout_test.cc b/absl/container/internal/layout_test.cc
index f35157a..33b72bd 100644
--- a/absl/container/internal/layout_test.cc
+++ b/absl/container/internal/layout_test.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -45,7 +45,25 @@
   return val;
 }
 
-using Int128 = int64_t[2];
+// Helper classes to test different size and alignments.
+struct alignas(8) Int128 {
+  uint64_t a, b;
+  friend bool operator==(Int128 lhs, Int128 rhs) {
+    return std::tie(lhs.a, lhs.b) == std::tie(rhs.a, rhs.b);
+  }
+
+  static std::string Name() {
+    return internal_layout::adl_barrier::TypeName<Int128>();
+  }
+};
+
+// int64_t is *not* 8-byte aligned on all platforms!
+struct alignas(8) Int64 {
+  int64_t a;
+  friend bool operator==(Int64 lhs, Int64 rhs) {
+    return lhs.a == rhs.a;
+  }
+};
 
 // Properties of types that this test relies on.
 static_assert(sizeof(int8_t) == 1, "");
@@ -54,6 +72,8 @@
 static_assert(alignof(int16_t) == 2, "");
 static_assert(sizeof(int32_t) == 4, "");
 static_assert(alignof(int32_t) == 4, "");
+static_assert(sizeof(Int64) == 8, "");
+static_assert(alignof(Int64) == 8, "");
 static_assert(sizeof(Int128) == 16, "");
 static_assert(alignof(Int128) == 8, "");
 
@@ -1271,14 +1291,14 @@
 TEST(Layout, Alignment) {
   static_assert(Layout<int8_t>::Alignment() == 1, "");
   static_assert(Layout<int32_t>::Alignment() == 4, "");
-  static_assert(Layout<int64_t>::Alignment() == 8, "");
+  static_assert(Layout<Int64>::Alignment() == 8, "");
   static_assert(Layout<Aligned<int8_t, 64>>::Alignment() == 64, "");
-  static_assert(Layout<int8_t, int32_t, int64_t>::Alignment() == 8, "");
-  static_assert(Layout<int8_t, int64_t, int32_t>::Alignment() == 8, "");
-  static_assert(Layout<int32_t, int8_t, int64_t>::Alignment() == 8, "");
-  static_assert(Layout<int32_t, int64_t, int8_t>::Alignment() == 8, "");
-  static_assert(Layout<int64_t, int8_t, int32_t>::Alignment() == 8, "");
-  static_assert(Layout<int64_t, int32_t, int8_t>::Alignment() == 8, "");
+  static_assert(Layout<int8_t, int32_t, Int64>::Alignment() == 8, "");
+  static_assert(Layout<int8_t, Int64, int32_t>::Alignment() == 8, "");
+  static_assert(Layout<int32_t, int8_t, Int64>::Alignment() == 8, "");
+  static_assert(Layout<int32_t, Int64, int8_t>::Alignment() == 8, "");
+  static_assert(Layout<Int64, int8_t, int32_t>::Alignment() == 8, "");
+  static_assert(Layout<Int64, int32_t, int8_t>::Alignment() == 8, "");
 }
 
 TEST(Layout, ConstexprPartial) {
@@ -1313,7 +1333,7 @@
 }
 
 TEST(Layout, PoisonPadding) {
-  using L = Layout<int8_t, int64_t, int32_t, Int128>;
+  using L = Layout<int8_t, Int64, int32_t, Int128>;
 
   constexpr size_t n = L::Partial(1, 2, 3, 4).AllocSize();
   {
@@ -1361,12 +1381,6 @@
 }
 
 TEST(Layout, DebugString) {
-  const std::string int64_type =
-#ifdef _MSC_VER
-  "__int64";
-#else   // _MSC_VER
-  std::is_same<int64_t, long long>::value ? "long long" : "long";  // NOLINT
-#endif  // _MSC_VER
   {
     constexpr auto x = Layout<int8_t, int32_t, int8_t, Int128>::Partial();
     EXPECT_EQ("@0<signed char>(1)", x.DebugString());
@@ -1384,24 +1398,24 @@
     constexpr auto x = Layout<int8_t, int32_t, int8_t, Int128>::Partial(1, 2, 3);
     EXPECT_EQ(
         "@0<signed char>(1)[1]; @4<int>(4)[2]; @12<signed char>(1)[3]; "
-        "@16<" +
-            int64_type + " [2]>(16)",
+        "@16" +
+            Int128::Name() + "(16)",
         x.DebugString());
   }
   {
     constexpr auto x = Layout<int8_t, int32_t, int8_t, Int128>::Partial(1, 2, 3, 4);
     EXPECT_EQ(
         "@0<signed char>(1)[1]; @4<int>(4)[2]; @12<signed char>(1)[3]; "
-        "@16<" +
-            int64_type + " [2]>(16)[4]",
+        "@16" +
+            Int128::Name() + "(16)[4]",
         x.DebugString());
   }
   {
     constexpr Layout<int8_t, int32_t, int8_t, Int128> x(1, 2, 3, 4);
     EXPECT_EQ(
         "@0<signed char>(1)[1]; @4<int>(4)[2]; @12<signed char>(1)[3]; "
-        "@16<" +
-            int64_type + " [2]>(16)[4]",
+        "@16" +
+            Int128::Name() + "(16)[4]",
         x.DebugString());
   }
 }
@@ -1528,8 +1542,7 @@
   const char* c_str() const {
     // Equivalent to reinterpret_cast<char*>(p.get() + sizeof(size_t)).
     // The argument in Partial(1) specifies that we have size_t[1] in front of
-    // the
-    // characters.
+    // the characters.
     return L::Partial(1).Pointer<char>(p_.get());
   }
 
diff --git a/absl/container/internal/node_hash_policy.h b/absl/container/internal/node_hash_policy.h
index 065e700..19b4fc0 100644
--- a/absl/container/internal/node_hash_policy.h
+++ b/absl/container/internal/node_hash_policy.h
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
diff --git a/absl/container/internal/node_hash_policy_test.cc b/absl/container/internal/node_hash_policy_test.cc
index 43d287e..f1d3ec3 100644
--- a/absl/container/internal/node_hash_policy_test.cc
+++ b/absl/container/internal/node_hash_policy_test.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
diff --git a/absl/container/internal/raw_hash_map.h b/absl/container/internal/raw_hash_map.h
index 1edc007..0014cf8 100644
--- a/absl/container/internal/raw_hash_map.h
+++ b/absl/container/internal/raw_hash_map.h
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -39,11 +39,14 @@
   using MappedConstReference = decltype(P::value(
       std::addressof(std::declval<typename raw_hash_map::const_reference>())));
 
+  using KeyArgImpl =
+      KeyArg<IsTransparent<Eq>::value && IsTransparent<Hash>::value>;
+
  public:
   using key_type = typename Policy::key_type;
   using mapped_type = typename Policy::mapped_type;
-  template <typename K>
-  using key_arg = typename raw_hash_map::raw_hash_set::template key_arg<K>;
+  template <class K>
+  using key_arg = typename KeyArgImpl::template type<K, key_type>;
 
   static_assert(!std::is_reference<key_type>::value, "");
   // TODO(alkis): remove this assertion and verify that reference mapped_type is
diff --git a/absl/container/internal/raw_hash_set.cc b/absl/container/internal/raw_hash_set.cc
index 1015312..ac2d10a 100644
--- a/absl/container/internal/raw_hash_set.cc
+++ b/absl/container/internal/raw_hash_set.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -14,6 +14,7 @@
 
 #include "absl/container/internal/raw_hash_set.h"
 
+#include <atomic>
 #include <cstddef>
 
 #include "absl/base/config.h"
@@ -29,7 +30,7 @@
   static thread_local size_t counter = 0;
   size_t value = ++counter;
 #else   // ABSL_HAVE_THREAD_LOCAL
-  static std::atomic<size_t> counter;
+  static std::atomic<size_t> counter(0);
   size_t value = counter.fetch_add(1, std::memory_order_relaxed);
 #endif  // ABSL_HAVE_THREAD_LOCAL
   return value ^ static_cast<size_t>(reinterpret_cast<uintptr_t>(&counter));
diff --git a/absl/container/internal/raw_hash_set.h b/absl/container/internal/raw_hash_set.h
index 70da90f..85e3334 100644
--- a/absl/container/internal/raw_hash_set.h
+++ b/absl/container/internal/raw_hash_set.h
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -91,30 +91,6 @@
 #ifndef ABSL_CONTAINER_INTERNAL_RAW_HASH_SET_H_
 #define ABSL_CONTAINER_INTERNAL_RAW_HASH_SET_H_
 
-#ifndef SWISSTABLE_HAVE_SSE2
-#ifdef __SSE2__
-#define SWISSTABLE_HAVE_SSE2 1
-#else
-#define SWISSTABLE_HAVE_SSE2 0
-#endif
-#endif
-
-#ifndef SWISSTABLE_HAVE_SSSE3
-#ifdef __SSSE3__
-#define SWISSTABLE_HAVE_SSSE3 1
-#else
-#define SWISSTABLE_HAVE_SSSE3 0
-#endif
-#endif
-
-#if SWISSTABLE_HAVE_SSSE3 && !SWISSTABLE_HAVE_SSE2
-#error "Bad configuration!"
-#endif
-
-#if SWISSTABLE_HAVE_SSE2
-#include <x86intrin.h>
-#endif
-
 #include <algorithm>
 #include <cmath>
 #include <cstdint>
@@ -129,14 +105,16 @@
 #include "absl/base/internal/bits.h"
 #include "absl/base/internal/endian.h"
 #include "absl/base/port.h"
+#include "absl/container/internal/common.h"
 #include "absl/container/internal/compressed_tuple.h"
 #include "absl/container/internal/container_memory.h"
 #include "absl/container/internal/hash_policy_traits.h"
 #include "absl/container/internal/hashtable_debug_hooks.h"
+#include "absl/container/internal/hashtablez_sampler.h"
+#include "absl/container/internal/have_sse.h"
 #include "absl/container/internal/layout.h"
 #include "absl/memory/memory.h"
 #include "absl/meta/type_traits.h"
-#include "absl/types/optional.h"
 #include "absl/utility/utility.h"
 
 namespace absl {
@@ -187,12 +165,6 @@
                       std::declval<Ts>()...))>,
     Policy, Hash, Eq, Ts...> : std::true_type {};
 
-template <class, class = void>
-struct IsTransparent : std::false_type {};
-template <class T>
-struct IsTransparent<T, absl::void_t<typename T::is_transparent>>
-    : std::true_type {};
-
 // TODO(alkis): Switch to std::is_nothrow_swappable when gcc/clang supports it.
 template <class T>
 constexpr bool IsNoThrowSwappable() {
@@ -202,14 +174,17 @@
 
 template <typename T>
 int TrailingZeros(T x) {
-  return sizeof(T) == 8 ? base_internal::CountTrailingZerosNonZero64(x)
-                        : base_internal::CountTrailingZerosNonZero32(x);
+  return sizeof(T) == 8 ? base_internal::CountTrailingZerosNonZero64(
+                              static_cast<uint64_t>(x))
+                        : base_internal::CountTrailingZerosNonZero32(
+                              static_cast<uint32_t>(x));
 }
 
 template <typename T>
 int LeadingZeros(T x) {
-  return sizeof(T) == 8 ? base_internal::CountLeadingZeros64(x)
-                        : base_internal::CountLeadingZeros32(x);
+  return sizeof(T) == 8
+             ? base_internal::CountLeadingZeros64(static_cast<uint64_t>(x))
+             : base_internal::CountLeadingZeros32(static_cast<uint32_t>(x));
 }
 
 // An abstraction over a bitmask. It provides an easy way to iterate through the
@@ -337,10 +312,27 @@
 inline bool IsEmptyOrDeleted(ctrl_t c) { return c < kSentinel; }
 
 #if SWISSTABLE_HAVE_SSE2
-struct Group {
+
+// https://github.com/abseil/abseil-cpp/issues/209
+// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87853
+// _mm_cmpgt_epi8 is broken under GCC with -funsigned-char
+// Work around this by using the portable implementation of Group
+// when using -funsigned-char under GCC.
+inline __m128i _mm_cmpgt_epi8_fixed(__m128i a, __m128i b) {
+#if defined(__GNUC__) && !defined(__clang__)
+  if (std::is_unsigned<char>::value) {
+    const __m128i mask = _mm_set1_epi8(0x80);
+    const __m128i diff = _mm_subs_epi8(b, a);
+    return _mm_cmpeq_epi8(_mm_and_si128(diff, mask), mask);
+  }
+#endif
+  return _mm_cmpgt_epi8(a, b);
+}
+
+struct GroupSse2Impl {
   static constexpr size_t kWidth = 16;  // the number of slots per group
 
-  explicit Group(const ctrl_t* pos) {
+  explicit GroupSse2Impl(const ctrl_t* pos) {
     ctrl = _mm_loadu_si128(reinterpret_cast<const __m128i*>(pos));
   }
 
@@ -366,23 +358,24 @@
   BitMask<uint32_t, kWidth> MatchEmptyOrDeleted() const {
     auto special = _mm_set1_epi8(kSentinel);
     return BitMask<uint32_t, kWidth>(
-        _mm_movemask_epi8(_mm_cmpgt_epi8(special, ctrl)));
+        _mm_movemask_epi8(_mm_cmpgt_epi8_fixed(special, ctrl)));
   }
 
   // Returns the number of trailing empty or deleted elements in the group.
   uint32_t CountLeadingEmptyOrDeleted() const {
     auto special = _mm_set1_epi8(kSentinel);
-    return TrailingZeros(_mm_movemask_epi8(_mm_cmpgt_epi8(special, ctrl)) + 1);
+    return TrailingZeros(
+        _mm_movemask_epi8(_mm_cmpgt_epi8_fixed(special, ctrl)) + 1);
   }
 
   void ConvertSpecialToEmptyAndFullToDeleted(ctrl_t* dst) const {
-    auto msbs = _mm_set1_epi8(0x80);
+    auto msbs = _mm_set1_epi8(static_cast<char>(-128));
     auto x126 = _mm_set1_epi8(126);
 #if SWISSTABLE_HAVE_SSSE3
     auto res = _mm_or_si128(_mm_shuffle_epi8(x126, ctrl), msbs);
 #else
     auto zero = _mm_setzero_si128();
-    auto special_mask = _mm_cmpgt_epi8(zero, ctrl);
+    auto special_mask = _mm_cmpgt_epi8_fixed(zero, ctrl);
     auto res = _mm_or_si128(msbs, _mm_andnot_si128(special_mask, x126));
 #endif
     _mm_storeu_si128(reinterpret_cast<__m128i*>(dst), res);
@@ -390,11 +383,13 @@
 
   __m128i ctrl;
 };
-#else
-struct Group {
+#endif  // SWISSTABLE_HAVE_SSE2
+
+struct GroupPortableImpl {
   static constexpr size_t kWidth = 8;
 
-  explicit Group(const ctrl_t* pos) : ctrl(little_endian::Load64(pos)) {}
+  explicit GroupPortableImpl(const ctrl_t* pos)
+      : ctrl(little_endian::Load64(pos)) {}
 
   BitMask<uint64_t, kWidth, 3> Match(h2_t hash) const {
     // For the technique, see:
@@ -441,15 +436,17 @@
 
   uint64_t ctrl;
 };
-#endif  // SWISSTABLE_HAVE_SSE2
+
+#if SWISSTABLE_HAVE_SSE2
+using Group = GroupSse2Impl;
+#else
+using Group = GroupPortableImpl;
+#endif
 
 template <class Policy, class Hash, class Eq, class Alloc>
 class raw_hash_set;
 
-
-inline bool IsValidCapacity(size_t n) {
-  return ((n + 1) & n) == 0 && n >= Group::kWidth - 1;
-}
+inline bool IsValidCapacity(size_t n) { return ((n + 1) & n) == 0 && n > 0; }
 
 // PRECONDITION:
 //   IsValidCapacity(capacity)
@@ -471,152 +468,32 @@
   ctrl[capacity] = kSentinel;
 }
 
-// Rounds up the capacity to the next power of 2 minus 1 and ensures it is
-// greater or equal to Group::kWidth - 1.
+// Rounds up the capacity to the next power of 2 minus 1, with a minimum of 1.
 inline size_t NormalizeCapacity(size_t n) {
-  constexpr size_t kMinCapacity = Group::kWidth - 1;
-  return n <= kMinCapacity
-             ? kMinCapacity
-             : std::numeric_limits<size_t>::max() >> LeadingZeros(n);
+  return n ? ~size_t{} >> LeadingZeros(n) : 1;
 }
 
-// The node_handle concept from C++17.
-// We specialize node_handle for sets and maps. node_handle_base holds the
-// common API of both.
-template <typename Policy, typename Alloc>
-class node_handle_base {
- protected:
-  using PolicyTraits = hash_policy_traits<Policy>;
-  using slot_type = typename PolicyTraits::slot_type;
-
- public:
-  using allocator_type = Alloc;
-
-  constexpr node_handle_base() {}
-  node_handle_base(node_handle_base&& other) noexcept {
-    *this = std::move(other);
+// We use 7/8th as maximum load factor.
+// For 16-wide groups, that gives an average of two empty slots per group.
+inline size_t CapacityToGrowth(size_t capacity) {
+  assert(IsValidCapacity(capacity));
+  // `capacity*7/8`
+  if (Group::kWidth == 8 && capacity == 7) {
+    // x-x/8 does not work when x==7.
+    return 6;
   }
-  ~node_handle_base() { destroy(); }
-  node_handle_base& operator=(node_handle_base&& other) {
-    destroy();
-    if (!other.empty()) {
-      alloc_ = other.alloc_;
-      PolicyTraits::transfer(alloc(), slot(), other.slot());
-      other.reset();
-    }
-    return *this;
+  return capacity - capacity / 8;
+}
+// From desired "growth" to a lowerbound of the necessary capacity.
+// Might not be a valid one and required NormalizeCapacity().
+inline size_t GrowthToLowerboundCapacity(size_t growth) {
+  // `growth*8/7`
+  if (Group::kWidth == 8 && growth == 7) {
+    // x+(x-1)/7 does not work when x==7.
+    return 8;
   }
-
-  bool empty() const noexcept { return !alloc_; }
-  explicit operator bool() const noexcept { return !empty(); }
-  allocator_type get_allocator() const { return *alloc_; }
-
- protected:
-  template <typename, typename, typename, typename>
-  friend class raw_hash_set;
-
-  node_handle_base(const allocator_type& a, slot_type* s) : alloc_(a) {
-    PolicyTraits::transfer(alloc(), slot(), s);
-  }
-
-  void destroy() {
-    if (!empty()) {
-      PolicyTraits::destroy(alloc(), slot());
-      reset();
-    }
-  }
-
-  void reset() {
-    assert(alloc_.has_value());
-    alloc_ = absl::nullopt;
-  }
-
-  slot_type* slot() const {
-    assert(!empty());
-    return reinterpret_cast<slot_type*>(std::addressof(slot_space_));
-  }
-  allocator_type* alloc() { return std::addressof(*alloc_); }
-
- private:
-  absl::optional<allocator_type> alloc_;
-  mutable absl::aligned_storage_t<sizeof(slot_type), alignof(slot_type)>
-      slot_space_;
-};
-
-// For sets.
-template <typename Policy, typename Alloc, typename = void>
-class node_handle : public node_handle_base<Policy, Alloc> {
-  using Base = typename node_handle::node_handle_base;
-
- public:
-  using value_type = typename Base::PolicyTraits::value_type;
-
-  constexpr node_handle() {}
-
-  value_type& value() const {
-    return Base::PolicyTraits::element(this->slot());
-  }
-
- private:
-  template <typename, typename, typename, typename>
-  friend class raw_hash_set;
-
-  node_handle(const Alloc& a, typename Base::slot_type* s) : Base(a, s) {}
-};
-
-// For maps.
-template <typename Policy, typename Alloc>
-class node_handle<Policy, Alloc, absl::void_t<typename Policy::mapped_type>>
-    : public node_handle_base<Policy, Alloc> {
-  using Base = typename node_handle::node_handle_base;
-
- public:
-  using key_type = typename Policy::key_type;
-  using mapped_type = typename Policy::mapped_type;
-
-  constexpr node_handle() {}
-
-  auto key() const -> decltype(Base::PolicyTraits::key(this->slot())) {
-    return Base::PolicyTraits::key(this->slot());
-  }
-
-  mapped_type& mapped() const {
-    return Base::PolicyTraits::value(
-        &Base::PolicyTraits::element(this->slot()));
-  }
-
- private:
-  template <typename, typename, typename, typename>
-  friend class raw_hash_set;
-
-  node_handle(const Alloc& a, typename Base::slot_type* s) : Base(a, s) {}
-};
-
-// Implement the insert_return_type<> concept of C++17.
-template <class Iterator, class NodeType>
-struct insert_return_type {
-  Iterator position;
-  bool inserted;
-  NodeType node;
-};
-
-// Helper trait to allow or disallow arbitrary keys when the hash and
-// eq functions are transparent.
-// It is very important that the inner template is an alias and that the type it
-// produces is not a dependent type. Otherwise, type deduction would fail.
-template <bool is_transparent>
-struct KeyArg {
-  // Transparent. Forward `K`.
-  template <typename K, typename key_type>
-  using type = K;
-};
-
-template <>
-struct KeyArg<false> {
-  // Not transparent. Always use `key_type`.
-  template <typename K, typename key_type>
-  using type = key_type;
-};
+  return growth + static_cast<size_t>((static_cast<int64_t>(growth) - 1) / 7);
+}
 
 // Policy: a policy defines how to perform different operations on
 // the slots of the hashtable (see hash_policy_traits.h for the full interface
@@ -632,14 +509,14 @@
 // if they are equal, false if they are not. If two keys compare equal, then
 // their hash values as defined by Hash MUST be equal.
 //
-// Allocator: an Allocator [http://devdocs.io/cpp/concept/allocator] with which
+// Allocator: an Allocator [https://devdocs.io/cpp/concept/allocator] with which
 // the storage of the hashtable will be allocated and the elements will be
 // constructed and destroyed.
 template <class Policy, class Hash, class Eq, class Alloc>
 class raw_hash_set {
   using PolicyTraits = hash_policy_traits<Policy>;
-  using KeyArgImpl = container_internal::KeyArg<IsTransparent<Eq>::value &&
-                                                IsTransparent<Hash>::value>;
+  using KeyArgImpl =
+      KeyArg<IsTransparent<Eq>::value && IsTransparent<Hash>::value>;
 
  public:
   using init_type = typename PolicyTraits::init_type;
@@ -662,7 +539,7 @@
       allocator_type>::template rebind_traits<value_type>::const_pointer;
 
   // Alias used for heterogeneous lookup functions.
-  // `key_arg<K>` evaluates to `K` when the functors are tranparent and to
+  // `key_arg<K>` evaluates to `K` when the functors are transparent and to
   // `key_type` otherwise. It permits template argument deduction on `K` for the
   // transparent case.
   template <class K>
@@ -780,7 +657,11 @@
     }
 
     ctrl_t* ctrl_ = nullptr;
-    slot_type* slot_;
+    // To avoid uninitialized member warnigs, put slot_ in an anonymous union.
+    // The member is not initialized on singleton and end iterators.
+    union {
+      slot_type* slot_;
+    };
   };
 
   class const_iterator {
@@ -820,7 +701,8 @@
     iterator inner_;
   };
 
-  using node_type = container_internal::node_handle<Policy, Alloc>;
+  using node_type = node_handle<Policy, hash_policy_traits<Policy>, Alloc>;
+  using insert_return_type = InsertReturnType<iterator, node_type>;
 
   raw_hash_set() noexcept(
       std::is_nothrow_default_constructible<hasher>::value&&
@@ -833,7 +715,7 @@
       : ctrl_(EmptyGroup()), settings_(0, hash, eq, alloc) {
     if (bucket_count) {
       capacity_ = NormalizeCapacity(bucket_count);
-      growth_left() = static_cast<size_t>(capacity_ * kMaxLoadFactor);
+      reset_growth_left();
       initialize_slots();
     }
   }
@@ -875,8 +757,8 @@
   // that accept std::initializer_list<T> and std::initializer_list<init_type>.
   // This is advantageous for performance.
   //
-  //   // Turns {"abc", "def"} into std::initializer_list<std::string>, then copies
-  //   // the strings into the set.
+  //   // Turns {"abc", "def"} into std::initializer_list<std::string>, then
+  //   // copies the strings into the set.
   //   std::unordered_set<std::string> s = {"abc", "def"};
   //
   //   // Turns {"abc", "def"} into std::initializer_list<const char*>, then
@@ -939,9 +821,10 @@
     // than a full `insert`.
     for (const auto& v : that) {
       const size_t hash = PolicyTraits::apply(HashElement{hash_ref()}, v);
-      const size_t i = find_first_non_full(hash);
-      set_ctrl(i, H2(hash));
-      emplace_at(i, v);
+      auto target = find_first_non_full(hash);
+      set_ctrl(target.offset, H2(hash));
+      emplace_at(target.offset, v);
+      infoz_.RecordInsert(hash, target.probe_length);
     }
     size_ = that.size();
     growth_left() -= that.size();
@@ -955,6 +838,7 @@
         slots_(absl::exchange(that.slots_, nullptr)),
         size_(absl::exchange(that.size_, 0)),
         capacity_(absl::exchange(that.capacity_, 0)),
+        infoz_(absl::exchange(that.infoz_, HashtablezInfoHandle())),
         // Hash, equality and allocator are copied instead of moved because
         // `that` must be left valid. If Hash is std::function<Key>, moving it
         // would create a nullptr functor that cannot be called.
@@ -975,6 +859,7 @@
       std::swap(size_, that.size_);
       std::swap(capacity_, that.capacity_);
       std::swap(growth_left(), that.growth_left());
+      std::swap(infoz_, that.infoz_);
     } else {
       reserve(that.size());
       // Note: this will copy elements of dense_set and unordered_set instead of
@@ -1022,9 +907,9 @@
   bool empty() const { return !size(); }
   size_t size() const { return size_; }
   size_t capacity() const { return capacity_; }
-  size_t max_size() const { return std::numeric_limits<size_t>::max(); }
+  size_t max_size() const { return (std::numeric_limits<size_t>::max)(); }
 
-  void clear() {
+  ABSL_ATTRIBUTE_REINITIALIZES void clear() {
     // Iterating over this container is O(bucket_count()). When bucket_count()
     // is much greater than size(), iteration becomes prohibitively expensive.
     // For clear() it is more important to reuse the allocated array when the
@@ -1042,9 +927,10 @@
       }
       size_ = 0;
       reset_ctrl();
-      growth_left() = static_cast<size_t>(capacity_ * kMaxLoadFactor);
+      reset_growth_left();
     }
     assert(empty());
+    infoz_.RecordStorageChanged(0, capacity_);
   }
 
   // This overload kicks in when the argument is an rvalue of insertable and
@@ -1124,13 +1010,14 @@
     insert(ilist.begin(), ilist.end());
   }
 
-  insert_return_type<iterator, node_type> insert(node_type&& node) {
+  insert_return_type insert(node_type&& node) {
     if (!node) return {end(), false, node_type()};
-    const auto& elem = PolicyTraits::element(node.slot());
+    const auto& elem = PolicyTraits::element(CommonAccess::GetSlot(node));
     auto res = PolicyTraits::apply(
-        InsertSlot<false>{*this, std::move(*node.slot())}, elem);
+        InsertSlot<false>{*this, std::move(*CommonAccess::GetSlot(node))},
+        elem);
     if (res.second) {
-      node.reset();
+      CommonAccess::Reset(&node);
       return {res.first, true, node_type()};
     } else {
       return {res.first, false, std::move(node)};
@@ -1294,7 +1181,8 @@
   }
 
   node_type extract(const_iterator position) {
-    node_type node(alloc_ref(), position.inner_.slot_);
+    auto node =
+        CommonAccess::Make<node_type>(alloc_ref(), position.inner_.slot_);
     erase_meta_only(position);
     return node;
   }
@@ -1319,6 +1207,7 @@
     swap(growth_left(), that.growth_left());
     swap(hash_ref(), that.hash_ref());
     swap(eq_ref(), that.eq_ref());
+    swap(infoz_, that.infoz_);
     if (AllocTraits::propagate_on_container_swap::value) {
       swap(alloc_ref(), that.alloc_ref());
     } else {
@@ -1329,17 +1218,21 @@
 
   void rehash(size_t n) {
     if (n == 0 && capacity_ == 0) return;
-    if (n == 0 && size_ == 0) return destroy_slots();
-    auto m = NormalizeCapacity(std::max(n, NumSlotsFast(size())));
+    if (n == 0 && size_ == 0) {
+      destroy_slots();
+      infoz_.RecordStorageChanged(0, 0);
+      return;
+    }
+    // bitor is a faster way of doing `max` here. We will round up to the next
+    // power-of-2-minus-1, so bitor is good enough.
+    auto m = NormalizeCapacity(n | GrowthToLowerboundCapacity(size()));
     // n == 0 unconditionally rehashes as per the standard.
     if (n == 0 || m > capacity_) {
       resize(m);
     }
   }
 
-  void reserve(size_t n) {
-    rehash(NumSlotsFast(n));
-  }
+  void reserve(size_t n) { rehash(GrowthToLowerboundCapacity(n)); }
 
   // Extension API: support for heterogeneous keys.
   //
@@ -1517,13 +1410,6 @@
     slot_type&& slot;
   };
 
-  // Computes std::ceil(n / kMaxLoadFactor). Faster than calling std::ceil.
-  static inline size_t NumSlotsFast(size_t n) {
-    return static_cast<size_t>(
-        (n * kMaxLoadFactorDenominator + (kMaxLoadFactorNumerator - 1)) /
-        kMaxLoadFactorNumerator);
-  }
-
   // "erases" the object from the container, except that it doesn't actually
   // destroy the object. It only updates all the metadata of the class.
   // This can be used in conjunction with Policy::transfer to move the object to
@@ -1546,17 +1432,23 @@
 
     set_ctrl(index, was_never_full ? kEmpty : kDeleted);
     growth_left() += was_never_full;
+    infoz_.RecordErase();
   }
 
   void initialize_slots() {
     assert(capacity_);
+    if (slots_ == nullptr) {
+      infoz_ = Sample();
+    }
+
     auto layout = MakeLayout(capacity_);
     char* mem = static_cast<char*>(
         Allocate<Layout::Alignment()>(&alloc_ref(), layout.AllocSize()));
     ctrl_ = reinterpret_cast<ctrl_t*>(layout.template Pointer<0>(mem));
     slots_ = layout.template Pointer<1>(mem);
     reset_ctrl();
-    growth_left() = static_cast<size_t>(capacity_ * kMaxLoadFactor) - size_;
+    reset_growth_left();
+    infoz_.RecordStorageChanged(size_, capacity_);
   }
 
   void destroy_slots() {
@@ -1585,11 +1477,14 @@
     capacity_ = new_capacity;
     initialize_slots();
 
+    size_t total_probe_length = 0;
     for (size_t i = 0; i != old_capacity; ++i) {
       if (IsFull(old_ctrl[i])) {
         size_t hash = PolicyTraits::apply(HashElement{hash_ref()},
                                           PolicyTraits::element(old_slots + i));
-        size_t new_i = find_first_non_full(hash);
+        auto target = find_first_non_full(hash);
+        size_t new_i = target.offset;
+        total_probe_length += target.probe_length;
         set_ctrl(new_i, H2(hash));
         PolicyTraits::transfer(&alloc_ref(), slots_ + new_i, old_slots + i);
       }
@@ -1601,10 +1496,12 @@
       Deallocate<Layout::Alignment()>(&alloc_ref(), old_ctrl,
                                       layout.AllocSize());
     }
+    infoz_.RecordRehash(total_probe_length);
   }
 
   void drop_deletes_without_resize() ABSL_ATTRIBUTE_NOINLINE {
     assert(IsValidCapacity(capacity_));
+    assert(!is_small());
     // Algorithm:
     // - mark all DELETED slots as EMPTY
     // - mark all FULL slots as DELETED
@@ -1624,12 +1521,15 @@
     ConvertDeletedToEmptyAndFullToDeleted(ctrl_, capacity_);
     typename std::aligned_storage<sizeof(slot_type), alignof(slot_type)>::type
         raw;
+    size_t total_probe_length = 0;
     slot_type* slot = reinterpret_cast<slot_type*>(&raw);
     for (size_t i = 0; i != capacity_; ++i) {
       if (!IsDeleted(ctrl_[i])) continue;
       size_t hash = PolicyTraits::apply(HashElement{hash_ref()},
                                         PolicyTraits::element(slots_ + i));
-      size_t new_i = find_first_non_full(hash);
+      auto target = find_first_non_full(hash);
+      size_t new_i = target.offset;
+      total_probe_length += target.probe_length;
 
       // Verify if the old and new i fall within the same group wrt the hash.
       // If they do, we don't need to move the object as it falls already in the
@@ -1661,13 +1561,14 @@
         --i;  // repeat
       }
     }
-    growth_left() = static_cast<size_t>(capacity_ * kMaxLoadFactor) - size_;
+    reset_growth_left();
+    infoz_.RecordRehash(total_probe_length);
   }
 
   void rehash_and_grow_if_necessary() {
     if (capacity_ == 0) {
-      resize(Group::kWidth - 1);
-    } else if (size() <= kMaxLoadFactor / 2 * capacity_) {
+      resize(1);
+    } else if (size() <= CapacityToGrowth(capacity()) / 2) {
       // Squash DELETED without growing if there is enough capacity.
       drop_deletes_without_resize();
     } else {
@@ -1702,24 +1603,26 @@
   // - the input is already a set
   // - there are enough slots
   // - the element with the hash is not in the table
-  size_t find_first_non_full(size_t hash) {
+  struct FindInfo {
+    size_t offset;
+    size_t probe_length;
+  };
+  FindInfo find_first_non_full(size_t hash) {
     auto seq = probe(hash);
     while (true) {
       Group g{ctrl_ + seq.offset()};
       auto mask = g.MatchEmptyOrDeleted();
       if (mask) {
 #if !defined(NDEBUG)
-        // We want to force small tables to have random entries too, so
-        // in debug build we will randomly insert in either the front or back of
+        // We want to add entropy even when ASLR is not enabled.
+        // In debug build we will randomly insert in either the front or back of
         // the group.
         // TODO(kfm,sbenza): revisit after we do unconditional mixing
-        if (ShouldInsertBackwards(hash, ctrl_))
-          return seq.offset(mask.HighestBitSet());
-        else
-          return seq.offset(mask.LowestBitSet());
-#else
-        return seq.offset(mask.LowestBitSet());
+        if (!is_small() && ShouldInsertBackwards(hash, ctrl_)) {
+          return {seq.offset(mask.HighestBitSet()), seq.index()};
+        }
 #endif
+        return {seq.offset(mask.LowestBitSet()), seq.index()};
       }
       assert(seq.index() < capacity_ && "full table!");
       seq.next();
@@ -1758,15 +1661,17 @@
   }
 
   size_t prepare_insert(size_t hash) ABSL_ATTRIBUTE_NOINLINE {
-    size_t target = find_first_non_full(hash);
-    if (ABSL_PREDICT_FALSE(growth_left() == 0 && !IsDeleted(ctrl_[target]))) {
+    auto target = find_first_non_full(hash);
+    if (ABSL_PREDICT_FALSE(growth_left() == 0 &&
+                           !IsDeleted(ctrl_[target.offset]))) {
       rehash_and_grow_if_necessary();
       target = find_first_non_full(hash);
     }
     ++size_;
-    growth_left() -= IsEmpty(ctrl_[target]);
-    set_ctrl(target, H2(hash));
-    return target;
+    growth_left() -= IsEmpty(ctrl_[target.offset]);
+    set_ctrl(target.offset, H2(hash));
+    infoz_.RecordInsert(hash, target.probe_length);
+    return target.offset;
   }
 
   // Constructs the value in the space pointed by the iterator. This only works
@@ -1804,6 +1709,10 @@
     SanitizerPoisonMemoryRegion(slots_, sizeof(slot_type) * capacity_);
   }
 
+  void reset_growth_left() {
+    growth_left() = CapacityToGrowth(capacity()) - size_;
+  }
+
   // Sets the control byte, and if `i < Group::kWidth`, set the cloned byte at
   // the end too.
   void set_ctrl(size_t i, ctrl_t h) {
@@ -1816,11 +1725,28 @@
     }
 
     ctrl_[i] = h;
-    ctrl_[((i - Group::kWidth) & capacity_) + Group::kWidth] = h;
+    ctrl_[((i - Group::kWidth) & capacity_) + 1 +
+          ((Group::kWidth - 1) & capacity_)] = h;
   }
 
   size_t& growth_left() { return settings_.template get<0>(); }
 
+  // The representation of the object has two modes:
+  //  - small: For capacities < kWidth-1
+  //  - large: For the rest.
+  //
+  // Differences:
+  //  - In small mode we are able to use the whole capacity. The extra control
+  //  bytes give us at least one "empty" control byte to stop the iteration.
+  //  This is important to make 1 a valid capacity.
+  //
+  //  - In small mode only the first `capacity()` control bytes after the
+  //  sentinel are valid. The rest contain dummy kEmpty values that do not
+  //  represent a real slot. This is important to take into account on
+  //  find_first_non_full(), where we never try ShouldInsertBackwards() for
+  //  small tables.
+  bool is_small() const { return capacity_ < Group::kWidth - 1; }
+
   hasher& hash_ref() { return settings_.template get<1>(); }
   const hasher& hash_ref() const { return settings_.template get<1>(); }
   key_equal& eq_ref() { return settings_.template get<2>(); }
@@ -1830,12 +1756,6 @@
     return settings_.template get<3>();
   }
 
-  // On average each group has 2 empty slot (for the vectorized case).
-  static constexpr int64_t kMaxLoadFactorNumerator = 14;
-  static constexpr int64_t kMaxLoadFactorDenominator = 16;
-  static constexpr float kMaxLoadFactor =
-      1.0 * kMaxLoadFactorNumerator / kMaxLoadFactorDenominator;
-
   // TODO(alkis): Investigate removing some of these fields:
   // - ctrl/slots can be derived from each other
   // - size can be moved into the slot array
@@ -1843,6 +1763,7 @@
   slot_type* slots_ = nullptr;     // [capacity * slot_type]
   size_t size_ = 0;                // number of full slots
   size_t capacity_ = 0;            // total number of slots
+  HashtablezInfoHandle infoz_;
   absl::container_internal::CompressedTuple<size_t /* growth_left */, hasher,
                                             key_equal, allocator_type>
       settings_{0, hasher{}, key_equal{}, allocator_type{}};
@@ -1895,10 +1816,9 @@
   }
 
   static size_t LowerBoundAllocatedByteSize(size_t size) {
-    size_t capacity = container_internal::NormalizeCapacity(
-        std::ceil(size / Set::kMaxLoadFactor));
+    size_t capacity = GrowthToLowerboundCapacity(size);
     if (capacity == 0) return 0;
-    auto layout = Set::MakeLayout(capacity);
+    auto layout = Set::MakeLayout(NormalizeCapacity(capacity));
     size_t m = layout.AllocSize();
     size_t per_slot = Traits::space_used(static_cast<const Slot*>(nullptr));
     if (per_slot != ~size_t{}) {
diff --git a/absl/container/internal/raw_hash_set_allocator_test.cc b/absl/container/internal/raw_hash_set_allocator_test.cc
index 891fa45..a5eff0b 100644
--- a/absl/container/internal/raw_hash_set_allocator_test.cc
+++ b/absl/container/internal/raw_hash_set_allocator_test.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
diff --git a/absl/container/internal/raw_hash_set_test.cc b/absl/container/internal/raw_hash_set_test.cc
index cd33a3a..02fd0bf 100644
--- a/absl/container/internal/raw_hash_set_test.cc
+++ b/absl/container/internal/raw_hash_set_test.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -14,7 +14,6 @@
 
 #include "absl/container/internal/raw_hash_set.h"
 
-#include <array>
 #include <cmath>
 #include <cstdint>
 #include <deque>
@@ -49,18 +48,47 @@
 
 using ::testing::DoubleNear;
 using ::testing::ElementsAre;
+using ::testing::Ge;
+using ::testing::Lt;
 using ::testing::Optional;
 using ::testing::Pair;
 using ::testing::UnorderedElementsAre;
 
 TEST(Util, NormalizeCapacity) {
-  constexpr size_t kMinCapacity = Group::kWidth - 1;
-  EXPECT_EQ(kMinCapacity, NormalizeCapacity(0));
-  EXPECT_EQ(kMinCapacity, NormalizeCapacity(1));
-  EXPECT_EQ(kMinCapacity, NormalizeCapacity(2));
-  EXPECT_EQ(kMinCapacity, NormalizeCapacity(kMinCapacity));
-  EXPECT_EQ(kMinCapacity * 2 + 1, NormalizeCapacity(kMinCapacity + 1));
-  EXPECT_EQ(kMinCapacity * 2 + 1, NormalizeCapacity(kMinCapacity + 2));
+  EXPECT_EQ(1, NormalizeCapacity(0));
+  EXPECT_EQ(1, NormalizeCapacity(1));
+  EXPECT_EQ(3, NormalizeCapacity(2));
+  EXPECT_EQ(3, NormalizeCapacity(3));
+  EXPECT_EQ(7, NormalizeCapacity(4));
+  EXPECT_EQ(7, NormalizeCapacity(7));
+  EXPECT_EQ(15, NormalizeCapacity(8));
+  EXPECT_EQ(15, NormalizeCapacity(15));
+  EXPECT_EQ(15 * 2 + 1, NormalizeCapacity(15 + 1));
+  EXPECT_EQ(15 * 2 + 1, NormalizeCapacity(15 + 2));
+}
+
+TEST(Util, GrowthAndCapacity) {
+  // Verify that GrowthToCapacity gives the minimum capacity that has enough
+  // growth.
+  for (size_t growth = 0; growth < 10000; ++growth) {
+    SCOPED_TRACE(growth);
+    size_t capacity = NormalizeCapacity(GrowthToLowerboundCapacity(growth));
+    // The capacity is large enough for `growth`
+    EXPECT_THAT(CapacityToGrowth(capacity), Ge(growth));
+    if (growth != 0 && capacity > 1) {
+      // There is no smaller capacity that works.
+      EXPECT_THAT(CapacityToGrowth(capacity / 2), Lt(growth));
+    }
+  }
+
+  for (size_t capacity = Group::kWidth - 1; capacity < 10000;
+       capacity = 2 * capacity + 1) {
+    SCOPED_TRACE(capacity);
+    size_t growth = CapacityToGrowth(capacity);
+    EXPECT_THAT(growth, Lt(capacity));
+    EXPECT_LE(GrowthToLowerboundCapacity(growth), capacity);
+    EXPECT_EQ(NormalizeCapacity(GrowthToLowerboundCapacity(growth)), capacity);
+  }
 }
 
 TEST(Util, probe_seq) {
@@ -107,14 +135,14 @@
 }
 
 TEST(BitMask, LeadingTrailing) {
-  EXPECT_EQ((BitMask<uint32_t, 16>(0b0001101001000000).LeadingZeros()), 3);
-  EXPECT_EQ((BitMask<uint32_t, 16>(0b0001101001000000).TrailingZeros()), 6);
+  EXPECT_EQ((BitMask<uint32_t, 16>(0x00001a40).LeadingZeros()), 3);
+  EXPECT_EQ((BitMask<uint32_t, 16>(0x00001a40).TrailingZeros()), 6);
 
-  EXPECT_EQ((BitMask<uint32_t, 16>(0b0000000000000001).LeadingZeros()), 15);
-  EXPECT_EQ((BitMask<uint32_t, 16>(0b0000000000000001).TrailingZeros()), 0);
+  EXPECT_EQ((BitMask<uint32_t, 16>(0x00000001).LeadingZeros()), 15);
+  EXPECT_EQ((BitMask<uint32_t, 16>(0x00000001).TrailingZeros()), 0);
 
-  EXPECT_EQ((BitMask<uint32_t, 16>(0b1000000000000000).LeadingZeros()), 0);
-  EXPECT_EQ((BitMask<uint32_t, 16>(0b1000000000000000).TrailingZeros()), 15);
+  EXPECT_EQ((BitMask<uint32_t, 16>(0x00008000).LeadingZeros()), 0);
+  EXPECT_EQ((BitMask<uint32_t, 16>(0x00008000).TrailingZeros()), 15);
 
   EXPECT_EQ((BitMask<uint64_t, 8, 3>(0x0000008080808000).LeadingZeros()), 3);
   EXPECT_EQ((BitMask<uint64_t, 8, 3>(0x0000008080808000).TrailingZeros()), 1);
@@ -130,45 +158,50 @@
   for (h2_t h = 0; h != 128; ++h) EXPECT_FALSE(Group{EmptyGroup()}.Match(h));
 }
 
-#if SWISSTABLE_HAVE_SSE2
 TEST(Group, Match) {
-  ctrl_t group[] = {kEmpty, 1, kDeleted, 3, kEmpty, 5, kSentinel, 7,
-                    7,      5, 3,        1, 1,      1, 1,         1};
-  EXPECT_THAT(Group{group}.Match(0), ElementsAre());
-  EXPECT_THAT(Group{group}.Match(1), ElementsAre(1, 11, 12, 13, 14, 15));
-  EXPECT_THAT(Group{group}.Match(3), ElementsAre(3, 10));
-  EXPECT_THAT(Group{group}.Match(5), ElementsAre(5, 9));
-  EXPECT_THAT(Group{group}.Match(7), ElementsAre(7, 8));
+  if (Group::kWidth == 16) {
+    ctrl_t group[] = {kEmpty, 1, kDeleted, 3, kEmpty, 5, kSentinel, 7,
+                      7,      5, 3,        1, 1,      1, 1,         1};
+    EXPECT_THAT(Group{group}.Match(0), ElementsAre());
+    EXPECT_THAT(Group{group}.Match(1), ElementsAre(1, 11, 12, 13, 14, 15));
+    EXPECT_THAT(Group{group}.Match(3), ElementsAre(3, 10));
+    EXPECT_THAT(Group{group}.Match(5), ElementsAre(5, 9));
+    EXPECT_THAT(Group{group}.Match(7), ElementsAre(7, 8));
+  } else if (Group::kWidth == 8) {
+    ctrl_t group[] = {kEmpty, 1, 2, kDeleted, 2, 1, kSentinel, 1};
+    EXPECT_THAT(Group{group}.Match(0), ElementsAre());
+    EXPECT_THAT(Group{group}.Match(1), ElementsAre(1, 5, 7));
+    EXPECT_THAT(Group{group}.Match(2), ElementsAre(2, 4));
+  } else {
+    FAIL() << "No test coverage for Group::kWidth==" << Group::kWidth;
+  }
 }
 
 TEST(Group, MatchEmpty) {
-  ctrl_t group[] = {kEmpty, 1, kDeleted, 3, kEmpty, 5, kSentinel, 7,
-                    7,      5, 3,        1, 1,      1, 1,         1};
-  EXPECT_THAT(Group{group}.MatchEmpty(), ElementsAre(0, 4));
+  if (Group::kWidth == 16) {
+    ctrl_t group[] = {kEmpty, 1, kDeleted, 3, kEmpty, 5, kSentinel, 7,
+                      7,      5, 3,        1, 1,      1, 1,         1};
+    EXPECT_THAT(Group{group}.MatchEmpty(), ElementsAre(0, 4));
+  } else if (Group::kWidth == 8) {
+    ctrl_t group[] = {kEmpty, 1, 2, kDeleted, 2, 1, kSentinel, 1};
+    EXPECT_THAT(Group{group}.MatchEmpty(), ElementsAre(0));
+  } else {
+    FAIL() << "No test coverage for Group::kWidth==" << Group::kWidth;
+  }
 }
 
 TEST(Group, MatchEmptyOrDeleted) {
-  ctrl_t group[] = {kEmpty, 1, kDeleted, 3, kEmpty, 5, kSentinel, 7,
-                    7,      5, 3,        1, 1,      1, 1,         1};
-  EXPECT_THAT(Group{group}.MatchEmptyOrDeleted(), ElementsAre(0, 2, 4));
+  if (Group::kWidth == 16) {
+    ctrl_t group[] = {kEmpty, 1, kDeleted, 3, kEmpty, 5, kSentinel, 7,
+                      7,      5, 3,        1, 1,      1, 1,         1};
+    EXPECT_THAT(Group{group}.MatchEmptyOrDeleted(), ElementsAre(0, 2, 4));
+  } else if (Group::kWidth == 8) {
+    ctrl_t group[] = {kEmpty, 1, 2, kDeleted, 2, 1, kSentinel, 1};
+    EXPECT_THAT(Group{group}.MatchEmptyOrDeleted(), ElementsAre(0, 3));
+  } else {
+    FAIL() << "No test coverage for Group::kWidth==" << Group::kWidth;
+  }
 }
-#else
-TEST(Group, Match) {
-  ctrl_t group[] = {kEmpty, 1, 2, kDeleted, 2, 1, kSentinel, 1};
-  EXPECT_THAT(Group{group}.Match(0), ElementsAre());
-  EXPECT_THAT(Group{group}.Match(1), ElementsAre(1, 5, 7));
-  EXPECT_THAT(Group{group}.Match(2), ElementsAre(2, 4));
-}
-TEST(Group, MatchEmpty) {
-  ctrl_t group[] = {kEmpty, 1, 2, kDeleted, 2, 1, kSentinel, 1};
-  EXPECT_THAT(Group{group}.MatchEmpty(), ElementsAre(0));
-}
-
-TEST(Group, MatchEmptyOrDeleted) {
-  ctrl_t group[] = {kEmpty, 1, 2, kDeleted, 2, 1, kSentinel, 1};
-  EXPECT_THAT(Group{group}.MatchEmptyOrDeleted(), ElementsAre(0, 3));
-}
-#endif
 
 TEST(Batch, DropDeletes) {
   constexpr size_t kCapacity = 63;
@@ -338,6 +371,7 @@
     size_t size;
     size_t capacity;
     size_t growth_left;
+    void* infoz;
   };
   struct StatelessHash {
     size_t operator()(absl::string_view) const { return 0; }
@@ -386,7 +420,8 @@
     !defined(UNDEFINED_BEHAVIOR_SANITIZER)
   const auto now = [] { return absl::base_internal::CycleClock::Now(); };
 
-  static constexpr int size = 1000000;
+  // Make size enough to not fit in L2 cache (16.7 Mb)
+  static constexpr int size = 1 << 22;
   for (int i = 0; i < size; ++i) t.insert(i);
 
   int64_t no_prefetch = 0, prefetch = 0;
@@ -687,7 +722,7 @@
   Modulo1000HashTable t;
   // Adding the same length (and the same hash) strings
   // to have at least kMinFullGroups groups
-  // with Group::kWidth collisions. Then feel upto MaxDensitySize;
+  // with Group::kWidth collisions. Then fill up to MaxDensitySize;
   const size_t kMinFullGroups = 7;
   std::vector<int> keys;
   for (size_t i = 0; i < MaxDensitySize(Group::kWidth * kMinFullGroups); ++i) {
@@ -779,7 +814,7 @@
 TEST(Table, ClearBug) {
   IntTable t;
   constexpr size_t capacity = container_internal::Group::kWidth - 1;
-  constexpr size_t max_size = capacity / 2;
+  constexpr size_t max_size = capacity / 2 + 1;
   for (size_t i = 0; i < max_size; ++i) {
     t.insert(i);
   }
@@ -810,6 +845,25 @@
   EXPECT_TRUE(t.find(0) == t.end());
 }
 
+TEST(Table, EraseMaintainsValidIterator) {
+  IntTable t;
+  const int kNumElements = 100;
+  for (int i = 0; i < kNumElements; i ++) {
+    EXPECT_TRUE(t.emplace(i).second);
+  }
+  EXPECT_EQ(t.size(), kNumElements);
+
+  int num_erase_calls = 0;
+  auto it = t.begin();
+  while (it != t.end()) {
+    t.erase(it++);
+    num_erase_calls++;
+  }
+
+  EXPECT_TRUE(t.empty());
+  EXPECT_EQ(num_erase_calls, kNumElements);
+}
+
 // Collect N bad keys by following algorithm:
 // 1. Create an empty table and reserve it to 2 * N.
 // 2. Insert N random elements.
@@ -1029,7 +1083,6 @@
           {{0.95, 0.1}},
           {{0.95, 0}, {0.99, 2}, {0.999, 4}, {0.9999, 10}}};
       }
-      break;
     case 16:
       if (kRandomizesInserts) {
         return {0.1,
@@ -1042,12 +1095,11 @@
                 {{0.95, 0.05}},
                 {{0.95, 0}, {0.99, 1}, {0.999, 4}, {0.9999, 10}}};
       }
-      break;
-    default:
-      ABSL_RAW_LOG(FATAL, "%s", "Unknown Group width");
   }
+  ABSL_RAW_LOG(FATAL, "%s", "Unknown Group width");
   return {};
 }
+
 TEST(Table, DISABLED_EnsureNonQuadraticTopNXorSeedByProbeSeqLength) {
   ProbeStatsPerSize stats;
   std::vector<size_t> sizes = {Group::kWidth << 5, Group::kWidth << 10};
@@ -1125,7 +1177,6 @@
                 {{0.95, 0.3}},
                 {{0.95, 0}, {0.99, 3}, {0.999, 15}, {0.9999, 25}}};
       }
-      break;
     case 16:
       if (kRandomizesInserts) {
         return {0.1,
@@ -1138,12 +1189,11 @@
                 {{0.95, 0.1}},
                 {{0.95, 0}, {0.99, 1}, {0.999, 6}, {0.9999, 10}}};
       }
-      break;
-    default:
-      ABSL_RAW_LOG(FATAL, "%s", "Unknown Group width");
   }
+  ABSL_RAW_LOG(FATAL, "%s", "Unknown Group width");
   return {};
 }
+
 TEST(Table, DISABLED_EnsureNonQuadraticTopNLinearTransformByProbeSeqLength) {
   ProbeStatsPerSize stats;
   std::vector<size_t> sizes = {Group::kWidth << 5, Group::kWidth << 10};
@@ -1431,7 +1481,8 @@
 
 TEST(Table, Equality) {
   StringTable t;
-  std::vector<std::pair<std::string, std::string>> v = {{"a", "b"}, {"aa", "bb"}};
+  std::vector<std::pair<std::string, std::string>> v = {{"a", "b"},
+                                                        {"aa", "bb"}};
   t.insert(std::begin(v), std::end(v));
   StringTable u = t;
   EXPECT_EQ(u, t);
@@ -1439,20 +1490,24 @@
 
 TEST(Table, Equality2) {
   StringTable t;
-  std::vector<std::pair<std::string, std::string>> v1 = {{"a", "b"}, {"aa", "bb"}};
+  std::vector<std::pair<std::string, std::string>> v1 = {{"a", "b"},
+                                                         {"aa", "bb"}};
   t.insert(std::begin(v1), std::end(v1));
   StringTable u;
-  std::vector<std::pair<std::string, std::string>> v2 = {{"a", "a"}, {"aa", "aa"}};
+  std::vector<std::pair<std::string, std::string>> v2 = {{"a", "a"},
+                                                         {"aa", "aa"}};
   u.insert(std::begin(v2), std::end(v2));
   EXPECT_NE(u, t);
 }
 
 TEST(Table, Equality3) {
   StringTable t;
-  std::vector<std::pair<std::string, std::string>> v1 = {{"b", "b"}, {"bb", "bb"}};
+  std::vector<std::pair<std::string, std::string>> v1 = {{"b", "b"},
+                                                         {"bb", "bb"}};
   t.insert(std::begin(v1), std::end(v1));
   StringTable u;
-  std::vector<std::pair<std::string, std::string>> v2 = {{"a", "a"}, {"aa", "aa"}};
+  std::vector<std::pair<std::string, std::string>> v2 = {{"a", "a"},
+                                                         {"aa", "aa"}};
   u.insert(std::begin(v2), std::end(v2));
   EXPECT_NE(u, t);
 }
@@ -1677,7 +1732,7 @@
   EXPECT_FALSE(node.empty());
 
   StringTable t2;
-  auto res = t2.insert(std::move(node));
+  StringTable::insert_return_type res = t2.insert(std::move(node));
   EXPECT_TRUE(res.inserted);
   EXPECT_THAT(*res.position, Pair(k0, ""));
   EXPECT_FALSE(res.node);
@@ -1707,73 +1762,49 @@
   EXPECT_FALSE(node);
 }
 
-StringTable MakeSimpleTable(size_t size) {
-  StringTable t;
-  for (size_t i = 0; i < size; ++i) t.emplace(std::string(1, 'A' + i), "");
+IntTable MakeSimpleTable(size_t size) {
+  IntTable t;
+  while (t.size() < size) t.insert(t.size());
   return t;
 }
 
-std::string OrderOfIteration(const StringTable& t) {
-  std::string order;
-  for (auto& p : t) order += p.first;
-  return order;
+std::vector<int> OrderOfIteration(const IntTable& t) {
+  return {t.begin(), t.end()};
 }
 
+// These IterationOrderChanges tests depend on non-deterministic behavior.
+// We are injecting non-determinism from the pointer of the table, but do so in
+// a way that only the page matters. We have to retry enough times to make sure
+// we are touching different memory pages to cause the ordering to change.
+// We also need to keep the old tables around to avoid getting the same memory
+// blocks over and over.
 TEST(Table, IterationOrderChangesByInstance) {
-  // Needs to be more than kWidth elements to be able to affect order.
-  const StringTable reference = MakeSimpleTable(20);
+  for (size_t size : {2, 6, 12, 20}) {
+    const auto reference_table = MakeSimpleTable(size);
+    const auto reference = OrderOfIteration(reference_table);
 
-  // Since order is non-deterministic we can't just try once and verify.
-  // We'll try until we find that order changed. It should not take many tries
-  // for that.
-  // Important: we have to keep the old tables around. Otherwise tcmalloc will
-  // just give us the same blocks and we would be doing the same order again.
-  std::vector<StringTable> garbage;
-  for (int i = 0; i < 10; ++i) {
-    auto trial = MakeSimpleTable(20);
-    if (OrderOfIteration(trial) != OrderOfIteration(reference)) {
-      // We are done.
-      return;
+    std::vector<IntTable> tables;
+    bool found_difference = false;
+    for (int i = 0; !found_difference && i < 500; ++i) {
+      tables.push_back(MakeSimpleTable(size));
+      found_difference = OrderOfIteration(tables.back()) != reference;
     }
-    garbage.push_back(std::move(trial));
+    if (!found_difference) {
+      FAIL()
+          << "Iteration order remained the same across many attempts with size "
+          << size;
+    }
   }
-  FAIL();
 }
 
 TEST(Table, IterationOrderChangesOnRehash) {
-  // Since order is non-deterministic we can't just try once and verify.
-  // We'll try until we find that order changed. It should not take many tries
-  // for that.
-  // Important: we have to keep the old tables around. Otherwise tcmalloc will
-  // just give us the same blocks and we would be doing the same order again.
-  std::vector<StringTable> garbage;
-  for (int i = 0; i < 10; ++i) {
-    // Needs to be more than kWidth elements to be able to affect order.
-    StringTable t = MakeSimpleTable(20);
-    const std::string reference = OrderOfIteration(t);
+  std::vector<IntTable> garbage;
+  for (int i = 0; i < 500; ++i) {
+    auto t = MakeSimpleTable(20);
+    const auto reference = OrderOfIteration(t);
     // Force rehash to the same size.
     t.rehash(0);
-    std::string trial = OrderOfIteration(t);
-    if (trial != reference) {
-      // We are done.
-      return;
-    }
-    garbage.push_back(std::move(t));
-  }
-  FAIL();
-}
-
-TEST(Table, IterationOrderChangesForSmallTables) {
-  // Since order is non-deterministic we can't just try once and verify.
-  // We'll try until we find that order changed.
-  // Important: we have to keep the old tables around. Otherwise tcmalloc will
-  // just give us the same blocks and we would be doing the same order again.
-  StringTable reference_table = MakeSimpleTable(5);
-  const std::string reference = OrderOfIteration(reference_table);
-  std::vector<StringTable> garbage;
-  for (int i = 0; i < 50; ++i) {
-    StringTable t = MakeSimpleTable(5);
-    std::string trial = OrderOfIteration(t);
+    auto trial = OrderOfIteration(t);
     if (trial != reference) {
       // We are done.
       return;
@@ -1783,136 +1814,22 @@
   FAIL() << "Iteration order remained the same across many attempts.";
 }
 
-// Fill the table to 3 different load factors (min, median, max) and evaluate
-// the percentage of perfect hits using the debug API.
-template <class Table, class AddFn>
-std::vector<double> CollectPerfectRatios(Table t, AddFn add) {
-  using Key = typename Table::key_type;
+// Verify that pointers are invalidated as soon as a second element is inserted.
+// This prevents dependency on pointer stability on small tables.
+TEST(Table, UnstablePointers) {
+  IntTable table;
 
-  // First, fill enough to have a good distribution.
-  constexpr size_t kMinSize = 10000;
-  std::vector<Key> keys;
-  while (t.size() < kMinSize) keys.push_back(add(t));
-  // Then, insert until we reach min load factor.
-  double lf = t.load_factor();
-  while (lf <= t.load_factor()) keys.push_back(add(t));
-
-  // We are now at min load factor. Take a snapshot.
-  size_t perfect = 0;
-  auto update_perfect = [&](Key k) {
-    perfect += GetHashtableDebugNumProbes(t, k) == 0;
+  const auto addr = [&](int i) {
+    return reinterpret_cast<uintptr_t>(&*table.find(i));
   };
-  for (const auto& k : keys) update_perfect(k);
 
-  std::vector<double> perfect_ratios;
-  // Keep going until we hit max load factor.
-  while (t.load_factor() < .6) {
-    perfect_ratios.push_back(1.0 * perfect / t.size());
-    update_perfect(add(t));
-  }
-  while (t.load_factor() > .5) {
-    perfect_ratios.push_back(1.0 * perfect / t.size());
-    update_perfect(add(t));
-  }
-  return perfect_ratios;
-}
+  table.insert(0);
+  const uintptr_t old_ptr = addr(0);
 
-std::vector<std::pair<double, double>> StringTablePefectRatios() {
-  constexpr bool kRandomizesInserts =
-#if NDEBUG
-      false;
-#else   // NDEBUG
-      true;
-#endif  // NDEBUG
+  // This causes a rehash.
+  table.insert(1);
 
-  // The effective load factor is larger in non-opt mode because we insert
-  // elements out of order.
-  switch (container_internal::Group::kWidth) {
-    case 8:
-      if (kRandomizesInserts) {
-        return {{0.986, 0.02}, {0.95, 0.02}, {0.89, 0.02}};
-      } else {
-        return {{0.995, 0.01}, {0.97, 0.01}, {0.89, 0.02}};
-      }
-      break;
-    case 16:
-      if (kRandomizesInserts) {
-        return {{0.973, 0.01}, {0.965, 0.01}, {0.92, 0.02}};
-      } else {
-        return {{0.995, 0.005}, {0.99, 0.005}, {0.94, 0.01}};
-      }
-      break;
-    default:
-      // Ignore anything else.
-      return {};
-  }
-}
-
-// This is almost a change detector, but it allows us to know how we are
-// affecting the probe distribution.
-TEST(Table, EffectiveLoadFactorStrings) {
-  std::vector<double> perfect_ratios =
-      CollectPerfectRatios(StringTable(), [](StringTable& t) {
-        return t.emplace(std::to_string(t.size()), "").first->first;
-      });
-
-  auto ratios = StringTablePefectRatios();
-  if (ratios.empty()) return;
-
-  EXPECT_THAT(perfect_ratios.front(),
-              DoubleNear(ratios[0].first, ratios[0].second));
-  EXPECT_THAT(perfect_ratios[perfect_ratios.size() / 2],
-              DoubleNear(ratios[1].first, ratios[1].second));
-  EXPECT_THAT(perfect_ratios.back(),
-              DoubleNear(ratios[2].first, ratios[2].second));
-}
-
-std::vector<std::pair<double, double>> IntTablePefectRatios() {
-  constexpr bool kRandomizesInserts =
-#ifdef NDEBUG
-      false;
-#else   // NDEBUG
-      true;
-#endif  // NDEBUG
-
-  // The effective load factor is larger in non-opt mode because we insert
-  // elements out of order.
-  switch (container_internal::Group::kWidth) {
-    case 8:
-      if (kRandomizesInserts) {
-        return {{0.99, 0.02}, {0.985, 0.02}, {0.95, 0.05}};
-      } else {
-        return {{0.99, 0.01}, {0.99, 0.01}, {0.95, 0.02}};
-      }
-      break;
-    case 16:
-      if (kRandomizesInserts) {
-        return {{0.98, 0.02}, {0.978, 0.02}, {0.96, 0.02}};
-      } else {
-        return {{0.998, 0.003}, {0.995, 0.01}, {0.975, 0.02}};
-      }
-      break;
-    default:
-      // Ignore anything else.
-      return {};
-  }
-}
-
-// This is almost a change detector, but it allows us to know how we are
-// affecting the probe distribution.
-TEST(Table, EffectiveLoadFactorInts) {
-  std::vector<double> perfect_ratios = CollectPerfectRatios(
-      IntTable(), [](IntTable& t) { return *t.emplace(t.size()).first; });
-
-  auto ratios = IntTablePefectRatios();
-  if (ratios.empty()) return;
-
-  EXPECT_THAT(perfect_ratios.front(),
-              DoubleNear(ratios[0].first, ratios[0].second));
-  EXPECT_THAT(perfect_ratios[perfect_ratios.size() / 2],
-              DoubleNear(ratios[1].first, ratios[1].second));
-  EXPECT_THAT(perfect_ratios.back(),
-              DoubleNear(ratios[2].first, ratios[2].second));
+  EXPECT_NE(old_ptr, addr(0));
 }
 
 // Confirm that we assert if we try to erase() end().
@@ -1931,9 +1848,31 @@
   EXPECT_DEATH_IF_SUPPORTED(t.erase(t.end()), kDeathMsg);
 }
 
+TEST(RawHashSamplerTest, Sample) {
+  // Enable the feature even if the prod default is off.
+  SetHashtablezEnabled(true);
+  SetHashtablezSampleParameter(100);
+
+  auto& sampler = HashtablezSampler::Global();
+  size_t start_size = 0;
+  start_size += sampler.Iterate([&](const HashtablezInfo&) { ++start_size; });
+
+  std::vector<IntTable> tables;
+  for (int i = 0; i < 1000000; ++i) {
+    tables.emplace_back();
+    tables.back().insert(1);
+  }
+  size_t end_size = 0;
+  end_size += sampler.Iterate([&](const HashtablezInfo&) { ++end_size; });
+
+  EXPECT_NEAR((end_size - start_size) / static_cast<double>(tables.size()),
+              0.01, 0.005);
+}
+
 #ifdef ADDRESS_SANITIZER
 TEST(Sanitizer, PoisoningUnused) {
   IntTable t;
+  t.reserve(5);
   // Insert something to force an allocation.
   int64_t& v1 = *t.insert(0).first;
 
diff --git a/absl/container/internal/test_instance_tracker.cc b/absl/container/internal/test_instance_tracker.cc
index b18e0bb..5a66cb4 100644
--- a/absl/container/internal/test_instance_tracker.cc
+++ b/absl/container/internal/test_instance_tracker.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
diff --git a/absl/container/internal/test_instance_tracker.h b/absl/container/internal/test_instance_tracker.h
index ec45f57..032d16d 100644
--- a/absl/container/internal/test_instance_tracker.h
+++ b/absl/container/internal/test_instance_tracker.h
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
diff --git a/absl/container/internal/test_instance_tracker_test.cc b/absl/container/internal/test_instance_tracker_test.cc
index 0ae5763..091f428 100644
--- a/absl/container/internal/test_instance_tracker_test.cc
+++ b/absl/container/internal/test_instance_tracker_test.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
diff --git a/absl/container/internal/tracked.h b/absl/container/internal/tracked.h
index 7d14af0..75173ab 100644
--- a/absl/container/internal/tracked.h
+++ b/absl/container/internal/tracked.h
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
diff --git a/absl/container/internal/unordered_map_constructor_test.h b/absl/container/internal/unordered_map_constructor_test.h
index 2ffb646..68817e4 100644
--- a/absl/container/internal/unordered_map_constructor_test.h
+++ b/absl/container/internal/unordered_map_constructor_test.h
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -29,7 +29,7 @@
 template <class UnordMap>
 class ConstructorTest : public ::testing::Test {};
 
-TYPED_TEST_CASE_P(ConstructorTest);
+TYPED_TEST_SUITE_P(ConstructorTest);
 
 TYPED_TEST_P(ConstructorTest, NoArgs) {
   TypeParam m;
@@ -83,8 +83,28 @@
   EXPECT_GE(m.bucket_count(), 123);
 }
 
-TYPED_TEST_P(ConstructorTest, BucketCountAlloc) {
+template <typename T>
+struct is_std_unordered_map : std::false_type {};
+
+template <typename... T>
+struct is_std_unordered_map<std::unordered_map<T...>> : std::true_type {};
+
 #if defined(UNORDERED_MAP_CXX14) || defined(UNORDERED_MAP_CXX17)
+using has_cxx14_std_apis = std::true_type;
+#else
+using has_cxx14_std_apis = std::false_type;
+#endif
+
+template <typename T>
+using expect_cxx14_apis =
+    absl::disjunction<absl::negation<is_std_unordered_map<T>>,
+                      has_cxx14_std_apis>;
+
+template <typename TypeParam>
+void BucketCountAllocTest(std::false_type) {}
+
+template <typename TypeParam>
+void BucketCountAllocTest(std::true_type) {
   using A = typename TypeParam::allocator_type;
   A alloc(0);
   TypeParam m(123, alloc);
@@ -92,11 +112,17 @@
   EXPECT_TRUE(m.empty());
   EXPECT_THAT(m, ::testing::UnorderedElementsAre());
   EXPECT_GE(m.bucket_count(), 123);
-#endif
 }
 
-TYPED_TEST_P(ConstructorTest, BucketCountHashAlloc) {
-#if defined(UNORDERED_MAP_CXX14) || defined(UNORDERED_MAP_CXX17)
+TYPED_TEST_P(ConstructorTest, BucketCountAlloc) {
+  BucketCountAllocTest<TypeParam>(expect_cxx14_apis<TypeParam>());
+}
+
+template <typename TypeParam>
+void BucketCountHashAllocTest(std::false_type) {}
+
+template <typename TypeParam>
+void BucketCountHashAllocTest(std::true_type) {
   using H = typename TypeParam::hasher;
   using A = typename TypeParam::allocator_type;
   H hasher;
@@ -107,18 +133,38 @@
   EXPECT_TRUE(m.empty());
   EXPECT_THAT(m, ::testing::UnorderedElementsAre());
   EXPECT_GE(m.bucket_count(), 123);
-#endif
 }
 
-TYPED_TEST_P(ConstructorTest, BucketAlloc) {
+TYPED_TEST_P(ConstructorTest, BucketCountHashAlloc) {
+  BucketCountHashAllocTest<TypeParam>(expect_cxx14_apis<TypeParam>());
+}
+
 #if ABSL_UNORDERED_SUPPORTS_ALLOC_CTORS
+using has_alloc_std_constructors = std::true_type;
+#else
+using has_alloc_std_constructors = std::false_type;
+#endif
+
+template <typename T>
+using expect_alloc_constructors =
+    absl::disjunction<absl::negation<is_std_unordered_map<T>>,
+                      has_alloc_std_constructors>;
+
+template <typename TypeParam>
+void AllocTest(std::false_type) {}
+
+template <typename TypeParam>
+void AllocTest(std::true_type) {
   using A = typename TypeParam::allocator_type;
   A alloc(0);
   TypeParam m(alloc);
   EXPECT_EQ(m.get_allocator(), alloc);
   EXPECT_TRUE(m.empty());
   EXPECT_THAT(m, ::testing::UnorderedElementsAre());
-#endif
+}
+
+TYPED_TEST_P(ConstructorTest, Alloc) {
+  AllocTest<TypeParam>(expect_alloc_constructors<TypeParam>());
 }
 
 TYPED_TEST_P(ConstructorTest, InputIteratorBucketHashEqualAlloc) {
@@ -140,8 +186,11 @@
   EXPECT_GE(m.bucket_count(), 123);
 }
 
-TYPED_TEST_P(ConstructorTest, InputIteratorBucketAlloc) {
-#if defined(UNORDERED_MAP_CXX14) || defined(UNORDERED_MAP_CXX17)
+template <typename TypeParam>
+void InputIteratorBucketAllocTest(std::false_type) {}
+
+template <typename TypeParam>
+void InputIteratorBucketAllocTest(std::true_type) {
   using T = hash_internal::GeneratedType<TypeParam>;
   using A = typename TypeParam::allocator_type;
   A alloc(0);
@@ -152,11 +201,17 @@
   EXPECT_EQ(m.get_allocator(), alloc);
   EXPECT_THAT(items(m), ::testing::UnorderedElementsAreArray(values));
   EXPECT_GE(m.bucket_count(), 123);
-#endif
 }
 
-TYPED_TEST_P(ConstructorTest, InputIteratorBucketHashAlloc) {
-#if defined(UNORDERED_MAP_CXX14) || defined(UNORDERED_MAP_CXX17)
+TYPED_TEST_P(ConstructorTest, InputIteratorBucketAlloc) {
+  InputIteratorBucketAllocTest<TypeParam>(expect_cxx14_apis<TypeParam>());
+}
+
+template <typename TypeParam>
+void InputIteratorBucketHashAllocTest(std::false_type) {}
+
+template <typename TypeParam>
+void InputIteratorBucketHashAllocTest(std::true_type) {
   using T = hash_internal::GeneratedType<TypeParam>;
   using H = typename TypeParam::hasher;
   using A = typename TypeParam::allocator_type;
@@ -170,7 +225,10 @@
   EXPECT_EQ(m.get_allocator(), alloc);
   EXPECT_THAT(items(m), ::testing::UnorderedElementsAreArray(values));
   EXPECT_GE(m.bucket_count(), 123);
-#endif
+}
+
+TYPED_TEST_P(ConstructorTest, InputIteratorBucketHashAlloc) {
+  InputIteratorBucketHashAllocTest<TypeParam>(expect_cxx14_apis<TypeParam>());
 }
 
 TYPED_TEST_P(ConstructorTest, CopyConstructor) {
@@ -190,8 +248,11 @@
   EXPECT_EQ(m, n);
 }
 
-TYPED_TEST_P(ConstructorTest, CopyConstructorAlloc) {
-#if ABSL_UNORDERED_SUPPORTS_ALLOC_CTORS
+template <typename TypeParam>
+void CopyConstructorAllocTest(std::false_type) {}
+
+template <typename TypeParam>
+void CopyConstructorAllocTest(std::true_type) {
   using T = hash_internal::GeneratedType<TypeParam>;
   using H = typename TypeParam::hasher;
   using E = typename TypeParam::key_equal;
@@ -206,7 +267,10 @@
   EXPECT_EQ(m.key_eq(), n.key_eq());
   EXPECT_NE(m.get_allocator(), n.get_allocator());
   EXPECT_EQ(m, n);
-#endif
+}
+
+TYPED_TEST_P(ConstructorTest, CopyConstructorAlloc) {
+  CopyConstructorAllocTest<TypeParam>(expect_alloc_constructors<TypeParam>());
 }
 
 // TODO(alkis): Test non-propagating allocators on copy constructors.
@@ -229,8 +293,11 @@
   EXPECT_EQ(m, n);
 }
 
-TYPED_TEST_P(ConstructorTest, MoveConstructorAlloc) {
-#if ABSL_UNORDERED_SUPPORTS_ALLOC_CTORS
+template <typename TypeParam>
+void MoveConstructorAllocTest(std::false_type) {}
+
+template <typename TypeParam>
+void MoveConstructorAllocTest(std::true_type) {
   using T = hash_internal::GeneratedType<TypeParam>;
   using H = typename TypeParam::hasher;
   using E = typename TypeParam::key_equal;
@@ -246,7 +313,10 @@
   EXPECT_EQ(m.key_eq(), n.key_eq());
   EXPECT_NE(m.get_allocator(), n.get_allocator());
   EXPECT_EQ(m, n);
-#endif
+}
+
+TYPED_TEST_P(ConstructorTest, MoveConstructorAlloc) {
+  MoveConstructorAllocTest<TypeParam>(expect_alloc_constructors<TypeParam>());
 }
 
 // TODO(alkis): Test non-propagating allocators on move constructors.
@@ -269,8 +339,11 @@
   EXPECT_GE(m.bucket_count(), 123);
 }
 
-TYPED_TEST_P(ConstructorTest, InitializerListBucketAlloc) {
-#if defined(UNORDERED_MAP_CXX14) || defined(UNORDERED_MAP_CXX17)
+template <typename TypeParam>
+void InitializerListBucketAllocTest(std::false_type) {}
+
+template <typename TypeParam>
+void InitializerListBucketAllocTest(std::true_type) {
   using T = hash_internal::GeneratedType<TypeParam>;
   using A = typename TypeParam::allocator_type;
   hash_internal::Generator<T> gen;
@@ -280,11 +353,17 @@
   EXPECT_EQ(m.get_allocator(), alloc);
   EXPECT_THAT(items(m), ::testing::UnorderedElementsAreArray(values));
   EXPECT_GE(m.bucket_count(), 123);
-#endif
 }
 
-TYPED_TEST_P(ConstructorTest, InitializerListBucketHashAlloc) {
-#if defined(UNORDERED_MAP_CXX14) || defined(UNORDERED_MAP_CXX17)
+TYPED_TEST_P(ConstructorTest, InitializerListBucketAlloc) {
+  InitializerListBucketAllocTest<TypeParam>(expect_cxx14_apis<TypeParam>());
+}
+
+template <typename TypeParam>
+void InitializerListBucketHashAllocTest(std::false_type) {}
+
+template <typename TypeParam>
+void InitializerListBucketHashAllocTest(std::true_type) {
   using T = hash_internal::GeneratedType<TypeParam>;
   using H = typename TypeParam::hasher;
   using A = typename TypeParam::allocator_type;
@@ -297,7 +376,10 @@
   EXPECT_EQ(m.get_allocator(), alloc);
   EXPECT_THAT(items(m), ::testing::UnorderedElementsAreArray(values));
   EXPECT_GE(m.bucket_count(), 123);
-#endif
+}
+
+TYPED_TEST_P(ConstructorTest, InitializerListBucketHashAlloc) {
+  InitializerListBucketHashAllocTest<TypeParam>(expect_cxx14_apis<TypeParam>());
 }
 
 TYPED_TEST_P(ConstructorTest, Assignment) {
@@ -390,15 +472,16 @@
 
 REGISTER_TYPED_TEST_CASE_P(
     ConstructorTest, NoArgs, BucketCount, BucketCountHash, BucketCountHashEqual,
-    BucketCountHashEqualAlloc, BucketCountAlloc, BucketCountHashAlloc,
-    BucketAlloc, InputIteratorBucketHashEqualAlloc, InputIteratorBucketAlloc,
+    BucketCountHashEqualAlloc, BucketCountAlloc, BucketCountHashAlloc, Alloc,
+    InputIteratorBucketHashEqualAlloc, InputIteratorBucketAlloc,
     InputIteratorBucketHashAlloc, CopyConstructor, CopyConstructorAlloc,
     MoveConstructor, MoveConstructorAlloc, InitializerListBucketHashEqualAlloc,
     InitializerListBucketAlloc, InitializerListBucketHashAlloc, Assignment,
-    MoveAssignment, AssignmentFromInitializerList,
-    AssignmentOverwritesExisting, MoveAssignmentOverwritesExisting,
+    MoveAssignment, AssignmentFromInitializerList, AssignmentOverwritesExisting,
+    MoveAssignmentOverwritesExisting,
     AssignmentFromInitializerListOverwritesExisting, AssignmentOnSelf);
 
 }  // namespace container_internal
 }  // namespace absl
+
 #endif  // ABSL_CONTAINER_INTERNAL_UNORDERED_MAP_CONSTRUCTOR_TEST_H_
diff --git a/absl/container/internal/unordered_map_lookup_test.h b/absl/container/internal/unordered_map_lookup_test.h
index 1f1b6b4..ebd3612 100644
--- a/absl/container/internal/unordered_map_lookup_test.h
+++ b/absl/container/internal/unordered_map_lookup_test.h
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -26,7 +26,7 @@
 template <class UnordMap>
 class LookupTest : public ::testing::Test {};
 
-TYPED_TEST_CASE_P(LookupTest);
+TYPED_TEST_SUITE_P(LookupTest);
 
 TYPED_TEST_P(LookupTest, At) {
   using T = hash_internal::GeneratedType<TypeParam>;
@@ -111,4 +111,5 @@
 
 }  // namespace container_internal
 }  // namespace absl
+
 #endif  // ABSL_CONTAINER_INTERNAL_UNORDERED_MAP_LOOKUP_TEST_H_
diff --git a/absl/container/internal/unordered_map_members_test.h b/absl/container/internal/unordered_map_members_test.h
new file mode 100644
index 0000000..1bf31ab
--- /dev/null
+++ b/absl/container/internal/unordered_map_members_test.h
@@ -0,0 +1,85 @@
+// Copyright 2019 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
+//
+//      https://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.
+
+#ifndef ABSL_CONTAINER_INTERNAL_UNORDERED_MAP_MEMBERS_TEST_H_
+#define ABSL_CONTAINER_INTERNAL_UNORDERED_MAP_MEMBERS_TEST_H_
+
+#include <type_traits>
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "absl/meta/type_traits.h"
+
+namespace absl {
+namespace container_internal {
+
+template <class UnordMap>
+class MembersTest : public ::testing::Test {};
+
+TYPED_TEST_SUITE_P(MembersTest);
+
+template <typename T>
+void UseType() {}
+
+TYPED_TEST_P(MembersTest, Typedefs) {
+  EXPECT_TRUE((std::is_same<std::pair<const typename TypeParam::key_type,
+                                      typename TypeParam::mapped_type>,
+                            typename TypeParam::value_type>()));
+  EXPECT_TRUE((absl::conjunction<
+               absl::negation<std::is_signed<typename TypeParam::size_type>>,
+               std::is_integral<typename TypeParam::size_type>>()));
+  EXPECT_TRUE((absl::conjunction<
+               std::is_signed<typename TypeParam::difference_type>,
+               std::is_integral<typename TypeParam::difference_type>>()));
+  EXPECT_TRUE((std::is_convertible<
+               decltype(std::declval<const typename TypeParam::hasher&>()(
+                   std::declval<const typename TypeParam::key_type&>())),
+               size_t>()));
+  EXPECT_TRUE((std::is_convertible<
+               decltype(std::declval<const typename TypeParam::key_equal&>()(
+                   std::declval<const typename TypeParam::key_type&>(),
+                   std::declval<const typename TypeParam::key_type&>())),
+               bool>()));
+  EXPECT_TRUE((std::is_same<typename TypeParam::allocator_type::value_type,
+                            typename TypeParam::value_type>()));
+  EXPECT_TRUE((std::is_same<typename TypeParam::value_type&,
+                            typename TypeParam::reference>()));
+  EXPECT_TRUE((std::is_same<const typename TypeParam::value_type&,
+                            typename TypeParam::const_reference>()));
+  EXPECT_TRUE((std::is_same<typename std::allocator_traits<
+                                typename TypeParam::allocator_type>::pointer,
+                            typename TypeParam::pointer>()));
+  EXPECT_TRUE(
+      (std::is_same<typename std::allocator_traits<
+                        typename TypeParam::allocator_type>::const_pointer,
+                    typename TypeParam::const_pointer>()));
+}
+
+TYPED_TEST_P(MembersTest, SimpleFunctions) {
+  EXPECT_GT(TypeParam().max_size(), 0);
+}
+
+TYPED_TEST_P(MembersTest, BeginEnd) {
+  TypeParam t = {typename TypeParam::value_type{}};
+  EXPECT_EQ(t.begin(), t.cbegin());
+  EXPECT_EQ(t.end(), t.cend());
+  EXPECT_NE(t.begin(), t.end());
+  EXPECT_NE(t.cbegin(), t.cend());
+}
+
+REGISTER_TYPED_TEST_SUITE_P(MembersTest, Typedefs, SimpleFunctions, BeginEnd);
+
+}  // namespace container_internal
+}  // namespace absl
+
+#endif  // ABSL_CONTAINER_INTERNAL_UNORDERED_MAP_MEMBERS_TEST_H_
diff --git a/absl/container/internal/unordered_map_modifiers_test.h b/absl/container/internal/unordered_map_modifiers_test.h
index b6c633a..52a1092 100644
--- a/absl/container/internal/unordered_map_modifiers_test.h
+++ b/absl/container/internal/unordered_map_modifiers_test.h
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -26,7 +26,7 @@
 template <class UnordMap>
 class ModifiersTest : public ::testing::Test {};
 
-TYPED_TEST_CASE_P(ModifiersTest);
+TYPED_TEST_SUITE_P(ModifiersTest);
 
 TYPED_TEST_P(ModifiersTest, Clear) {
   using T = hash_internal::GeneratedType<TypeParam>;
@@ -269,4 +269,5 @@
 
 }  // namespace container_internal
 }  // namespace absl
+
 #endif  // ABSL_CONTAINER_INTERNAL_UNORDERED_MAP_MODIFIERS_TEST_H_
diff --git a/absl/container/internal/unordered_map_test.cc b/absl/container/internal/unordered_map_test.cc
index 40e799c..72567ea 100644
--- a/absl/container/internal/unordered_map_test.cc
+++ b/absl/container/internal/unordered_map_test.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -16,6 +16,7 @@
 
 #include "absl/container/internal/unordered_map_constructor_test.h"
 #include "absl/container/internal/unordered_map_lookup_test.h"
+#include "absl/container/internal/unordered_map_members_test.h"
 #include "absl/container/internal/unordered_map_modifiers_test.h"
 
 namespace absl {
@@ -29,9 +30,10 @@
                        StatefulTestingEqual,
                        Alloc<std::pair<const std::string, std::string>>>>;
 
-INSTANTIATE_TYPED_TEST_CASE_P(UnorderedMap, ConstructorTest, MapTypes);
-INSTANTIATE_TYPED_TEST_CASE_P(UnorderedMap, LookupTest, MapTypes);
-INSTANTIATE_TYPED_TEST_CASE_P(UnorderedMap, ModifiersTest, MapTypes);
+INSTANTIATE_TYPED_TEST_SUITE_P(UnorderedMap, ConstructorTest, MapTypes);
+INSTANTIATE_TYPED_TEST_SUITE_P(UnorderedMap, LookupTest, MapTypes);
+INSTANTIATE_TYPED_TEST_SUITE_P(UnorderedMap, MembersTest, MapTypes);
+INSTANTIATE_TYPED_TEST_SUITE_P(UnorderedMap, ModifiersTest, MapTypes);
 
 }  // namespace
 }  // namespace container_internal
diff --git a/absl/container/internal/unordered_set_constructor_test.h b/absl/container/internal/unordered_set_constructor_test.h
index cb59370..f484468 100644
--- a/absl/container/internal/unordered_set_constructor_test.h
+++ b/absl/container/internal/unordered_set_constructor_test.h
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -16,12 +16,14 @@
 #define ABSL_CONTAINER_INTERNAL_UNORDERED_SET_CONSTRUCTOR_TEST_H_
 
 #include <algorithm>
+#include <unordered_set>
 #include <vector>
 
 #include "gmock/gmock.h"
 #include "gtest/gtest.h"
 #include "absl/container/internal/hash_generator_testing.h"
 #include "absl/container/internal/hash_policy_testing.h"
+#include "absl/meta/type_traits.h"
 
 namespace absl {
 namespace container_internal {
@@ -29,7 +31,7 @@
 template <class UnordMap>
 class ConstructorTest : public ::testing::Test {};
 
-TYPED_TEST_CASE_P(ConstructorTest);
+TYPED_TEST_SUITE_P(ConstructorTest);
 
 TYPED_TEST_P(ConstructorTest, NoArgs) {
   TypeParam m;
@@ -91,8 +93,28 @@
   EXPECT_GE(cm.bucket_count(), 123);
 }
 
-TYPED_TEST_P(ConstructorTest, BucketCountAlloc) {
+template <typename T>
+struct is_std_unordered_set : std::false_type {};
+
+template <typename... T>
+struct is_std_unordered_set<std::unordered_set<T...>> : std::true_type {};
+
 #if defined(UNORDERED_SET_CXX14) || defined(UNORDERED_SET_CXX17)
+using has_cxx14_std_apis = std::true_type;
+#else
+using has_cxx14_std_apis = std::false_type;
+#endif
+
+template <typename T>
+using expect_cxx14_apis =
+    absl::disjunction<absl::negation<is_std_unordered_set<T>>,
+                      has_cxx14_std_apis>;
+
+template <typename TypeParam>
+void BucketCountAllocTest(std::false_type) {}
+
+template <typename TypeParam>
+void BucketCountAllocTest(std::true_type) {
   using A = typename TypeParam::allocator_type;
   A alloc(0);
   TypeParam m(123, alloc);
@@ -100,11 +122,17 @@
   EXPECT_TRUE(m.empty());
   EXPECT_THAT(keys(m), ::testing::UnorderedElementsAre());
   EXPECT_GE(m.bucket_count(), 123);
-#endif
 }
 
-TYPED_TEST_P(ConstructorTest, BucketCountHashAlloc) {
-#if defined(UNORDERED_SET_CXX14) || defined(UNORDERED_SET_CXX17)
+TYPED_TEST_P(ConstructorTest, BucketCountAlloc) {
+  BucketCountAllocTest<TypeParam>(expect_cxx14_apis<TypeParam>());
+}
+
+template <typename TypeParam>
+void BucketCountHashAllocTest(std::false_type) {}
+
+template <typename TypeParam>
+void BucketCountHashAllocTest(std::true_type) {
   using H = typename TypeParam::hasher;
   using A = typename TypeParam::allocator_type;
   H hasher;
@@ -115,18 +143,38 @@
   EXPECT_TRUE(m.empty());
   EXPECT_THAT(keys(m), ::testing::UnorderedElementsAre());
   EXPECT_GE(m.bucket_count(), 123);
-#endif
 }
 
-TYPED_TEST_P(ConstructorTest, BucketAlloc) {
+TYPED_TEST_P(ConstructorTest, BucketCountHashAlloc) {
+  BucketCountHashAllocTest<TypeParam>(expect_cxx14_apis<TypeParam>());
+}
+
 #if ABSL_UNORDERED_SUPPORTS_ALLOC_CTORS
+using has_alloc_std_constructors = std::true_type;
+#else
+using has_alloc_std_constructors = std::false_type;
+#endif
+
+template <typename T>
+using expect_alloc_constructors =
+    absl::disjunction<absl::negation<is_std_unordered_set<T>>,
+                      has_alloc_std_constructors>;
+
+template <typename TypeParam>
+void AllocTest(std::false_type) {}
+
+template <typename TypeParam>
+void AllocTest(std::true_type) {
   using A = typename TypeParam::allocator_type;
   A alloc(0);
   TypeParam m(alloc);
   EXPECT_EQ(m.get_allocator(), alloc);
   EXPECT_TRUE(m.empty());
   EXPECT_THAT(keys(m), ::testing::UnorderedElementsAre());
-#endif
+}
+
+TYPED_TEST_P(ConstructorTest, Alloc) {
+  AllocTest<TypeParam>(expect_alloc_constructors<TypeParam>());
 }
 
 TYPED_TEST_P(ConstructorTest, InputIteratorBucketHashEqualAlloc) {
@@ -148,8 +196,11 @@
   EXPECT_GE(m.bucket_count(), 123);
 }
 
-TYPED_TEST_P(ConstructorTest, InputIteratorBucketAlloc) {
-#if defined(UNORDERED_SET_CXX14) || defined(UNORDERED_SET_CXX17)
+template <typename TypeParam>
+void InputIteratorBucketAllocTest(std::false_type) {}
+
+template <typename TypeParam>
+void InputIteratorBucketAllocTest(std::true_type) {
   using T = hash_internal::GeneratedType<TypeParam>;
   using A = typename TypeParam::allocator_type;
   A alloc(0);
@@ -160,11 +211,17 @@
   EXPECT_EQ(m.get_allocator(), alloc);
   EXPECT_THAT(keys(m), ::testing::UnorderedElementsAreArray(values));
   EXPECT_GE(m.bucket_count(), 123);
-#endif
 }
 
-TYPED_TEST_P(ConstructorTest, InputIteratorBucketHashAlloc) {
-#if defined(UNORDERED_SET_CXX14) || defined(UNORDERED_SET_CXX17)
+TYPED_TEST_P(ConstructorTest, InputIteratorBucketAlloc) {
+  InputIteratorBucketAllocTest<TypeParam>(expect_cxx14_apis<TypeParam>());
+}
+
+template <typename TypeParam>
+void InputIteratorBucketHashAllocTest(std::false_type) {}
+
+template <typename TypeParam>
+void InputIteratorBucketHashAllocTest(std::true_type) {
   using T = hash_internal::GeneratedType<TypeParam>;
   using H = typename TypeParam::hasher;
   using A = typename TypeParam::allocator_type;
@@ -178,7 +235,10 @@
   EXPECT_EQ(m.get_allocator(), alloc);
   EXPECT_THAT(keys(m), ::testing::UnorderedElementsAreArray(values));
   EXPECT_GE(m.bucket_count(), 123);
-#endif
+}
+
+TYPED_TEST_P(ConstructorTest, InputIteratorBucketHashAlloc) {
+  InputIteratorBucketHashAllocTest<TypeParam>(expect_cxx14_apis<TypeParam>());
 }
 
 TYPED_TEST_P(ConstructorTest, CopyConstructor) {
@@ -196,10 +256,14 @@
   EXPECT_EQ(m.key_eq(), n.key_eq());
   EXPECT_EQ(m.get_allocator(), n.get_allocator());
   EXPECT_EQ(m, n);
+  EXPECT_NE(TypeParam(0, hasher, equal, alloc), n);
 }
 
-TYPED_TEST_P(ConstructorTest, CopyConstructorAlloc) {
-#if ABSL_UNORDERED_SUPPORTS_ALLOC_CTORS
+template <typename TypeParam>
+void CopyConstructorAllocTest(std::false_type) {}
+
+template <typename TypeParam>
+void CopyConstructorAllocTest(std::true_type) {
   using T = hash_internal::GeneratedType<TypeParam>;
   using H = typename TypeParam::hasher;
   using E = typename TypeParam::key_equal;
@@ -214,7 +278,10 @@
   EXPECT_EQ(m.key_eq(), n.key_eq());
   EXPECT_NE(m.get_allocator(), n.get_allocator());
   EXPECT_EQ(m, n);
-#endif
+}
+
+TYPED_TEST_P(ConstructorTest, CopyConstructorAlloc) {
+  CopyConstructorAllocTest<TypeParam>(expect_alloc_constructors<TypeParam>());
 }
 
 // TODO(alkis): Test non-propagating allocators on copy constructors.
@@ -237,8 +304,11 @@
   EXPECT_EQ(m, n);
 }
 
-TYPED_TEST_P(ConstructorTest, MoveConstructorAlloc) {
-#if ABSL_UNORDERED_SUPPORTS_ALLOC_CTORS
+template <typename TypeParam>
+void MoveConstructorAllocTest(std::false_type) {}
+
+template <typename TypeParam>
+void MoveConstructorAllocTest(std::true_type) {
   using T = hash_internal::GeneratedType<TypeParam>;
   using H = typename TypeParam::hasher;
   using E = typename TypeParam::key_equal;
@@ -254,7 +324,10 @@
   EXPECT_EQ(m.key_eq(), n.key_eq());
   EXPECT_NE(m.get_allocator(), n.get_allocator());
   EXPECT_EQ(m, n);
-#endif
+}
+
+TYPED_TEST_P(ConstructorTest, MoveConstructorAlloc) {
+  MoveConstructorAllocTest<TypeParam>(expect_alloc_constructors<TypeParam>());
 }
 
 // TODO(alkis): Test non-propagating allocators on move constructors.
@@ -277,8 +350,11 @@
   EXPECT_GE(m.bucket_count(), 123);
 }
 
-TYPED_TEST_P(ConstructorTest, InitializerListBucketAlloc) {
-#if defined(UNORDERED_SET_CXX14) || defined(UNORDERED_SET_CXX17)
+template <typename TypeParam>
+void InitializerListBucketAllocTest(std::false_type) {}
+
+template <typename TypeParam>
+void InitializerListBucketAllocTest(std::true_type) {
   using T = hash_internal::GeneratedType<TypeParam>;
   using A = typename TypeParam::allocator_type;
   hash_internal::Generator<T> gen;
@@ -288,11 +364,17 @@
   EXPECT_EQ(m.get_allocator(), alloc);
   EXPECT_THAT(keys(m), ::testing::UnorderedElementsAreArray(values));
   EXPECT_GE(m.bucket_count(), 123);
-#endif
 }
 
-TYPED_TEST_P(ConstructorTest, InitializerListBucketHashAlloc) {
-#if defined(UNORDERED_SET_CXX14) || defined(UNORDERED_SET_CXX17)
+TYPED_TEST_P(ConstructorTest, InitializerListBucketAlloc) {
+  InitializerListBucketAllocTest<TypeParam>(expect_cxx14_apis<TypeParam>());
+}
+
+template <typename TypeParam>
+void InitializerListBucketHashAllocTest(std::false_type) {}
+
+template <typename TypeParam>
+void InitializerListBucketHashAllocTest(std::true_type) {
   using T = hash_internal::GeneratedType<TypeParam>;
   using H = typename TypeParam::hasher;
   using A = typename TypeParam::allocator_type;
@@ -305,10 +387,13 @@
   EXPECT_EQ(m.get_allocator(), alloc);
   EXPECT_THAT(keys(m), ::testing::UnorderedElementsAreArray(values));
   EXPECT_GE(m.bucket_count(), 123);
-#endif
 }
 
-TYPED_TEST_P(ConstructorTest, Assignment) {
+TYPED_TEST_P(ConstructorTest, InitializerListBucketHashAlloc) {
+  InitializerListBucketHashAllocTest<TypeParam>(expect_cxx14_apis<TypeParam>());
+}
+
+TYPED_TEST_P(ConstructorTest, CopyAssignment) {
   using T = hash_internal::GeneratedType<TypeParam>;
   using H = typename TypeParam::hasher;
   using E = typename TypeParam::key_equal;
@@ -394,15 +479,16 @@
 
 REGISTER_TYPED_TEST_CASE_P(
     ConstructorTest, NoArgs, BucketCount, BucketCountHash, BucketCountHashEqual,
-    BucketCountHashEqualAlloc, BucketCountAlloc, BucketCountHashAlloc,
-    BucketAlloc, InputIteratorBucketHashEqualAlloc, InputIteratorBucketAlloc,
+    BucketCountHashEqualAlloc, BucketCountAlloc, BucketCountHashAlloc, Alloc,
+    InputIteratorBucketHashEqualAlloc, InputIteratorBucketAlloc,
     InputIteratorBucketHashAlloc, CopyConstructor, CopyConstructorAlloc,
     MoveConstructor, MoveConstructorAlloc, InitializerListBucketHashEqualAlloc,
-    InitializerListBucketAlloc, InitializerListBucketHashAlloc, Assignment,
-    MoveAssignment, AssignmentFromInitializerList,
-    AssignmentOverwritesExisting, MoveAssignmentOverwritesExisting,
+    InitializerListBucketAlloc, InitializerListBucketHashAlloc, CopyAssignment,
+    MoveAssignment, AssignmentFromInitializerList, AssignmentOverwritesExisting,
+    MoveAssignmentOverwritesExisting,
     AssignmentFromInitializerListOverwritesExisting, AssignmentOnSelf);
 
 }  // namespace container_internal
 }  // namespace absl
+
 #endif  // ABSL_CONTAINER_INTERNAL_UNORDERED_SET_CONSTRUCTOR_TEST_H_
diff --git a/absl/container/internal/unordered_set_lookup_test.h b/absl/container/internal/unordered_set_lookup_test.h
index aca9c6a..05b32b5 100644
--- a/absl/container/internal/unordered_set_lookup_test.h
+++ b/absl/container/internal/unordered_set_lookup_test.h
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -26,7 +26,7 @@
 template <class UnordSet>
 class LookupTest : public ::testing::Test {};
 
-TYPED_TEST_CASE_P(LookupTest);
+TYPED_TEST_SUITE_P(LookupTest);
 
 TYPED_TEST_P(LookupTest, Count) {
   using T = hash_internal::GeneratedType<TypeParam>;
@@ -85,4 +85,5 @@
 
 }  // namespace container_internal
 }  // namespace absl
+
 #endif  // ABSL_CONTAINER_INTERNAL_UNORDERED_SET_LOOKUP_TEST_H_
diff --git a/absl/container/internal/unordered_set_members_test.h b/absl/container/internal/unordered_set_members_test.h
new file mode 100644
index 0000000..b96c945
--- /dev/null
+++ b/absl/container/internal/unordered_set_members_test.h
@@ -0,0 +1,84 @@
+// Copyright 2019 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
+//
+//      https://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.
+
+#ifndef ABSL_CONTAINER_INTERNAL_UNORDERED_SET_MEMBERS_TEST_H_
+#define ABSL_CONTAINER_INTERNAL_UNORDERED_SET_MEMBERS_TEST_H_
+
+#include <type_traits>
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "absl/meta/type_traits.h"
+
+namespace absl {
+namespace container_internal {
+
+template <class UnordSet>
+class MembersTest : public ::testing::Test {};
+
+TYPED_TEST_SUITE_P(MembersTest);
+
+template <typename T>
+void UseType() {}
+
+TYPED_TEST_P(MembersTest, Typedefs) {
+  EXPECT_TRUE((std::is_same<typename TypeParam::key_type,
+                            typename TypeParam::value_type>()));
+  EXPECT_TRUE((absl::conjunction<
+               absl::negation<std::is_signed<typename TypeParam::size_type>>,
+               std::is_integral<typename TypeParam::size_type>>()));
+  EXPECT_TRUE((absl::conjunction<
+               std::is_signed<typename TypeParam::difference_type>,
+               std::is_integral<typename TypeParam::difference_type>>()));
+  EXPECT_TRUE((std::is_convertible<
+               decltype(std::declval<const typename TypeParam::hasher&>()(
+                   std::declval<const typename TypeParam::key_type&>())),
+               size_t>()));
+  EXPECT_TRUE((std::is_convertible<
+               decltype(std::declval<const typename TypeParam::key_equal&>()(
+                   std::declval<const typename TypeParam::key_type&>(),
+                   std::declval<const typename TypeParam::key_type&>())),
+               bool>()));
+  EXPECT_TRUE((std::is_same<typename TypeParam::allocator_type::value_type,
+                            typename TypeParam::value_type>()));
+  EXPECT_TRUE((std::is_same<typename TypeParam::value_type&,
+                            typename TypeParam::reference>()));
+  EXPECT_TRUE((std::is_same<const typename TypeParam::value_type&,
+                            typename TypeParam::const_reference>()));
+  EXPECT_TRUE((std::is_same<typename std::allocator_traits<
+                                typename TypeParam::allocator_type>::pointer,
+                            typename TypeParam::pointer>()));
+  EXPECT_TRUE(
+      (std::is_same<typename std::allocator_traits<
+                        typename TypeParam::allocator_type>::const_pointer,
+                    typename TypeParam::const_pointer>()));
+}
+
+TYPED_TEST_P(MembersTest, SimpleFunctions) {
+  EXPECT_GT(TypeParam().max_size(), 0);
+}
+
+TYPED_TEST_P(MembersTest, BeginEnd) {
+  TypeParam t = {typename TypeParam::value_type{}};
+  EXPECT_EQ(t.begin(), t.cbegin());
+  EXPECT_EQ(t.end(), t.cend());
+  EXPECT_NE(t.begin(), t.end());
+  EXPECT_NE(t.cbegin(), t.cend());
+}
+
+REGISTER_TYPED_TEST_SUITE_P(MembersTest, Typedefs, SimpleFunctions, BeginEnd);
+
+}  // namespace container_internal
+}  // namespace absl
+
+#endif  // ABSL_CONTAINER_INTERNAL_UNORDERED_SET_MEMBERS_TEST_H_
diff --git a/absl/container/internal/unordered_set_modifiers_test.h b/absl/container/internal/unordered_set_modifiers_test.h
index 9beacf3..79a8d42 100644
--- a/absl/container/internal/unordered_set_modifiers_test.h
+++ b/absl/container/internal/unordered_set_modifiers_test.h
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -26,7 +26,7 @@
 template <class UnordSet>
 class ModifiersTest : public ::testing::Test {};
 
-TYPED_TEST_CASE_P(ModifiersTest);
+TYPED_TEST_SUITE_P(ModifiersTest);
 
 TYPED_TEST_P(ModifiersTest, Clear) {
   using T = hash_internal::GeneratedType<TypeParam>;
@@ -184,4 +184,5 @@
 
 }  // namespace container_internal
 }  // namespace absl
+
 #endif  // ABSL_CONTAINER_INTERNAL_UNORDERED_SET_MODIFIERS_TEST_H_
diff --git a/absl/container/internal/unordered_set_test.cc b/absl/container/internal/unordered_set_test.cc
index 1281ce5..6478fac 100644
--- a/absl/container/internal/unordered_set_test.cc
+++ b/absl/container/internal/unordered_set_test.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -16,21 +16,23 @@
 
 #include "absl/container/internal/unordered_set_constructor_test.h"
 #include "absl/container/internal/unordered_set_lookup_test.h"
+#include "absl/container/internal/unordered_set_members_test.h"
 #include "absl/container/internal/unordered_set_modifiers_test.h"
 
 namespace absl {
 namespace container_internal {
 namespace {
 
-using SetTypes =
-    ::testing::Types<std::unordered_set<int, StatefulTestingHash,
-                                        StatefulTestingEqual, Alloc<int>>,
-                     std::unordered_set<std::string, StatefulTestingHash,
-                                        StatefulTestingEqual, Alloc<std::string>>>;
+using SetTypes = ::testing::Types<
+    std::unordered_set<int, StatefulTestingHash, StatefulTestingEqual,
+                       Alloc<int>>,
+    std::unordered_set<std::string, StatefulTestingHash, StatefulTestingEqual,
+                       Alloc<std::string>>>;
 
-INSTANTIATE_TYPED_TEST_CASE_P(UnorderedSet, ConstructorTest, SetTypes);
-INSTANTIATE_TYPED_TEST_CASE_P(UnorderedSet, LookupTest, SetTypes);
-INSTANTIATE_TYPED_TEST_CASE_P(UnorderedSet, ModifiersTest, SetTypes);
+INSTANTIATE_TYPED_TEST_SUITE_P(UnorderedSet, ConstructorTest, SetTypes);
+INSTANTIATE_TYPED_TEST_SUITE_P(UnorderedSet, LookupTest, SetTypes);
+INSTANTIATE_TYPED_TEST_SUITE_P(UnorderedSet, MembersTest, SetTypes);
+INSTANTIATE_TYPED_TEST_SUITE_P(UnorderedSet, ModifiersTest, SetTypes);
 
 }  // namespace
 }  // namespace container_internal
diff --git a/absl/container/node_hash_map.h b/absl/container/node_hash_map.h
index 6369ec3..a841f5a 100644
--- a/absl/container/node_hash_map.h
+++ b/absl/container/node_hash_map.h
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -40,6 +40,7 @@
 #include <type_traits>
 #include <utility>
 
+#include "absl/algorithm/container.h"
 #include "absl/container/internal/container_memory.h"
 #include "absl/container/internal/hash_function_defaults.h"  // IWYU pragma: export
 #include "absl/container/internal/node_hash_policy.h"
@@ -71,7 +72,7 @@
 // By default, `node_hash_map` uses the `absl::Hash` hashing framework.
 // All fundamental and Abseil types that support the `absl::Hash` framework have
 // a compatible equality operator for comparing insertions into `node_hash_map`.
-// If your type is not yet supported by the `asbl::Hash` framework, see
+// If your type is not yet supported by the `absl::Hash` framework, see
 // absl/hash/hash.h for information on extending Abseil hashing to user-defined
 // types.
 //
@@ -91,7 +92,7 @@
 //  std::string search_key = "b";
 //  auto result = ducks.find(search_key);
 //  if (result != ducks.end()) {
-//    std::cout << "Result: " << search_key->second << std::endl;
+//    std::cout << "Result: " << result->second << std::endl;
 //  }
 template <class Key, class Value,
           class Hash = absl::container_internal::hash_default_hash<Key>,
@@ -104,6 +105,46 @@
   using Base = typename node_hash_map::raw_hash_map;
 
  public:
+  // Constructors and Assignment Operators
+  //
+  // A node_hash_map supports the same overload set as `std::unordered_map`
+  // for construction and assignment:
+  //
+  // *  Default constructor
+  //
+  //    // No allocation for the table's elements is made.
+  //    absl::node_hash_map<int, std::string> map1;
+  //
+  // * Initializer List constructor
+  //
+  //   absl::node_hash_map<int, std::string> map2 =
+  //       {{1, "huey"}, {2, "dewey"}, {3, "louie"},};
+  //
+  // * Copy constructor
+  //
+  //   absl::node_hash_map<int, std::string> map3(map2);
+  //
+  // * Copy assignment operator
+  //
+  //  // Hash functor and Comparator are copied as well
+  //  absl::node_hash_map<int, std::string> map4;
+  //  map4 = map3;
+  //
+  // * Move constructor
+  //
+  //   // Move is guaranteed efficient
+  //   absl::node_hash_map<int, std::string> map5(std::move(map4));
+  //
+  // * Move assignment operator
+  //
+  //   // May be efficient if allocators are compatible
+  //   absl::node_hash_map<int, std::string> map6;
+  //   map6 = std::move(map5);
+  //
+  // * Range constructor
+  //
+  //   std::vector<std::pair<int, std::string>> v = {{1, "a"}, {2, "b"}};
+  //   absl::node_hash_map<int, std::string> map7(v.begin(), v.end());
   node_hash_map() {}
   using Base::Base;
 
@@ -526,5 +567,16 @@
   static const Value& value(const value_type* elem) { return elem->second; }
 };
 }  // namespace container_internal
+
+namespace container_algorithm_internal {
+
+// Specialization of trait in absl/algorithm/container.h
+template <class Key, class T, class Hash, class KeyEqual, class Allocator>
+struct IsUnorderedContainer<
+    absl::node_hash_map<Key, T, Hash, KeyEqual, Allocator>> : std::true_type {};
+
+}  // namespace container_algorithm_internal
+
 }  // namespace absl
+
 #endif  // ABSL_CONTAINER_NODE_HASH_MAP_H_
diff --git a/absl/container/node_hash_map_test.cc b/absl/container/node_hash_map_test.cc
index bd78964..0f2714a 100644
--- a/absl/container/node_hash_map_test.cc
+++ b/absl/container/node_hash_map_test.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -17,6 +17,7 @@
 #include "absl/container/internal/tracked.h"
 #include "absl/container/internal/unordered_map_constructor_test.h"
 #include "absl/container/internal/unordered_map_lookup_test.h"
+#include "absl/container/internal/unordered_map_members_test.h"
 #include "absl/container/internal/unordered_map_modifiers_test.h"
 
 namespace absl {
@@ -34,9 +35,10 @@
                         StatefulTestingEqual,
                         Alloc<std::pair<const std::string, std::string>>>>;
 
-INSTANTIATE_TYPED_TEST_CASE_P(NodeHashMap, ConstructorTest, MapTypes);
-INSTANTIATE_TYPED_TEST_CASE_P(NodeHashMap, LookupTest, MapTypes);
-INSTANTIATE_TYPED_TEST_CASE_P(NodeHashMap, ModifiersTest, MapTypes);
+INSTANTIATE_TYPED_TEST_SUITE_P(NodeHashMap, ConstructorTest, MapTypes);
+INSTANTIATE_TYPED_TEST_SUITE_P(NodeHashMap, LookupTest, MapTypes);
+INSTANTIATE_TYPED_TEST_SUITE_P(NodeHashMap, MembersTest, MapTypes);
+INSTANTIATE_TYPED_TEST_SUITE_P(NodeHashMap, ModifiersTest, MapTypes);
 
 using M = absl::node_hash_map<std::string, Tracked<int>>;
 
diff --git a/absl/container/node_hash_set.h b/absl/container/node_hash_set.h
index 90d4ce0..0cd1fe5 100644
--- a/absl/container/node_hash_set.h
+++ b/absl/container/node_hash_set.h
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -37,6 +37,7 @@
 
 #include <type_traits>
 
+#include "absl/algorithm/container.h"
 #include "absl/container/internal/hash_function_defaults.h"  // IWYU pragma: export
 #include "absl/container/internal/node_hash_policy.h"
 #include "absl/container/internal/raw_hash_set.h"  // IWYU pragma: export
@@ -67,7 +68,7 @@
 // By default, `node_hash_set` uses the `absl::Hash` hashing framework.
 // All fundamental and Abseil types that support the `absl::Hash` framework have
 // a compatible equality operator for comparing insertions into `node_hash_set`.
-// If your type is not yet supported by the `asbl::Hash` framework, see
+// If your type is not yet supported by the `absl::Hash` framework, see
 // absl/hash/hash.h for information on extending Abseil hashing to user-defined
 // types.
 //
@@ -96,6 +97,46 @@
   using Base = typename node_hash_set::raw_hash_set;
 
  public:
+  // Constructors and Assignment Operators
+  //
+  // A node_hash_set supports the same overload set as `std::unordered_map`
+  // for construction and assignment:
+  //
+  // *  Default constructor
+  //
+  //    // No allocation for the table's elements is made.
+  //    absl::node_hash_set<std::string> set1;
+  //
+  // * Initializer List constructor
+  //
+  //   absl::node_hash_set<std::string> set2 =
+  //       {{"huey"}, {"dewey"}, {"louie"},};
+  //
+  // * Copy constructor
+  //
+  //   absl::node_hash_set<std::string> set3(set2);
+  //
+  // * Copy assignment operator
+  //
+  //  // Hash functor and Comparator are copied as well
+  //  absl::node_hash_set<std::string> set4;
+  //  set4 = set3;
+  //
+  // * Move constructor
+  //
+  //   // Move is guaranteed efficient
+  //   absl::node_hash_set<std::string> set5(std::move(set4));
+  //
+  // * Move assignment operator
+  //
+  //   // May be efficient if allocators are compatible
+  //   absl::node_hash_set<std::string> set6;
+  //   set6 = std::move(set5);
+  //
+  // * Range constructor
+  //
+  //   std::vector<std::string> v = {"a", "b"};
+  //   absl::node_hash_set<std::string> set7(v.begin(), v.end());
   node_hash_set() {}
   using Base::Base;
 
@@ -232,8 +273,7 @@
   //
   // The element may be constructed even if there already is an element with the
   // key in the container, in which case the newly constructed element will be
-  // destroyed immediately. Prefer `try_emplace()` unless your key is not
-  // copyable or moveable.
+  // destroyed immediately.
   //
   // If rehashing occurs due to the insertion, all iterators are invalidated.
   using Base::emplace;
@@ -247,8 +287,7 @@
   //
   // The element may be constructed even if there already is an element with the
   // key in the container, in which case the newly constructed element will be
-  // destroyed immediately. Prefer `try_emplace()` unless your key is not
-  // copyable or moveable.
+  // destroyed immediately.
   //
   // If rehashing occurs due to the insertion, all iterators are invalidated.
   using Base::emplace_hint;
@@ -435,5 +474,15 @@
   static size_t element_space_used(const T*) { return sizeof(T); }
 };
 }  // namespace container_internal
+
+namespace container_algorithm_internal {
+
+// Specialization of trait in absl/algorithm/container.h
+template <class Key, class Hash, class KeyEqual, class Allocator>
+struct IsUnorderedContainer<absl::node_hash_set<Key, Hash, KeyEqual, Allocator>>
+    : std::true_type {};
+
+}  // namespace container_algorithm_internal
 }  // namespace absl
+
 #endif  // ABSL_CONTAINER_NODE_HASH_SET_H_
diff --git a/absl/container/node_hash_set_test.cc b/absl/container/node_hash_set_test.cc
index 7e498f0..0ea76e7 100644
--- a/absl/container/node_hash_set_test.cc
+++ b/absl/container/node_hash_set_test.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -16,6 +16,7 @@
 
 #include "absl/container/internal/unordered_set_constructor_test.h"
 #include "absl/container/internal/unordered_set_lookup_test.h"
+#include "absl/container/internal/unordered_set_members_test.h"
 #include "absl/container/internal/unordered_set_modifiers_test.h"
 
 namespace absl {
@@ -29,14 +30,15 @@
 using SetTypes = ::testing::Types<
     node_hash_set<int, StatefulTestingHash, StatefulTestingEqual, Alloc<int>>,
     node_hash_set<std::string, StatefulTestingHash, StatefulTestingEqual,
-                  Alloc<int>>,
+                  Alloc<std::string>>,
     node_hash_set<Enum, StatefulTestingHash, StatefulTestingEqual, Alloc<Enum>>,
     node_hash_set<EnumClass, StatefulTestingHash, StatefulTestingEqual,
                   Alloc<EnumClass>>>;
 
-INSTANTIATE_TYPED_TEST_CASE_P(NodeHashSet, ConstructorTest, SetTypes);
-INSTANTIATE_TYPED_TEST_CASE_P(NodeHashSet, LookupTest, SetTypes);
-INSTANTIATE_TYPED_TEST_CASE_P(NodeHashSet, ModifiersTest, SetTypes);
+INSTANTIATE_TYPED_TEST_SUITE_P(NodeHashSet, ConstructorTest, SetTypes);
+INSTANTIATE_TYPED_TEST_SUITE_P(NodeHashSet, LookupTest, SetTypes);
+INSTANTIATE_TYPED_TEST_SUITE_P(NodeHashSet, MembersTest, SetTypes);
+INSTANTIATE_TYPED_TEST_SUITE_P(NodeHashSet, ModifiersTest, SetTypes);
 
 TEST(NodeHashSet, MoveableNotCopyableCompiles) {
   node_hash_set<std::unique_ptr<void*>> t;
diff --git a/absl/copts.bzl b/absl/copts.bzl
deleted file mode 100644
index 5c508f1..0000000
--- a/absl/copts.bzl
+++ /dev/null
@@ -1,164 +0,0 @@
-"""absl specific copts.
-
-Flags specified here must not impact ABI. Code compiled with and without these
-opts will be linked together, and in some cases headers compiled with and
-without these options will be part of the same program.
-"""
-GCC_FLAGS = [
-    "-Wall",
-    "-Wextra",
-    "-Wcast-qual",
-    "-Wconversion-null",
-    "-Wmissing-declarations",
-    "-Woverlength-strings",
-    "-Wpointer-arith",
-    "-Wunused-local-typedefs",
-    "-Wunused-result",
-    "-Wvarargs",
-    "-Wvla",  # variable-length array
-    "-Wwrite-strings",
-    # Google style does not use unsigned integers, though STL containers
-    # have unsigned types.
-    "-Wno-sign-compare",
-]
-
-GCC_TEST_FLAGS = [
-    "-Wno-conversion-null",
-    "-Wno-missing-declarations",
-    "-Wno-sign-compare",
-    "-Wno-unused-function",
-    "-Wno-unused-parameter",
-    "-Wno-unused-private-field",
-]
-
-# Docs on single flags is preceded by a comment.
-# Docs on groups of flags is preceded by ###.
-
-LLVM_FLAGS = [
-    "-Wall",
-    "-Wextra",
-    "-Weverything",
-    # Abseil does not support C++98
-    "-Wno-c++98-compat-pedantic",
-    # Turns off all implicit conversion warnings. Most are re-enabled below.
-    "-Wno-conversion",
-    "-Wno-covered-switch-default",
-    "-Wno-deprecated",
-    "-Wno-disabled-macro-expansion",
-    "-Wno-double-promotion",
-    ###
-    # Turned off as they include valid C++ code.
-    "-Wno-comma",
-    "-Wno-extra-semi",
-    "-Wno-packed",
-    "-Wno-padded",
-    ###
-    # Google style does not use unsigned integers, though STL containers
-    # have unsigned types.
-    "-Wno-sign-compare",
-    ###
-    "-Wno-float-conversion",
-    "-Wno-float-equal",
-    "-Wno-format-nonliteral",
-    # Too aggressive: warns on Clang extensions enclosed in Clang-only
-    # compilation paths.
-    "-Wno-gcc-compat",
-    ###
-    # Some internal globals are necessary. Don't do this at home.
-    "-Wno-global-constructors",
-    "-Wno-exit-time-destructors",
-    ###
-    "-Wno-nested-anon-types",
-    "-Wno-non-modular-include-in-module",
-    "-Wno-old-style-cast",
-    # Warns on preferred usage of non-POD types such as string_view
-    "-Wno-range-loop-analysis",
-    "-Wno-reserved-id-macro",
-    "-Wno-shorten-64-to-32",
-    "-Wno-switch-enum",
-    "-Wno-thread-safety-negative",
-    "-Wno-undef",
-    "-Wno-unknown-warning-option",
-    "-Wno-unreachable-code",
-    # Causes warnings on include guards
-    "-Wno-unused-macros",
-    "-Wno-weak-vtables",
-    ###
-    # Implicit conversion warnings turned off by -Wno-conversion
-    # which are re-enabled below.
-    "-Wbitfield-enum-conversion",
-    "-Wbool-conversion",
-    "-Wconstant-conversion",
-    "-Wenum-conversion",
-    "-Wint-conversion",
-    "-Wliteral-conversion",
-    "-Wnon-literal-null-conversion",
-    "-Wnull-conversion",
-    "-Wobjc-literal-conversion",
-    "-Wno-sign-conversion",
-    "-Wstring-conversion",
-    ###
-]
-
-LLVM_TEST_FLAGS = [
-    "-Wno-c99-extensions",
-    "-Wno-missing-noreturn",
-    "-Wno-missing-prototypes",
-    "-Wno-missing-variable-declarations",
-    "-Wno-null-conversion",
-    "-Wno-shadow",
-    "-Wno-shift-sign-overflow",
-    "-Wno-sign-compare",
-    "-Wno-unused-function",
-    "-Wno-unused-member-function",
-    "-Wno-unused-parameter",
-    "-Wno-unused-private-field",
-    "-Wno-unused-template",
-    "-Wno-used-but-marked-unused",
-    "-Wno-zero-as-null-pointer-constant",
-    # gtest depends on this GNU extension being offered.
-    "-Wno-gnu-zero-variadic-macro-arguments",
-]
-
-MSVC_FLAGS = [
-    "/W3",
-    "/wd4005",  # macro-redefinition
-    "/wd4068",  # unknown pragma
-    "/wd4180",  # qualifier applied to function type has no meaning; ignored
-    "/wd4244",  # conversion from 'type1' to 'type2', possible loss of data
-    "/wd4267",  # conversion from 'size_t' to 'type', possible loss of data
-    "/wd4800",  # forcing value to bool 'true' or 'false' (performance warning)
-    "/DNOMINMAX",  # Don't define min and max macros (windows.h)
-    "/DWIN32_LEAN_AND_MEAN",  # Don't bloat namespace with incompatible winsock versions.
-    "/D_CRT_SECURE_NO_WARNINGS",  # Don't warn about usage of insecure C functions
-]
-
-MSVC_TEST_FLAGS = [
-    "/wd4018",  # signed/unsigned mismatch
-    "/wd4101",  # unreferenced local variable
-    "/wd4503",  # decorated name length exceeded, name was truncated
-]
-
-# /Wall with msvc includes unhelpful warnings such as C4711, C4710, ...
-ABSL_DEFAULT_COPTS = select({
-    "//absl:windows": MSVC_FLAGS,
-    "//absl:llvm_compiler": LLVM_FLAGS,
-    "//conditions:default": GCC_FLAGS,
-})
-
-# in absence of modules (--compiler=gcc or -c opt), cc_tests leak their copts
-# to their (included header) dependencies and fail to build outside absl
-ABSL_TEST_COPTS = ABSL_DEFAULT_COPTS + select({
-    "//absl:windows": MSVC_TEST_FLAGS,
-    "//absl:llvm_compiler": LLVM_TEST_FLAGS,
-    "//conditions:default": GCC_TEST_FLAGS,
-})
-
-ABSL_EXCEPTIONS_FLAG = select({
-    "//absl:windows": ["/U_HAS_EXCEPTIONS", "/D_HAS_EXCEPTIONS=1", "/EHsc"],
-    "//conditions:default": ["-fexceptions"],
-})
-
-ABSL_EXCEPTIONS_FLAG_LINKOPTS = select({
-    "//conditions:default": [],
-})
diff --git a/absl/copts/AbseilConfigureCopts.cmake b/absl/copts/AbseilConfigureCopts.cmake
new file mode 100644
index 0000000..5084958
--- /dev/null
+++ b/absl/copts/AbseilConfigureCopts.cmake
@@ -0,0 +1,52 @@
+# See absl/copts/copts.py and absl/copts/generate_copts.py
+include(GENERATED_AbseilCopts)
+
+set(ABSL_LSAN_LINKOPTS "")
+set(ABSL_HAVE_LSAN OFF)
+
+if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
+  set(ABSL_DEFAULT_COPTS "${ABSL_GCC_FLAGS}")
+  set(ABSL_TEST_COPTS "${ABSL_GCC_FLAGS};${ABSL_GCC_TEST_FLAGS}")
+  set(ABSL_EXCEPTIONS_FLAG "${ABSL_GCC_EXCEPTIONS_FLAGS}")
+elseif("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
+  # MATCHES so we get both Clang and AppleClang
+  if (MSVC)
+    # clang-cl is half MSVC, half LLVM
+    set(ABSL_DEFAULT_COPTS "${ABSL_CLANG_CL_FLAGS}")
+    set(ABSL_TEST_COPTS "${ABSL_CLANG_CL_FLAGS};${ABSL_CLANG_CL_TEST_FLAGS}")
+    set(ABSL_EXCEPTIONS_FLAG "${ABSL_CLANG_CL_EXCEPTIONS_FLAGS}")
+  else()
+    set(ABSL_DEFAULT_COPTS "${ABSL_LLVM_FLAGS}")
+    set(ABSL_TEST_COPTS "${ABSL_LLVM_FLAGS};${ABSL_LLVM_TEST_FLAGS}")
+    set(ABSL_EXCEPTIONS_FLAG "${ABSL_LLVM_EXCEPTIONS_FLAGS}")
+    if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
+      # AppleClang doesn't have lsan
+      # https://developer.apple.com/documentation/code_diagnostics
+      if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 3.5)
+        set(ABSL_LSAN_LINKOPTS "-fsanitize=leak")
+        set(ABSL_HAVE_LSAN ON)
+      endif()
+    endif()
+  endif()
+elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
+  set(ABSL_DEFAULT_COPTS "${ABSL_MSVC_FLAGS}")
+  set(ABSL_TEST_COPTS "${ABSL_MSVC_FLAGS};${ABSL_MSVC_TEST_FLAGS}")
+  set(ABSL_EXCEPTIONS_FLAG "${ABSL_MSVC_EXCEPTIONS_FLAGS}")
+else()
+  message(WARNING "Unknown compiler: ${CMAKE_CXX_COMPILER}.  Building with no default flags")
+  set(ABSL_DEFAULT_COPTS "")
+  set(ABSL_TEST_COPTS "")
+  set(ABSL_EXCEPTIONS_FLAG "")
+endif()
+
+# This flag is used internally for Bazel builds and is kept here for consistency
+set(ABSL_EXCEPTIONS_FLAG_LINKOPTS "")
+
+if("${CMAKE_CXX_STANDARD}" EQUAL 98)
+  message(FATAL_ERROR "Abseil requires at least C++11")
+elseif(NOT "${CMAKE_CXX_STANDARD}")
+  message(STATUS "No CMAKE_CXX_STANDARD set, assuming 11")
+  set(ABSL_CXX_STANDARD 11)
+else()
+  set(ABSL_CXX_STANDARD "${CMAKE_CXX_STANDARD}")
+endif()
diff --git a/absl/copts/GENERATED_AbseilCopts.cmake b/absl/copts/GENERATED_AbseilCopts.cmake
new file mode 100644
index 0000000..9031bfa
--- /dev/null
+++ b/absl/copts/GENERATED_AbseilCopts.cmake
@@ -0,0 +1,208 @@
+# GENERATED! DO NOT MANUALLY EDIT THIS FILE.
+#
+# (1) Edit absl/copts/copts.py.
+# (2) Run `python <path_to_absl>/copts/generate_copts.py`.
+
+list(APPEND ABSL_CLANG_CL_EXCEPTIONS_FLAGS
+    "/U_HAS_EXCEPTIONS"
+    "/D_HAS_EXCEPTIONS=1"
+    "/EHsc"
+)
+
+list(APPEND ABSL_CLANG_CL_FLAGS
+    "/W3"
+    "-Wno-c++98-compat-pedantic"
+    "-Wno-conversion"
+    "-Wno-covered-switch-default"
+    "-Wno-deprecated"
+    "-Wno-disabled-macro-expansion"
+    "-Wno-double-promotion"
+    "-Wno-comma"
+    "-Wno-extra-semi"
+    "-Wno-extra-semi-stmt"
+    "-Wno-packed"
+    "-Wno-padded"
+    "-Wno-sign-compare"
+    "-Wno-float-conversion"
+    "-Wno-float-equal"
+    "-Wno-format-nonliteral"
+    "-Wno-gcc-compat"
+    "-Wno-global-constructors"
+    "-Wno-exit-time-destructors"
+    "-Wno-nested-anon-types"
+    "-Wno-non-modular-include-in-module"
+    "-Wno-old-style-cast"
+    "-Wno-range-loop-analysis"
+    "-Wno-reserved-id-macro"
+    "-Wno-shorten-64-to-32"
+    "-Wno-switch-enum"
+    "-Wno-thread-safety-negative"
+    "-Wno-undef"
+    "-Wno-unknown-warning-option"
+    "-Wno-unreachable-code"
+    "-Wno-unused-macros"
+    "-Wno-weak-vtables"
+    "-Wbitfield-enum-conversion"
+    "-Wbool-conversion"
+    "-Wconstant-conversion"
+    "-Wenum-conversion"
+    "-Wint-conversion"
+    "-Wliteral-conversion"
+    "-Wnon-literal-null-conversion"
+    "-Wnull-conversion"
+    "-Wobjc-literal-conversion"
+    "-Wno-sign-conversion"
+    "-Wstring-conversion"
+    "/DNOMINMAX"
+    "/DWIN32_LEAN_AND_MEAN"
+    "/D_CRT_SECURE_NO_WARNINGS"
+    "/D_SCL_SECURE_NO_WARNINGS"
+    "/D_ENABLE_EXTENDED_ALIGNED_STORAGE"
+)
+
+list(APPEND ABSL_CLANG_CL_TEST_FLAGS
+    "-Wno-c99-extensions"
+    "-Wno-missing-noreturn"
+    "-Wno-missing-prototypes"
+    "-Wno-missing-variable-declarations"
+    "-Wno-null-conversion"
+    "-Wno-shadow"
+    "-Wno-shift-sign-overflow"
+    "-Wno-sign-compare"
+    "-Wno-unused-function"
+    "-Wno-unused-member-function"
+    "-Wno-unused-parameter"
+    "-Wno-unused-private-field"
+    "-Wno-unused-template"
+    "-Wno-used-but-marked-unused"
+    "-Wno-zero-as-null-pointer-constant"
+    "-Wno-gnu-zero-variadic-macro-arguments"
+)
+
+list(APPEND ABSL_GCC_EXCEPTIONS_FLAGS
+    "-fexceptions"
+)
+
+list(APPEND ABSL_GCC_FLAGS
+    "-Wall"
+    "-Wextra"
+    "-Wcast-qual"
+    "-Wconversion-null"
+    "-Wmissing-declarations"
+    "-Woverlength-strings"
+    "-Wpointer-arith"
+    "-Wunused-local-typedefs"
+    "-Wunused-result"
+    "-Wvarargs"
+    "-Wvla"
+    "-Wwrite-strings"
+    "-Wno-missing-field-initializers"
+    "-Wno-sign-compare"
+)
+
+list(APPEND ABSL_GCC_TEST_FLAGS
+    "-Wno-conversion-null"
+    "-Wno-missing-declarations"
+    "-Wno-sign-compare"
+    "-Wno-unused-function"
+    "-Wno-unused-parameter"
+    "-Wno-unused-private-field"
+)
+
+list(APPEND ABSL_LLVM_EXCEPTIONS_FLAGS
+    "-fexceptions"
+)
+
+list(APPEND ABSL_LLVM_FLAGS
+    "-Wall"
+    "-Wextra"
+    "-Weverything"
+    "-Wno-c++98-compat-pedantic"
+    "-Wno-conversion"
+    "-Wno-covered-switch-default"
+    "-Wno-deprecated"
+    "-Wno-disabled-macro-expansion"
+    "-Wno-double-promotion"
+    "-Wno-comma"
+    "-Wno-extra-semi"
+    "-Wno-extra-semi-stmt"
+    "-Wno-packed"
+    "-Wno-padded"
+    "-Wno-sign-compare"
+    "-Wno-float-conversion"
+    "-Wno-float-equal"
+    "-Wno-format-nonliteral"
+    "-Wno-gcc-compat"
+    "-Wno-global-constructors"
+    "-Wno-exit-time-destructors"
+    "-Wno-nested-anon-types"
+    "-Wno-non-modular-include-in-module"
+    "-Wno-old-style-cast"
+    "-Wno-range-loop-analysis"
+    "-Wno-reserved-id-macro"
+    "-Wno-shorten-64-to-32"
+    "-Wno-switch-enum"
+    "-Wno-thread-safety-negative"
+    "-Wno-undef"
+    "-Wno-unknown-warning-option"
+    "-Wno-unreachable-code"
+    "-Wno-unused-macros"
+    "-Wno-weak-vtables"
+    "-Wbitfield-enum-conversion"
+    "-Wbool-conversion"
+    "-Wconstant-conversion"
+    "-Wenum-conversion"
+    "-Wint-conversion"
+    "-Wliteral-conversion"
+    "-Wnon-literal-null-conversion"
+    "-Wnull-conversion"
+    "-Wobjc-literal-conversion"
+    "-Wno-sign-conversion"
+    "-Wstring-conversion"
+)
+
+list(APPEND ABSL_LLVM_TEST_FLAGS
+    "-Wno-c99-extensions"
+    "-Wno-missing-noreturn"
+    "-Wno-missing-prototypes"
+    "-Wno-missing-variable-declarations"
+    "-Wno-null-conversion"
+    "-Wno-shadow"
+    "-Wno-shift-sign-overflow"
+    "-Wno-sign-compare"
+    "-Wno-unused-function"
+    "-Wno-unused-member-function"
+    "-Wno-unused-parameter"
+    "-Wno-unused-private-field"
+    "-Wno-unused-template"
+    "-Wno-used-but-marked-unused"
+    "-Wno-zero-as-null-pointer-constant"
+    "-Wno-gnu-zero-variadic-macro-arguments"
+)
+
+list(APPEND ABSL_MSVC_EXCEPTIONS_FLAGS
+    "/U_HAS_EXCEPTIONS"
+    "/D_HAS_EXCEPTIONS=1"
+    "/EHsc"
+)
+
+list(APPEND ABSL_MSVC_FLAGS
+    "/W3"
+    "/DNOMINMAX"
+    "/DWIN32_LEAN_AND_MEAN"
+    "/D_CRT_SECURE_NO_WARNINGS"
+    "/D_SCL_SECURE_NO_WARNINGS"
+    "/D_ENABLE_EXTENDED_ALIGNED_STORAGE"
+    "/wd4005"
+    "/wd4068"
+    "/wd4180"
+    "/wd4244"
+    "/wd4267"
+    "/wd4800"
+)
+
+list(APPEND ABSL_MSVC_TEST_FLAGS
+    "/wd4018"
+    "/wd4101"
+    "/wd4503"
+)
diff --git a/absl/copts/GENERATED_copts.bzl b/absl/copts/GENERATED_copts.bzl
new file mode 100644
index 0000000..e05a58e
--- /dev/null
+++ b/absl/copts/GENERATED_copts.bzl
@@ -0,0 +1,209 @@
+"""GENERATED! DO NOT MANUALLY EDIT THIS FILE.
+
+(1) Edit absl/copts/copts.py.
+(2) Run `python <path_to_absl>/copts/generate_copts.py`.
+"""
+
+ABSL_CLANG_CL_EXCEPTIONS_FLAGS = [
+    "/U_HAS_EXCEPTIONS",
+    "/D_HAS_EXCEPTIONS=1",
+    "/EHsc",
+]
+
+ABSL_CLANG_CL_FLAGS = [
+    "/W3",
+    "-Wno-c++98-compat-pedantic",
+    "-Wno-conversion",
+    "-Wno-covered-switch-default",
+    "-Wno-deprecated",
+    "-Wno-disabled-macro-expansion",
+    "-Wno-double-promotion",
+    "-Wno-comma",
+    "-Wno-extra-semi",
+    "-Wno-extra-semi-stmt",
+    "-Wno-packed",
+    "-Wno-padded",
+    "-Wno-sign-compare",
+    "-Wno-float-conversion",
+    "-Wno-float-equal",
+    "-Wno-format-nonliteral",
+    "-Wno-gcc-compat",
+    "-Wno-global-constructors",
+    "-Wno-exit-time-destructors",
+    "-Wno-nested-anon-types",
+    "-Wno-non-modular-include-in-module",
+    "-Wno-old-style-cast",
+    "-Wno-range-loop-analysis",
+    "-Wno-reserved-id-macro",
+    "-Wno-shorten-64-to-32",
+    "-Wno-switch-enum",
+    "-Wno-thread-safety-negative",
+    "-Wno-undef",
+    "-Wno-unknown-warning-option",
+    "-Wno-unreachable-code",
+    "-Wno-unused-macros",
+    "-Wno-weak-vtables",
+    "-Wbitfield-enum-conversion",
+    "-Wbool-conversion",
+    "-Wconstant-conversion",
+    "-Wenum-conversion",
+    "-Wint-conversion",
+    "-Wliteral-conversion",
+    "-Wnon-literal-null-conversion",
+    "-Wnull-conversion",
+    "-Wobjc-literal-conversion",
+    "-Wno-sign-conversion",
+    "-Wstring-conversion",
+    "/DNOMINMAX",
+    "/DWIN32_LEAN_AND_MEAN",
+    "/D_CRT_SECURE_NO_WARNINGS",
+    "/D_SCL_SECURE_NO_WARNINGS",
+    "/D_ENABLE_EXTENDED_ALIGNED_STORAGE",
+]
+
+ABSL_CLANG_CL_TEST_FLAGS = [
+    "-Wno-c99-extensions",
+    "-Wno-missing-noreturn",
+    "-Wno-missing-prototypes",
+    "-Wno-missing-variable-declarations",
+    "-Wno-null-conversion",
+    "-Wno-shadow",
+    "-Wno-shift-sign-overflow",
+    "-Wno-sign-compare",
+    "-Wno-unused-function",
+    "-Wno-unused-member-function",
+    "-Wno-unused-parameter",
+    "-Wno-unused-private-field",
+    "-Wno-unused-template",
+    "-Wno-used-but-marked-unused",
+    "-Wno-zero-as-null-pointer-constant",
+    "-Wno-gnu-zero-variadic-macro-arguments",
+]
+
+ABSL_GCC_EXCEPTIONS_FLAGS = [
+    "-fexceptions",
+]
+
+ABSL_GCC_FLAGS = [
+    "-Wall",
+    "-Wextra",
+    "-Wcast-qual",
+    "-Wconversion-null",
+    "-Wmissing-declarations",
+    "-Woverlength-strings",
+    "-Wpointer-arith",
+    "-Wunused-local-typedefs",
+    "-Wunused-result",
+    "-Wvarargs",
+    "-Wvla",
+    "-Wwrite-strings",
+    "-Wno-missing-field-initializers",
+    "-Wno-sign-compare",
+]
+
+ABSL_GCC_TEST_FLAGS = [
+    "-Wno-conversion-null",
+    "-Wno-missing-declarations",
+    "-Wno-sign-compare",
+    "-Wno-unused-function",
+    "-Wno-unused-parameter",
+    "-Wno-unused-private-field",
+]
+
+ABSL_LLVM_EXCEPTIONS_FLAGS = [
+    "-fexceptions",
+]
+
+ABSL_LLVM_FLAGS = [
+    "-Wall",
+    "-Wextra",
+    "-Weverything",
+    "-Wno-c++98-compat-pedantic",
+    "-Wno-conversion",
+    "-Wno-covered-switch-default",
+    "-Wno-deprecated",
+    "-Wno-disabled-macro-expansion",
+    "-Wno-double-promotion",
+    "-Wno-comma",
+    "-Wno-extra-semi",
+    "-Wno-extra-semi-stmt",
+    "-Wno-packed",
+    "-Wno-padded",
+    "-Wno-sign-compare",
+    "-Wno-float-conversion",
+    "-Wno-float-equal",
+    "-Wno-format-nonliteral",
+    "-Wno-gcc-compat",
+    "-Wno-global-constructors",
+    "-Wno-exit-time-destructors",
+    "-Wno-nested-anon-types",
+    "-Wno-non-modular-include-in-module",
+    "-Wno-old-style-cast",
+    "-Wno-range-loop-analysis",
+    "-Wno-reserved-id-macro",
+    "-Wno-shorten-64-to-32",
+    "-Wno-switch-enum",
+    "-Wno-thread-safety-negative",
+    "-Wno-undef",
+    "-Wno-unknown-warning-option",
+    "-Wno-unreachable-code",
+    "-Wno-unused-macros",
+    "-Wno-weak-vtables",
+    "-Wbitfield-enum-conversion",
+    "-Wbool-conversion",
+    "-Wconstant-conversion",
+    "-Wenum-conversion",
+    "-Wint-conversion",
+    "-Wliteral-conversion",
+    "-Wnon-literal-null-conversion",
+    "-Wnull-conversion",
+    "-Wobjc-literal-conversion",
+    "-Wno-sign-conversion",
+    "-Wstring-conversion",
+]
+
+ABSL_LLVM_TEST_FLAGS = [
+    "-Wno-c99-extensions",
+    "-Wno-missing-noreturn",
+    "-Wno-missing-prototypes",
+    "-Wno-missing-variable-declarations",
+    "-Wno-null-conversion",
+    "-Wno-shadow",
+    "-Wno-shift-sign-overflow",
+    "-Wno-sign-compare",
+    "-Wno-unused-function",
+    "-Wno-unused-member-function",
+    "-Wno-unused-parameter",
+    "-Wno-unused-private-field",
+    "-Wno-unused-template",
+    "-Wno-used-but-marked-unused",
+    "-Wno-zero-as-null-pointer-constant",
+    "-Wno-gnu-zero-variadic-macro-arguments",
+]
+
+ABSL_MSVC_EXCEPTIONS_FLAGS = [
+    "/U_HAS_EXCEPTIONS",
+    "/D_HAS_EXCEPTIONS=1",
+    "/EHsc",
+]
+
+ABSL_MSVC_FLAGS = [
+    "/W3",
+    "/DNOMINMAX",
+    "/DWIN32_LEAN_AND_MEAN",
+    "/D_CRT_SECURE_NO_WARNINGS",
+    "/D_SCL_SECURE_NO_WARNINGS",
+    "/D_ENABLE_EXTENDED_ALIGNED_STORAGE",
+    "/wd4005",
+    "/wd4068",
+    "/wd4180",
+    "/wd4244",
+    "/wd4267",
+    "/wd4800",
+]
+
+ABSL_MSVC_TEST_FLAGS = [
+    "/wd4018",
+    "/wd4101",
+    "/wd4503",
+]
diff --git a/absl/copts/configure_copts.bzl b/absl/copts/configure_copts.bzl
new file mode 100644
index 0000000..1655add
--- /dev/null
+++ b/absl/copts/configure_copts.bzl
@@ -0,0 +1,42 @@
+"""absl specific copts.
+
+This file simply selects the correct options from the generated files.  To
+change Abseil copts, edit absl/copts/copts.py
+"""
+
+load(
+    "//absl:copts/GENERATED_copts.bzl",
+    "ABSL_GCC_EXCEPTIONS_FLAGS",
+    "ABSL_GCC_FLAGS",
+    "ABSL_GCC_TEST_FLAGS",
+    "ABSL_LLVM_EXCEPTIONS_FLAGS",
+    "ABSL_LLVM_FLAGS",
+    "ABSL_LLVM_TEST_FLAGS",
+    "ABSL_MSVC_EXCEPTIONS_FLAGS",
+    "ABSL_MSVC_FLAGS",
+    "ABSL_MSVC_TEST_FLAGS",
+)
+
+ABSL_DEFAULT_COPTS = select({
+    "//absl:windows": ABSL_MSVC_FLAGS,
+    "//absl:llvm_compiler": ABSL_LLVM_FLAGS,
+    "//conditions:default": ABSL_GCC_FLAGS,
+})
+
+# in absence of modules (--compiler=gcc or -c opt), cc_tests leak their copts
+# to their (included header) dependencies and fail to build outside absl
+ABSL_TEST_COPTS = ABSL_DEFAULT_COPTS + select({
+    "//absl:windows": ABSL_MSVC_TEST_FLAGS,
+    "//absl:llvm_compiler": ABSL_LLVM_TEST_FLAGS,
+    "//conditions:default": ABSL_GCC_TEST_FLAGS,
+})
+
+ABSL_EXCEPTIONS_FLAG = select({
+    "//absl:windows": ABSL_MSVC_EXCEPTIONS_FLAGS,
+    "//absl:llvm_compiler": ABSL_LLVM_EXCEPTIONS_FLAGS,
+    "//conditions:default": ABSL_GCC_EXCEPTIONS_FLAGS,
+})
+
+ABSL_EXCEPTIONS_FLAG_LINKOPTS = select({
+    "//conditions:default": [],
+})
diff --git a/absl/copts/copts.py b/absl/copts/copts.py
new file mode 100644
index 0000000..3c9d429
--- /dev/null
+++ b/absl/copts/copts.py
@@ -0,0 +1,178 @@
+"""Abseil compiler options.
+
+This is the source of truth for Abseil compiler options.  To modify Abseil
+compilation options:
+
+  (1) Edit the appropriate list in this file based on the platform the flag is
+      needed on.
+  (2) Run `<path_to_absl>/copts/generate_copts.py`.
+
+The generated copts are consumed by configure_copts.bzl and
+AbseilConfigureCopts.cmake.
+"""
+
+# /Wall with msvc includes unhelpful warnings such as C4711, C4710, ...
+MSVC_BIG_WARNING_FLAGS = [
+    "/W3",
+]
+
+LLVM_BIG_WARNING_FLAGS = [
+    "-Wall",
+    "-Wextra",
+    "-Weverything",
+]
+
+# Docs on single flags is preceded by a comment.
+# Docs on groups of flags is preceded by ###.
+LLVM_DISABLE_WARNINGS_FLAGS = [
+    # Abseil does not support C++98
+    "-Wno-c++98-compat-pedantic",
+    # Turns off all implicit conversion warnings. Most are re-enabled below.
+    "-Wno-conversion",
+    "-Wno-covered-switch-default",
+    "-Wno-deprecated",
+    "-Wno-disabled-macro-expansion",
+    "-Wno-double-promotion",
+    ###
+    # Turned off as they include valid C++ code.
+    "-Wno-comma",
+    "-Wno-extra-semi",
+    "-Wno-extra-semi-stmt",
+    "-Wno-packed",
+    "-Wno-padded",
+    ###
+    # Google style does not use unsigned integers, though STL containers
+    # have unsigned types.
+    "-Wno-sign-compare",
+    ###
+    "-Wno-float-conversion",
+    "-Wno-float-equal",
+    "-Wno-format-nonliteral",
+    # Too aggressive: warns on Clang extensions enclosed in Clang-only
+    # compilation paths.
+    "-Wno-gcc-compat",
+    ###
+    # Some internal globals are necessary. Don't do this at home.
+    "-Wno-global-constructors",
+    "-Wno-exit-time-destructors",
+    ###
+    "-Wno-nested-anon-types",
+    "-Wno-non-modular-include-in-module",
+    "-Wno-old-style-cast",
+    # Warns on preferred usage of non-POD types such as string_view
+    "-Wno-range-loop-analysis",
+    "-Wno-reserved-id-macro",
+    "-Wno-shorten-64-to-32",
+    "-Wno-switch-enum",
+    "-Wno-thread-safety-negative",
+    "-Wno-undef",
+    "-Wno-unknown-warning-option",
+    "-Wno-unreachable-code",
+    # Causes warnings on include guards
+    "-Wno-unused-macros",
+    "-Wno-weak-vtables",
+    ###
+    # Implicit conversion warnings turned off by -Wno-conversion
+    # which are re-enabled below.
+    "-Wbitfield-enum-conversion",
+    "-Wbool-conversion",
+    "-Wconstant-conversion",
+    "-Wenum-conversion",
+    "-Wint-conversion",
+    "-Wliteral-conversion",
+    "-Wnon-literal-null-conversion",
+    "-Wnull-conversion",
+    "-Wobjc-literal-conversion",
+    "-Wno-sign-conversion",
+    "-Wstring-conversion",
+]
+
+LLVM_TEST_DISABLE_WARNINGS_FLAGS = [
+    "-Wno-c99-extensions",
+    "-Wno-missing-noreturn",
+    "-Wno-missing-prototypes",
+    "-Wno-missing-variable-declarations",
+    "-Wno-null-conversion",
+    "-Wno-shadow",
+    "-Wno-shift-sign-overflow",
+    "-Wno-sign-compare",
+    "-Wno-unused-function",
+    "-Wno-unused-member-function",
+    "-Wno-unused-parameter",
+    "-Wno-unused-private-field",
+    "-Wno-unused-template",
+    "-Wno-used-but-marked-unused",
+    "-Wno-zero-as-null-pointer-constant",
+    # gtest depends on this GNU extension being offered.
+    "-Wno-gnu-zero-variadic-macro-arguments",
+]
+
+MSVC_STYLE_EXCEPTIONS_FLAGS = [
+    "/U_HAS_EXCEPTIONS", "/D_HAS_EXCEPTIONS=1", "/EHsc"
+]
+
+MSVC_DEFINES = [
+    "/DNOMINMAX",  # Don't define min and max macros (windows.h)
+    # Don't bloat namespace with incompatible winsock versions.
+    "/DWIN32_LEAN_AND_MEAN",
+    # Don't warn about usage of insecure C functions.
+    "/D_CRT_SECURE_NO_WARNINGS",
+    "/D_SCL_SECURE_NO_WARNINGS",
+    # Introduced in VS 2017 15.8, allow overaligned types in aligned_storage
+    "/D_ENABLE_EXTENDED_ALIGNED_STORAGE",
+]
+
+COPT_VARS = {
+    "ABSL_GCC_FLAGS": [
+        "-Wall",
+        "-Wextra",
+        "-Wcast-qual",
+        "-Wconversion-null",
+        "-Wmissing-declarations",
+        "-Woverlength-strings",
+        "-Wpointer-arith",
+        "-Wunused-local-typedefs",
+        "-Wunused-result",
+        "-Wvarargs",
+        "-Wvla",  # variable-length array
+        "-Wwrite-strings",
+        # gcc-4.x has spurious missing field initializer warnings.
+        # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=36750
+        # Remove when gcc-4.x is no longer supported.
+        "-Wno-missing-field-initializers",
+        # Google style does not use unsigned integers, though STL containers
+        # have unsigned types.
+        "-Wno-sign-compare",
+    ],
+    "ABSL_GCC_TEST_FLAGS": [
+        "-Wno-conversion-null",
+        "-Wno-missing-declarations",
+        "-Wno-sign-compare",
+        "-Wno-unused-function",
+        "-Wno-unused-parameter",
+        "-Wno-unused-private-field",
+    ],
+    "ABSL_GCC_EXCEPTIONS_FLAGS": ["-fexceptions"],
+    "ABSL_LLVM_FLAGS": LLVM_BIG_WARNING_FLAGS + LLVM_DISABLE_WARNINGS_FLAGS,
+    "ABSL_LLVM_TEST_FLAGS": LLVM_TEST_DISABLE_WARNINGS_FLAGS,
+    "ABSL_LLVM_EXCEPTIONS_FLAGS": ["-fexceptions"],
+    "ABSL_CLANG_CL_FLAGS": (MSVC_BIG_WARNING_FLAGS +
+                            LLVM_DISABLE_WARNINGS_FLAGS + MSVC_DEFINES),
+    "ABSL_CLANG_CL_TEST_FLAGS": LLVM_TEST_DISABLE_WARNINGS_FLAGS,
+    "ABSL_CLANG_CL_EXCEPTIONS_FLAGS": MSVC_STYLE_EXCEPTIONS_FLAGS,
+    "ABSL_MSVC_FLAGS": MSVC_BIG_WARNING_FLAGS + MSVC_DEFINES + [
+        "/wd4005",  # macro-redefinition
+        "/wd4068",  # unknown pragma
+        "/wd4180",  # qualifier applied to function type has no meaning; ignored
+        "/wd4244",  # conversion from 'type1' to 'type2', possible loss of data
+        "/wd4267",  # conversion from 'size_t' to 'type', possible loss of data
+        # forcing value to bool 'true' or 'false' (performance warning)
+        "/wd4800",
+    ],
+    "ABSL_MSVC_TEST_FLAGS": [
+        "/wd4018",  # signed/unsigned mismatch
+        "/wd4101",  # unreferenced local variable
+        "/wd4503",  # decorated name length exceeded, name was truncated
+    ],
+    "ABSL_MSVC_EXCEPTIONS_FLAGS": MSVC_STYLE_EXCEPTIONS_FLAGS,
+}
diff --git a/absl/copts/generate_copts.py b/absl/copts/generate_copts.py
new file mode 100755
index 0000000..28b677e
--- /dev/null
+++ b/absl/copts/generate_copts.py
@@ -0,0 +1,108 @@
+#!/usr/bin/python
+"""Generate Abseil compile compile option configs.
+
+Usage: <path_to_absl>/copts/generate_copts.py
+
+The configs are generated from copts.py.
+"""
+
+from os import path
+import sys
+from copts import COPT_VARS
+
+
+# Helper functions
+def file_header_lines():
+  return [
+      "GENERATED! DO NOT MANUALLY EDIT THIS FILE.", "",
+      "(1) Edit absl/copts/copts.py.",
+      "(2) Run `python <path_to_absl>/copts/generate_copts.py`."
+  ]
+
+
+def flatten(*lists):
+  return [item for sublist in lists for item in sublist]
+
+
+def relative_filename(filename):
+  return path.join(path.dirname(__file__), filename)
+
+
+# Style classes.  These contain all the syntactic styling needed to generate a
+# copt file for different build tools.
+class CMakeStyle(object):
+  """Style object for CMake copts file."""
+
+  def separator(self):
+    return ""
+
+  def list_introducer(self, name):
+    return "list(APPEND " + name
+
+  def list_closer(self):
+    return ")\n"
+
+  def docstring(self):
+    return "\n".join((("# " + line).strip() for line in file_header_lines()))
+
+  def filename(self):
+    return "GENERATED_AbseilCopts.cmake"
+
+
+class StarlarkStyle(object):
+  """Style object for Starlark copts file."""
+
+  def separator(self):
+    return ","
+
+  def list_introducer(self, name):
+    return name + " = ["
+
+  def list_closer(self):
+    return "]\n"
+
+  def docstring(self):
+    docstring_quotes = "\"\"\""
+    return docstring_quotes + "\n".join(
+        flatten(file_header_lines(), [docstring_quotes]))
+
+  def filename(self):
+    return "GENERATED_copts.bzl"
+
+
+# Copt file generation
+def copt_list(name, arg_list, style):
+  make_line = lambda s: "    \"" + s + "\"" + style.separator()
+  external_str_list = [make_line(s) for s in arg_list]
+
+  return "\n".join(
+      flatten(
+          [style.list_introducer(name)],
+          external_str_list,
+          [style.list_closer()]))
+
+
+def generate_copt_file(style):
+  """Creates a generated copt file using the given style object.
+
+  Args:
+    style: either StarlarkStyle() or CMakeStyle()
+  """
+  with open(relative_filename(style.filename()), "w") as f:
+    f.write(style.docstring())
+    f.write("\n")
+    for var_name, arg_list in sorted(COPT_VARS.items()):
+      f.write("\n")
+      f.write(copt_list(var_name, arg_list, style))
+
+
+def main(argv):
+  if len(argv) > 1:
+    raise RuntimeError("generate_copts needs no command line args")
+
+  generate_copt_file(StarlarkStyle())
+  generate_copt_file(CMakeStyle())
+
+
+if __name__ == "__main__":
+  main(sys.argv)
diff --git a/absl/debugging/BUILD.bazel b/absl/debugging/BUILD.bazel
index e1e7fce..c9184f9 100644
--- a/absl/debugging/BUILD.bazel
+++ b/absl/debugging/BUILD.bazel
@@ -5,7 +5,7 @@
 # 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
+#      https://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,
@@ -15,7 +15,7 @@
 #
 
 load(
-    "//absl:copts.bzl",
+    "//absl:copts/configure_copts.bzl",
     "ABSL_DEFAULT_COPTS",
     "ABSL_TEST_COPTS",
 )
@@ -149,6 +149,7 @@
     copts = ABSL_DEFAULT_COPTS,
     deps = [
         "//absl/base",
+        "//absl/base:core_headers",
         "//absl/base:dynamic_annotations",
     ],
 )
@@ -180,22 +181,8 @@
 
 cc_library(
     name = "leak_check",
-    srcs = select({
-        # The leak checking interface depends on weak function
-        # declarations that may not necessarily have definitions.
-        # Windows doesn't support this, and ios requires
-        # guaranteed definitions for weak symbols.
-        "//absl:ios": [],
-        "//absl:windows": [],
-        "//conditions:default": [
-            "leak_check.cc",
-        ],
-    }),
-    hdrs = select({
-        "//absl:ios": [],
-        "//absl:windows": [],
-        "//conditions:default": ["leak_check.h"],
-    }),
+    srcs = ["leak_check.cc"],
+    hdrs = ["leak_check.h"],
     deps = ["//absl/base:core_headers"],
 )
 
diff --git a/absl/debugging/CMakeLists.txt b/absl/debugging/CMakeLists.txt
index 4af2ec8..dccd4a5 100644
--- a/absl/debugging/CMakeLists.txt
+++ b/absl/debugging/CMakeLists.txt
@@ -5,7 +5,7 @@
 # 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
+#      https://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,
@@ -14,204 +14,292 @@
 # limitations under the License.
 #
 
-list(APPEND DEBUGGING_PUBLIC_HEADERS
-  "failure_signal_handler.h"
-  "leak_check.h"
-  "stacktrace.h"
-  "symbolize.h"
-)
-
-# TODO(cohenjon) The below is all kinds of wrong.  Make this match what we do in
-# Bazel
-list(APPEND DEBUGGING_INTERNAL_HEADERS
-  "internal/address_is_readable.h"
-  "internal/demangle.h"
-  "internal/elf_mem_image.h"
-  "internal/examine_stack.h"
-  "internal/stacktrace_config.h"
-  "internal/symbolize.h"
-  "internal/vdso_support.h"
-)
-
-list(APPEND DEBUGGING_INTERNAL_SRC
-  "internal/address_is_readable.cc"
-  "internal/elf_mem_image.cc"
-  "internal/vdso_support.cc"
-)
-
-
-list(APPEND STACKTRACE_SRC
-  "stacktrace.cc"
-  ${DEBUGGING_INTERNAL_SRC}
-  ${DEBUGGING_PUBLIC_HEADERS}
-  ${DEBUGGING_INTERNAL_HEADERS}
-)
-
-list(APPEND SYMBOLIZE_SRC
-  "symbolize.cc"
-  "symbolize_elf.inc"
-  "symbolize_unimplemented.inc"
-  "symbolize_win32.inc"
-  "internal/demangle.cc"
-  ${DEBUGGING_PUBLIC_HEADERS}
-  ${DEBUGGING_INTERNAL_HEADERS}
-  ${DEBUGGING_INTERNAL_SRC}
-)
-
-list(APPEND FAILURE_SIGNAL_HANDLER_SRC
-  "failure_signal_handler.cc"
-  ${DEBUGGING_PUBLIC_HEADERS}
-)
-
-list(APPEND EXAMINE_STACK_SRC
-  "internal/examine_stack.cc"
-  ${DEBUGGING_PUBLIC_HEADERS}
-  ${DEBUGGING_INTERNAL_HEADERS}
-)
-
-absl_library(
-  TARGET
-    absl_stacktrace
-  SOURCES
-    ${STACKTRACE_SRC}
-  EXPORT_NAME
+absl_cc_library(
+  NAME
     stacktrace
+  HDRS
+    "stacktrace.h"
+  SRCS
+    "stacktrace.cc"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::debugging_internal
+    absl::base
+    absl::core_headers
+  PUBLIC
 )
 
-absl_library(
-  TARGET
-    absl_symbolize
-  SOURCES
-    ${SYMBOLIZE_SRC}
-  PUBLIC_LIBRARIES
-    absl::base
-    absl_malloc_internal
-  EXPORT_NAME
+absl_cc_library(
+  NAME
     symbolize
-)
-
-absl_library(
-  TARGET
-    absl_failure_signal_handler
-  SOURCES
-    ${FAILURE_SIGNAL_HANDLER_SRC}
-  PUBLIC_LIBRARIES
-    absl_base absl::examine_stack absl::stacktrace absl_synchronization
-  EXPORT_NAME
-    failure_signal_handler
-)
-
-# Internal-only. Projects external to Abseil should not depend
-# directly on this library.
-absl_library(
-  TARGET
-    absl_examine_stack
-  SOURCES
-    ${EXAMINE_STACK_SRC}
-  EXPORT_NAME
-    examine_stack
-)
-
-list(APPEND LEAK_CHECK_SRC
-  "leak_check.cc"
-)
-
-
-# leak_check library
-absl_library(
-  TARGET
-    absl_leak_check
-  SOURCES
-    ${LEAK_CHECK_SRC}
-  PUBLIC_LIBRARIES
-    absl_base
-  EXPORT_NAME
-    leak_check
-)
-
-
-# component target
-absl_header_library(
-  TARGET
-    absl_debugging
-  PUBLIC_LIBRARIES
-    absl_stacktrace absl_leak_check
-  EXPORT_NAME
-    debugging
-)
-
-#
-## TESTS
-#
-
-list(APPEND STACK_CONSUMPTION_SRC
-  "internal/stack_consumption.cc"
-  "internal/stack_consumption.h"
-)
-
-absl_library(
-  TARGET
-    absl_stack_consumption
-  SOURCES
-    ${STACK_CONSUMPTION_SRC}
-)
-
-absl_test(
-  TARGET
-    absl_stack_consumption_test
-  SOURCES
-    "internal/stack_consumption_test.cc"
-  PUBLIC_LIBRARIES
-    absl_stack_consumption
+  HDRS
+    "symbolize.h"
+    "internal/symbolize.h"
+  SRCS
+    "symbolize.cc"
+    "symbolize_elf.inc"
+    "symbolize_unimplemented.inc"
+    "symbolize_win32.inc"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::debugging_internal
+    absl::demangle_internal
     absl::base
+    absl::core_headers
+    absl::malloc_internal
+  PUBLIC
 )
 
-list(APPEND DEMANGLE_TEST_SRC "internal/demangle_test.cc")
-
-absl_test(
-  TARGET
-    demangle_test
-  SOURCES
-    ${DEMANGLE_TEST_SRC}
-  PUBLIC_LIBRARIES
-    absl_symbolize absl_stack_consumption
-)
-
-list(APPEND SYMBOLIZE_TEST_SRC "symbolize_test.cc")
-
-absl_test(
-  TARGET
+absl_cc_test(
+  NAME
     symbolize_test
-  SOURCES
-    ${SYMBOLIZE_TEST_SRC}
-  PUBLIC_LIBRARIES
-    absl::base absl::memory absl_symbolize absl_stack_consumption
+  SRCS
+    "symbolize_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::stack_consumption
+    absl::symbolize
+    absl::base
+    absl::core_headers
+    absl::memory
+    gmock
 )
 
-list(APPEND FAILURE_SIGNAL_HANDLER_TEST_SRC "failure_signal_handler_test.cc")
+absl_cc_library(
+  NAME
+    examine_stack
+  HDRS
+    "internal/examine_stack.h"
+  SRCS
+    "internal/examine_stack.cc"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::stacktrace
+    absl::symbolize
+    absl::base
+    absl::core_headers
+)
 
-absl_test(
-  TARGET
+absl_cc_library(
+  NAME
+    failure_signal_handler
+  HDRS
+    "failure_signal_handler.h"
+  SRCS
+    "failure_signal_handler.cc"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::examine_stack
+    absl::stacktrace
+    absl::base
+    absl::config
+    absl::core_headers
+  PUBLIC
+)
+
+absl_cc_test(
+  NAME
     failure_signal_handler_test
-  SOURCES
-    ${FAILURE_SIGNAL_HANDLER_TEST_SRC}
-  PUBLIC_LIBRARIES
-    absl_examine_stack
-    absl_failure_signal_handler
-    absl_stacktrace
-    absl_symbolize
+  SRCS
+    "failure_signal_handler_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::failure_signal_handler
+    absl::stacktrace
+    absl::symbolize
     absl::base
     absl::strings
+    Threads::Threads
+    gmock
 )
 
-# test leak_check_test
-list(APPEND LEAK_CHECK_TEST_SRC "leak_check_test.cc")
+absl_cc_library(
+  NAME
+    debugging_internal
+  HDRS
+    "internal/address_is_readable.h"
+    "internal/elf_mem_image.h"
+    "internal/stacktrace_aarch64-inl.inc"
+    "internal/stacktrace_arm-inl.inc"
+    "internal/stacktrace_config.h"
+    "internal/stacktrace_generic-inl.inc"
+    "internal/stacktrace_powerpc-inl.inc"
+    "internal/stacktrace_unimplemented-inl.inc"
+    "internal/stacktrace_win32-inl.inc"
+    "internal/stacktrace_x86-inl.inc"
+    "internal/vdso_support.h"
+  SRCS
+    "internal/address_is_readable.cc"
+    "internal/elf_mem_image.cc"
+    "internal/vdso_support.cc"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::base
+    absl::core_headers
+    absl::dynamic_annotations
+)
 
-absl_test(
-  TARGET
+absl_cc_library(
+  NAME
+    demangle_internal
+  HDRS
+    "internal/demangle.h"
+  SRCS
+    "internal/demangle.cc"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::base
+    absl::core_headers
+  PUBLIC
+)
+
+absl_cc_test(
+  NAME
+    demangle_test
+  SRCS
+    "internal/demangle_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::demangle_internal
+    absl::stack_consumption
+    absl::base
+    absl::core_headers
+    absl::memory
+    gmock_main
+)
+
+absl_cc_library(
+  NAME
+    leak_check
+  HDRS
+    "leak_check.h"
+  SRCS
+    "leak_check.cc"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::core_headers
+  PUBLIC
+)
+
+absl_cc_library(
+  NAME
+    leak_check_disable
+  SRCS
+    "leak_check_disable.cc"
+  PUBLIC
+)
+
+absl_cc_library(
+  NAME
+    leak_check_api_enabled_for_testing
+  HDRS
+    "leak_check.h"
+  SRCS
+    "leak_check.cc"
+  COPTS
+    $<$<BOOL:${ABSL_HAVE_LSAN}>:-DLEAK_SANITIZER>
+  TESTONLY
+)
+
+absl_cc_library(
+  NAME
+    leak_check_api_disabled_for_testing
+  HDRS
+    "leak_check.h"
+  SRCS
+    "leak_check.cc"
+  COPTS
+    "-ULEAK_SANITIZER"
+  TESTONLY
+)
+
+absl_cc_test(
+  NAME
     leak_check_test
-  SOURCES
-    ${LEAK_CHECK_TEST_SRC}
-  PUBLIC_LIBRARIES
-    absl_leak_check
+  SRCS
+    "leak_check_test.cc"
+  COPTS
+    "$<$<BOOL:${ABSL_HAVE_LSAN}>:-DABSL_EXPECT_LEAK_SANITIZER>"
+  LINKOPTS
+    "${ABSL_LSAN_LINKOPTS}"
+  DEPS
+    absl::leak_check_api_enabled_for_testing
+    absl::base
+    gmock_main
+)
+
+absl_cc_test(
+  NAME
+    leak_check_no_lsan_test
+  SRCS
+    "leak_check_test.cc"
+  COPTS
+    "-UABSL_EXPECT_LEAK_SANITIZER"
+  DEPS
+    absl::leak_check_api_disabled_for_testing
+    absl::base
+    gmock_main
+)
+
+absl_cc_test(
+  NAME
+    disabled_leak_check_test
+  SRCS
+    "leak_check_fail_test.cc"
+  LINKOPTS
+    "${ABSL_LSAN_LINKOPTS}"
+  DEPS
+    absl::leak_check_api_enabled_for_testing
+    absl::leak_check_disable
+    absl::base
+    gmock_main
+)
+
+absl_cc_library(
+  NAME
+    stack_consumption
+  HDRS
+    "internal/stack_consumption.h"
+  SRCS
+    "internal/stack_consumption.cc"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::base
+    absl::core_headers
+  TESTONLY
+)
+
+absl_cc_test(
+  NAME
+    stack_consumption_test
+  SRCS
+    "internal/stack_consumption_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::stack_consumption
+    absl::base
+    absl::core_headers
+    gmock_main
+)
+
+# component target
+absl_cc_library(
+  NAME
+    debugging
+  DEPS
+    absl::stacktrace
+    absl::leak_check
+  PUBLIC
 )
diff --git a/absl/debugging/failure_signal_handler.cc b/absl/debugging/failure_signal_handler.cc
index d4b957b..c6a4d96 100644
--- a/absl/debugging/failure_signal_handler.cc
+++ b/absl/debugging/failure_signal_handler.cc
@@ -5,7 +5,7 @@
 // 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
+//      https://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,
@@ -119,7 +119,11 @@
 #ifndef _WIN32
 
 static bool SetupAlternateStackOnce() {
+#if defined(__wasm__) || defined (__asjms__)
   const size_t page_mask = getpagesize() - 1;
+#else
+  const size_t page_mask = sysconf(_SC_PAGESIZE) - 1;
+#endif
   size_t stack_size = (std::max(SIGSTKSZ, 65536) + page_mask) & ~page_mask;
 #if defined(ADDRESS_SANITIZER) || defined(MEMORY_SANITIZER) || \
     defined(THREAD_SANITIZER)
diff --git a/absl/debugging/failure_signal_handler.h b/absl/debugging/failure_signal_handler.h
index c57954e..1beb78b 100644
--- a/absl/debugging/failure_signal_handler.h
+++ b/absl/debugging/failure_signal_handler.h
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
diff --git a/absl/debugging/failure_signal_handler_test.cc b/absl/debugging/failure_signal_handler_test.cc
index ba52091..bb2cc48 100644
--- a/absl/debugging/failure_signal_handler_test.cc
+++ b/absl/debugging/failure_signal_handler_test.cc
@@ -5,7 +5,7 @@
 // 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
+//      https://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,
@@ -133,16 +133,17 @@
 };
 
 std::string SignalParamToString(const ::testing::TestParamInfo<int>& info) {
-  std::string result = absl::debugging_internal::FailureSignalToString(info.param);
+  std::string result =
+      absl::debugging_internal::FailureSignalToString(info.param);
   if (result.empty()) {
     result = absl::StrCat(info.param);
   }
   return result;
 }
 
-INSTANTIATE_TEST_CASE_P(AbslDeathTest, FailureSignalHandlerDeathTest,
-                        ::testing::ValuesIn(kFailureSignals),
-                        SignalParamToString);
+INSTANTIATE_TEST_SUITE_P(AbslDeathTest, FailureSignalHandlerDeathTest,
+                         ::testing::ValuesIn(kFailureSignals),
+                         SignalParamToString);
 
 #endif  // GTEST_HAS_DEATH_TEST
 
diff --git a/absl/debugging/internal/address_is_readable.cc b/absl/debugging/internal/address_is_readable.cc
index 7455aa0..99c4c64 100644
--- a/absl/debugging/internal/address_is_readable.cc
+++ b/absl/debugging/internal/address_is_readable.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
diff --git a/absl/debugging/internal/address_is_readable.h b/absl/debugging/internal/address_is_readable.h
index 9d48030..ca8003e 100644
--- a/absl/debugging/internal/address_is_readable.h
+++ b/absl/debugging/internal/address_is_readable.h
@@ -4,14 +4,13 @@
 // 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
+//      https://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.
-//
 
 #ifndef ABSL_DEBUGGING_INTERNAL_ADDRESS_IS_READABLE_H_
 #define ABSL_DEBUGGING_INTERNAL_ADDRESS_IS_READABLE_H_
diff --git a/absl/debugging/internal/demangle.cc b/absl/debugging/internal/demangle.cc
index 4835445..52a553f 100644
--- a/absl/debugging/internal/demangle.cc
+++ b/absl/debugging/internal/demangle.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -749,8 +749,8 @@
 // <local-source-name> ::= L <source-name> [<discriminator>]
 //
 // References:
-//   http://gcc.gnu.org/bugzilla/show_bug.cgi?id=31775
-//   http://gcc.gnu.org/viewcvs?view=rev&revision=124467
+//   https://gcc.gnu.org/bugzilla/show_bug.cgi?id=31775
+//   https://gcc.gnu.org/viewcvs?view=rev&revision=124467
 static bool ParseLocalSourceName(State *state) {
   ComplexityGuard guard(state);
   if (guard.IsTooComplex()) return false;
@@ -1168,6 +1168,12 @@
   }
   state->parse_state = copy;
 
+  // nullptr_t, i.e. decltype(nullptr).
+  if (ParseTwoCharToken(state, "Dn")) {
+    return true;
+  }
+  state->parse_state = copy;
+
   if (ParseOneCharToken(state, 'U') && ParseSourceName(state) &&
       ParseType(state)) {
     return true;
@@ -1636,6 +1642,15 @@
   }
   state->parse_state = copy;
 
+  // Pointer-to-member access expressions.  This parses the same as a binary
+  // operator, but it's implemented separately because "ds" shouldn't be
+  // accepted in other contexts that parse an operator name.
+  if (ParseTwoCharToken(state, "ds") && ParseExpression(state) &&
+      ParseExpression(state)) {
+    return true;
+  }
+  state->parse_state = copy;
+
   // Parameter pack expansion
   if (ParseTwoCharToken(state, "sp") && ParseExpression(state)) {
     return true;
diff --git a/absl/debugging/internal/demangle.h b/absl/debugging/internal/demangle.h
index 2e75564..81bb0df 100644
--- a/absl/debugging/internal/demangle.h
+++ b/absl/debugging/internal/demangle.h
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
diff --git a/absl/debugging/internal/demangle_test.cc b/absl/debugging/internal/demangle_test.cc
index b9d9008..883b92d 100644
--- a/absl/debugging/internal/demangle_test.cc
+++ b/absl/debugging/internal/demangle_test.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -176,6 +176,7 @@
 TEST(DemangleRegression, NegativeLength) {
   TestOnInput("_ZZn4");
 }
+
 TEST(DemangleRegression, DeeplyNestedArrayType) {
   const int depth = 100000;
   std::string data = "_ZStI";
diff --git a/absl/debugging/internal/elf_mem_image.cc b/absl/debugging/internal/elf_mem_image.cc
index 3f747e7..e7408bc 100644
--- a/absl/debugging/internal/elf_mem_image.cc
+++ b/absl/debugging/internal/elf_mem_image.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
diff --git a/absl/debugging/internal/elf_mem_image.h b/absl/debugging/internal/elf_mem_image.h
index 3b57726..99b3758 100644
--- a/absl/debugging/internal/elf_mem_image.h
+++ b/absl/debugging/internal/elf_mem_image.h
@@ -5,7 +5,7 @@
  * 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
+ *      https://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,
diff --git a/absl/debugging/internal/examine_stack.cc b/absl/debugging/internal/examine_stack.cc
index faf8883..1ebc788 100644
--- a/absl/debugging/internal/examine_stack.cc
+++ b/absl/debugging/internal/examine_stack.cc
@@ -5,7 +5,7 @@
 // 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
+//      https://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,
diff --git a/absl/debugging/internal/examine_stack.h b/absl/debugging/internal/examine_stack.h
index a16c03b..56c9763 100644
--- a/absl/debugging/internal/examine_stack.h
+++ b/absl/debugging/internal/examine_stack.h
@@ -5,7 +5,7 @@
 // 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
+//      https://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,
diff --git a/absl/debugging/internal/stack_consumption.cc b/absl/debugging/internal/stack_consumption.cc
index 2b3b972..4b05f49 100644
--- a/absl/debugging/internal/stack_consumption.cc
+++ b/absl/debugging/internal/stack_consumption.cc
@@ -5,7 +5,7 @@
 // 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
+//      https://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,
diff --git a/absl/debugging/internal/stack_consumption.h b/absl/debugging/internal/stack_consumption.h
index 4c5fa0f..b860a3c 100644
--- a/absl/debugging/internal/stack_consumption.h
+++ b/absl/debugging/internal/stack_consumption.h
@@ -5,7 +5,7 @@
 // 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
+//      https://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,
diff --git a/absl/debugging/internal/stack_consumption_test.cc b/absl/debugging/internal/stack_consumption_test.cc
index 5ce3846..68bfa12 100644
--- a/absl/debugging/internal/stack_consumption_test.cc
+++ b/absl/debugging/internal/stack_consumption_test.cc
@@ -5,7 +5,7 @@
 // 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
+//      https://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,
diff --git a/absl/debugging/internal/stacktrace_config.h b/absl/debugging/internal/stacktrace_config.h
index dd713da..d4e8480 100644
--- a/absl/debugging/internal/stacktrace_config.h
+++ b/absl/debugging/internal/stacktrace_config.h
@@ -5,7 +5,7 @@
  * 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
+ *      https://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,
@@ -41,8 +41,9 @@
 #define ABSL_STACKTRACE_INL_HEADER \
     "absl/debugging/internal/stacktrace_aarch64-inl.inc"
 # elif defined(__arm__)
+// Note: When using glibc this may require -funwind-tables to function properly.
 #define ABSL_STACKTRACE_INL_HEADER \
-    "absl/debugging/internal/stacktrace_arm-inl.inc"
+  "absl/debugging/internal/stacktrace_generic-inl.inc"
 # else
 #define ABSL_STACKTRACE_INL_HEADER \
    "absl/debugging/internal/stacktrace_unimplemented-inl.inc"
diff --git a/absl/debugging/internal/stacktrace_generic-inl.inc b/absl/debugging/internal/stacktrace_generic-inl.inc
index 2c9ca41..2e876fe 100644
--- a/absl/debugging/internal/stacktrace_generic-inl.inc
+++ b/absl/debugging/internal/stacktrace_generic-inl.inc
@@ -12,13 +12,48 @@
 #define ABSL_DEBUGGING_INTERNAL_STACKTRACE_GENERIC_INL_H_
 
 #include <execinfo.h>
+#include <atomic>
 #include <cstring>
 
 #include "absl/debugging/stacktrace.h"
 
+// Sometimes, we can try to get a stack trace from within a stack
+// trace, because we don't block signals inside this code (which would be too
+// expensive: the two extra system calls per stack trace do matter here).
+// That can cause a self-deadlock.
+// Protect against such reentrant call by failing to get a stack trace.
+//
+// We use __thread here because the code here is extremely low level -- it is
+// called while collecting stack traces from within malloc and mmap, and thus
+// can not call anything which might call malloc or mmap itself.
+static __thread int recursive = 0;
+
+// The stack trace function might be invoked very early in the program's
+// execution (e.g. from the very first malloc if using tcmalloc). Also, the
+// glibc implementation itself will trigger malloc the first time it is called.
+// As such, we suppress usage of backtrace during this early stage of execution.
+static std::atomic<bool> disable_stacktraces(true);  // Disabled until healthy.
+// Waiting until static initializers run seems to be late enough.
+// This file is included into stacktrace.cc so this will only run once.
+static int stacktraces_enabler = []() {
+  void* unused_stack[1];
+  // Force the first backtrace to happen early to get the one-time shared lib
+  // loading (allocation) out of the way. After the first call it is much safer
+  // to use backtrace from a signal handler if we crash somewhere later.
+  backtrace(unused_stack, 1);
+  disable_stacktraces.store(false, std::memory_order_relaxed);
+  return 0;
+}();
+
 template <bool IS_STACK_FRAMES, bool IS_WITH_CONTEXT>
 static int UnwindImpl(void** result, int* sizes, int max_depth, int skip_count,
                       const void *ucp, int *min_dropped_frames) {
+  if (recursive || disable_stacktraces.load(std::memory_order_relaxed)) {
+    return 0;
+  }
+  ++recursive;
+
+  static_cast<void>(ucp);  // Unused.
   static const int kStackLength = 64;
   void * stack[kStackLength];
   int size;
@@ -45,6 +80,8 @@
     }
   }
 
+  --recursive;
+
   return result_count;
 }
 
diff --git a/absl/debugging/internal/stacktrace_powerpc-inl.inc b/absl/debugging/internal/stacktrace_powerpc-inl.inc
index 860ac2b..9e0f2aa 100644
--- a/absl/debugging/internal/stacktrace_powerpc-inl.inc
+++ b/absl/debugging/internal/stacktrace_powerpc-inl.inc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -14,8 +14,8 @@
 //
 // Produce stack trace.  I'm guessing (hoping!) the code is much like
 // for x86.  For apple machines, at least, it seems to be; see
-//    http://developer.apple.com/documentation/mac/runtimehtml/RTArch-59.html
-//    http://www.linux-foundation.org/spec/ELF/ppc64/PPC-elf64abi-1.9.html#STACK
+//    https://developer.apple.com/documentation/mac/runtimehtml/RTArch-59.html
+//    https://www.linux-foundation.org/spec/ELF/ppc64/PPC-elf64abi-1.9.html#STACK
 // Linux has similar code: http://patchwork.ozlabs.org/linuxppc/patch?id=8882
 
 #ifndef ABSL_DEBUGGING_INTERNAL_STACKTRACE_POWERPC_INL_H_
diff --git a/absl/debugging/internal/stacktrace_win32-inl.inc b/absl/debugging/internal/stacktrace_win32-inl.inc
index a8f8a56..b46491f 100644
--- a/absl/debugging/internal/stacktrace_win32-inl.inc
+++ b/absl/debugging/internal/stacktrace_win32-inl.inc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -32,7 +32,7 @@
 // server.
 //
 // This code is inspired by a patch from David Vitek:
-//   http://code.google.com/p/google-perftools/issues/detail?id=83
+//   https://code.google.com/p/google-perftools/issues/detail?id=83
 
 #ifndef ABSL_DEBUGGING_INTERNAL_STACKTRACE_WIN32_INL_H_
 #define ABSL_DEBUGGING_INTERNAL_STACKTRACE_WIN32_INL_H_
diff --git a/absl/debugging/internal/stacktrace_x86-inl.inc b/absl/debugging/internal/stacktrace_x86-inl.inc
index ac85b92..25aa8bd 100644
--- a/absl/debugging/internal/stacktrace_x86-inl.inc
+++ b/absl/debugging/internal/stacktrace_x86-inl.inc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -33,6 +33,7 @@
 #include "absl/debugging/internal/address_is_readable.h"
 #include "absl/debugging/internal/vdso_support.h"  // a no-op on non-elf or non-glibc systems
 #include "absl/debugging/stacktrace.h"
+
 #include "absl/base/internal/raw_logging.h"
 
 #if defined(__linux__) && defined(__i386__)
diff --git a/absl/debugging/internal/symbolize.h b/absl/debugging/internal/symbolize.h
index 8d926fe..3e53789 100644
--- a/absl/debugging/internal/symbolize.h
+++ b/absl/debugging/internal/symbolize.h
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -20,7 +20,6 @@
 
 #include <cstddef>
 #include <cstdint>
-#include "absl/base/port.h"  // Needed for string vs std::string
 
 #ifdef ABSL_INTERNAL_HAVE_ELF_SYMBOLIZE
 #error ABSL_INTERNAL_HAVE_ELF_SYMBOLIZE cannot be directly set
@@ -42,9 +41,9 @@
 // Returns true on success; otherwise returns false in case of errors.
 //
 // This is not async-signal-safe.
-bool ForEachSection(
-    int fd, const std::function<bool(const std::string& name, const ElfW(Shdr) &)>&
-                callback);
+bool ForEachSection(int fd,
+                    const std::function<bool(const std::string& name,
+                                             const ElfW(Shdr) &)>& callback);
 
 // Gets the section header for the given name, if it exists. Returns true on
 // success. Otherwise, returns false.
diff --git a/absl/debugging/internal/vdso_support.cc b/absl/debugging/internal/vdso_support.cc
index e8129e8..23c3084 100644
--- a/absl/debugging/internal/vdso_support.cc
+++ b/absl/debugging/internal/vdso_support.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
diff --git a/absl/debugging/internal/vdso_support.h b/absl/debugging/internal/vdso_support.h
index 8002c74..9895b48 100644
--- a/absl/debugging/internal/vdso_support.h
+++ b/absl/debugging/internal/vdso_support.h
@@ -5,7 +5,7 @@
 // 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
+//      https://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,
diff --git a/absl/debugging/leak_check.cc b/absl/debugging/leak_check.cc
index e01e5f8..ffe3d1b 100644
--- a/absl/debugging/leak_check.cc
+++ b/absl/debugging/leak_check.cc
@@ -4,13 +4,14 @@
 // 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
+//      https://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.
+
 // Wrappers around lsan_interface functions.
 // When lsan is not linked in, these functions are not available,
 // therefore Abseil code which depends on these functions is conditioned on the
diff --git a/absl/debugging/leak_check.h b/absl/debugging/leak_check.h
index c930684..4d489c5 100644
--- a/absl/debugging/leak_check.h
+++ b/absl/debugging/leak_check.h
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
diff --git a/absl/debugging/leak_check_disable.cc b/absl/debugging/leak_check_disable.cc
index df22c1c..924d6e3 100644
--- a/absl/debugging/leak_check_disable.cc
+++ b/absl/debugging/leak_check_disable.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
diff --git a/absl/debugging/leak_check_fail_test.cc b/absl/debugging/leak_check_fail_test.cc
index bf541fe..2887cea 100644
--- a/absl/debugging/leak_check_fail_test.cc
+++ b/absl/debugging/leak_check_fail_test.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
diff --git a/absl/debugging/leak_check_test.cc b/absl/debugging/leak_check_test.cc
index febd1ee..93a7edd 100644
--- a/absl/debugging/leak_check_test.cc
+++ b/absl/debugging/leak_check_test.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
diff --git a/absl/debugging/stacktrace.cc b/absl/debugging/stacktrace.cc
index 463fad2..9de8782 100644
--- a/absl/debugging/stacktrace.cc
+++ b/absl/debugging/stacktrace.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -46,6 +46,7 @@
 #include ABSL_STACKTRACE_INL_HEADER
 #else
 # error Cannot calculate stack trace: will need to write for your environment
+
 # include "absl/debugging/internal/stacktrace_aarch64-inl.inc"
 # include "absl/debugging/internal/stacktrace_arm-inl.inc"
 # include "absl/debugging/internal/stacktrace_generic-inl.inc"
@@ -80,29 +81,29 @@
 
 }  // anonymous namespace
 
-ABSL_ATTRIBUTE_NOINLINE
-int GetStackFrames(void** result, int* sizes, int max_depth, int skip_count) {
+ABSL_ATTRIBUTE_NOINLINE ABSL_ATTRIBUTE_NO_TAIL_CALL int GetStackFrames(
+    void** result, int* sizes, int max_depth, int skip_count) {
   return Unwind<true, false>(result, sizes, max_depth, skip_count, nullptr,
                              nullptr);
 }
 
-ABSL_ATTRIBUTE_NOINLINE
-int GetStackFramesWithContext(void** result, int* sizes, int max_depth,
-                              int skip_count, const void* uc,
-                              int* min_dropped_frames) {
+ABSL_ATTRIBUTE_NOINLINE ABSL_ATTRIBUTE_NO_TAIL_CALL int
+GetStackFramesWithContext(void** result, int* sizes, int max_depth,
+                          int skip_count, const void* uc,
+                          int* min_dropped_frames) {
   return Unwind<true, true>(result, sizes, max_depth, skip_count, uc,
                             min_dropped_frames);
 }
 
-ABSL_ATTRIBUTE_NOINLINE
-int GetStackTrace(void** result, int max_depth, int skip_count) {
+ABSL_ATTRIBUTE_NOINLINE ABSL_ATTRIBUTE_NO_TAIL_CALL int GetStackTrace(
+    void** result, int max_depth, int skip_count) {
   return Unwind<false, false>(result, nullptr, max_depth, skip_count, nullptr,
                               nullptr);
 }
 
-ABSL_ATTRIBUTE_NOINLINE
-int GetStackTraceWithContext(void** result, int max_depth, int skip_count,
-                             const void* uc, int* min_dropped_frames) {
+ABSL_ATTRIBUTE_NOINLINE ABSL_ATTRIBUTE_NO_TAIL_CALL int
+GetStackTraceWithContext(void** result, int max_depth, int skip_count,
+                         const void* uc, int* min_dropped_frames) {
   return Unwind<false, true>(result, nullptr, max_depth, skip_count, uc,
                              min_dropped_frames);
 }
diff --git a/absl/debugging/stacktrace.h b/absl/debugging/stacktrace.h
index 8b831e2..3fc1c03 100644
--- a/absl/debugging/stacktrace.h
+++ b/absl/debugging/stacktrace.h
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
diff --git a/absl/debugging/symbolize.cc b/absl/debugging/symbolize.cc
index a35e24c..24e3a7f 100644
--- a/absl/debugging/symbolize.cc
+++ b/absl/debugging/symbolize.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
diff --git a/absl/debugging/symbolize.h b/absl/debugging/symbolize.h
index 24e6e64..a73dbd9 100644
--- a/absl/debugging/symbolize.h
+++ b/absl/debugging/symbolize.h
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
diff --git a/absl/debugging/symbolize_elf.inc b/absl/debugging/symbolize_elf.inc
index b16a42a..34def5c 100644
--- a/absl/debugging/symbolize_elf.inc
+++ b/absl/debugging/symbolize_elf.inc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -333,7 +333,11 @@
 }  // namespace
 
 static int SymbolizerSize() {
+#if defined(__wasm__) || defined(__asmjs__)
   int pagesize = getpagesize();
+#else
+  int pagesize = sysconf(_SC_PAGESIZE);
+#endif
   return ((sizeof(Symbolizer) - 1) / pagesize + 1) * pagesize;
 }
 
@@ -921,6 +925,14 @@
   return p;
 }
 
+// Normally we are only interested in "r?x" maps.
+// On the PowerPC, function pointers point to descriptors in the .opd
+// section.  The descriptors themselves are not executable code, so
+// we need to relax the check below to "r??".
+static bool ShouldUseMapping(const char *const flags) {
+  return flags[0] == 'r' && (kPlatformUsesOPDSections || flags[2] == 'x');
+}
+
 // Read /proc/self/maps and run "callback" for each mmapped file found.  If
 // "callback" returns false, stop scanning and return true. Else continue
 // scanning /proc/self/maps. Return true if no parse error is found.
@@ -990,12 +1002,8 @@
       return false;
     }
 
-    // Check flags.  Normally we are only interested in "r-x" maps.  On
-    // the PowerPC, function pointers point to descriptors in the .opd
-    // section.  The descriptors themselves are not executable code.  So
-    // we need to relax the check below to "r**".
-    if (memcmp(flags_start, "r-x", 3) != 0 &&  // Not a "r-x" map.
-        !(kPlatformUsesOPDSections && flags_start[0] == 'r')) {
+    // Check flags.
+    if (!ShouldUseMapping(flags_start)) {
       continue;  // We skip this map.
     }
     ++cursor;  // Skip ' '.
diff --git a/absl/debugging/symbolize_test.cc b/absl/debugging/symbolize_test.cc
index 8029fbe..fc3ed93 100644
--- a/absl/debugging/symbolize_test.cc
+++ b/absl/debugging/symbolize_test.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -392,16 +392,20 @@
 extern "C" {
 inline void *ABSL_ATTRIBUTE_ALWAYS_INLINE inline_func() {
   void *pc = nullptr;
-#if defined(__i386__) || defined(__x86_64__)
-  __asm__ __volatile__("call 1f; 1: pop %0" : "=r"(pc));
+#if defined(__i386__)
+  __asm__ __volatile__("call 1f;\n 1: pop %[PC]" : [ PC ] "=r"(pc));
+#elif defined(__x86_64__)
+  __asm__ __volatile__("leaq 0(%%rip),%[PC];\n" : [ PC ] "=r"(pc));
 #endif
   return pc;
 }
 
 void *ABSL_ATTRIBUTE_NOINLINE non_inline_func() {
   void *pc = nullptr;
-#if defined(__i386__) || defined(__x86_64__)
-  __asm__ __volatile__("call 1f; 1: pop %0" : "=r"(pc));
+#if defined(__i386__)
+  __asm__ __volatile__("call 1f;\n 1: pop %[PC]" : [ PC ] "=r"(pc));
+#elif defined(__x86_64__)
+  __asm__ __volatile__("leaq 0(%%rip),%[PC];\n" : [ PC ] "=r"(pc));
 #endif
   return pc;
 }
diff --git a/absl/debugging/symbolize_unimplemented.inc b/absl/debugging/symbolize_unimplemented.inc
index 2a3f4ac..7c580fe 100644
--- a/absl/debugging/symbolize_unimplemented.inc
+++ b/absl/debugging/symbolize_unimplemented.inc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -26,6 +26,9 @@
 bool RegisterFileMappingHint(const void *, const void *, uint64_t, const char *) {
   return false;
 }
+bool GetFileMappingHint(const void **, const void **, uint64_t *, const char **) {
+  return false;
+}
 
 }  // namespace debugging_internal
 
diff --git a/absl/debugging/symbolize_win32.inc b/absl/debugging/symbolize_win32.inc
index e3fff74..17ea618 100644
--- a/absl/debugging/symbolize_win32.inc
+++ b/absl/debugging/symbolize_win32.inc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
diff --git a/absl/hash/BUILD.bazel b/absl/hash/BUILD.bazel
index 50aa550..69860d9 100644
--- a/absl/hash/BUILD.bazel
+++ b/absl/hash/BUILD.bazel
@@ -5,7 +5,7 @@
 # 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
+#      https://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,
@@ -15,7 +15,7 @@
 #
 
 load(
-    "//absl:copts.bzl",
+    "//absl:copts/configure_copts.bzl",
     "ABSL_DEFAULT_COPTS",
     "ABSL_TEST_COPTS",
 )
@@ -93,7 +93,6 @@
     srcs = ["internal/city.cc"],
     hdrs = [
         "internal/city.h",
-        "internal/city_crc.h",
     ],
     copts = ABSL_DEFAULT_COPTS,
     deps = [
diff --git a/absl/hash/BUILD.gn b/absl/hash/BUILD.gn
index 40b6b3a..cbe3abf 100644
--- a/absl/hash/BUILD.gn
+++ b/absl/hash/BUILD.gn
@@ -91,7 +91,6 @@
   public_configs = [ "//third_party/abseil-cpp:absl_include_config" ]
   public = [
     "internal/city.h",
-    "internal/city_crc.h",
   ]
   sources = [
     "internal/city.cc",
diff --git a/absl/hash/CMakeLists.txt b/absl/hash/CMakeLists.txt
index 35081e3..4cafc13 100644
--- a/absl/hash/CMakeLists.txt
+++ b/absl/hash/CMakeLists.txt
@@ -5,7 +5,7 @@
 # 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
+#      https://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,
@@ -14,67 +14,98 @@
 # limitations under the License.
 #
 
-list(APPEND HASH_PUBLIC_HEADERS
-  "hash.h"
-)
-
-list(APPEND HASH_INTERNAL_HEADERS
-  "internal/city.h"
-  "internal/city_crc.h"
-  "internal/hash.h"
-)
-
-# absl_hash library
-list(APPEND HASH_SRC
-  "internal/city.cc"
-  "internal/hash.cc"
-  ${HASH_PUBLIC_HEADERS}
-  ${HASH_INTERNAL_HEADERS}
-)
-
-set(HASH_PUBLIC_LIBRARIES absl::hash absl::container absl::strings absl::str_format absl::utility)
-
-absl_library(
-  TARGET
-    absl_hash
-  SOURCES
-    ${HASH_SRC}
-  PUBLIC_LIBRARIES
-    ${HASH_PUBLIC_LIBRARIES}
-  EXPORT_NAME
+absl_cc_library(
+  NAME
     hash
+  HDRS
+    "hash.h"
+  SRCS
+    "internal/hash.cc"
+    "internal/hash.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::core_headers
+    absl::endian
+    absl::fixed_array
+    absl::meta
+    absl::int128
+    absl::strings
+    absl::optional
+    absl::variant
+    absl::utility
+    absl::city
+  PUBLIC
 )
 
-#
-## TESTS
-#
+absl_cc_library(
+  NAME
+    hash_testing
+  HDRS
+    "hash_testing.h"
+  DEPS
+    absl::spy_hash_state
+    absl::meta
+    absl::strings
+    absl::variant
+    gmock
+  TESTONLY
+)
 
-# testing support
-set(HASH_TEST_HEADERS hash_testing.h internal/spy_hash_state.h)
-set(HASH_TEST_PUBLIC_LIBRARIES absl::hash absl::container absl::numeric absl::strings absl::str_format)
-
-# hash_test
-set(HASH_TEST_SRC "hash_test.cc" ${HASH_TEST_HEADERS})
-
-absl_test(
-  TARGET
+absl_cc_test(
+  NAME
     hash_test
-  SOURCES
-    ${HASH_TEST_SRC}
-  PUBLIC_LIBRARIES
-    ${HASH_TEST_PUBLIC_LIBRARIES}
+  SRCS
+   "hash_test.cc"
+  DEPS
+    absl::hash
+    absl::hash_testing
+    absl::core_headers
+    absl::flat_hash_set
+    absl::spy_hash_state
+    absl::meta
+    absl::int128
+    gmock_main
 )
 
-# hash_test
-set(CITY_TEST_SRC "internal/city_test.cc")
+absl_cc_library(
+  NAME
+    spy_hash_state
+  HDRS
+    "internal/spy_hash_state.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::hash
+    absl::strings
+    absl::str_format
+  TESTONLY
+)
 
-absl_test(
-  TARGET
+absl_cc_library(
+  NAME
+    city
+  HDRS
+    "internal/city.h"
+  SRCS
+    "internal/city.cc"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::config
+    absl::core_headers
+    absl::endian
+)
+
+absl_cc_test(
+  NAME
     city_test
-  SOURCES
-    ${CITY_TEST_SRC}
-  PUBLIC_LIBRARIES
-    ${HASH_TEST_PUBLIC_LIBRARIES}
+  SRCS
+    "internal/city_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::city
+    gmock_main
 )
 
-
diff --git a/absl/hash/hash.h b/absl/hash/hash.h
index c7ba4c2..c0ede35 100644
--- a/absl/hash/hash.h
+++ b/absl/hash/hash.h
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -25,8 +25,8 @@
 //   * `AbslHashValue`, an extension point that allows you to extend types to
 //     support Abseil hashing without requiring you to define a hashing
 //     algorithm.
-//   * `HashState`, a type-erased class which implement the manipulation of the
-//     hash state (H) itself. containing member functions `combine()` and
+//   * `HashState`, a type-erased class which implements the manipulation of the
+//     hash state (H) itself, contains member functions `combine()` and
 //     `combine_contiguous()`, which you can use to contribute to an existing
 //     hash state when hashing your types.
 //
@@ -69,7 +69,7 @@
 // `absl::Hash`
 // -----------------------------------------------------------------------------
 //
-// `absl::Hash<T>` is a convenient general-purpose hash functor for a type `T`
+// `absl::Hash<T>` is a convenient general-purpose hash functor for any type `T`
 // satisfying any of the following conditions (in order):
 //
 //  * T is an arithmetic or pointer type
@@ -98,7 +98,7 @@
 //    * absl::string_view
 //    * absl::InlinedVector
 //    * absl::FixedArray
-//    * absl::unit128
+//    * absl::uint128
 //    * absl::Time, absl::Duration, and absl::TimeZone
 //
 // Note: the list above is not meant to be exhaustive. Additional type support
@@ -142,7 +142,7 @@
 //
 // The "hash state" concept contains two member functions for mixing hash state:
 //
-// * `H::combine()`
+// * `H::combine(state, values...)`
 //
 //   Combines an arbitrary number of values into a hash state, returning the
 //   updated state. Note that the existing hash state is move-only and must be
@@ -160,7 +160,7 @@
 //     state = H::combine(std::move(state), value2);
 //     state = H::combine(std::move(state), value3);
 //
-// * `H::combine_contiguous()`
+// * `H::combine_contiguous(state, data, size)`
 //
 //    Combines a contiguous array of `size` elements into a hash state,
 //    returning the updated state. Note that the existing hash state is
@@ -243,7 +243,7 @@
 //       absl::HashState::combine(std::move(state), v1_, v2_);
 //     }
 //     int v1_;
-//     string v2_;
+//     std::string v2_;
 //   };
 class HashState : public hash_internal::HashStateBase<HashState> {
  public:
@@ -309,4 +309,5 @@
 };
 
 }  // namespace absl
+
 #endif  // ABSL_HASH_HASH_H_
diff --git a/absl/hash/hash_test.cc b/absl/hash/hash_test.cc
index 7b6fb2e..af95938 100644
--- a/absl/hash/hash_test.cc
+++ b/absl/hash/hash_test.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -15,6 +15,7 @@
 #include "absl/hash/hash.h"
 
 #include <array>
+#include <bitset>
 #include <cstring>
 #include <deque>
 #include <forward_list>
@@ -50,7 +51,7 @@
 template <typename T>
 class HashValueIntTest : public testing::Test {
 };
-TYPED_TEST_CASE_P(HashValueIntTest);
+TYPED_TEST_SUITE_P(HashValueIntTest);
 
 template <typename T>
 SpyHashState SpyHash(const T& value) {
@@ -84,6 +85,345 @@
                                 uint64_t, size_t>;
 INSTANTIATE_TYPED_TEST_CASE_P(My, HashValueIntTest, IntTypes);
 
+enum LegacyEnum { kValue1, kValue2, kValue3 };
+
+enum class EnumClass { kValue4, kValue5, kValue6 };
+
+TEST(HashValueTest, EnumAndBool) {
+  EXPECT_TRUE((is_hashable<LegacyEnum>::value));
+  EXPECT_TRUE((is_hashable<EnumClass>::value));
+  EXPECT_TRUE((is_hashable<bool>::value));
+
+  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple(
+      LegacyEnum::kValue1, LegacyEnum::kValue2, LegacyEnum::kValue3)));
+  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple(
+      EnumClass::kValue4, EnumClass::kValue5, EnumClass::kValue6)));
+  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(
+      std::make_tuple(true, false)));
+}
+
+TEST(HashValueTest, FloatingPoint) {
+  EXPECT_TRUE((is_hashable<float>::value));
+  EXPECT_TRUE((is_hashable<double>::value));
+  EXPECT_TRUE((is_hashable<long double>::value));
+
+  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(
+      std::make_tuple(42.f, 0.f, -0.f, std::numeric_limits<float>::infinity(),
+                      -std::numeric_limits<float>::infinity())));
+
+  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(
+      std::make_tuple(42., 0., -0., std::numeric_limits<double>::infinity(),
+                      -std::numeric_limits<double>::infinity())));
+
+  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple(
+      // Add some values with small exponent to test that NORMAL values also
+      // append their category.
+      .5L, 1.L, 2.L, 4.L, 42.L, 0.L, -0.L,
+      17 * static_cast<long double>(std::numeric_limits<double>::max()),
+      std::numeric_limits<long double>::infinity(),
+      -std::numeric_limits<long double>::infinity())));
+}
+
+TEST(HashValueTest, Pointer) {
+  EXPECT_TRUE((is_hashable<int*>::value));
+
+  int i;
+  int* ptr = &i;
+  int* n = nullptr;
+
+  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(
+      std::make_tuple(&i, ptr, nullptr, ptr + 1, n)));
+}
+
+TEST(HashValueTest, PointerAlignment) {
+  // We want to make sure that pointer alignment will not cause bits to be
+  // stuck.
+
+  constexpr size_t kTotalSize = 1 << 20;
+  std::unique_ptr<char[]> data(new char[kTotalSize]);
+  constexpr size_t kLog2NumValues = 5;
+  constexpr size_t kNumValues = 1 << kLog2NumValues;
+
+  for (size_t align = 1; align < kTotalSize / kNumValues;
+       align < 8 ? align += 1 : align < 1024 ? align += 8 : align += 32) {
+    SCOPED_TRACE(align);
+    ASSERT_LE(align * kNumValues, kTotalSize);
+
+    size_t bits_or = 0;
+    size_t bits_and = ~size_t{};
+
+    for (size_t i = 0; i < kNumValues; ++i) {
+      size_t hash = absl::Hash<void*>()(data.get() + i * align);
+      bits_or |= hash;
+      bits_and &= hash;
+    }
+
+    // Limit the scope to the bits we would be using for Swisstable.
+    constexpr size_t kMask = (1 << (kLog2NumValues + 7)) - 1;
+    size_t stuck_bits = (~bits_or | bits_and) & kMask;
+    EXPECT_EQ(stuck_bits, 0) << "0x" << std::hex << stuck_bits;
+  }
+}
+
+TEST(HashValueTest, PairAndTuple) {
+  EXPECT_TRUE((is_hashable<std::pair<int, int>>::value));
+  EXPECT_TRUE((is_hashable<std::pair<const int&, const int&>>::value));
+  EXPECT_TRUE((is_hashable<std::tuple<int&, int&>>::value));
+  EXPECT_TRUE((is_hashable<std::tuple<int&&, int&&>>::value));
+
+  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple(
+      std::make_pair(0, 42), std::make_pair(0, 42), std::make_pair(42, 0),
+      std::make_pair(0, 0), std::make_pair(42, 42), std::make_pair(1, 42))));
+
+  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(
+      std::make_tuple(std::make_tuple(0, 0, 0), std::make_tuple(0, 0, 42),
+                      std::make_tuple(0, 23, 0), std::make_tuple(17, 0, 0),
+                      std::make_tuple(42, 0, 0), std::make_tuple(3, 9, 9),
+                      std::make_tuple(0, 0, -42))));
+
+  // Test that tuples of lvalue references work (so we need a few lvalues):
+  int a = 0, b = 1, c = 17, d = 23;
+  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple(
+      std::tie(a, a), std::tie(a, b), std::tie(b, c), std::tie(c, d))));
+
+  // Test that tuples of rvalue references work:
+  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple(
+      std::forward_as_tuple(0, 0, 0), std::forward_as_tuple(0, 0, 42),
+      std::forward_as_tuple(0, 23, 0), std::forward_as_tuple(17, 0, 0),
+      std::forward_as_tuple(42, 0, 0), std::forward_as_tuple(3, 9, 9),
+      std::forward_as_tuple(0, 0, -42))));
+}
+
+TEST(HashValueTest, CombineContiguousWorks) {
+  std::vector<std::tuple<int>> v1 = {std::make_tuple(1), std::make_tuple(3)};
+  std::vector<std::tuple<int>> v2 = {std::make_tuple(1), std::make_tuple(2)};
+
+  auto vh1 = SpyHash(v1);
+  auto vh2 = SpyHash(v2);
+  EXPECT_NE(vh1, vh2);
+}
+
+struct DummyDeleter {
+  template <typename T>
+  void operator() (T* ptr) {}
+};
+
+struct SmartPointerEq {
+  template <typename T, typename U>
+  bool operator()(const T& t, const U& u) const {
+    return GetPtr(t) == GetPtr(u);
+  }
+
+  template <typename T>
+  static auto GetPtr(const T& t) -> decltype(&*t) {
+    return t ? &*t : nullptr;
+  }
+
+  static std::nullptr_t GetPtr(std::nullptr_t) { return nullptr; }
+};
+
+TEST(HashValueTest, SmartPointers) {
+  EXPECT_TRUE((is_hashable<std::unique_ptr<int>>::value));
+  EXPECT_TRUE((is_hashable<std::unique_ptr<int, DummyDeleter>>::value));
+  EXPECT_TRUE((is_hashable<std::shared_ptr<int>>::value));
+
+  int i, j;
+  std::unique_ptr<int, DummyDeleter> unique1(&i);
+  std::unique_ptr<int, DummyDeleter> unique2(&i);
+  std::unique_ptr<int, DummyDeleter> unique_other(&j);
+  std::unique_ptr<int, DummyDeleter> unique_null;
+
+  std::shared_ptr<int> shared1(&i, DummyDeleter());
+  std::shared_ptr<int> shared2(&i, DummyDeleter());
+  std::shared_ptr<int> shared_other(&j, DummyDeleter());
+  std::shared_ptr<int> shared_null;
+
+  // Sanity check of the Eq function.
+  ASSERT_TRUE(SmartPointerEq{}(unique1, shared1));
+  ASSERT_FALSE(SmartPointerEq{}(unique1, shared_other));
+  ASSERT_TRUE(SmartPointerEq{}(unique_null, nullptr));
+  ASSERT_FALSE(SmartPointerEq{}(shared2, nullptr));
+
+  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(
+      std::forward_as_tuple(&i, nullptr,                    //
+                            unique1, unique2, unique_null,  //
+                            absl::make_unique<int>(),       //
+                            shared1, shared2, shared_null,  //
+                            std::make_shared<int>()),
+      SmartPointerEq{}));
+}
+
+TEST(HashValueTest, FunctionPointer) {
+  using Func = int (*)();
+  EXPECT_TRUE(is_hashable<Func>::value);
+
+  Func p1 = [] { return 2; }, p2 = [] { return 1; };
+  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(
+      std::make_tuple(p1, p2, nullptr)));
+}
+
+struct WrapInTuple {
+  template <typename T>
+  std::tuple<int, T, size_t> operator()(const T& t) const {
+    return std::make_tuple(7, t, 0xdeadbeef);
+  }
+};
+
+TEST(HashValueTest, Strings) {
+  EXPECT_TRUE((is_hashable<std::string>::value));
+
+  const std::string small = "foo";
+  const std::string dup = "foofoo";
+  const std::string large = "large";
+  const std::string huge = std::string(5000, 'a');
+
+  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple(
+      std::string(), absl::string_view(),
+      std::string(""), absl::string_view(""),
+      std::string(small), absl::string_view(small),
+      std::string(dup), absl::string_view(dup),
+      std::string(large), absl::string_view(large),
+      std::string(huge), absl::string_view(huge))));
+
+  // Also check that nested types maintain the same hash.
+  const WrapInTuple t{};
+  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple(
+      //
+      t(std::string()), t(absl::string_view()),
+      t(std::string("")), t(absl::string_view("")),
+      t(std::string(small)), t(absl::string_view(small)),
+      t(std::string(dup)), t(absl::string_view(dup)),
+      t(std::string(large)), t(absl::string_view(large)),
+      t(std::string(huge)), t(absl::string_view(huge)))));
+
+  // Make sure that hashing a `const char*` does not use its std::string-value.
+  EXPECT_NE(SpyHash(static_cast<const char*>("ABC")),
+            SpyHash(absl::string_view("ABC")));
+}
+
+TEST(HashValueTest, StdArray) {
+  EXPECT_TRUE((is_hashable<std::array<int, 3>>::value));
+
+  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(
+      std::make_tuple(std::array<int, 3>{}, std::array<int, 3>{{0, 23, 42}})));
+}
+
+TEST(HashValueTest, StdBitset) {
+  EXPECT_TRUE((is_hashable<std::bitset<257>>::value));
+
+  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(
+      {std::bitset<2>("00"), std::bitset<2>("01"), std::bitset<2>("10"),
+       std::bitset<2>("11")}));
+  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(
+      {std::bitset<5>("10101"), std::bitset<5>("10001"), std::bitset<5>()}));
+
+  constexpr int kNumBits = 256;
+  std::array<std::string, 6> bit_strings;
+  bit_strings.fill(std::string(kNumBits, '1'));
+  bit_strings[1][0] = '0';
+  bit_strings[2][1] = '0';
+  bit_strings[3][kNumBits / 3] = '0';
+  bit_strings[4][kNumBits - 2] = '0';
+  bit_strings[5][kNumBits - 1] = '0';
+  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(
+      {std::bitset<kNumBits>(bit_strings[0].c_str()),
+       std::bitset<kNumBits>(bit_strings[1].c_str()),
+       std::bitset<kNumBits>(bit_strings[2].c_str()),
+       std::bitset<kNumBits>(bit_strings[3].c_str()),
+       std::bitset<kNumBits>(bit_strings[4].c_str()),
+       std::bitset<kNumBits>(bit_strings[5].c_str())}));
+}  // namespace
+
+template <typename T>
+class HashValueSequenceTest : public testing::Test {
+};
+TYPED_TEST_SUITE_P(HashValueSequenceTest);
+
+TYPED_TEST_P(HashValueSequenceTest, BasicUsage) {
+  EXPECT_TRUE((is_hashable<TypeParam>::value));
+
+  using ValueType = typename TypeParam::value_type;
+  auto a = static_cast<ValueType>(0);
+  auto b = static_cast<ValueType>(23);
+  auto c = static_cast<ValueType>(42);
+
+  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(
+      std::make_tuple(TypeParam(), TypeParam{}, TypeParam{a, b, c},
+                      TypeParam{a, b}, TypeParam{b, c})));
+}
+
+REGISTER_TYPED_TEST_CASE_P(HashValueSequenceTest, BasicUsage);
+using IntSequenceTypes =
+    testing::Types<std::deque<int>, std::forward_list<int>, std::list<int>,
+                   std::vector<int>, std::vector<bool>, std::set<int>,
+                   std::multiset<int>>;
+INSTANTIATE_TYPED_TEST_CASE_P(My, HashValueSequenceTest, IntSequenceTypes);
+
+// Private type that only supports AbslHashValue to make sure our chosen hash
+// implentation is recursive within absl::Hash.
+// It uses std::abs() on the value to provide different bitwise representations
+// of the same logical value.
+struct Private {
+  int i;
+  template <typename H>
+  friend H AbslHashValue(H h, Private p) {
+    return H::combine(std::move(h), std::abs(p.i));
+  }
+
+  friend bool operator==(Private a, Private b) {
+    return std::abs(a.i) == std::abs(b.i);
+  }
+
+  friend std::ostream& operator<<(std::ostream& o, Private p) {
+    return o << p.i;
+  }
+};
+
+TEST(HashValueTest, PrivateSanity) {
+  // Sanity check that Private is working as the tests below expect it to work.
+  EXPECT_TRUE(is_hashable<Private>::value);
+  EXPECT_NE(SpyHash(Private{0}), SpyHash(Private{1}));
+  EXPECT_EQ(SpyHash(Private{1}), SpyHash(Private{1}));
+}
+
+TEST(HashValueTest, Optional) {
+  EXPECT_TRUE(is_hashable<absl::optional<Private>>::value);
+
+  using O = absl::optional<Private>;
+  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(
+      std::make_tuple(O{}, O{{1}}, O{{-1}}, O{{10}})));
+}
+
+TEST(HashValueTest, Variant) {
+  using V = absl::variant<Private, std::string>;
+  EXPECT_TRUE(is_hashable<V>::value);
+
+  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple(
+      V(Private{1}), V(Private{-1}), V(Private{2}), V("ABC"), V("BCD"))));
+
+#if ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_
+  struct S {};
+  EXPECT_FALSE(is_hashable<absl::variant<S>>::value);
+#endif
+}
+
+TEST(HashValueTest, Maps) {
+  EXPECT_TRUE((is_hashable<std::map<int, std::string>>::value));
+
+  using M = std::map<int, std::string>;
+  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple(
+      M{}, M{{0, "foo"}}, M{{1, "foo"}}, M{{0, "bar"}}, M{{1, "bar"}},
+      M{{0, "foo"}, {42, "bar"}}, M{{1, "foo"}, {42, "bar"}},
+      M{{1, "foo"}, {43, "bar"}}, M{{1, "foo"}, {43, "baz"}})));
+
+  using MM = std::multimap<int, std::string>;
+  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple(
+      MM{}, MM{{0, "foo"}}, MM{{1, "foo"}}, MM{{0, "bar"}}, MM{{1, "bar"}},
+      MM{{0, "foo"}, {0, "bar"}}, MM{{0, "bar"}, {0, "foo"}},
+      MM{{0, "foo"}, {42, "bar"}}, MM{{1, "foo"}, {42, "bar"}},
+      MM{{1, "foo"}, {1, "foo"}, {43, "bar"}}, MM{{1, "foo"}, {43, "baz"}})));
+}
+
 template <typename T, typename = void>
 struct IsHashCallble : std::false_type {};
 
@@ -108,7 +448,8 @@
   EXPECT_TRUE(IsHashCallble<int>::value);
   EXPECT_TRUE(IsAggregateInitializable<absl::Hash<int>>::value);
 }
-#if ABSL_HASH_INTERNAL_CAN_POISON_ && !defined(__APPLE__)
+
+#if ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_
 TEST(IsHashableTest, PoisonHash) {
   struct X {};
   EXPECT_FALSE((is_hashable<X>::value));
@@ -120,7 +461,7 @@
   EXPECT_FALSE(IsHashCallble<X>::value);
   EXPECT_FALSE(IsAggregateInitializable<absl::Hash<X>>::value);
 }
-#endif  // ABSL_HASH_INTERNAL_CAN_POISON_
+#endif  // ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_
 
 // Hashable types
 //
@@ -159,8 +500,16 @@
                              Int(4));
   }
 };
+enum class InvokeTag {
+  kUniquelyRepresented,
+  kHashValue,
+#if ABSL_HASH_INTERNAL_SUPPORT_LEGACY_HASH_
+  kLegacyHash,
+#endif  // ABSL_HASH_INTERNAL_SUPPORT_LEGACY_HASH_
+  kStdHash,
+  kNone
+};
 
-using InvokeTag = absl::hash_internal::InvokeHashTag;
 template <InvokeTag T>
 using InvokeTagConstant = std::integral_constant<InvokeTag, T>;
 
@@ -245,13 +594,13 @@
 }
 
 void TestCustomHashType(InvokeTagConstant<InvokeTag::kNone>) {
-#if ABSL_HASH_INTERNAL_CAN_POISON_
+#if ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_
   // is_hashable is false if we don't support any of the hooks.
   using type = CustomHashType<>;
   EXPECT_FALSE(is_hashable<type>());
   EXPECT_FALSE(is_hashable<const type>());
   EXPECT_FALSE(is_hashable<const type&>());
-#endif  // ABSL_HASH_INTERNAL_CAN_POISON_
+#endif  // ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_
 }
 
 template <InvokeTag Tag, typename... T>
@@ -273,7 +622,7 @@
 template <typename T>
 class HashIntTest : public testing::Test {
 };
-TYPED_TEST_CASE_P(HashIntTest);
+TYPED_TEST_SUITE_P(HashIntTest);
 
 TYPED_TEST_P(HashIntTest, BasicUsage) {
   EXPECT_NE(Hash<NoOp>()({}), Hash<TypeParam>()(0));
@@ -352,7 +701,8 @@
 }
 
 TEST(HashTest, StandardHashContainerUsage) {
-  std::unordered_map<int, std::string, Hash<int>> map = {{0, "foo"}, { 42, "bar" }};
+  std::unordered_map<int, std::string, Hash<int>> map = {{0, "foo"},
+                                                         {42, "bar"}};
 
   EXPECT_NE(map.find(0), map.end());
   EXPECT_EQ(map.find(1), map.end());
@@ -422,4 +772,24 @@
             SpyHash(std::make_pair(size_t{7}, 17)));
 }
 
+struct ValueWithBoolConversion {
+  operator bool() const { return false; }
+  int i;
+};
+
+}  // namespace
+namespace std {
+template <>
+struct hash<ValueWithBoolConversion> {
+  size_t operator()(ValueWithBoolConversion v) { return v.i; }
+};
+}  // namespace std
+
+namespace {
+
+TEST(HashTest, DoesNotUseImplicitConversionsToBool) {
+  EXPECT_NE(absl::Hash<ValueWithBoolConversion>()(ValueWithBoolConversion{0}),
+            absl::Hash<ValueWithBoolConversion>()(ValueWithBoolConversion{1}));
+}
+
 }  // namespace
diff --git a/absl/hash/hash_testing.h b/absl/hash/hash_testing.h
index 1e3cda6..c45bc15 100644
--- a/absl/hash/hash_testing.h
+++ b/absl/hash/hash_testing.h
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -90,7 +90,7 @@
 //   template <typename H>
 //   friend H AbslHashValue(H state, Bad2 x) {
 //     // Uses a and b.
-//     return H::combine(x.a, x.b);
+//     return H::combine(std::move(state), x.a, x.b);
 //   }
 //   friend bool operator==(Bad2 x, Bad2 y) {
 //     // Only uses a.
@@ -107,7 +107,7 @@
 //   template <typename H>
 //   friend H AbslHashValue(H state, Bad3 x) {
 //     // Only uses a.
-//     return H::combine(x.a);
+//     return H::combine(std::move(state), x.a);
 //   }
 //   friend bool operator==(Bad3 x, Bad3 y) {
 //     // Uses a and b.
@@ -123,19 +123,21 @@
 //   int *p, size;
 //   template <typename H>
 //   friend H AbslHashValue(H state, Bad4 x) {
-//     return H::combine_range(x.p, x.p + x.size);
+//     return H::combine_contiguous(std::move(state), x.p, x.p + x.size);
 //   }
 //   friend bool operator==(Bad4 x, Bad4 y) {
-//     return std::equal(x.p, x.p + x.size, y.p, y.p + y.size);
+//    // Compare two ranges for equality. C++14 code can instead use std::equal.
+//     return absl::equal(x.p, x.p + x.size, y.p, y.p + y.size);
 //   }
 // };
 //
 // An easy solution to this is to combine the size after combining the range,
 // like so:
-//   template <typename H>
-//   friend H AbslHashValue(H state, Bad4 x) {
-//     return H::combine(H::combine_range(x.p, x.p + x.size), x.size);
-//   }
+// template <typename H>
+// friend H AbslHashValue(H state, Bad4 x) {
+//   return H::combine(
+//       H::combine_contiguous(std::move(state), x.p, x.p + x.size), x.size);
+// }
 //
 template <int&... ExplicitBarrier, typename Container>
 ABSL_MUST_USE_RESULT testing::AssertionResult
@@ -188,7 +190,9 @@
   struct Info {
     const V& value;
     size_t index;
-    std::string ToString() const { return absl::visit(PrintVisitor{index}, value); }
+    std::string ToString() const {
+      return absl::visit(PrintVisitor{index}, value);
+    }
     SpyHashState expand() const { return absl::visit(ExpandVisitor{}, value); }
   };
 
@@ -227,7 +231,8 @@
   // Now we verify that AbslHashValue is also correctly implemented.
 
   for (const auto& c : classes) {
-    // All elements of the equivalence class must have the same hash expansion.
+    // All elements of the equivalence class must have the same hash
+    // expansion.
     const SpyHashState expected = c[0].expand();
     for (const Info& v : c) {
       if (v.expand() != v.expand()) {
@@ -285,7 +290,7 @@
 };
 
 template <typename... T>
-struct MakeTypeSet : TypeSet<>{};
+struct MakeTypeSet : TypeSet<> {};
 template <typename T, typename... Ts>
 struct MakeTypeSet<T, Ts...> : MakeTypeSet<Ts...>::template Insert<T>::type {};
 
@@ -346,8 +351,7 @@
 ABSL_MUST_USE_RESULT testing::AssertionResult
 VerifyTypeImplementsAbslHashCorrectly(const Container& values, Eq equals) {
   return hash_internal::VerifyTypeImplementsAbslHashCorrectly(
-      hash_internal::ContainerAsVector<Container>::Do(values),
-      equals);
+      hash_internal::ContainerAsVector<Container>::Do(values), equals);
 }
 
 template <int&..., typename T>
diff --git a/absl/hash/internal/city.cc b/absl/hash/internal/city.cc
index 8f72dd1..dc7650a 100644
--- a/absl/hash/internal/city.cc
+++ b/absl/hash/internal/city.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -340,251 +340,5 @@
   return HashLen16(CityHash64(s, len) - seed0, seed1);
 }
 
-// A subroutine for CityHash128().  Returns a decent 128-bit hash for strings
-// of any length representable in signed long.  Based on City and Murmur.
-static uint128 CityMurmur(const char *s, size_t len, uint128 seed) {
-  uint64_t a = Uint128Low64(seed);
-  uint64_t b = Uint128High64(seed);
-  uint64_t c = 0;
-  uint64_t d = 0;
-  int64_t l = len - 16;
-  if (l <= 0) {  // len <= 16
-    a = ShiftMix(a * k1) * k1;
-    c = b * k1 + HashLen0to16(s, len);
-    d = ShiftMix(a + (len >= 8 ? Fetch64(s) : c));
-  } else {  // len > 16
-    c = HashLen16(Fetch64(s + len - 8) + k1, a);
-    d = HashLen16(b + len, c + Fetch64(s + len - 16));
-    a += d;
-    do {
-      a ^= ShiftMix(Fetch64(s) * k1) * k1;
-      a *= k1;
-      b ^= a;
-      c ^= ShiftMix(Fetch64(s + 8) * k1) * k1;
-      c *= k1;
-      d ^= c;
-      s += 16;
-      l -= 16;
-    } while (l > 0);
-  }
-  a = HashLen16(a, c);
-  b = HashLen16(d, b);
-  return uint128(a ^ b, HashLen16(b, a));
-}
-
-uint128 CityHash128WithSeed(const char *s, size_t len, uint128 seed) {
-  if (len < 128) {
-    return CityMurmur(s, len, seed);
-  }
-
-  // We expect len >= 128 to be the common case.  Keep 56 bytes of state:
-  // v, w, x, y, and z.
-  std::pair<uint64_t, uint64_t> v, w;
-  uint64_t x = Uint128Low64(seed);
-  uint64_t y = Uint128High64(seed);
-  uint64_t z = len * k1;
-  v.first = Rotate(y ^ k1, 49) * k1 + Fetch64(s);
-  v.second = Rotate(v.first, 42) * k1 + Fetch64(s + 8);
-  w.first = Rotate(y + z, 35) * k1 + x;
-  w.second = Rotate(x + Fetch64(s + 88), 53) * k1;
-
-  // This is the same inner loop as CityHash64(), manually unrolled.
-  do {
-    x = Rotate(x + y + v.first + Fetch64(s + 8), 37) * k1;
-    y = Rotate(y + v.second + Fetch64(s + 48), 42) * k1;
-    x ^= w.second;
-    y += v.first + Fetch64(s + 40);
-    z = Rotate(z + w.first, 33) * k1;
-    v = WeakHashLen32WithSeeds(s, v.second * k1, x + w.first);
-    w = WeakHashLen32WithSeeds(s + 32, z + w.second, y + Fetch64(s + 16));
-    std::swap(z, x);
-    s += 64;
-    x = Rotate(x + y + v.first + Fetch64(s + 8), 37) * k1;
-    y = Rotate(y + v.second + Fetch64(s + 48), 42) * k1;
-    x ^= w.second;
-    y += v.first + Fetch64(s + 40);
-    z = Rotate(z + w.first, 33) * k1;
-    v = WeakHashLen32WithSeeds(s, v.second * k1, x + w.first);
-    w = WeakHashLen32WithSeeds(s + 32, z + w.second, y + Fetch64(s + 16));
-    std::swap(z, x);
-    s += 64;
-    len -= 128;
-  } while (ABSL_PREDICT_TRUE(len >= 128));
-  x += Rotate(v.first + z, 49) * k0;
-  y = y * k0 + Rotate(w.second, 37);
-  z = z * k0 + Rotate(w.first, 27);
-  w.first *= 9;
-  v.first *= k0;
-  // If 0 < len < 128, hash up to 4 chunks of 32 bytes each from the end of s.
-  for (size_t tail_done = 0; tail_done < len;) {
-    tail_done += 32;
-    y = Rotate(x + y, 42) * k0 + v.second;
-    w.first += Fetch64(s + len - tail_done + 16);
-    x = x * k0 + w.first;
-    z += w.second + Fetch64(s + len - tail_done);
-    w.second += v.first;
-    v = WeakHashLen32WithSeeds(s + len - tail_done, v.first + z, v.second);
-    v.first *= k0;
-  }
-  // At this point our 56 bytes of state should contain more than
-  // enough information for a strong 128-bit hash.  We use two
-  // different 56-byte-to-8-byte hashes to get a 16-byte final result.
-  x = HashLen16(x, v.first);
-  y = HashLen16(y + z, w.first);
-  return uint128(HashLen16(x + v.second, w.second) + y,
-                 HashLen16(x + w.second, y + v.second));
-}
-
-uint128 CityHash128(const char *s, size_t len) {
-  return len >= 16
-             ? CityHash128WithSeed(s + 16, len - 16,
-                                   uint128(Fetch64(s), Fetch64(s + 8) + k0))
-             : CityHash128WithSeed(s, len, uint128(k0, k1));
-}
 }  // namespace hash_internal
 }  // namespace absl
-
-#ifdef __SSE4_2__
-#include <nmmintrin.h>
-#include "absl/hash/internal/city_crc.h"
-
-namespace absl {
-namespace hash_internal {
-
-// Requires len >= 240.
-static void CityHashCrc256Long(const char *s, size_t len, uint32_t seed,
-                               uint64_t *result) {
-  uint64_t a = Fetch64(s + 56) + k0;
-  uint64_t b = Fetch64(s + 96) + k0;
-  uint64_t c = result[0] = HashLen16(b, len);
-  uint64_t d = result[1] = Fetch64(s + 120) * k0 + len;
-  uint64_t e = Fetch64(s + 184) + seed;
-  uint64_t f = 0;
-  uint64_t g = 0;
-  uint64_t h = c + d;
-  uint64_t x = seed;
-  uint64_t y = 0;
-  uint64_t z = 0;
-
-  // 240 bytes of input per iter.
-  size_t iters = len / 240;
-  len -= iters * 240;
-  do {
-#undef CHUNK
-#define CHUNK(r)               \
-  PERMUTE3(x, z, y);           \
-  b += Fetch64(s);             \
-  c += Fetch64(s + 8);         \
-  d += Fetch64(s + 16);        \
-  e += Fetch64(s + 24);        \
-  f += Fetch64(s + 32);        \
-  a += b;                      \
-  h += f;                      \
-  b += c;                      \
-  f += d;                      \
-  g += e;                      \
-  e += z;                      \
-  g += x;                      \
-  z = _mm_crc32_u64(z, b + g); \
-  y = _mm_crc32_u64(y, e + h); \
-  x = _mm_crc32_u64(x, f + a); \
-  e = Rotate(e, r);            \
-  c += e;                      \
-  s += 40
-
-    CHUNK(0);
-    PERMUTE3(a, h, c);
-    CHUNK(33);
-    PERMUTE3(a, h, f);
-    CHUNK(0);
-    PERMUTE3(b, h, f);
-    CHUNK(42);
-    PERMUTE3(b, h, d);
-    CHUNK(0);
-    PERMUTE3(b, h, e);
-    CHUNK(33);
-    PERMUTE3(a, h, e);
-  } while (--iters > 0);
-
-  while (len >= 40) {
-    CHUNK(29);
-    e ^= Rotate(a, 20);
-    h += Rotate(b, 30);
-    g ^= Rotate(c, 40);
-    f += Rotate(d, 34);
-    PERMUTE3(c, h, g);
-    len -= 40;
-  }
-  if (len > 0) {
-    s = s + len - 40;
-    CHUNK(33);
-    e ^= Rotate(a, 43);
-    h += Rotate(b, 42);
-    g ^= Rotate(c, 41);
-    f += Rotate(d, 40);
-  }
-  result[0] ^= h;
-  result[1] ^= g;
-  g += h;
-  a = HashLen16(a, g + z);
-  x += y << 32;
-  b += x;
-  c = HashLen16(c, z) + h;
-  d = HashLen16(d, e + result[0]);
-  g += e;
-  h += HashLen16(x, f);
-  e = HashLen16(a, d) + g;
-  z = HashLen16(b, c) + a;
-  y = HashLen16(g, h) + c;
-  result[0] = e + z + y + x;
-  a = ShiftMix((a + y) * k0) * k0 + b;
-  result[1] += a + result[0];
-  a = ShiftMix(a * k0) * k0 + c;
-  result[2] = a + result[1];
-  a = ShiftMix((a + e) * k0) * k0;
-  result[3] = a + result[2];
-}
-
-// Requires len < 240.
-static void CityHashCrc256Short(const char *s, size_t len, uint64_t *result) {
-  char buf[240];
-  memcpy(buf, s, len);
-  memset(buf + len, 0, 240 - len);
-  CityHashCrc256Long(buf, 240, ~static_cast<uint32_t>(len), result);
-}
-
-void CityHashCrc256(const char *s, size_t len, uint64_t *result) {
-  if (ABSL_PREDICT_TRUE(len >= 240)) {
-    CityHashCrc256Long(s, len, 0, result);
-  } else {
-    CityHashCrc256Short(s, len, result);
-  }
-}
-
-uint128 CityHashCrc128WithSeed(const char *s, size_t len, uint128 seed) {
-  if (len <= 900) {
-    return CityHash128WithSeed(s, len, seed);
-  } else {
-    uint64_t result[4];
-    CityHashCrc256(s, len, result);
-    uint64_t u = Uint128High64(seed) + result[0];
-    uint64_t v = Uint128Low64(seed) + result[1];
-    return uint128(HashLen16(u, v + result[2]),
-                   HashLen16(Rotate(v, 32), u * k0 + result[3]));
-  }
-}
-
-uint128 CityHashCrc128(const char *s, size_t len) {
-  if (len <= 900) {
-    return CityHash128(s, len);
-  } else {
-    uint64_t result[4];
-    CityHashCrc256(s, len, result);
-    return uint128(result[2], result[3]);
-  }
-}
-
-}  // namespace hash_internal
-}  // namespace absl
-
-#endif
diff --git a/absl/hash/internal/city.h b/absl/hash/internal/city.h
index 55b37b8..b43d340 100644
--- a/absl/hash/internal/city.h
+++ b/absl/hash/internal/city.h
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 //
-// http://code.google.com/p/cityhash/
+// https://code.google.com/p/cityhash/
 //
 // This file provides a few functions for hashing strings.  All of them are
 // high-quality functions in the sense that they pass standard tests such
@@ -23,15 +23,6 @@
 // is Murmur3.  For 64-bit x86 code, CityHash64 is an excellent choice for hash
 // tables and most other hashing (excluding cryptography).
 //
-// For 64-bit x86 code, on long strings, the picture is more complicated.
-// On many recent Intel CPUs, such as Nehalem, Westmere, Sandy Bridge, etc.,
-// CityHashCrc128 appears to be faster than all competitors of comparable
-// quality.  CityHash128 is also good but not quite as fast.  We believe our
-// nearest competitor is Bob Jenkins' Spooky.  We don't have great data for
-// other 64-bit CPUs, but for long strings we know that Spooky is slightly
-// faster than CityHash on some relatively recent AMD x86-64 CPUs, for example.
-// Note that CityHashCrc128 is declared in citycrc.h.
-//
 // For 32-bit x86 code, we don't know of anything faster than CityHash32 that
 // is of comparable quality.  We believe our nearest competitor is Murmur3A.
 // (On 64-bit CPUs, it is typically faster to use the other CityHash variants.)
@@ -58,7 +49,6 @@
 #include <stdlib.h>  // for size_t.
 #include <utility>
 
-
 namespace absl {
 namespace hash_internal {
 
@@ -79,13 +69,6 @@
 uint64_t CityHash64WithSeeds(const char *s, size_t len, uint64_t seed0,
                            uint64_t seed1);
 
-// Hash function for a byte array.
-uint128 CityHash128(const char *s, size_t len);
-
-// Hash function for a byte array.  For convenience, a 128-bit seed is also
-// hashed into the result.
-uint128 CityHash128WithSeed(const char *s, size_t len, uint128 seed);
-
 // Hash function for a byte array.  Most useful in 32-bit binaries.
 uint32_t CityHash32(const char *s, size_t len);
 
diff --git a/absl/hash/internal/city_crc.h b/absl/hash/internal/city_crc.h
deleted file mode 100644
index 6be6557..0000000
--- a/absl/hash/internal/city_crc.h
+++ /dev/null
@@ -1,41 +0,0 @@
-// 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.
-//
-// This file declares the subset of the CityHash functions that require
-// _mm_crc32_u64().  See the CityHash README for details.
-//
-// Functions in the CityHash family are not suitable for cryptography.
-
-#ifndef ABSL_HASH_INTERNAL_CITY_CRC_H_
-#define ABSL_HASH_INTERNAL_CITY_CRC_H_
-
-#include "absl/hash/internal/city.h"
-
-namespace absl {
-namespace hash_internal {
-
-// Hash function for a byte array.
-uint128 CityHashCrc128(const char *s, size_t len);
-
-// Hash function for a byte array.  For convenience, a 128-bit seed is also
-// hashed into the result.
-uint128 CityHashCrc128WithSeed(const char *s, size_t len, uint128 seed);
-
-// Hash function for a byte array.  Sets result[0] ... result[3].
-void CityHashCrc256(const char *s, size_t len, uint64_t *result);
-
-}  // namespace hash_internal
-}  // namespace absl
-
-#endif  // ABSL_HASH_INTERNAL_CITY_CRC_H_
diff --git a/absl/hash/internal/city_test.cc b/absl/hash/internal/city_test.cc
index 678da53..71b4ecc 100644
--- a/absl/hash/internal/city_test.cc
+++ b/absl/hash/internal/city_test.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -18,9 +18,6 @@
 #include <cstdio>
 #include <iostream>
 #include "gtest/gtest.h"
-#ifdef __SSE4_2__
-#include "absl/hash/internal/city_crc.h"
-#endif
 
 namespace absl {
 namespace hash_internal {
@@ -28,7 +25,6 @@
 static const uint64_t k0 = 0xc3a5c85c97cb3127ULL;
 static const uint64_t kSeed0 = 1234567;
 static const uint64_t kSeed1 = k0;
-static const uint128 kSeed128(kSeed0, kSeed1);
 static const int kDataSize = 1 << 20;
 static const int kTestSize = 300;
 
@@ -49,1754 +45,539 @@
 }
 
 #define C(x) 0x##x##ULL
-static const uint64_t testdata[kTestSize][16] = {
+static const uint64_t testdata[kTestSize][4] = {
     {C(9ae16a3b2f90404f), C(75106db890237a4a), C(3feac5f636039766),
-     C(3df09dfc64c09a2b), C(3cb540c392e51e29), C(6b56343feac0663),
-     C(5b7bc50fd8e8ad92), C(3df09dfc64c09a2b), C(3cb540c392e51e29),
-     C(6b56343feac0663), C(5b7bc50fd8e8ad92), C(95162f24e6a5f930),
-     C(6808bdf4f1eb06e0), C(b3b1f3a67b624d82), C(c9a62f12bd4cd80b),
      C(dc56d17a)},
     {C(541150e87f415e96), C(1aef0d24b3148a1a), C(bacc300e1e82345a),
-     C(c3cdc41e1df33513), C(2c138ff2596d42f6), C(f58e9082aed3055f),
-     C(162e192b2957163d), C(c3cdc41e1df33513), C(2c138ff2596d42f6),
-     C(f58e9082aed3055f), C(162e192b2957163d), C(fb99e85e0d16f90c),
-     C(608462c15bdf27e8), C(e7d2c5c943572b62), C(1baaa9327642798c),
      C(99929334)},
-    {C(f3786a4b25827c1), C(34ee1a2bf767bd1c), C(2f15ca2ebfb631f2),
-     C(3149ba1dac77270d), C(70e2e076e30703c), C(59bcc9659bc5296),
-     C(9ecbc8132ae2f1d7), C(3149ba1dac77270d), C(70e2e076e30703c),
-     C(59bcc9659bc5296), C(9ecbc8132ae2f1d7), C(a01d30789bad7cf2),
-     C(ae03fe371981a0e0), C(127e3883b8788934), C(d0ac3d4c0a6fca32),
-     C(4252edb7)},
+    {C(f3786a4b25827c1), C(34ee1a2bf767bd1c), C(2f15ca2ebfb631f2), C(4252edb7)},
     {C(ef923a7a1af78eab), C(79163b1e1e9a9b18), C(df3b2aca6e1e4a30),
-     C(2193fb7620cbf23b), C(8b6a8ff06cda8302), C(1a44469afd3e091f),
-     C(8b0449376612506), C(2193fb7620cbf23b), C(8b6a8ff06cda8302),
-     C(1a44469afd3e091f), C(8b0449376612506), C(e9d9d41c32ad91d1),
-     C(b44ab09f58e3c608), C(19e9175f9fcf784), C(839b3c9581b4a480), C(ebc34f3c)},
+     C(ebc34f3c)},
     {C(11df592596f41d88), C(843ec0bce9042f9c), C(cce2ea1e08b1eb30),
-     C(4d09e42f09cc3495), C(666236631b9f253b), C(d28b3763cd02b6a3),
-     C(43b249e57c4d0c1b), C(4d09e42f09cc3495), C(666236631b9f253b),
-     C(d28b3763cd02b6a3), C(43b249e57c4d0c1b), C(3887101c8adea101),
-     C(8a9355d4efc91df0), C(3e610944cc9fecfd), C(5bf9eb60b08ac0ce),
      C(26f2b463)},
     {C(831f448bdc5600b3), C(62a24be3120a6919), C(1b44098a41e010da),
-     C(dc07df53b949c6b), C(d2b11b2081aeb002), C(d212b02c1b13f772),
-     C(c0bed297b4be1912), C(dc07df53b949c6b), C(d2b11b2081aeb002),
-     C(d212b02c1b13f772), C(c0bed297b4be1912), C(682d3d2ad304e4af),
-     C(40e9112a655437a1), C(268b09f7ee09843f), C(6b9698d43859ca47),
      C(b042c047)},
-    {C(3eca803e70304894), C(d80de767e4a920a), C(a51cfbb292efd53d),
-     C(d183dcda5f73edfa), C(3a93cbf40f30128c), C(1a92544d0b41dbda),
-     C(aec2c4bee81975e1), C(d183dcda5f73edfa), C(3a93cbf40f30128c),
-     C(1a92544d0b41dbda), C(aec2c4bee81975e1), C(5f91814d1126ba4b),
-     C(f8ac57eee87fcf1f), C(c55c644a5d0023cd), C(adb761e827825ff2),
-     C(e73bb0a8)},
+    {C(3eca803e70304894), C(d80de767e4a920a), C(a51cfbb292efd53d), C(e73bb0a8)},
     {C(1b5a063fb4c7f9f1), C(318dbc24af66dee9), C(10ef7b32d5c719af),
-     C(b140a02ef5c97712), C(b7d00ef065b51b33), C(635121d532897d98),
-     C(532daf21b312a6d6), C(b140a02ef5c97712), C(b7d00ef065b51b33),
-     C(635121d532897d98), C(532daf21b312a6d6), C(c0b09b75d943910),
-     C(8c84dfb5ef2a8e96), C(e5c06034b0353433), C(3170faf1c33a45dd),
      C(91dfdd75)},
     {C(a0f10149a0e538d6), C(69d008c20f87419f), C(41b36376185b3e9e),
-     C(26b6689960ccf81d), C(55f23b27bb9efd94), C(3a17f6166dd765db),
-     C(c891a8a62931e782), C(26b6689960ccf81d), C(55f23b27bb9efd94),
-     C(3a17f6166dd765db), C(c891a8a62931e782), C(23852dc37ddd2607),
-     C(8b7f1b1ec897829e), C(d1d69452a54eed8a), C(56431f2bd766ec24),
      C(c87f95de)},
     {C(fb8d9c70660b910b), C(a45b0cc3476bff1b), C(b28d1996144f0207),
-     C(98ec31113e5e35d2), C(5e4aeb853f1b9aa7), C(bcf5c8fe4465b7c8),
-     C(b1ea3a8243996f15), C(98ec31113e5e35d2), C(5e4aeb853f1b9aa7),
-     C(bcf5c8fe4465b7c8), C(b1ea3a8243996f15), C(cabbccedb6407571),
-     C(d1e40a84c445ec3a), C(33302aa908cf4039), C(9f15f79211b5cdf8),
      C(3f5538ef)},
     {C(236827beae282a46), C(e43970221139c946), C(4f3ac6faa837a3aa),
-     C(71fec0f972248915), C(2170ec2061f24574), C(9eb346b6caa36e82),
-     C(2908f0fdbca48e73), C(71fec0f972248915), C(2170ec2061f24574),
-     C(9eb346b6caa36e82), C(2908f0fdbca48e73), C(8101c99f07c64abb),
-     C(b9f4b02b1b6a96a7), C(583a2b10cd222f88), C(199dae4cf9db24c), C(70eb1a1f)},
+     C(70eb1a1f)},
     {C(c385e435136ecf7c), C(d9d17368ff6c4a08), C(1b31eed4e5251a67),
-     C(df01a322c43a6200), C(298b65a1714b5a7e), C(933b83f0aedf23c),
-     C(157bcb44d63f765a), C(df01a322c43a6200), C(298b65a1714b5a7e),
-     C(933b83f0aedf23c), C(157bcb44d63f765a), C(d6e9fc7a272d8b51),
-     C(3ee5073ef1a9b777), C(63149e31fac02c59), C(2f7979ff636ba1d8),
      C(cfd63b83)},
     {C(e3f6828b6017086d), C(21b4d1900554b3b0), C(bef38be1809e24f1),
-     C(d93251758985ee6c), C(32a9e9f82ba2a932), C(3822aacaa95f3329),
-     C(db349b2f90a490d8), C(d93251758985ee6c), C(32a9e9f82ba2a932),
-     C(3822aacaa95f3329), C(db349b2f90a490d8), C(8d49194a894a19ca),
-     C(79a78b06e42738e6), C(7e0f1eda3d390c66), C(1c291d7e641100a5),
      C(894a52ef)},
     {C(851fff285561dca0), C(4d1277d73cdf416f), C(28ccffa61010ebe2),
-     C(77a4ccacd131d9ee), C(e1d08eeb2f0e29aa), C(70b9e3051383fa45),
-     C(582d0120425caba), C(77a4ccacd131d9ee), C(e1d08eeb2f0e29aa),
-     C(70b9e3051383fa45), C(582d0120425caba), C(a740eef1846e4564),
-     C(572dddb74ac3ae00), C(fdb5ca9579163bbd), C(a649b9b799c615d2),
      C(9cde6a54)},
     {C(61152a63595a96d9), C(d1a3a91ef3a7ba45), C(443b6bb4a493ad0c),
-     C(a154296d11362d06), C(d0f0bf1f1cb02fc1), C(ccb87e09309f90d1),
-     C(b24a8e4881911101), C(a154296d11362d06), C(d0f0bf1f1cb02fc1),
-     C(ccb87e09309f90d1), C(b24a8e4881911101), C(1a481b4528559f58),
-     C(bf837a3150896995), C(4989ef6b941a3757), C(2e725ab72d0b2948),
      C(6c4898d5)},
     {C(44473e03be306c88), C(30097761f872472a), C(9fd1b669bfad82d7),
-     C(3bab18b164396783), C(47e385ff9d4c06f), C(18062081bf558df),
-     C(63416eb68f104a36), C(3bab18b164396783), C(47e385ff9d4c06f),
-     C(18062081bf558df), C(63416eb68f104a36), C(4abda1560c47ac80),
-     C(1ea0e63dc6587aee), C(33ec79d92ebc1de), C(94f9dccef771e048), C(13e1978e)},
-    {C(3ead5f21d344056), C(fb6420393cfb05c3), C(407932394cbbd303),
-     C(ac059617f5906673), C(94d50d3dcd3069a7), C(2b26c3b92dea0f0),
-     C(99b7374cc78fc3fb), C(ac059617f5906673), C(94d50d3dcd3069a7),
-     C(2b26c3b92dea0f0), C(99b7374cc78fc3fb), C(1a8e3c73cdd40ee8),
-     C(cbb5fca06747f45b), C(ceec44238b291841), C(28bf35cce9c90a25), C(51b4ba8)},
+     C(13e1978e)},
+    {C(3ead5f21d344056), C(fb6420393cfb05c3), C(407932394cbbd303), C(51b4ba8)},
     {C(6abbfde37ee03b5b), C(83febf188d2cc113), C(cda7b62d94d5b8ee),
-     C(a4375590b8ae7c82), C(168fd42f9ecae4ff), C(23bbde43de2cb214),
-     C(a8c333112a243c8c), C(a4375590b8ae7c82), C(168fd42f9ecae4ff),
-     C(23bbde43de2cb214), C(a8c333112a243c8c), C(10ac012e8c518b49),
-     C(64a44605d8b29458), C(a67e701d2a679075), C(3a3a20f43ec92303),
      C(b6b06e40)},
-    {C(943e7ed63b3c080), C(1ef207e9444ef7f8), C(ef4a9f9f8c6f9b4a),
-     C(6b54fc38d6a84108), C(32f4212a47a4665), C(6b5a9a8f64ee1da6),
-     C(9f74e86c6da69421), C(6b54fc38d6a84108), C(32f4212a47a4665),
-     C(6b5a9a8f64ee1da6), C(9f74e86c6da69421), C(946dd0cb30c1a08e),
-     C(fdf376956907eaaa), C(a59074c6eec03028), C(b1a3abcf283f34ac), C(240a2f2)},
+    {C(943e7ed63b3c080), C(1ef207e9444ef7f8), C(ef4a9f9f8c6f9b4a), C(240a2f2)},
     {C(d72ce05171ef8a1a), C(c6bd6bd869203894), C(c760e6396455d23a),
-     C(f86af0b40dcce7b), C(8d3c15d613394d3c), C(491e400491cd4ece),
-     C(7c19d3530ea3547f), C(f86af0b40dcce7b), C(8d3c15d613394d3c),
-     C(491e400491cd4ece), C(7c19d3530ea3547f), C(1362963a1dc32af9),
-     C(fb9bc11762e1385c), C(9e164ef1f5376083), C(6c15819b5e828a7e),
      C(5dcefc30)},
     {C(4182832b52d63735), C(337097e123eea414), C(b5a72ca0456df910),
-     C(7ebc034235bc122f), C(d9a7783d4edd8049), C(5f8b04a15ae42361),
-     C(fc193363336453dd), C(7ebc034235bc122f), C(d9a7783d4edd8049),
-     C(5f8b04a15ae42361), C(fc193363336453dd), C(9b6c50224ef8c4f8),
-     C(ba225c7942d16c3f), C(6f6d55226a73c412), C(abca061fe072152a),
      C(7a48b105)},
     {C(d6cdae892584a2cb), C(58de0fa4eca17dcd), C(43df30b8f5f1cb00),
-     C(9e4ea5a4941e097d), C(547e048d5a9daaba), C(eb6ecbb0b831d185),
-     C(e0168df5fad0c670), C(9e4ea5a4941e097d), C(547e048d5a9daaba),
-     C(eb6ecbb0b831d185), C(e0168df5fad0c670), C(afa9705f98c2c96a),
-     C(749436f48137a96b), C(759c041fc21df486), C(b23bf400107aa2ec),
      C(fd55007b)},
     {C(5c8e90bc267c5ee4), C(e9ae044075d992d9), C(f234cbfd1f0a1e59),
-     C(ce2744521944f14c), C(104f8032f99dc152), C(4e7f425bfac67ca7),
-     C(9461b911a1c6d589), C(ce2744521944f14c), C(104f8032f99dc152),
-     C(4e7f425bfac67ca7), C(9461b911a1c6d589), C(5e5ecc726db8b60d),
-     C(cce68b0586083b51), C(8a7f8e54a9cba0fc), C(42f010181d16f049),
      C(6b95894c)},
     {C(bbd7f30ac310a6f3), C(b23b570d2666685f), C(fb13fb08c9814fe7),
-     C(4ee107042e512374), C(1e2c8c0d16097e13), C(210c7500995aa0e6),
-     C(6c13190557106457), C(4ee107042e512374), C(1e2c8c0d16097e13),
-     C(210c7500995aa0e6), C(6c13190557106457), C(a99b31c96777f381),
-     C(8312ae8301d386c0), C(ed5042b2a4fa96a3), C(d71d1bb23907fe97),
      C(3360e827)},
-    {C(36a097aa49519d97), C(8204380a73c4065), C(77c2004bdd9e276a),
-     C(6ee1f817ce0b7aee), C(e9dcb3507f0596ca), C(6bc63c666b5100e2),
-     C(e0b056f1821752af), C(6ee1f817ce0b7aee), C(e9dcb3507f0596ca),
-     C(6bc63c666b5100e2), C(e0b056f1821752af), C(8ea1114e60292678),
-     C(904b80b46becc77), C(46cd9bb6e9dff52f), C(4c91e3b698355540), C(45177e0b)},
-    {C(dc78cb032c49217), C(112464083f83e03a), C(96ae53e28170c0f5),
-     C(d367ff54952a958), C(cdad930657371147), C(aa24dc2a9573d5fe),
-     C(eb136daa89da5110), C(d367ff54952a958), C(cdad930657371147),
-     C(aa24dc2a9573d5fe), C(eb136daa89da5110), C(de623005f6d46057),
-     C(b50c0c92b95e9b7f), C(a8aa54050b81c978), C(573fb5c7895af9b5),
-     C(7c6fffe4)},
+    {C(36a097aa49519d97), C(8204380a73c4065), C(77c2004bdd9e276a), C(45177e0b)},
+    {C(dc78cb032c49217), C(112464083f83e03a), C(96ae53e28170c0f5), C(7c6fffe4)},
     {C(441593e0da922dfe), C(936ef46061469b32), C(204a1921197ddd87),
-     C(50d8a70e7a8d8f56), C(256d150ae75dab76), C(e81f4c4a1989036a),
-     C(d0f8db365f9d7e00), C(50d8a70e7a8d8f56), C(256d150ae75dab76),
-     C(e81f4c4a1989036a), C(d0f8db365f9d7e00), C(753d686677b14522),
-     C(9f76e0cb6f2d0a66), C(ab14f95988ec0d39), C(97621d9da9c9812f),
      C(bbc78da4)},
     {C(2ba3883d71cc2133), C(72f2bbb32bed1a3c), C(27e1bd96d4843251),
-     C(a90f761e8db1543a), C(c339e23c09703cd8), C(f0c6624c4b098fd3),
-     C(1bae2053e41fa4d9), C(a90f761e8db1543a), C(c339e23c09703cd8),
-     C(f0c6624c4b098fd3), C(1bae2053e41fa4d9), C(3589e273c22ba059),
-     C(63798246e5911a0b), C(18e710ec268fc5dc), C(714a122de1d074f3),
      C(c5c25d39)},
     {C(f2b6d2adf8423600), C(7514e2f016a48722), C(43045743a50396ba),
-     C(23dacb811652ad4f), C(c982da480e0d4c7d), C(3a9c8ed5a399d0a9),
-     C(951b8d084691d4e4), C(23dacb811652ad4f), C(c982da480e0d4c7d),
-     C(3a9c8ed5a399d0a9), C(951b8d084691d4e4), C(d9f87b4988cff2f7),
-     C(217a191d986aa3bc), C(6ad23c56b480350), C(dd78673938ceb2e7), C(b6e5d06e)},
+     C(b6e5d06e)},
     {C(38fffe7f3680d63c), C(d513325255a7a6d1), C(31ed47790f6ca62f),
-     C(c801faaa0a2e331f), C(491dbc58279c7f88), C(9c0178848321c97a),
-     C(9d934f814f4d6a3c), C(c801faaa0a2e331f), C(491dbc58279c7f88),
-     C(9c0178848321c97a), C(9d934f814f4d6a3c), C(606a3e4fc8763192),
-     C(bc15cb36a677ee84), C(52d5904157e1fe71), C(1588dd8b1145b79b),
      C(6178504e)},
-    {C(b7477bf0b9ce37c6), C(63b1c580a7fd02a4), C(f6433b9f10a5dac),
-     C(68dd76db9d64eca7), C(36297682b64b67), C(42b192d71f414b7a),
-     C(79692cef44fa0206), C(68dd76db9d64eca7), C(36297682b64b67),
-     C(42b192d71f414b7a), C(79692cef44fa0206), C(f0979252f4776d07),
-     C(4b87cd4f1c9bbf52), C(51b84bbc6312c710), C(150720fbf85428a7),
-     C(bd4c3637)},
+    {C(b7477bf0b9ce37c6), C(63b1c580a7fd02a4), C(f6433b9f10a5dac), C(bd4c3637)},
     {C(55bdb0e71e3edebd), C(c7ab562bcf0568bc), C(43166332f9ee684f),
-     C(b2e25964cd409117), C(a010599d6287c412), C(fa5d6461e768dda2),
-     C(cb3ce74e8ec4f906), C(b2e25964cd409117), C(a010599d6287c412),
-     C(fa5d6461e768dda2), C(cb3ce74e8ec4f906), C(6120abfd541a2610),
-     C(aa88b148cc95794d), C(2686ca35df6590e3), C(c6b02d18616ce94d),
      C(6e7ac474)},
-    {C(782fa1b08b475e7), C(fb7138951c61b23b), C(9829105e234fb11e),
-     C(9a8c431f500ef06e), C(d848581a580b6c12), C(fecfe11e13a2bdb4),
-     C(6c4fa0273d7db08c), C(9a8c431f500ef06e), C(d848581a580b6c12),
-     C(fecfe11e13a2bdb4), C(6c4fa0273d7db08c), C(482f43bf5ae59fcb),
-     C(f651fbca105d79e6), C(f09f78695d865817), C(7a99d0092085cf47),
-     C(1fb4b518)},
+    {C(782fa1b08b475e7), C(fb7138951c61b23b), C(9829105e234fb11e), C(1fb4b518)},
     {C(c5dc19b876d37a80), C(15ffcff666cfd710), C(e8c30c72003103e2),
-     C(7870765b470b2c5d), C(78a9103ff960d82), C(7bb50ffc9fac74b3),
-     C(477e70ab2b347db2), C(7870765b470b2c5d), C(78a9103ff960d82),
-     C(7bb50ffc9fac74b3), C(477e70ab2b347db2), C(a625238bdf7c07cf),
-     C(1128d515174809f5), C(b0f1647e82f45873), C(17792d1c4f222c39),
      C(31d13d6d)},
     {C(5e1141711d2d6706), C(b537f6dee8de6933), C(3af0a1fbbe027c54),
-     C(ea349dbc16c2e441), C(38a7455b6a877547), C(5f97b9750e365411),
-     C(e8cde7f93af49a3), C(ea349dbc16c2e441), C(38a7455b6a877547),
-     C(5f97b9750e365411), C(e8cde7f93af49a3), C(ba101925ec1f7e26),
-     C(d5e84cab8192c71e), C(e256427726fdd633), C(a4f38e2c6116890d),
      C(26fa72e3)},
-    {C(782edf6da001234f), C(f48cbd5c66c48f3), C(808754d1e64e2a32),
-     C(5d9dde77353b1a6d), C(11f58c54581fa8b1), C(da90fa7c28c37478),
-     C(5e9a2eafc670a88a), C(5d9dde77353b1a6d), C(11f58c54581fa8b1),
-     C(da90fa7c28c37478), C(5e9a2eafc670a88a), C(e35e1bc172e011ef),
-     C(bf9255a4450ae7fe), C(55f85194e26bc55f), C(4f327873e14d0e54),
-     C(6a7433bf)},
+    {C(782edf6da001234f), C(f48cbd5c66c48f3), C(808754d1e64e2a32), C(6a7433bf)},
     {C(d26285842ff04d44), C(8f38d71341eacca9), C(5ca436f4db7a883c),
-     C(bf41e5376b9f0eec), C(2252d21eb7e1c0e9), C(f4b70a971855e732),
-     C(40c7695aa3662afd), C(bf41e5376b9f0eec), C(2252d21eb7e1c0e9),
-     C(f4b70a971855e732), C(40c7695aa3662afd), C(770fe19e16ab73bb),
-     C(d603ebda6393d749), C(e58c62439aa50dbd), C(96d51e5a02d2d7cf),
      C(4e6df758)},
     {C(c6ab830865a6bae6), C(6aa8e8dd4b98815c), C(efe3846713c371e5),
-     C(a1924cbf0b5f9222), C(7f4872369c2b4258), C(cd6da30530f3ea89),
-     C(b7f8b9a704e6cea1), C(a1924cbf0b5f9222), C(7f4872369c2b4258),
-     C(cd6da30530f3ea89), C(b7f8b9a704e6cea1), C(fa06ff40433fd535),
-     C(fb1c36fe8f0737f1), C(bb7050561171f80), C(b1bc23235935d897), C(d57f63ea)},
-    {C(44b3a1929232892), C(61dca0e914fc217), C(a607cc142096b964),
-     C(f7dbc8433c89b274), C(2f5f70581c9b7d32), C(39bf5e5fec82dcca),
-     C(8ade56388901a619), C(f7dbc8433c89b274), C(2f5f70581c9b7d32),
-     C(39bf5e5fec82dcca), C(8ade56388901a619), C(c1c6a725caab3ea9),
-     C(c1c7906c2f80b898), C(9c3871a04cc884e6), C(df01813cbbdf217f),
-     C(52ef73b3)},
-    {C(4b603d7932a8de4f), C(fae64c464b8a8f45), C(8fafab75661d602a),
-     C(8ffe870ef4adc087), C(65bea2be41f55b54), C(82f3503f636aef1),
-     C(5f78a282378b6bb0), C(8ffe870ef4adc087), C(65bea2be41f55b54),
-     C(82f3503f636aef1), C(5f78a282378b6bb0), C(7bf2422c0beceddb),
-     C(9d238d4780114bd), C(7ad198311906597f), C(ec8f892c0422aca3), C(3cb36c3)},
+     C(d57f63ea)},
+    {C(44b3a1929232892), C(61dca0e914fc217), C(a607cc142096b964), C(52ef73b3)},
+    {C(4b603d7932a8de4f), C(fae64c464b8a8f45), C(8fafab75661d602a), C(3cb36c3)},
     {C(4ec0b54cf1566aff), C(30d2c7269b206bf4), C(77c22e82295e1061),
-     C(3df9b04434771542), C(feddce785ccb661f), C(a644aff716928297),
-     C(dd46aee73824b4ed), C(3df9b04434771542), C(feddce785ccb661f),
-     C(a644aff716928297), C(dd46aee73824b4ed), C(bf8d71879da29b02),
-     C(fc82dccbfc8022a0), C(31bfcd0d9f48d1d3), C(c64ee24d0e7b5f8b),
      C(72c39bea)},
     {C(ed8b7a4b34954ff7), C(56432de31f4ee757), C(85bd3abaa572b155),
-     C(7d2c38a926dc1b88), C(5245b9eb4cd6791d), C(fb53ab03b9ad0855),
-     C(3664026c8fc669d7), C(7d2c38a926dc1b88), C(5245b9eb4cd6791d),
-     C(fb53ab03b9ad0855), C(3664026c8fc669d7), C(45024d5080bc196),
-     C(b236ebec2cc2740), C(27231ad0e3443be4), C(145780b63f809250), C(a65aa25c)},
+     C(a65aa25c)},
     {C(5d28b43694176c26), C(714cc8bc12d060ae), C(3437726273a83fe6),
-     C(864b1b28ec16ea86), C(6a78a5a4039ec2b9), C(8e959533e35a766),
-     C(347b7c22b75ae65f), C(864b1b28ec16ea86), C(6a78a5a4039ec2b9),
-     C(8e959533e35a766), C(347b7c22b75ae65f), C(5005892bb61e647c),
-     C(fe646519b4a1894d), C(cd801026f74a8a53), C(8713463e9a1ab9ce),
      C(74740539)},
     {C(6a1ef3639e1d202e), C(919bc1bd145ad928), C(30f3f7e48c28a773),
-     C(2e8c49d7c7aaa527), C(5e2328fc8701db7c), C(89ef1afca81f7de8),
-     C(b1857db11985d296), C(2e8c49d7c7aaa527), C(5e2328fc8701db7c),
-     C(89ef1afca81f7de8), C(b1857db11985d296), C(17763d695f616115),
-     C(b8f7bf1fcdc8322c), C(cf0c61938ab07a27), C(1122d3e6edb4e866),
      C(c3ae3c26)},
-    {C(159f4d9e0307b111), C(3e17914a5675a0c), C(af849bd425047b51),
-     C(3b69edadf357432b), C(3a2e311c121e6bf2), C(380fad1e288d57e5),
-     C(bf7c7e8ef0e3b83a), C(3b69edadf357432b), C(3a2e311c121e6bf2),
-     C(380fad1e288d57e5), C(bf7c7e8ef0e3b83a), C(92966d5f4356ae9b),
-     C(2a03fc66c4d6c036), C(2516d8bddb0d5259), C(b3ffe9737ff5090), C(f29db8a2)},
+    {C(159f4d9e0307b111), C(3e17914a5675a0c), C(af849bd425047b51), C(f29db8a2)},
     {C(cc0a840725a7e25b), C(57c69454396e193a), C(976eaf7eee0b4540),
-     C(cd7a46850b95e901), C(c57f7d060dda246f), C(6b9406ead64079bf),
-     C(11b28e20a573b7bd), C(cd7a46850b95e901), C(c57f7d060dda246f),
-     C(6b9406ead64079bf), C(11b28e20a573b7bd), C(2d6db356e9369ace),
-     C(dc0afe10fba193), C(5cdb10885dbbfce), C(5c700e205782e35a), C(1ef4cbf4)},
+     C(1ef4cbf4)},
     {C(a2b27ee22f63c3f1), C(9ebde0ce1b3976b2), C(2fe6a92a257af308),
-     C(8c1df927a930af59), C(a462f4423c9e384e), C(236542255b2ad8d9),
-     C(595d201a2c19d5bc), C(8c1df927a930af59), C(a462f4423c9e384e),
-     C(236542255b2ad8d9), C(595d201a2c19d5bc), C(22c87d4604a67f3),
-     C(585a06eb4bc44c4f), C(b4175a7ac7eabcd8), C(a457d3eeba14ab8c),
      C(a9be6c41)},
-    {C(d8f2f234899bcab3), C(b10b037297c3a168), C(debea2c510ceda7f),
-     C(9498fefb890287ce), C(ae68c2be5b1a69a6), C(6189dfba34ed656c),
-     C(91658f95836e5206), C(9498fefb890287ce), C(ae68c2be5b1a69a6),
-     C(6189dfba34ed656c), C(91658f95836e5206), C(c0bb4fff32aecd4d),
-     C(94125f505a50eef9), C(6ac406e7cfbce5bb), C(344a4b1dcdb7f5d8), C(fa31801)},
+    {C(d8f2f234899bcab3), C(b10b037297c3a168), C(debea2c510ceda7f), C(fa31801)},
     {C(584f28543864844f), C(d7cee9fc2d46f20d), C(a38dca5657387205),
-     C(7a0b6dbab9a14e69), C(c6d0a9d6b0e31ac4), C(a674d85812c7cf6),
-     C(63538c0351049940), C(7a0b6dbab9a14e69), C(c6d0a9d6b0e31ac4),
-     C(a674d85812c7cf6), C(63538c0351049940), C(9710e5f0bc93d1d),
-     C(c2bea5bd7c54ddd4), C(48739af2bed0d32d), C(ba2c4e09e21fba85),
      C(8331c5d8)},
-    {C(a94be46dd9aa41af), C(a57e5b7723d3f9bd), C(34bf845a52fd2f),
-     C(843b58463c8df0ae), C(74b258324e916045), C(bdd7353230eb2b38),
-     C(fad31fced7abade5), C(843b58463c8df0ae), C(74b258324e916045),
-     C(bdd7353230eb2b38), C(fad31fced7abade5), C(2436aeafb0046f85),
-     C(65bc9af9e5e33161), C(92733b1b3ae90628), C(f48143eaf78a7a89),
-     C(e9876db8)},
+    {C(a94be46dd9aa41af), C(a57e5b7723d3f9bd), C(34bf845a52fd2f), C(e9876db8)},
     {C(9a87bea227491d20), C(a468657e2b9c43e7), C(af9ba60db8d89ef7),
-     C(cc76f429ea7a12bb), C(5f30eaf2bb14870a), C(434e824cb3e0cd11),
-     C(431a4d382e39d16e), C(cc76f429ea7a12bb), C(5f30eaf2bb14870a),
-     C(434e824cb3e0cd11), C(431a4d382e39d16e), C(9e51f913c4773a8),
-     C(32ab1925823d0add), C(99c61b54c1d8f69d), C(38cfb80f02b43b1f),
      C(27b0604e)},
     {C(27688c24958d1a5c), C(e3b4a1c9429cf253), C(48a95811f70d64bc),
-     C(328063229db22884), C(67e9c95f8ba96028), C(7c6bf01c60436075),
-     C(fa55161e7d9030b2), C(328063229db22884), C(67e9c95f8ba96028),
-     C(7c6bf01c60436075), C(fa55161e7d9030b2), C(dadbc2f0dab91681),
-     C(da39d7a4934ca11), C(162e845d24c1b45c), C(eb5b9dcd8c6ed31b), C(dcec07f2)},
+     C(dcec07f2)},
     {C(5d1d37790a1873ad), C(ed9cd4bcc5fa1090), C(ce51cde05d8cd96a),
-     C(f72c26e624407e66), C(a0eb541bdbc6d409), C(c3f40a2f40b3b213),
-     C(6a784de68794492d), C(f72c26e624407e66), C(a0eb541bdbc6d409),
-     C(c3f40a2f40b3b213), C(6a784de68794492d), C(10a38a23dbef7937),
-     C(6a5560f853252278), C(c3387bbf3c7b82ba), C(fbee7c12eb072805),
      C(cff0a82a)},
     {C(1f03fd18b711eea9), C(566d89b1946d381a), C(6e96e83fc92563ab),
-     C(405f66cf8cae1a32), C(d7261740d8f18ce6), C(fea3af64a413d0b2),
-     C(d64d1810e83520fe), C(405f66cf8cae1a32), C(d7261740d8f18ce6),
-     C(fea3af64a413d0b2), C(d64d1810e83520fe), C(e1334a00a580c6e8),
-     C(454049e1b52c15f), C(8895d823d9778247), C(efa7f2e88b826618), C(fec83621)},
-    {C(f0316f286cf527b6), C(f84c29538de1aa5a), C(7612ed3c923d4a71),
-     C(d4eccebe9393ee8a), C(2eb7867c2318cc59), C(1ce621fd700fe396),
-     C(686450d7a346878a), C(d4eccebe9393ee8a), C(2eb7867c2318cc59),
-     C(1ce621fd700fe396), C(686450d7a346878a), C(75a5f37579f8b4cb),
-     C(500cc16eb6541dc7), C(b7b02317b539d9a6), C(3519ddff5bc20a29), C(743d8dc)},
+     C(fec83621)},
+    {C(f0316f286cf527b6), C(f84c29538de1aa5a), C(7612ed3c923d4a71), C(743d8dc)},
     {C(297008bcb3e3401d), C(61a8e407f82b0c69), C(a4a35bff0524fa0e),
-     C(7a61d8f552a53442), C(821d1d8d8cfacf35), C(7cc06361b86d0559),
-     C(119b617a8c2be199), C(7a61d8f552a53442), C(821d1d8d8cfacf35),
-     C(7cc06361b86d0559), C(119b617a8c2be199), C(2996487da6721759),
-     C(61a901376070b91d), C(d88dee12ae9c9b3c), C(5665491be1fa53a7),
      C(64d41d26)},
-    {C(43c6252411ee3be), C(b4ca1b8077777168), C(2746dc3f7da1737f),
-     C(2247a4b2058d1c50), C(1b3fa184b1d7bcc0), C(deb85613995c06ed),
-     C(cbe1d957485a3ccd), C(2247a4b2058d1c50), C(1b3fa184b1d7bcc0),
-     C(deb85613995c06ed), C(cbe1d957485a3ccd), C(dfe241f8f33c96b6),
-     C(6597eb05019c2109), C(da344b2a63a219cf), C(79b8e3887612378a),
-     C(acd90c81)},
+    {C(43c6252411ee3be), C(b4ca1b8077777168), C(2746dc3f7da1737f), C(acd90c81)},
     {C(ce38a9a54fad6599), C(6d6f4a90b9e8755e), C(c3ecc79ff105de3f),
-     C(e8b9ee96efa2d0e), C(90122905c4ab5358), C(84f80c832d71979c),
-     C(229310f3ffbbf4c6), C(e8b9ee96efa2d0e), C(90122905c4ab5358),
-     C(84f80c832d71979c), C(229310f3ffbbf4c6), C(cc9eb42100cd63a7),
-     C(7a283f2f3da7b9f), C(359b061d314e7a72), C(d0d959720028862), C(7c746a4b)},
-    {C(270a9305fef70cf), C(600193999d884f3a), C(f4d49eae09ed8a1),
-     C(2e091b85660f1298), C(bfe37fae1cdd64c9), C(8dddfbab930f6494),
-     C(2ccf4b08f5d417a), C(2e091b85660f1298), C(bfe37fae1cdd64c9),
-     C(8dddfbab930f6494), C(2ccf4b08f5d417a), C(365c2ee85582fe6),
-     C(dee027bcd36db62a), C(b150994d3c7e5838), C(fdfd1a0e692e436d),
-     C(b1047e99)},
+     C(7c746a4b)},
+    {C(270a9305fef70cf), C(600193999d884f3a), C(f4d49eae09ed8a1), C(b1047e99)},
     {C(e71be7c28e84d119), C(eb6ace59932736e6), C(70c4397807ba12c5),
-     C(7a9d77781ac53509), C(4489c3ccfda3b39c), C(fa722d4f243b4964),
-     C(25f15800bffdd122), C(7a9d77781ac53509), C(4489c3ccfda3b39c),
-     C(fa722d4f243b4964), C(25f15800bffdd122), C(ed85e4157fbd3297),
-     C(aab1967227d59efd), C(2199631212eb3839), C(3e4c19359aae1cc2),
      C(d1fd1068)},
     {C(b5b58c24b53aaa19), C(d2a6ab0773dd897f), C(ef762fe01ecb5b97),
-     C(9deefbcfa4cab1f1), C(b58f5943cd2492ba), C(a96dcc4d1f4782a7),
-     C(102b62a82309dde5), C(9deefbcfa4cab1f1), C(b58f5943cd2492ba),
-     C(a96dcc4d1f4782a7), C(102b62a82309dde5), C(35fe52684763b338),
-     C(afe2616651eaad1f), C(43e38715bdfa05e7), C(83c9ba83b5ec4a40),
      C(56486077)},
     {C(44dd59bd301995cf), C(3ccabd76493ada1a), C(540db4c87d55ef23),
-     C(cfc6d7adda35797), C(14c7d1f32332cf03), C(2d553ffbff3be99d),
-     C(c91c4ee0cb563182), C(cfc6d7adda35797), C(14c7d1f32332cf03),
-     C(2d553ffbff3be99d), C(c91c4ee0cb563182), C(9aa5e507f49136f0),
-     C(760c5dd1a82c4888), C(beea7e974a1cfb5c), C(640b247774fe4bf7),
      C(6069be80)},
-    {C(b4d4789eb6f2630b), C(bf6973263ce8ef0e), C(d1c75c50844b9d3),
-     C(bce905900c1ec6ea), C(c30f304f4045487d), C(a5c550166b3a142b),
-     C(2f482b4e35327287), C(bce905900c1ec6ea), C(c30f304f4045487d),
-     C(a5c550166b3a142b), C(2f482b4e35327287), C(15b21ddddf355438),
-     C(496471fa3006bab), C(2a8fd458d06c1a32), C(db91e8ae812f0b8d), C(2078359b)},
+    {C(b4d4789eb6f2630b), C(bf6973263ce8ef0e), C(d1c75c50844b9d3), C(2078359b)},
     {C(12807833c463737c), C(58e927ea3b3776b4), C(72dd20ef1c2f8ad0),
-     C(910b610de7a967bf), C(801bc862120f6bf5), C(9653efeed5897681),
-     C(f5367ff83e9ebbb3), C(910b610de7a967bf), C(801bc862120f6bf5),
-     C(9653efeed5897681), C(f5367ff83e9ebbb3), C(cf56d489afd1b0bf),
-     C(c7c793715cae3de8), C(631f91d64abae47c), C(5f1f42fb14a444a2),
      C(9ea21004)},
     {C(e88419922b87176f), C(bcf32f41a7ddbf6f), C(d6ebefd8085c1a0f),
-     C(d1d44fe99451ef72), C(ec951ba8e51e3545), C(c0ca86b360746e96),
-     C(aa679cc066a8040b), C(d1d44fe99451ef72), C(ec951ba8e51e3545),
-     C(c0ca86b360746e96), C(aa679cc066a8040b), C(51065861ece6ffc1),
-     C(76777368a2997e11), C(87f278f46731100c), C(bbaa4140bdba4527),
      C(9c9cfe88)},
     {C(105191e0ec8f7f60), C(5918dbfcca971e79), C(6b285c8a944767b9),
-     C(d3e86ac4f5eccfa4), C(e5399df2b106ca1), C(814aadfacd217f1d),
-     C(2754e3def1c405a9), C(d3e86ac4f5eccfa4), C(e5399df2b106ca1),
-     C(814aadfacd217f1d), C(2754e3def1c405a9), C(99290323b9f06e74),
-     C(a9782e043f271461), C(13c8b3b8c275a860), C(6038d620e581e9e7),
      C(b70a6ddd)},
     {C(a5b88bf7399a9f07), C(fca3ddfd96461cc4), C(ebe738fdc0282fc6),
-     C(69afbc800606d0fb), C(6104b97a9db12df7), C(fcc09198bb90bf9f),
-     C(c5e077e41a65ba91), C(69afbc800606d0fb), C(6104b97a9db12df7),
-     C(fcc09198bb90bf9f), C(c5e077e41a65ba91), C(db261835ee8aa08e),
-     C(db0ee662e5796dc9), C(fc1880ecec499e5f), C(648866fbe1502034),
      C(dea37298)},
     {C(d08c3f5747d84f50), C(4e708b27d1b6f8ac), C(70f70fd734888606),
-     C(909ae019d761d019), C(368bf4aab1b86ef9), C(308bd616d5460239),
-     C(4fd33269f76783ea), C(909ae019d761d019), C(368bf4aab1b86ef9),
-     C(308bd616d5460239), C(4fd33269f76783ea), C(7d53b37c19713eab),
-     C(6bba6eabda58a897), C(91abb50efc116047), C(4e902f347e0e0e35),
      C(8f480819)},
-    {C(2f72d12a40044b4b), C(889689352fec53de), C(f03e6ad87eb2f36),
-     C(ef79f28d874b9e2d), C(b512089e8e63b76c), C(24dc06833bf193a9),
-     C(3c23308ba8e99d7e), C(ef79f28d874b9e2d), C(b512089e8e63b76c),
-     C(24dc06833bf193a9), C(3c23308ba8e99d7e), C(5ceff7b85cacefb7),
-     C(ef390338898cd73), C(b12967d7d2254f54), C(de874cbd8aef7b75), C(30b3b16)},
+    {C(2f72d12a40044b4b), C(889689352fec53de), C(f03e6ad87eb2f36), C(30b3b16)},
     {C(aa1f61fdc5c2e11e), C(c2c56cd11277ab27), C(a1e73069fdf1f94f),
-     C(8184bab36bb79df0), C(c81929ce8655b940), C(301b11bf8a4d8ce8),
-     C(73126fd45ab75de9), C(8184bab36bb79df0), C(c81929ce8655b940),
-     C(301b11bf8a4d8ce8), C(73126fd45ab75de9), C(4bd6f76e4888229a),
-     C(9aae355b54a756d5), C(ca3de9726f6e99d5), C(83f80cac5bc36852),
      C(f31bc4e8)},
     {C(9489b36fe2246244), C(3355367033be74b8), C(5f57c2277cbce516),
-     C(bc61414f9802ecaf), C(8edd1e7a50562924), C(48f4ab74a35e95f2),
-     C(cc1afcfd99a180e7), C(bc61414f9802ecaf), C(8edd1e7a50562924),
-     C(48f4ab74a35e95f2), C(cc1afcfd99a180e7), C(517dd5e3acf66110),
-     C(7dd3ad9e8978b30d), C(1f6d5dfc70de812b), C(947daaba6441aaf3),
      C(419f953b)},
     {C(358d7c0476a044cd), C(e0b7b47bcbd8854f), C(ffb42ec696705519),
-     C(d45e44c263e95c38), C(df61db53923ae3b1), C(f2bc948cc4fc027c),
-     C(8a8000c6066772a3), C(d45e44c263e95c38), C(df61db53923ae3b1),
-     C(f2bc948cc4fc027c), C(8a8000c6066772a3), C(9fd93c942d31fa17),
-     C(d7651ecebe09cbd3), C(68682cefb6a6f165), C(541eb99a2dcee40e),
      C(20e9e76d)},
     {C(b0c48df14275265a), C(9da4448975905efa), C(d716618e414ceb6d),
-     C(30e888af70df1e56), C(4bee54bd47274f69), C(178b4059e1a0afe5),
-     C(6e2c96b7f58e5178), C(30e888af70df1e56), C(4bee54bd47274f69),
-     C(178b4059e1a0afe5), C(6e2c96b7f58e5178), C(bb429d3b9275e9bc),
-     C(c198013f09cafdc6), C(ec0a6ee4fb5de348), C(744e1e8ed2eb1eb0),
      C(646f0ff8)},
     {C(daa70bb300956588), C(410ea6883a240c6d), C(f5c8239fb5673eb3),
-     C(8b1d7bb4903c105f), C(cfb1c322b73891d4), C(5f3b792b22f07297),
-     C(fd64061f8be86811), C(8b1d7bb4903c105f), C(cfb1c322b73891d4),
-     C(5f3b792b22f07297), C(fd64061f8be86811), C(1d2db712921cfc2b),
-     C(cd1b2b2f2cee18ae), C(6b6f8790dc7feb09), C(46c179efa3f0f518),
      C(eeb7eca8)},
-    {C(4ec97a20b6c4c7c2), C(5913b1cd454f29fd), C(a9629f9daf06d685),
-     C(852c9499156a8f3), C(3a180a6abfb79016), C(9fc3c4764037c3c9),
-     C(2890c42fc0d972cf), C(852c9499156a8f3), C(3a180a6abfb79016),
-     C(9fc3c4764037c3c9), C(2890c42fc0d972cf), C(1f92231d4e537651),
-     C(fab8bb07aa54b7b9), C(e05d2d771c485ed4), C(d50b34bf808ca731), C(8112bb9)},
+    {C(4ec97a20b6c4c7c2), C(5913b1cd454f29fd), C(a9629f9daf06d685), C(8112bb9)},
     {C(5c3323628435a2e8), C(1bea45ce9e72a6e3), C(904f0a7027ddb52e),
-     C(939f31de14dcdc7b), C(a68fdf4379df068), C(f169e1f0b835279d),
-     C(7498e432f9619b27), C(939f31de14dcdc7b), C(a68fdf4379df068),
-     C(f169e1f0b835279d), C(7498e432f9619b27), C(1aa2a1f11088e785),
-     C(d6ad72f45729de78), C(9a63814157c80267), C(55538e35c648e435),
      C(85a6d477)},
     {C(c1ef26bea260abdb), C(6ee423f2137f9280), C(df2118b946ed0b43),
-     C(11b87fb1b900cc39), C(e33e59b90dd815b1), C(aa6cb5c4bafae741),
-     C(739699951ca8c713), C(11b87fb1b900cc39), C(e33e59b90dd815b1),
-     C(aa6cb5c4bafae741), C(739699951ca8c713), C(2b4389a967310077),
-     C(1d5382568a31c2c9), C(55d1e787fbe68991), C(277c254bc31301e7),
      C(56f76c84)},
     {C(6be7381b115d653a), C(ed046190758ea511), C(de6a45ffc3ed1159),
-     C(a64760e4041447d0), C(e3eac49f3e0c5109), C(dd86c4d4cb6258e2),
-     C(efa9857afd046c7f), C(a64760e4041447d0), C(e3eac49f3e0c5109),
-     C(dd86c4d4cb6258e2), C(efa9857afd046c7f), C(fab793dae8246f16),
-     C(c9e3b121b31d094c), C(a2a0f55858465226), C(dba6f0ff39436344),
      C(9af45d55)},
     {C(ae3eece1711b2105), C(14fd3f4027f81a4a), C(abb7e45177d151db),
-     C(501f3e9b18861e44), C(465201170074e7d8), C(96d5c91970f2cb12),
-     C(40fd28c43506c95d), C(501f3e9b18861e44), C(465201170074e7d8),
-     C(96d5c91970f2cb12), C(40fd28c43506c95d), C(e86c4b07802aaff3),
-     C(f317d14112372a70), C(641b13e587711650), C(4915421ab1090eaa),
      C(d1c33760)},
     {C(376c28588b8fb389), C(6b045e84d8491ed2), C(4e857effb7d4e7dc),
-     C(154dd79fd2f984b4), C(f11171775622c1c3), C(1fbe30982e78e6f0),
-     C(a460a15dcf327e44), C(154dd79fd2f984b4), C(f11171775622c1c3),
-     C(1fbe30982e78e6f0), C(a460a15dcf327e44), C(f359e0900cc3d582),
-     C(7e11070447976d00), C(324e6daf276ea4b5), C(7aa6e2df0cc94fa2),
      C(c56bbf69)},
     {C(58d943503bb6748f), C(419c6c8e88ac70f6), C(586760cbf3d3d368),
-     C(b7e164979d5ccfc1), C(12cb4230d26bf286), C(f1bf910d44bd84cb),
-     C(b32c24c6a40272), C(b7e164979d5ccfc1), C(12cb4230d26bf286),
-     C(f1bf910d44bd84cb), C(b32c24c6a40272), C(11ed12e34c48c039),
-     C(b0c2538e51d0a6ac), C(4269bb773e1d553a), C(e35a9dbabd34867), C(abecfb9b)},
+     C(abecfb9b)},
     {C(dfff5989f5cfd9a1), C(bcee2e7ea3a96f83), C(681c7874adb29017),
-     C(3ff6c8ac7c36b63a), C(48bc8831d849e326), C(30b078e76b0214e2),
-     C(42954e6ad721b920), C(3ff6c8ac7c36b63a), C(48bc8831d849e326),
-     C(30b078e76b0214e2), C(42954e6ad721b920), C(f9aeb33d164b4472),
-     C(7b353b110831dbdc), C(16f64c82f44ae17b), C(b71244cc164b3b2b),
      C(8de13255)},
     {C(7fb19eb1a496e8f5), C(d49e5dfdb5c0833f), C(c0d5d7b2f7c48dc7),
-     C(1a57313a32f22dde), C(30af46e49850bf8b), C(aa0fe8d12f808f83),
-     C(443e31d70873bb6b), C(1a57313a32f22dde), C(30af46e49850bf8b),
-     C(aa0fe8d12f808f83), C(443e31d70873bb6b), C(bbeb67c49c9fdc13),
-     C(18f1e2a88f59f9d5), C(fb1b05038e5def11), C(d0450b5ce4c39c52),
      C(a98ee299)},
     {C(5dba5b0dadccdbaa), C(4ba8da8ded87fcdc), C(f693fdd25badf2f0),
-     C(e9029e6364286587), C(ae69f49ecb46726c), C(18e002679217c405),
-     C(bd6d66e85332ae9f), C(e9029e6364286587), C(ae69f49ecb46726c),
-     C(18e002679217c405), C(bd6d66e85332ae9f), C(6bf330b1c353dd2a),
-     C(74e9f2e71e3a4152), C(3f85560b50f6c413), C(d33a52a47eaed2b4),
      C(3015f556)},
     {C(688bef4b135a6829), C(8d31d82abcd54e8e), C(f95f8a30d55036d7),
-     C(3d8c90e27aa2e147), C(2ec937ce0aa236b4), C(89b563996d3a0b78),
-     C(39b02413b23c3f08), C(3d8c90e27aa2e147), C(2ec937ce0aa236b4),
-     C(89b563996d3a0b78), C(39b02413b23c3f08), C(8d475a2e64faf2d2),
-     C(48567f7dca46ecaf), C(254cda08d5f87a6d), C(ec6ae9f729c47039),
      C(5a430e29)},
     {C(d8323be05433a412), C(8d48fa2b2b76141d), C(3d346f23978336a5),
-     C(4d50c7537562033f), C(57dc7625b61dfe89), C(9723a9f4c08ad93a),
-     C(5309596f48ab456b), C(4d50c7537562033f), C(57dc7625b61dfe89),
-     C(9723a9f4c08ad93a), C(5309596f48ab456b), C(7e453088019d220f),
-     C(8776067ba6ab9714), C(67e1d06bd195de39), C(74a1a32f8994b918),
      C(2797add0)},
     {C(3b5404278a55a7fc), C(23ca0b327c2d0a81), C(a6d65329571c892c),
-     C(45504801e0e6066b), C(86e6c6d6152a3d04), C(4f3db1c53eca2952),
-     C(d24d69b3e9ef10f3), C(45504801e0e6066b), C(86e6c6d6152a3d04),
-     C(4f3db1c53eca2952), C(d24d69b3e9ef10f3), C(93a0de2219e66a70),
-     C(8932c7115ccb1f8a), C(5ef503fdf2841a8c), C(38064dd9efa80a41),
      C(27d55016)},
     {C(2a96a3f96c5e9bbc), C(8caf8566e212dda8), C(904de559ca16e45e),
-     C(f13bc2d9c2fe222e), C(be4ccec9a6cdccfd), C(37b2cbdd973a3ac9),
-     C(7b3223cd9c9497be), C(f13bc2d9c2fe222e), C(be4ccec9a6cdccfd),
-     C(37b2cbdd973a3ac9), C(7b3223cd9c9497be), C(d5904440f376f889),
-     C(62b13187699c473c), C(4751b89251f26726), C(9500d84fa3a61ba8),
      C(84945a82)},
     {C(22bebfdcc26d18ff), C(4b4d8dcb10807ba1), C(40265eee30c6b896),
-     C(3752b423073b119a), C(377dc5eb7c662bdb), C(2b9f07f93a6c25b9),
-     C(96f24ede2bdc0718), C(3752b423073b119a), C(377dc5eb7c662bdb),
-     C(2b9f07f93a6c25b9), C(96f24ede2bdc0718), C(f7699b12c31417bd),
-     C(17b366f401c58b2), C(bf60188d5f437b37), C(484436e56df17f04), C(3ef7e224)},
+     C(3ef7e224)},
     {C(627a2249ec6bbcc2), C(c0578b462a46735a), C(4974b8ee1c2d4f1f),
-     C(ebdbb918eb6d837f), C(8fb5f218dd84147c), C(c77dd1f881df2c54),
-     C(62eac298ec226dc3), C(ebdbb918eb6d837f), C(8fb5f218dd84147c),
-     C(c77dd1f881df2c54), C(62eac298ec226dc3), C(43eded83c4b60bd0),
-     C(9a0a403b5487503b), C(25f305d9147f0bda), C(3ad417f511bc1e64),
      C(35ed8dc8)},
-    {C(3abaf1667ba2f3e0), C(ee78476b5eeadc1), C(7e56ac0a6ca4f3f4),
-     C(f1b9b413df9d79ed), C(a7621b6fd02db503), C(d92f7ba9928a4ffe),
-     C(53f56babdcae96a6), C(f1b9b413df9d79ed), C(a7621b6fd02db503),
-     C(d92f7ba9928a4ffe), C(53f56babdcae96a6), C(5302b89fc48713ab),
-     C(d03e3b04dbe7a2f2), C(fa74ef8af6d376a7), C(103c8cdea1050ef2),
-     C(6a75e43d)},
+    {C(3abaf1667ba2f3e0), C(ee78476b5eeadc1), C(7e56ac0a6ca4f3f4), C(6a75e43d)},
     {C(3931ac68c5f1b2c9), C(efe3892363ab0fb0), C(40b707268337cd36),
-     C(a53a6b64b1ac85c9), C(d50e7f86ee1b832b), C(7bab08fdd26ba0a4),
-     C(7587743c18fe2475), C(a53a6b64b1ac85c9), C(d50e7f86ee1b832b),
-     C(7bab08fdd26ba0a4), C(7587743c18fe2475), C(e3b5d5d490cf5761),
-     C(dfc053f7d065edd5), C(42ffd8d5fb70129f), C(599ca38677cccdc3),
      C(235d9805)},
-    {C(b98fb0606f416754), C(46a6e5547ba99c1e), C(c909d82112a8ed2),
-     C(dbfaae9642b3205a), C(f676a1339402bcb9), C(f4f12a5b1ac11f29),
-     C(7db8bad81249dee4), C(dbfaae9642b3205a), C(f676a1339402bcb9),
-     C(f4f12a5b1ac11f29), C(7db8bad81249dee4), C(b26e46f2da95922e),
-     C(2aaedd5e12e3c611), C(a0e2d9082966074), C(c64da8a167add63d), C(f7d69572)},
+    {C(b98fb0606f416754), C(46a6e5547ba99c1e), C(c909d82112a8ed2), C(f7d69572)},
     {C(7f7729a33e58fcc4), C(2e4bc1e7a023ead4), C(e707008ea7ca6222),
-     C(47418a71800334a0), C(d10395d8fc64d8a4), C(8257a30062cb66f),
-     C(6786f9b2dc1ff18a), C(47418a71800334a0), C(d10395d8fc64d8a4),
-     C(8257a30062cb66f), C(6786f9b2dc1ff18a), C(5633f437bb2f180f),
-     C(e5a3a405737d22d6), C(ca0ff1ef6f7f0b74), C(d0ae600684b16df8),
      C(bacd0199)},
     {C(42a0aa9ce82848b3), C(57232730e6bee175), C(f89bb3f370782031),
-     C(caa33cf9b4f6619c), C(b2c8648ad49c209f), C(9e89ece0712db1c0),
-     C(101d8274a711a54b), C(caa33cf9b4f6619c), C(b2c8648ad49c209f),
-     C(9e89ece0712db1c0), C(101d8274a711a54b), C(538e79f1e70135cd),
-     C(e1f5a76f983c844e), C(653c082fd66088fc), C(1b9c9b464b654958),
      C(e428f50e)},
     {C(6b2c6d38408a4889), C(de3ef6f68fb25885), C(20754f456c203361),
-     C(941f5023c0c943f9), C(dfdeb9564fd66f24), C(2140cec706b9d406),
-     C(7b22429b131e9c72), C(941f5023c0c943f9), C(dfdeb9564fd66f24),
-     C(2140cec706b9d406), C(7b22429b131e9c72), C(94215c22eb940f45),
-     C(d28b9ed474f7249a), C(6f25e88f2fbf9f56), C(b6718f9e605b38ac),
      C(81eaaad3)},
     {C(930380a3741e862a), C(348d28638dc71658), C(89dedcfd1654ea0d),
-     C(7e7f61684080106), C(837ace9794582976), C(5ac8ca76a357eb1b),
-     C(32b58308625661fb), C(7e7f61684080106), C(837ace9794582976),
-     C(5ac8ca76a357eb1b), C(32b58308625661fb), C(c09705c4572025d9),
-     C(f9187f6af0291303), C(1c0edd8ee4b02538), C(e6cb105daa0578a), C(addbd3e3)},
+     C(addbd3e3)},
     {C(94808b5d2aa25f9a), C(cec72968128195e0), C(d9f4da2bdc1e130f),
-     C(272d8dd74f3006cc), C(ec6c2ad1ec03f554), C(4ad276b249a5d5dd),
-     C(549a22a17c0cde12), C(272d8dd74f3006cc), C(ec6c2ad1ec03f554),
-     C(4ad276b249a5d5dd), C(549a22a17c0cde12), C(602119cb824d7cde),
-     C(f4d3cef240ef35fa), C(e889895e01911bc7), C(785a7e5ac20e852b),
      C(e66dbca0)},
     {C(b31abb08ae6e3d38), C(9eb9a95cbd9e8223), C(8019e79b7ee94ea9),
-     C(7b2271a7a3248e22), C(3b4f700e5a0ba523), C(8ebc520c227206fe),
-     C(da3f861490f5d291), C(7b2271a7a3248e22), C(3b4f700e5a0ba523),
-     C(8ebc520c227206fe), C(da3f861490f5d291), C(d08a689f9f3aa60e),
-     C(547c1b97a068661f), C(4b15a67fa29172f0), C(eaf40c085191d80f),
      C(afe11fd5)},
     {C(dccb5534a893ea1a), C(ce71c398708c6131), C(fe2396315457c164),
-     C(3f1229f4d0fd96fb), C(33130aa5fa9d43f2), C(e42693d5b34e63ab),
-     C(2f4ef2be67f62104), C(3f1229f4d0fd96fb), C(33130aa5fa9d43f2),
-     C(e42693d5b34e63ab), C(2f4ef2be67f62104), C(372e5153516e37b9),
-     C(af9ec142ab12cc86), C(777920c09345e359), C(e7c4a383bef8adc6),
      C(a71a406f)},
     {C(6369163565814de6), C(8feb86fb38d08c2f), C(4976933485cc9a20),
-     C(7d3e82d5ba29a90d), C(d5983cc93a9d126a), C(37e9dfd950e7b692),
-     C(80673be6a7888b87), C(7d3e82d5ba29a90d), C(d5983cc93a9d126a),
-     C(37e9dfd950e7b692), C(80673be6a7888b87), C(57f732dc600808bc),
-     C(59477199802cc78b), C(f824810eb8f2c2de), C(c4a3437f05b3b61c),
      C(9d90eaf5)},
     {C(edee4ff253d9f9b3), C(96ef76fb279ef0ad), C(a4d204d179db2460),
-     C(1f3dcdfa513512d6), C(4dc7ec07283117e4), C(4438bae88ae28bf9),
-     C(aa7eae72c9244a0d), C(1f3dcdfa513512d6), C(4dc7ec07283117e4),
-     C(4438bae88ae28bf9), C(aa7eae72c9244a0d), C(b9aedc8d3ecc72df),
-     C(b75a8eb090a77d62), C(6b15677f9cd91507), C(51d8282cb3a9ddbf),
      C(6665db10)},
     {C(941993df6e633214), C(929bc1beca5b72c6), C(141fc52b8d55572d),
-     C(b3b782ad308f21ed), C(4f2676485041dee0), C(bfe279aed5cb4bc8),
-     C(2a62508a467a22ff), C(b3b782ad308f21ed), C(4f2676485041dee0),
-     C(bfe279aed5cb4bc8), C(2a62508a467a22ff), C(e74d29eab742385d),
-     C(56b05cd90ecfc293), C(c603728ea73f8844), C(8638fcd21bc692c4),
      C(9c977cbf)},
     {C(859838293f64cd4c), C(484403b39d44ad79), C(bf674e64d64b9339),
-     C(44d68afda9568f08), C(478568ed51ca1d65), C(679c204ad3d9e766),
-     C(b28e788878488dc1), C(44d68afda9568f08), C(478568ed51ca1d65),
-     C(679c204ad3d9e766), C(b28e788878488dc1), C(d001a84d3a84fae6),
-     C(d376958fe4cb913e), C(17435277e36c86f0), C(23657b263c347aa6),
      C(ee83ddd4)},
-    {C(c19b5648e0d9f555), C(328e47b2b7562993), C(e756b92ba4bd6a51),
-     C(c3314e362764ddb8), C(6481c084ee9ec6b5), C(ede23fb9a251771),
-     C(bd617f2643324590), C(c3314e362764ddb8), C(6481c084ee9ec6b5),
-     C(ede23fb9a251771), C(bd617f2643324590), C(d2d30c9b95e030f5),
-     C(8a517312ffc5795e), C(8b1f325033bd535e), C(3ee6e867e03f2892), C(26519cc)},
+    {C(c19b5648e0d9f555), C(328e47b2b7562993), C(e756b92ba4bd6a51), C(26519cc)},
     {C(f963b63b9006c248), C(9e9bf727ffaa00bc), C(c73bacc75b917e3a),
-     C(2c6aa706129cc54c), C(17a706f59a49f086), C(c7c1eec455217145),
-     C(6adfdc6e07602d42), C(2c6aa706129cc54c), C(17a706f59a49f086),
-     C(c7c1eec455217145), C(6adfdc6e07602d42), C(fb75fca30d848dd2),
-     C(5228c9ed14653ed4), C(953958910153b1a2), C(a430103a24f42a5d),
      C(a485a53f)},
     {C(6a8aa0852a8c1f3b), C(c8f1e5e206a21016), C(2aa554aed1ebb524),
-     C(fc3e3c322cd5d89b), C(b7e3911dc2bd4ebb), C(fcd6da5e5fae833a),
-     C(51ed3c41f87f9118), C(fc3e3c322cd5d89b), C(b7e3911dc2bd4ebb),
-     C(fcd6da5e5fae833a), C(51ed3c41f87f9118), C(f31750cbc19c420a),
-     C(186dab1abada1d86), C(ca7f88cb894b3cd7), C(2859eeb1c373790c),
      C(f62bc412)},
     {C(740428b4d45e5fb8), C(4c95a4ce922cb0a5), C(e99c3ba78feae796),
-     C(914f1ea2fdcebf5c), C(9566453c07cd0601), C(9841bf66d0462cd),
-     C(79140c1c18536aeb), C(914f1ea2fdcebf5c), C(9566453c07cd0601),
-     C(9841bf66d0462cd), C(79140c1c18536aeb), C(a963b930b05820c2),
-     C(6a7d9fa0c8c45153), C(64214c40d07cf39b), C(7057daf1d806c014),
      C(8975a436)},
-    {C(658b883b3a872b86), C(2f0e303f0f64827a), C(975337e23dc45e1),
-     C(99468a917986162b), C(7b31434aac6e0af0), C(f6915c1562c7d82f),
-     C(e4071d82a6dd71db), C(99468a917986162b), C(7b31434aac6e0af0),
-     C(f6915c1562c7d82f), C(e4071d82a6dd71db), C(5f5331f077b5d996),
-     C(7b314ba21b747a4f), C(5a73cb9521da17f5), C(12ed435fae286d86),
-     C(94ff7f41)},
-    {C(6df0a977da5d27d4), C(891dd0e7cb19508), C(fd65434a0b71e680),
-     C(8799e4740e573c50), C(9e739b52d0f341e8), C(cdfd34ba7d7b03eb),
-     C(5061812ce6c88499), C(8799e4740e573c50), C(9e739b52d0f341e8),
-     C(cdfd34ba7d7b03eb), C(5061812ce6c88499), C(612b8d8f2411dc5c),
-     C(878bd883d29c7787), C(47a846727182bb), C(ec4949508c8b3b9a), C(760aa031)},
-    {C(a900275464ae07ef), C(11f2cfda34beb4a3), C(9abf91e5a1c38e4),
-     C(8063d80ab26f3d6d), C(4177b4b9b4f0393f), C(6de42ba8672b9640),
-     C(d0bccdb72c51c18), C(8063d80ab26f3d6d), C(4177b4b9b4f0393f),
-     C(6de42ba8672b9640), C(d0bccdb72c51c18), C(af3f611b7f22cf12),
-     C(3863c41492645755), C(928c7a616a8f14f9), C(a82c78eb2eadc58b),
-     C(3bda76df)},
+    {C(658b883b3a872b86), C(2f0e303f0f64827a), C(975337e23dc45e1), C(94ff7f41)},
+    {C(6df0a977da5d27d4), C(891dd0e7cb19508), C(fd65434a0b71e680), C(760aa031)},
+    {C(a900275464ae07ef), C(11f2cfda34beb4a3), C(9abf91e5a1c38e4), C(3bda76df)},
     {C(810bc8aa0c40bcb0), C(448a019568d01441), C(f60ec52f60d3aeae),
-     C(52c44837aa6dfc77), C(15d8d8fccdd6dc5b), C(345b793ccfa93055),
-     C(932160fe802ca975), C(52c44837aa6dfc77), C(15d8d8fccdd6dc5b),
-     C(345b793ccfa93055), C(932160fe802ca975), C(a624b0dd93fc18cd),
-     C(d955b254c2037f1e), C(e540533d370a664c), C(2ba4ec12514e9d7), C(498e2e65)},
+     C(498e2e65)},
     {C(22036327deb59ed7), C(adc05ceb97026a02), C(48bff0654262672b),
-     C(c791b313aba3f258), C(443c7757a4727bee), C(e30e4b2372171bdf),
-     C(f3db986c4156f3cb), C(c791b313aba3f258), C(443c7757a4727bee),
-     C(e30e4b2372171bdf), C(f3db986c4156f3cb), C(a939aefab97c6e15),
-     C(dbeb8acf1d5b0e6c), C(1e0eab667a795bba), C(80dd539902df4d50),
      C(d38deb48)},
     {C(7d14dfa9772b00c8), C(595735efc7eeaed7), C(29872854f94c3507),
-     C(bc241579d8348401), C(16dc832804d728f0), C(e9cc71ae64e3f09e),
-     C(bef634bc978bac31), C(bc241579d8348401), C(16dc832804d728f0),
-     C(e9cc71ae64e3f09e), C(bef634bc978bac31), C(7f64b1fa2a9129e),
-     C(71d831bd530ac7f3), C(c7ad0a8a6d5be6f1), C(82a7d3a815c7aaab),
      C(82b3fb6b)},
     {C(2d777cddb912675d), C(278d7b10722a13f9), C(f5c02bfb7cc078af),
-     C(4283001239888836), C(f44ca39a6f79db89), C(ed186122d71bcc9f),
-     C(8620017ab5f3ba3b), C(4283001239888836), C(f44ca39a6f79db89),
-     C(ed186122d71bcc9f), C(8620017ab5f3ba3b), C(e787472187f176c),
-     C(267e64c4728cf181), C(f1ba4b3007c15e30), C(8e3a75d5b02ecfc0),
      C(e500e25f)},
     {C(f2ec98824e8aa613), C(5eb7e3fb53fe3bed), C(12c22860466e1dd4),
-     C(374dd4288e0b72e5), C(ff8916db706c0df4), C(cb1a9e85de5e4b8d),
-     C(d4d12afb67a27659), C(374dd4288e0b72e5), C(ff8916db706c0df4),
-     C(cb1a9e85de5e4b8d), C(d4d12afb67a27659), C(feb69095d1ba175a),
-     C(e2003aab23a47fad), C(8163a3ecab894b49), C(46d356674ce041f6),
      C(bd2bb07c)},
     {C(5e763988e21f487f), C(24189de8065d8dc5), C(d1519d2403b62aa0),
-     C(9136456740119815), C(4d8ff7733b27eb83), C(ea3040bc0c717ef8),
-     C(7617ab400dfadbc), C(9136456740119815), C(4d8ff7733b27eb83),
-     C(ea3040bc0c717ef8), C(7617ab400dfadbc), C(fb336770c10b17a1),
-     C(6123b68b5b31f151), C(1e147d5f295eccf2), C(9ecbb1333556f977),
      C(3a2b431d)},
     {C(48949dc327bb96ad), C(e1fd21636c5c50b4), C(3f6eb7f13a8712b4),
-     C(14cf7f02dab0eee8), C(6d01750605e89445), C(4f1cf4006e613b78),
-     C(57c40c4db32bec3b), C(14cf7f02dab0eee8), C(6d01750605e89445),
-     C(4f1cf4006e613b78), C(57c40c4db32bec3b), C(1fde5a347f4a326e),
-     C(cb5a54308adb0e3f), C(14994b2ba447a23c), C(7067d0abb4257b68),
      C(7322a83d)},
     {C(b7c4209fb24a85c5), C(b35feb319c79ce10), C(f0d3de191833b922),
-     C(570d62758ddf6397), C(5e0204fb68a7b800), C(4383a9236f8b5a2b),
-     C(7bc1a64641d803a4), C(570d62758ddf6397), C(5e0204fb68a7b800),
-     C(4383a9236f8b5a2b), C(7bc1a64641d803a4), C(5434d61285099f7a),
-     C(d49449aacdd5dd67), C(97855ba0e9a7d75d), C(da67328062f3a62f),
      C(a645ca1c)},
     {C(9c9e5be0943d4b05), C(b73dc69e45201cbb), C(aab17180bfe5083d),
-     C(c738a77a9a55f0e2), C(705221addedd81df), C(fd9bd8d397abcfa3),
-     C(8ccf0004aa86b795), C(c738a77a9a55f0e2), C(705221addedd81df),
-     C(fd9bd8d397abcfa3), C(8ccf0004aa86b795), C(2bb5db2280068206),
-     C(8c22d29f307a01d), C(274a22de02f473c8), C(b8791870f4268182), C(8909a45a)},
+     C(8909a45a)},
     {C(3898bca4dfd6638d), C(f911ff35efef0167), C(24bdf69e5091fc88),
-     C(9b82567ab6560796), C(891b69462b41c224), C(8eccc7e4f3af3b51),
-     C(381e54c3c8f1c7d0), C(9b82567ab6560796), C(891b69462b41c224),
-     C(8eccc7e4f3af3b51), C(381e54c3c8f1c7d0), C(c80fbc489a558a55),
-     C(1ba88e062a663af7), C(af7b1ef1c0116303), C(bd20e1a5a6b1a0cd),
      C(bd30074c)},
-    {C(5b5d2557400e68e7), C(98d610033574cee), C(dfd08772ce385deb),
-     C(3c13e894365dc6c2), C(26fc7bbcda3f0ef), C(dbb71106cdbfea36),
-     C(785239a742c6d26d), C(3c13e894365dc6c2), C(26fc7bbcda3f0ef),
-     C(dbb71106cdbfea36), C(785239a742c6d26d), C(f810c415ae05b2f4),
-     C(bb9b9e7398526088), C(70128f1bf830a32b), C(bcc73f82b6410899),
-     C(c17cf001)},
+    {C(5b5d2557400e68e7), C(98d610033574cee), C(dfd08772ce385deb), C(c17cf001)},
     {C(a927ed8b2bf09bb6), C(606e52f10ae94eca), C(71c2203feb35a9ee),
-     C(6e65ec14a8fb565), C(34bff6f2ee5a7f79), C(2e329a5be2c011b),
-     C(73161c93331b14f9), C(6e65ec14a8fb565), C(34bff6f2ee5a7f79),
-     C(2e329a5be2c011b), C(73161c93331b14f9), C(15d13f2408aecf88),
-     C(9f5b61b8a4b55b31), C(8fe25a43b296dba6), C(bdad03b7300f284e),
      C(26ffd25a)},
     {C(8d25746414aedf28), C(34b1629d28b33d3a), C(4d5394aea5f82d7b),
-     C(379f76458a3c8957), C(79dd080f9843af77), C(c46f0a7847f60c1d),
-     C(af1579c5797703cc), C(379f76458a3c8957), C(79dd080f9843af77),
-     C(c46f0a7847f60c1d), C(af1579c5797703cc), C(8b7d31f338755c14),
-     C(2eff97679512aaa8), C(df07d68e075179ed), C(c8fa6c7a729e7f1f),
      C(f1d8ce3c)},
     {C(b5bbdb73458712f2), C(1ff887b3c2a35137), C(7f7231f702d0ace9),
-     C(1e6f0910c3d25bd8), C(ad9e250862102467), C(1c842a07abab30cd),
-     C(cd8124176bac01ac), C(1e6f0910c3d25bd8), C(ad9e250862102467),
-     C(1c842a07abab30cd), C(cd8124176bac01ac), C(ea6ebe7a79b67edc),
-     C(73f598ac9db26713), C(4f4e72d7460b8fc), C(365dc4b9fdf13f21), C(3ee8fb17)},
+     C(3ee8fb17)},
     {C(3d32a26e3ab9d254), C(fc4070574dc30d3a), C(f02629579c2b27c9),
-     C(b1cf09b0184a4834), C(5c03db48eb6cc159), C(f18c7fcf34d1df47),
-     C(dfb043419ecf1fa9), C(b1cf09b0184a4834), C(5c03db48eb6cc159),
-     C(f18c7fcf34d1df47), C(dfb043419ecf1fa9), C(dcd78d13f9ca658f),
-     C(4355d408ffe8e49f), C(81eefee908b593b4), C(590c213c20e981a3),
      C(a77acc2a)},
-    {C(9371d3c35fa5e9a5), C(42967cf4d01f30), C(652d1eeae704145c),
-     C(ceaf1a0d15234f15), C(1450a54e45ba9b9), C(65e9c1fd885aa932),
-     C(354d4bc034ba8cbe), C(ceaf1a0d15234f15), C(1450a54e45ba9b9),
-     C(65e9c1fd885aa932), C(354d4bc034ba8cbe), C(8fd4ff484c08fb4b),
-     C(bf46749866f69ba0), C(cf1c21ede82c9477), C(4217548c43da109), C(f4556dee)},
-    {C(cbaa3cb8f64f54e0), C(76c3b48ee5c08417), C(9f7d24e87e61ce9),
-     C(85b8e53f22e19507), C(bb57137739ca486b), C(c77f131cca38f761),
-     C(c56ac3cf275be121), C(85b8e53f22e19507), C(bb57137739ca486b),
-     C(c77f131cca38f761), C(c56ac3cf275be121), C(9ec1a6c9109d2685),
-     C(3dad0922e76afdb0), C(fd58cbf952958103), C(7b04c908e78639a1),
-     C(de287a64)},
+    {C(9371d3c35fa5e9a5), C(42967cf4d01f30), C(652d1eeae704145c), C(f4556dee)},
+    {C(cbaa3cb8f64f54e0), C(76c3b48ee5c08417), C(9f7d24e87e61ce9), C(de287a64)},
     {C(b2e23e8116c2ba9f), C(7e4d9c0060101151), C(3310da5e5028f367),
-     C(adc52dddb76f6e5e), C(4aad4e925a962b68), C(204b79b7f7168e64),
-     C(df29ed6671c36952), C(adc52dddb76f6e5e), C(4aad4e925a962b68),
-     C(204b79b7f7168e64), C(df29ed6671c36952), C(e02927cac396d210),
-     C(5d500e71742b638a), C(5c9998af7f27b124), C(3fba9a2573dc2f7), C(878e55b9)},
-    {C(8aa77f52d7868eb9), C(4d55bd587584e6e2), C(d2db37041f495f5),
-     C(ce030d15b5fe2f4), C(86b4a7a0780c2431), C(ee070a9ae5b51db7),
-     C(edc293d9595be5d8), C(ce030d15b5fe2f4), C(86b4a7a0780c2431),
-     C(ee070a9ae5b51db7), C(edc293d9595be5d8), C(3dfc5ec108260a2b),
-     C(8afe28c7123bf4e2), C(da82ef38023a7a5f), C(3e1f77b0174b77c3), C(7648486)},
+     C(878e55b9)},
+    {C(8aa77f52d7868eb9), C(4d55bd587584e6e2), C(d2db37041f495f5), C(7648486)},
     {C(858fea922c7fe0c3), C(cfe8326bf733bc6f), C(4e5e2018cf8f7dfc),
-     C(64fd1bc011e5bab7), C(5c9e858728015568), C(97ac42c2b00b29b1),
-     C(7f89caf08c109aee), C(64fd1bc011e5bab7), C(5c9e858728015568),
-     C(97ac42c2b00b29b1), C(7f89caf08c109aee), C(9a8af34fd0e9dacf),
-     C(bbc54161aa1507e0), C(7cda723ccbbfe5ee), C(2c289d839fb93f58),
      C(57ac0fb1)},
     {C(46ef25fdec8392b1), C(e48d7b6d42a5cd35), C(56a6fe1c175299ca),
-     C(fdfa836b41dcef62), C(2f8db8030e847e1b), C(5ba0a49ac4f9b0f8),
-     C(dae897ed3e3fce44), C(fdfa836b41dcef62), C(2f8db8030e847e1b),
-     C(5ba0a49ac4f9b0f8), C(dae897ed3e3fce44), C(9c432e31aef626e7),
-     C(9a36e1c6cd6e3dd), C(5095a167c34d19d), C(a70005cfa6babbea), C(d01967ca)},
+     C(d01967ca)},
     {C(8d078f726b2df464), C(b50ee71cdcabb299), C(f4af300106f9c7ba),
-     C(7d222caae025158a), C(cc028d5fd40241b9), C(dd42515b639e6f97),
-     C(e08e86531a58f87f), C(7d222caae025158a), C(cc028d5fd40241b9),
-     C(dd42515b639e6f97), C(e08e86531a58f87f), C(d93612c835b37d7b),
-     C(91dd61729b2fa7f4), C(ba765a1bdda09db7), C(55258b451b2b1297),
      C(96ecdf74)},
     {C(35ea86e6960ca950), C(34fe1fe234fc5c76), C(a00207a3dc2a72b7),
-     C(80395e48739e1a67), C(74a67d8f7f43c3d7), C(dd2bdd1d62246c6e),
-     C(a1f44298ba80acf6), C(80395e48739e1a67), C(74a67d8f7f43c3d7),
-     C(dd2bdd1d62246c6e), C(a1f44298ba80acf6), C(ad86d86c187bf38),
-     C(26feea1f2eee240d), C(ed7f1fd066b23897), C(a768cf1e0fbb502), C(779f5506)},
+     C(779f5506)},
     {C(8aee9edbc15dd011), C(51f5839dc8462695), C(b2213e17c37dca2d),
-     C(133b299a939745c5), C(796e2aac053f52b3), C(e8d9fe1521a4a222),
-     C(819a8863e5d1c290), C(133b299a939745c5), C(796e2aac053f52b3),
-     C(e8d9fe1521a4a222), C(819a8863e5d1c290), C(c0737f0fe34d36ad),
-     C(e6d6d4a267a5cc31), C(98300a7911674c23), C(bef189661c257098),
      C(3c94c2de)},
     {C(c3e142ba98432dda), C(911d060cab126188), C(b753fbfa8365b844),
-     C(fd1a9ba5e71b08a2), C(7ac0dc2ed7778533), C(b543161ff177188a),
-     C(492fc08a6186f3f4), C(fd1a9ba5e71b08a2), C(7ac0dc2ed7778533),
-     C(b543161ff177188a), C(492fc08a6186f3f4), C(fc4745f516afd3b6),
-     C(88c30370a53080e), C(65a1bb34abc465e2), C(abbd14662911c8b3), C(39f98faf)},
+     C(39f98faf)},
     {C(123ba6b99c8cd8db), C(448e582672ee07c4), C(cebe379292db9e65),
-     C(938f5bbab544d3d6), C(d2a95f9f2d376d73), C(68b2f16149e81aa3),
-     C(ad7e32f82d86c79d), C(938f5bbab544d3d6), C(d2a95f9f2d376d73),
-     C(68b2f16149e81aa3), C(ad7e32f82d86c79d), C(4574015ae8626ce2),
-     C(455aa6137386a582), C(658ad2542e8ec20), C(e31d7be2ca35d00), C(7af31199)},
+     C(7af31199)},
     {C(ba87acef79d14f53), C(b3e0fcae63a11558), C(d5ac313a593a9f45),
-     C(eea5f5a9f74af591), C(578710bcc36fbea2), C(7a8393432188931d),
-     C(705cfc5ec7cc172), C(eea5f5a9f74af591), C(578710bcc36fbea2),
-     C(7a8393432188931d), C(705cfc5ec7cc172), C(da85ebe5fc427976),
-     C(bfa5c7a454df54c8), C(4632b72a81bf66d2), C(5dd72877db539ee2),
      C(e341a9d6)},
-    {C(bcd3957d5717dc3), C(2da746741b03a007), C(873816f4b1ece472),
-     C(2b826f1a2c08c289), C(da50f56863b55e74), C(b18712f6b3eed83b),
-     C(bdc7cc05ab4c685f), C(2b826f1a2c08c289), C(da50f56863b55e74),
-     C(b18712f6b3eed83b), C(bdc7cc05ab4c685f), C(9e45fb833d1b0af),
-     C(d7213081db29d82e), C(d2a6b6c6a09ed55e), C(98a7686cba323ca9),
-     C(ca24aeeb)},
+    {C(bcd3957d5717dc3), C(2da746741b03a007), C(873816f4b1ece472), C(ca24aeeb)},
     {C(61442ff55609168e), C(6447c5fc76e8c9cf), C(6a846de83ae15728),
-     C(effc2663cffc777f), C(93214f8f463afbed), C(a156ef06066f4e4e),
-     C(a407b6ed8769d51e), C(effc2663cffc777f), C(93214f8f463afbed),
-     C(a156ef06066f4e4e), C(a407b6ed8769d51e), C(bb2f9ed29745c02a),
-     C(981eecd435b36ad9), C(461a5a05fb9cdff4), C(bd6cb2a87b9f910c),
      C(b2252b57)},
-    {C(dbe4b1b2d174757f), C(506512da18712656), C(6857f3e0b8dd95f),
-     C(5a4fc2728a9bb671), C(ebb971522ec38759), C(1a5a093e6cf1f72b),
-     C(729b057fe784f504), C(5a4fc2728a9bb671), C(ebb971522ec38759),
-     C(1a5a093e6cf1f72b), C(729b057fe784f504), C(71fcbf42a767f9cf),
-     C(114cfe772da6cdd), C(60cdf9cb629d9d7a), C(e270d10ad088b24e), C(72c81da1)},
+    {C(dbe4b1b2d174757f), C(506512da18712656), C(6857f3e0b8dd95f), C(72c81da1)},
     {C(531e8e77b363161c), C(eece0b43e2dae030), C(8294b82c78f34ed1),
-     C(e777b1fd580582f2), C(7b880f58da112699), C(562c6b189a6333f4),
-     C(139d64f88a611d4), C(e777b1fd580582f2), C(7b880f58da112699),
-     C(562c6b189a6333f4), C(139d64f88a611d4), C(53d8ef17eda64fa4),
-     C(bf3eded14dc60a04), C(2b5c559cf5ec07c5), C(8895f7339d03a48a),
      C(6b9fce95)},
     {C(f71e9c926d711e2b), C(d77af2853a4ceaa1), C(9aa0d6d76a36fae7),
-     C(dd16cd0fbc08393), C(29a414a5d8c58962), C(72793d8d1022b5b2),
-     C(2e8e69cf7cbffdf0), C(dd16cd0fbc08393), C(29a414a5d8c58962),
-     C(72793d8d1022b5b2), C(2e8e69cf7cbffdf0), C(3721c0473aa99c9a),
-     C(1cff4ed9c31cd91c), C(4990735033cc482b), C(7fdf8c701c72f577),
      C(19399857)},
     {C(cb20ac28f52df368), C(e6705ee7880996de), C(9b665cc3ec6972f2),
-     C(4260e8c254e9924b), C(f197a6eb4591572d), C(8e867ff0fb7ab27c),
-     C(f95502fb503efaf3), C(4260e8c254e9924b), C(f197a6eb4591572d),
-     C(8e867ff0fb7ab27c), C(f95502fb503efaf3), C(30c41876b08e3e22),
-     C(958e2419e3cd22f4), C(f0f3aa1fe119a107), C(481662310a379100),
      C(3c57a994)},
     {C(e4a794b4acb94b55), C(89795358057b661b), C(9c4cdcec176d7a70),
-     C(4890a83ee435bc8b), C(d8c1c00fceb00914), C(9e7111ba234f900f),
-     C(eb8dbab364d8b604), C(4890a83ee435bc8b), C(d8c1c00fceb00914),
-     C(9e7111ba234f900f), C(eb8dbab364d8b604), C(b3261452963eebb),
-     C(6cf94b02792c4f95), C(d88fa815ef1e8fc), C(2d687af66604c73), C(c053e729)},
+     C(c053e729)},
     {C(cb942e91443e7208), C(e335de8125567c2a), C(d4d74d268b86df1f),
-     C(8ba0fdd2ffc8b239), C(f413b366c1ffe02f), C(c05b2717c59a8a28),
-     C(981188eab4fcc8fb), C(8ba0fdd2ffc8b239), C(f413b366c1ffe02f),
-     C(c05b2717c59a8a28), C(981188eab4fcc8fb), C(e563f49a1d9072ba),
-     C(3c6a3aa4a26367dc), C(ba0db13448653f34), C(31065d756074d7d6),
      C(51cbbba7)},
     {C(ecca7563c203f7ba), C(177ae2423ef34bb2), C(f60b7243400c5731),
-     C(cf1edbfe7330e94e), C(881945906bcb3cc6), C(4acf0293244855da),
-     C(65ae042c1c2a28c2), C(cf1edbfe7330e94e), C(881945906bcb3cc6),
-     C(4acf0293244855da), C(65ae042c1c2a28c2), C(b25fa0a1cab33559),
-     C(d98e8daa28124131), C(fce17f50b9c351b3), C(3f995ccf7386864b),
      C(1acde79a)},
     {C(1652cb940177c8b5), C(8c4fe7d85d2a6d6d), C(f6216ad097e54e72),
-     C(f6521b912b368ae6), C(a9fe4eff81d03e73), C(d6f623629f80d1a3),
-     C(2b9604f32cb7dc34), C(f6521b912b368ae6), C(a9fe4eff81d03e73),
-     C(d6f623629f80d1a3), C(2b9604f32cb7dc34), C(2a43d84dcf59c7e2),
-     C(d0a197c70c5dae0b), C(6e84d4bbc71d76a0), C(c7e94620378c6cb2),
      C(2d160d13)},
     {C(31fed0fc04c13ce8), C(3d5d03dbf7ff240a), C(727c5c9b51581203),
-     C(6b5ffc1f54fecb29), C(a8e8e7ad5b9a21d9), C(c4d5a32cd6aac22d),
-     C(d7e274ad22d4a79a), C(6b5ffc1f54fecb29), C(a8e8e7ad5b9a21d9),
-     C(c4d5a32cd6aac22d), C(d7e274ad22d4a79a), C(368841ea5731a112),
-     C(feaf7bc2e73ca48f), C(636fb272e9ea1f6), C(5d9cb7580c3f6207), C(787f5801)},
+     C(787f5801)},
     {C(e7b668947590b9b3), C(baa41ad32938d3fa), C(abcbc8d4ca4b39e4),
-     C(381ee1b7ea534f4e), C(da3759828e3de429), C(3e015d76729f9955),
-     C(cbbec51a6485fbde), C(381ee1b7ea534f4e), C(da3759828e3de429),
-     C(3e015d76729f9955), C(cbbec51a6485fbde), C(9b86605281f20727),
-     C(fc6fcf508676982a), C(3b135f7a813a1040), C(d3a4706bea1db9c9),
      C(c9629828)},
     {C(1de2119923e8ef3c), C(6ab27c096cf2fe14), C(8c3658edca958891),
-     C(4cc8ed3ada5f0f2), C(4a496b77c1f1c04e), C(9085b0a862084201),
-     C(a1894bde9e3dee21), C(4cc8ed3ada5f0f2), C(4a496b77c1f1c04e),
-     C(9085b0a862084201), C(a1894bde9e3dee21), C(367fb472dc5b277d),
-     C(7d39ccca16fc6745), C(763f988d70db9106), C(a8b66f7fecb70f02),
      C(be139231)},
     {C(1269df1e69e14fa7), C(992f9d58ac5041b7), C(e97fcf695a7cbbb4),
-     C(e5d0549802d15008), C(424c134ecd0db834), C(6fc44fd91be15c6c),
-     C(a1a5ef95d50e537d), C(e5d0549802d15008), C(424c134ecd0db834),
-     C(6fc44fd91be15c6c), C(a1a5ef95d50e537d), C(d1e3daf5d05f5308),
-     C(4c7f81600eaa1327), C(109d1b8d1f9d0d2b), C(871e8699e0aeb862),
      C(7df699ef)},
     {C(820826d7aba567ff), C(1f73d28e036a52f3), C(41c4c5a73f3b0893),
-     C(aa0d74d4a98db89b), C(36fd486d07c56e1d), C(d0ad23cbb6660d8a),
-     C(1264a84665b35e19), C(aa0d74d4a98db89b), C(36fd486d07c56e1d),
-     C(d0ad23cbb6660d8a), C(1264a84665b35e19), C(789682bf7d781b33),
-     C(6bfa6abd2fb5722d), C(6779cb3623d33900), C(435ca5214e1ee5f0),
      C(8ce6b96d)},
     {C(ffe0547e4923cef9), C(3534ed49b9da5b02), C(548a273700fba03d),
-     C(28ac84ca70958f7e), C(d8ae575a68faa731), C(2aaaee9b9dcffd4c),
-     C(6c7faab5c285c6da), C(28ac84ca70958f7e), C(d8ae575a68faa731),
-     C(2aaaee9b9dcffd4c), C(6c7faab5c285c6da), C(45d94235f99ba78f),
-     C(ab5ea16f39497f5b), C(fb4d6c86fccbdca3), C(8104e6310a5fd2c7),
      C(6f9ed99c)},
     {C(72da8d1b11d8bc8b), C(ba94b56b91b681c6), C(4e8cc51bd9b0fc8c),
-     C(43505ed133be672a), C(e8f2f9d973c2774e), C(677b9b9c7cad6d97),
-     C(4e1f5d56ef17b906), C(43505ed133be672a), C(e8f2f9d973c2774e),
-     C(677b9b9c7cad6d97), C(4e1f5d56ef17b906), C(eea3a6038f983767),
-     C(87109f077f86db01), C(ecc1ca41f74d61cc), C(34a87e86e83bed17),
      C(e0244796)},
-    {C(d62ab4e3f88fc797), C(ea86c7aeb6283ae4), C(b5b93e09a7fe465),
-     C(4344a1a0134afe2), C(ff5c17f02b62341d), C(3214c6a587ce4644),
-     C(a905e7ed0629d05c), C(4344a1a0134afe2), C(ff5c17f02b62341d),
-     C(3214c6a587ce4644), C(a905e7ed0629d05c), C(b5c72690cd716e82),
-     C(7c6097649e6ebe7b), C(7ceee8c6e56a4dcd), C(80ca849dc53eb9e4),
-     C(4ccf7e75)},
+    {C(d62ab4e3f88fc797), C(ea86c7aeb6283ae4), C(b5b93e09a7fe465), C(4ccf7e75)},
     {C(d0f06c28c7b36823), C(1008cb0874de4bb8), C(d6c7ff816c7a737b),
-     C(489b697fe30aa65f), C(4da0fb621fdc7817), C(dc43583b82c58107),
-     C(4b0261debdec3cd6), C(489b697fe30aa65f), C(4da0fb621fdc7817),
-     C(dc43583b82c58107), C(4b0261debdec3cd6), C(a9748d7b6c0e016c),
-     C(7e8828f7ba4b034b), C(da0fa54348a2512a), C(ebf9745c0962f9ad),
      C(915cef86)},
     {C(99b7042460d72ec6), C(2a53e5e2b8e795c2), C(53a78132d9e1b3e3),
-     C(c043e67e6fc64118), C(ff0abfe926d844d3), C(f2a9fe5db2e910fe),
-     C(ce352cdc84a964dd), C(c043e67e6fc64118), C(ff0abfe926d844d3),
-     C(f2a9fe5db2e910fe), C(ce352cdc84a964dd), C(b89bc028aa5e6063),
-     C(a354e7fdac04459c), C(68d6547e6e980189), C(c968dddfd573773e),
      C(5cb59482)},
-    {C(4f4dfcfc0ec2bae5), C(841233148268a1b8), C(9248a76ab8be0d3),
-     C(334c5a25b5903a8c), C(4c94fef443122128), C(743e7d8454655c40),
-     C(1ab1e6d1452ae2cd), C(334c5a25b5903a8c), C(4c94fef443122128),
-     C(743e7d8454655c40), C(1ab1e6d1452ae2cd), C(fec766de4a8e476c),
-     C(cc0929da9567e71b), C(5f9ef5b5f150c35a), C(87659cabd649768f),
-     C(6ca3f532)},
+    {C(4f4dfcfc0ec2bae5), C(841233148268a1b8), C(9248a76ab8be0d3), C(6ca3f532)},
     {C(fe86bf9d4422b9ae), C(ebce89c90641ef9c), C(1c84e2292c0b5659),
-     C(8bde625a10a8c50d), C(eb8271ded1f79a0b), C(14dc6844f0de7a3c),
-     C(f85b2f9541e7e6da), C(8bde625a10a8c50d), C(eb8271ded1f79a0b),
-     C(14dc6844f0de7a3c), C(f85b2f9541e7e6da), C(2fe22cfd1683b961),
-     C(ea1d75c5b7aa01ca), C(9eef60a44876bb95), C(950c818e505c6f7f),
      C(e24f3859)},
     {C(a90d81060932dbb0), C(8acfaa88c5fbe92b), C(7c6f3447e90f7f3f),
-     C(dd52fc14c8dd3143), C(1bc7508516e40628), C(3059730266ade626),
-     C(ffa526822f391c2), C(dd52fc14c8dd3143), C(1bc7508516e40628),
-     C(3059730266ade626), C(ffa526822f391c2), C(e25232d7afc8a406),
-     C(d2b8a5a3f3b5f670), C(6630f33edb7dfe32), C(c71250ba68c4ea86),
      C(adf5a9c7)},
     {C(17938a1b0e7f5952), C(22cadd2f56f8a4be), C(84b0d1183d5ed7c1),
-     C(c1336b92fef91bf6), C(80332a3945f33fa9), C(a0f68b86f726ff92),
-     C(a3db5282cf5f4c0b), C(c1336b92fef91bf6), C(80332a3945f33fa9),
-     C(a0f68b86f726ff92), C(a3db5282cf5f4c0b), C(82640b6fc4916607),
-     C(2dc2a3aa1a894175), C(8b4c852bdee7cc9), C(10b9d0a08b55ff83), C(32264b75)},
+     C(32264b75)},
     {C(de9e0cb0e16f6e6d), C(238e6283aa4f6594), C(4fb9c914c2f0a13b),
-     C(497cb912b670f3b), C(d963a3f02ff4a5b6), C(4fccefae11b50391),
-     C(42ba47db3f7672f), C(497cb912b670f3b), C(d963a3f02ff4a5b6),
-     C(4fccefae11b50391), C(42ba47db3f7672f), C(1d6b655a1889feef),
-     C(5f319abf8fafa19f), C(715c2e49deb14620), C(8d9153082ecdcea4),
      C(a64b3376)},
-    {C(6d4b876d9b146d1a), C(aab2d64ce8f26739), C(d315f93600e83fe5),
-     C(2fe9fabdbe7fdd4), C(755db249a2d81a69), C(f27929f360446d71),
-     C(79a1bf957c0c1b92), C(2fe9fabdbe7fdd4), C(755db249a2d81a69),
-     C(f27929f360446d71), C(79a1bf957c0c1b92), C(3c8a28d4c936c9cd),
-     C(df0d3d13b2c6a902), C(c76702dd97cd2edd), C(1aa220f7be16517), C(d33890e)},
+    {C(6d4b876d9b146d1a), C(aab2d64ce8f26739), C(d315f93600e83fe5), C(d33890e)},
     {C(e698fa3f54e6ea22), C(bd28e20e7455358c), C(9ace161f6ea76e66),
-     C(d53fb7e3c93a9e4), C(737ae71b051bf108), C(7ac71feb84c2df42),
-     C(3d8075cd293a15b4), C(d53fb7e3c93a9e4), C(737ae71b051bf108),
-     C(7ac71feb84c2df42), C(3d8075cd293a15b4), C(bf8cee5e095d8a7c),
-     C(e7086b3c7608143a), C(e55b0c2fa938d70c), C(fffb5f58e643649c),
      C(926d4b63)},
     {C(7bc0deed4fb349f7), C(1771aff25dc722fa), C(19ff0644d9681917),
-     C(cf7d7f25bd70cd2c), C(9464ed9baeb41b4f), C(b9064f5c3cb11b71),
-     C(237e39229b012b20), C(cf7d7f25bd70cd2c), C(9464ed9baeb41b4f),
-     C(b9064f5c3cb11b71), C(237e39229b012b20), C(dd54d3f5d982dffe),
-     C(7fc7562dbfc81dbf), C(5b0dd1924f70945), C(f1760537d8261135), C(d51ba539)},
+     C(d51ba539)},
     {C(db4b15e88533f622), C(256d6d2419b41ce9), C(9d7c5378396765d5),
-     C(9040e5b936b8661b), C(276e08fa53ac27fd), C(8c944d39c2bdd2cc),
-     C(e2514c9802a5743c), C(9040e5b936b8661b), C(276e08fa53ac27fd),
-     C(8c944d39c2bdd2cc), C(e2514c9802a5743c), C(e82107b11ac90386),
-     C(7d6a22bc35055e6), C(fd6ea9d1c438d8ae), C(be6015149e981553), C(7f37636d)},
+     C(7f37636d)},
     {C(922834735e86ecb2), C(363382685b88328e), C(e9c92960d7144630),
-     C(8431b1bfd0a2379c), C(90383913aea283f9), C(a6163831eb4924d2),
-     C(5f3921b4f9084aee), C(8431b1bfd0a2379c), C(90383913aea283f9),
-     C(a6163831eb4924d2), C(5f3921b4f9084aee), C(7a70061a1473e579),
-     C(5b19d80dcd2c6331), C(6196b97931faad27), C(869bf6828e237c3f),
      C(b98026c0)},
     {C(30f1d72c812f1eb8), C(b567cd4a69cd8989), C(820b6c992a51f0bc),
-     C(c54677a80367125e), C(3204fbdba462e606), C(8563278afc9eae69),
-     C(262147dd4bf7e566), C(c54677a80367125e), C(3204fbdba462e606),
-     C(8563278afc9eae69), C(262147dd4bf7e566), C(2178b63e7ee2d230),
-     C(e9c61ad81f5bff26), C(9af7a81b3c501eca), C(44104a3859f0238f),
      C(b877767e)},
-    {C(168884267f3817e9), C(5b376e050f637645), C(1c18314abd34497a),
-     C(9598f6ab0683fcc2), C(1c805abf7b80e1ee), C(dec9ac42ee0d0f32),
-     C(8cd72e3912d24663), C(9598f6ab0683fcc2), C(1c805abf7b80e1ee),
-     C(dec9ac42ee0d0f32), C(8cd72e3912d24663), C(1f025d405f1c1d87),
-     C(bf7b6221e1668f8f), C(52316f64e692dbb0), C(7bf43df61ec51b39), C(aefae77)},
-    {C(82e78596ee3e56a7), C(25697d9c87f30d98), C(7600a8342834924d),
-     C(6ba372f4b7ab268b), C(8c3237cf1fe243df), C(3833fc51012903df),
-     C(8e31310108c5683f), C(6ba372f4b7ab268b), C(8c3237cf1fe243df),
-     C(3833fc51012903df), C(8e31310108c5683f), C(126593715c2de429),
-     C(48ca8f35a3f54b90), C(b9322b632f4f8b0), C(926bb169b7337693), C(f686911)},
+    {C(168884267f3817e9), C(5b376e050f637645), C(1c18314abd34497a), C(aefae77)},
+    {C(82e78596ee3e56a7), C(25697d9c87f30d98), C(7600a8342834924d), C(f686911)},
     {C(aa2d6cf22e3cc252), C(9b4dec4f5e179f16), C(76fb0fba1d99a99a),
-     C(9a62af3dbba140da), C(27857ea044e9dfc1), C(33abce9da2272647),
-     C(b22a7993aaf32556), C(9a62af3dbba140da), C(27857ea044e9dfc1),
-     C(33abce9da2272647), C(b22a7993aaf32556), C(bf8f88f8019bedf0),
-     C(ed2d7f01fb273905), C(6b45f15901b481cd), C(f88ebb413ba6a8d5),
      C(3deadf12)},
     {C(7bf5ffd7f69385c7), C(fc077b1d8bc82879), C(9c04e36f9ed83a24),
-     C(82065c62e6582188), C(8ef787fd356f5e43), C(2922e53e36e17dfa),
-     C(9805f223d385010b), C(82065c62e6582188), C(8ef787fd356f5e43),
-     C(2922e53e36e17dfa), C(9805f223d385010b), C(692154f3491b787d),
-     C(e7e64700e414fbf), C(757d4d4ab65069a0), C(cd029446a8e348e2), C(ccf02a4e)},
+     C(ccf02a4e)},
     {C(e89c8ff9f9c6e34b), C(f54c0f669a49f6c4), C(fc3e46f5d846adef),
-     C(22f2aa3df2221cc), C(f66fea90f5d62174), C(b75defaeaa1dd2a7),
-     C(9b994cd9a7214fd5), C(22f2aa3df2221cc), C(f66fea90f5d62174),
-     C(b75defaeaa1dd2a7), C(9b994cd9a7214fd5), C(fac675a31804b773),
-     C(98bcb3b820c50fc6), C(e14af64d28cf0885), C(27466fbd2b360eb5),
      C(176c1722)},
-    {C(a18fbcdccd11e1f4), C(8248216751dfd65e), C(40c089f208d89d7c),
-     C(229b79ab69ae97d), C(a87aabc2ec26e582), C(be2b053721eb26d2),
-     C(10febd7f0c3d6fcb), C(229b79ab69ae97d), C(a87aabc2ec26e582),
-     C(be2b053721eb26d2), C(10febd7f0c3d6fcb), C(9cc5b9b2f6e3bf7b),
-     C(655d8495fe624a86), C(6381a9f3d1f2bd7e), C(79ebabbfc25c83e2), C(26f82ad)},
+    {C(a18fbcdccd11e1f4), C(8248216751dfd65e), C(40c089f208d89d7c), C(26f82ad)},
     {C(2d54f40cc4088b17), C(59d15633b0cd1399), C(a8cc04bb1bffd15b),
-     C(d332cdb073d8dc46), C(272c56466868cb46), C(7e7fcbe35ca6c3f3),
-     C(ee8f51e5a70399d4), C(d332cdb073d8dc46), C(272c56466868cb46),
-     C(7e7fcbe35ca6c3f3), C(ee8f51e5a70399d4), C(16737a9c7581fe7b),
-     C(ed04bf52f4b75dcb), C(9707ffb36bd30c1a), C(1390f236fdc0de3e),
      C(b5244f42)},
     {C(69276946cb4e87c7), C(62bdbe6183be6fa9), C(3ba9773dac442a1a),
-     C(702e2afc7f5a1825), C(8c49b11ea8151fdc), C(caf3fef61f5a86fa),
-     C(ef0b2ee8649d7272), C(702e2afc7f5a1825), C(8c49b11ea8151fdc),
-     C(caf3fef61f5a86fa), C(ef0b2ee8649d7272), C(9e34a4e08d9441e1),
-     C(7bdc0cd64d5af533), C(a926b14d99e3d868), C(fca923a17788cce4),
      C(49a689e5)},
-    {C(668174a3f443df1d), C(407299392da1ce86), C(c2a3f7d7f2c5be28),
-     C(a590b202a7a5807b), C(968d2593f7ccb54e), C(9dd8d669e3e95dec),
-     C(ee0cc5dd58b6e93a), C(a590b202a7a5807b), C(968d2593f7ccb54e),
-     C(9dd8d669e3e95dec), C(ee0cc5dd58b6e93a), C(ac65d5a9466fb483),
-     C(221be538b2c9d806), C(5cbe9441784f9fd9), C(d4c7d5d6e3c122b8), C(59fcdd3)},
-    {C(5e29be847bd5046), C(b561c7f19c8f80c3), C(5e5abd5021ccaeaf),
-     C(7432d63888e0c306), C(74bbceeed479cb71), C(6471586599575fdf),
-     C(6a859ad23365cba2), C(7432d63888e0c306), C(74bbceeed479cb71),
-     C(6471586599575fdf), C(6a859ad23365cba2), C(f9ceec84acd18dcc),
-     C(74a242ff1907437c), C(f70890194e1ee913), C(777dfcb4bb01f0ba),
-     C(4f4b04e9)},
+    {C(668174a3f443df1d), C(407299392da1ce86), C(c2a3f7d7f2c5be28), C(59fcdd3)},
+    {C(5e29be847bd5046), C(b561c7f19c8f80c3), C(5e5abd5021ccaeaf), C(4f4b04e9)},
     {C(cd0d79f2164da014), C(4c386bb5c5d6ca0c), C(8e771b03647c3b63),
-     C(69db23875cb0b715), C(ada8dd91504ae37f), C(46bf18dbf045ed6a),
-     C(e1b5f67b0645ab63), C(69db23875cb0b715), C(ada8dd91504ae37f),
-     C(46bf18dbf045ed6a), C(e1b5f67b0645ab63), C(877be8f5dcddff4),
-     C(6d471b5f9ca2e2d1), C(802c86d6f495b9bb), C(a1f9b9b22b3be704),
      C(8b00f891)},
     {C(e0e6fc0b1628af1d), C(29be5fb4c27a2949), C(1c3f781a604d3630),
-     C(c4af7faf883033aa), C(9bd296c4e9453cac), C(ca45426c1f7e33f9),
-     C(a6bbdcf7074d40c5), C(c4af7faf883033aa), C(9bd296c4e9453cac),
-     C(ca45426c1f7e33f9), C(a6bbdcf7074d40c5), C(e13a005d7142733b),
-     C(c02b7925c5eeefaf), C(d39119a60441e2d5), C(3c24c710df8f4d43),
      C(16e114f3)},
     {C(2058927664adfd93), C(6e8f968c7963baa5), C(af3dced6fff7c394),
-     C(42e34cf3d53c7876), C(9cddbb26424dc5e), C(64f6340a6d8eddad),
-     C(2196e488eb2a3a4b), C(42e34cf3d53c7876), C(9cddbb26424dc5e),
-     C(64f6340a6d8eddad), C(2196e488eb2a3a4b), C(c9e9da25911a16fd),
-     C(e21b4683f3e196a8), C(cb80bf1a4c6fdbb4), C(53792e9b3c3e67f8),
      C(d6b6dadc)},
     {C(dc107285fd8e1af7), C(a8641a0609321f3f), C(db06e89ffdc54466),
-     C(bcc7a81ed5432429), C(b6d7bdc6ad2e81f1), C(93605ec471aa37db),
-     C(a2a73f8a85a8e397), C(bcc7a81ed5432429), C(b6d7bdc6ad2e81f1),
-     C(93605ec471aa37db), C(a2a73f8a85a8e397), C(10a012b8ca7ac24b),
-     C(aac5fd63351595cf), C(5bb4c648a226dea0), C(9d11ecb2b5c05c5f),
      C(897e20ac)},
-    {C(fbba1afe2e3280f1), C(755a5f392f07fce), C(9e44a9a15402809a),
-     C(6226a32e25099848), C(ea895661ecf53004), C(4d7e0158db2228b9),
-     C(e5a7d82922f69842), C(6226a32e25099848), C(ea895661ecf53004),
-     C(4d7e0158db2228b9), C(e5a7d82922f69842), C(2cea7713b69840ca),
-     C(18de7b9ae938375b), C(f127cca08f3cc665), C(b1c22d727665ad2), C(f996e05d)},
+    {C(fbba1afe2e3280f1), C(755a5f392f07fce), C(9e44a9a15402809a), C(f996e05d)},
     {C(bfa10785ddc1011b), C(b6e1c4d2f670f7de), C(517d95604e4fcc1f),
-     C(ca6552a0dfb82c73), C(b024cdf09e34ba07), C(66cd8c5a95d7393b),
-     C(e3939acf790d4a74), C(ca6552a0dfb82c73), C(b024cdf09e34ba07),
-     C(66cd8c5a95d7393b), C(e3939acf790d4a74), C(97827541a1ef051e),
-     C(ac2fce47ebe6500c), C(b3f06d3bddf3bd6a), C(1d74afb25e1ce5fe),
      C(c4306af6)},
-    {C(534cc35f0ee1eb4e), C(b703820f1f3b3dce), C(884aa164cf22363),
-     C(f14ef7f47d8a57a3), C(80d1f86f2e061d7c), C(401d6c2f151b5a62),
-     C(e988460224108944), C(f14ef7f47d8a57a3), C(80d1f86f2e061d7c),
-     C(401d6c2f151b5a62), C(e988460224108944), C(7804d4135f68cd19),
-     C(5487b4b39e69fe8e), C(8cc5999015358a27), C(8f3729b61c2d5601),
-     C(6dcad433)},
-    {C(7ca6e3933995dac), C(fd118c77daa8188), C(3aceb7b5e7da6545),
-     C(c8389799445480db), C(5389f5df8aacd50d), C(d136581f22fab5f),
-     C(c2f31f85991da417), C(c8389799445480db), C(5389f5df8aacd50d),
-     C(d136581f22fab5f), C(c2f31f85991da417), C(aefbf9ff84035a43),
-     C(8accbaf44adadd7c), C(e57f3657344b67f5), C(21490e5e8abdec51),
-     C(3c07374d)},
+    {C(534cc35f0ee1eb4e), C(b703820f1f3b3dce), C(884aa164cf22363), C(6dcad433)},
+    {C(7ca6e3933995dac), C(fd118c77daa8188), C(3aceb7b5e7da6545), C(3c07374d)},
     {C(f0d6044f6efd7598), C(e044d6ba4369856e), C(91968e4f8c8a1a4c),
-     C(70bd1968996bffc2), C(4c613de5d8ab32ac), C(fe1f4f97206f79d8),
-     C(ac0434f2c4e213a9), C(70bd1968996bffc2), C(4c613de5d8ab32ac),
-     C(fe1f4f97206f79d8), C(ac0434f2c4e213a9), C(7490e9d82cfe22ca),
-     C(5fbbf7f987454238), C(c39e0dc8368ce949), C(22201d3894676c71),
      C(f0f4602c)},
     {C(3d69e52049879d61), C(76610636ea9f74fe), C(e9bf5602f89310c0),
-     C(8eeb177a86053c11), C(e390122c345f34a2), C(1e30e47afbaaf8d6),
-     C(7b892f68e5f91732), C(8eeb177a86053c11), C(e390122c345f34a2),
-     C(1e30e47afbaaf8d6), C(7b892f68e5f91732), C(b87922525fa44158),
-     C(f440a1ee1a1a766b), C(ee8efad279d08c5c), C(421f910c5b60216e),
      C(3e1ea071)},
-    {C(79da242a16acae31), C(183c5f438e29d40), C(6d351710ae92f3de),
-     C(27233b28b5b11e9b), C(c7dfe8988a942700), C(570ed11c4abad984),
-     C(4b4c04632f48311a), C(27233b28b5b11e9b), C(c7dfe8988a942700),
-     C(570ed11c4abad984), C(4b4c04632f48311a), C(12f33235442cbf9),
-     C(a35315ca0b5b8cdb), C(d8abde62ead5506b), C(fc0fcf8478ad5266),
-     C(67580f0c)},
+    {C(79da242a16acae31), C(183c5f438e29d40), C(6d351710ae92f3de), C(67580f0c)},
     {C(461c82656a74fb57), C(d84b491b275aa0f7), C(8f262cb29a6eb8b2),
-     C(49fa3070bc7b06d0), C(f12ed446bd0c0539), C(6d43ac5d1dd4b240),
-     C(7609524fe90bec93), C(49fa3070bc7b06d0), C(f12ed446bd0c0539),
-     C(6d43ac5d1dd4b240), C(7609524fe90bec93), C(391c2b2e076ec241),
-     C(f5e62deda7839f7b), C(3c7b3186a10d870f), C(77ef4f2cba4f1005),
      C(4e109454)},
-    {C(53c1a66d0b13003), C(731f060e6fe797fc), C(daa56811791371e3),
-     C(57466046cf6896ed), C(8ac37e0e8b25b0c6), C(3e6074b52ad3cf18),
-     C(aa491ce7b45db297), C(57466046cf6896ed), C(8ac37e0e8b25b0c6),
-     C(3e6074b52ad3cf18), C(aa491ce7b45db297), C(f7a9227c5e5e22c3),
-     C(3d92e0841e29ce28), C(2d30da5b2859e59d), C(ff37fa1c9cbfafc2),
-     C(88a474a7)},
-    {C(d3a2efec0f047e9), C(1cabce58853e58ea), C(7a17b2eae3256be4),
-     C(c2dcc9758c910171), C(cb5cddaeff4ddb40), C(5d7cc5869baefef1),
-     C(9644c5853af9cfeb), C(c2dcc9758c910171), C(cb5cddaeff4ddb40),
-     C(5d7cc5869baefef1), C(9644c5853af9cfeb), C(255c968184694ee1),
-     C(4e4d726eda360927), C(7d27dd5b6d100377), C(9a300e2020ddea2c), C(5b5bedd)},
+    {C(53c1a66d0b13003), C(731f060e6fe797fc), C(daa56811791371e3), C(88a474a7)},
+    {C(d3a2efec0f047e9), C(1cabce58853e58ea), C(7a17b2eae3256be4), C(5b5bedd)},
     {C(43c64d7484f7f9b2), C(5da002b64aafaeb7), C(b576c1e45800a716),
-     C(3ee84d3d5b4ca00b), C(5cbc6d701894c3f9), C(d9e946f5ae1ca95),
-     C(24ca06e67f0b1833), C(3ee84d3d5b4ca00b), C(5cbc6d701894c3f9),
-     C(d9e946f5ae1ca95), C(24ca06e67f0b1833), C(3413d46b4152650e),
-     C(cbdfdbc2ab516f9c), C(2aad8acb739e0c6c), C(2bfc950d9f9fa977),
      C(1aaddfa7)},
     {C(a7dec6ad81cf7fa1), C(180c1ab708683063), C(95e0fd7008d67cff),
-     C(6b11c5073687208), C(7e0a57de0d453f3), C(e48c267d4f646867),
-     C(2168e9136375f9cb), C(6b11c5073687208), C(7e0a57de0d453f3),
-     C(e48c267d4f646867), C(2168e9136375f9cb), C(64da194aeeea7fdf),
-     C(a3b9f01fa5885678), C(c316f8ee2eb2bd17), C(a7e4d80f83e4427f),
      C(5be07fd8)},
-    {C(5408a1df99d4aff), C(b9565e588740f6bd), C(abf241813b08006e),
-     C(7da9e81d89fda7ad), C(274157cabe71440d), C(2c22d9a480b331f7),
-     C(e835c8ac746472d5), C(7da9e81d89fda7ad), C(274157cabe71440d),
-     C(2c22d9a480b331f7), C(e835c8ac746472d5), C(2038ce817a201ae4),
-     C(46f3289dfe1c5e40), C(435578a42d4b7c56), C(f96d9f409fcf561), C(cbca8606)},
+    {C(5408a1df99d4aff), C(b9565e588740f6bd), C(abf241813b08006e), C(cbca8606)},
     {C(a8b27a6bcaeeed4b), C(aec1eeded6a87e39), C(9daf246d6fed8326),
-     C(d45a938b79f54e8f), C(366b219d6d133e48), C(5b14be3c25c49405),
-     C(fdd791d48811a572), C(d45a938b79f54e8f), C(366b219d6d133e48),
-     C(5b14be3c25c49405), C(fdd791d48811a572), C(3de67b8d9e95d335),
-     C(903c01307cfbeed5), C(af7d65f32274f1d1), C(4dba141b5fc03c42),
      C(bde64d01)},
     {C(9a952a8246fdc269), C(d0dcfcac74ef278c), C(250f7139836f0f1f),
-     C(c83d3c5f4e5f0320), C(694e7adeb2bf32e5), C(7ad09538a3da27f5),
-     C(2b5c18f934aa5303), C(c83d3c5f4e5f0320), C(694e7adeb2bf32e5),
-     C(7ad09538a3da27f5), C(2b5c18f934aa5303), C(c4dad7703d34326e),
-     C(825569e2bcdc6a25), C(b83d267709ca900d), C(44ed05151f5d74e6),
      C(ee90cf33)},
     {C(c930841d1d88684f), C(5eb66eb18b7f9672), C(e455d413008a2546),
-     C(bc271bc0df14d647), C(b071100a9ff2edbb), C(2b1a4c1cc31a119a),
-     C(b5d7caa1bd946cef), C(bc271bc0df14d647), C(b071100a9ff2edbb),
-     C(2b1a4c1cc31a119a), C(b5d7caa1bd946cef), C(e02623ae10f4aadd),
-     C(d79f600389cd06fd), C(1e8da7965303e62b), C(86f50e10eeab0925),
      C(4305c3ce)},
-    {C(94dc6971e3cf071a), C(994c7003b73b2b34), C(ea16e85978694e5),
-     C(336c1b59a1fc19f6), C(c173acaecc471305), C(db1267d24f3f3f36),
-     C(e9a5ee98627a6e78), C(336c1b59a1fc19f6), C(c173acaecc471305),
-     C(db1267d24f3f3f36), C(e9a5ee98627a6e78), C(718f334204305ae5),
-     C(e3b53c148f98d22c), C(a184012df848926), C(6e96386127d51183), C(4b3a1d76)},
-    {C(7fc98006e25cac9), C(77fee0484cda86a7), C(376ec3d447060456),
-     C(84064a6dcf916340), C(fbf55a26790e0ebb), C(2e7f84151c31a5c2),
-     C(9f7f6d76b950f9bf), C(84064a6dcf916340), C(fbf55a26790e0ebb),
-     C(2e7f84151c31a5c2), C(9f7f6d76b950f9bf), C(125e094fbee2b146),
-     C(5706aa72b2eef7c2), C(1c4a2daa905ee66e), C(83d48029b5451694),
-     C(a8bb6d80)},
-    {C(bd781c4454103f6), C(612197322f49c931), C(b9cf17fd7e5462d5),
-     C(e38e526cd3324364), C(85f2b63a5b5e840a), C(485d7cef5aaadd87),
-     C(d2b837a462f6db6d), C(e38e526cd3324364), C(85f2b63a5b5e840a),
-     C(485d7cef5aaadd87), C(d2b837a462f6db6d), C(3e41cef031520d9a),
-     C(82df73902d7f67e), C(3ba6fd54c15257cb), C(22f91f079be42d40), C(1f9fa607)},
+    {C(94dc6971e3cf071a), C(994c7003b73b2b34), C(ea16e85978694e5), C(4b3a1d76)},
+    {C(7fc98006e25cac9), C(77fee0484cda86a7), C(376ec3d447060456), C(a8bb6d80)},
+    {C(bd781c4454103f6), C(612197322f49c931), C(b9cf17fd7e5462d5), C(1f9fa607)},
     {C(da60e6b14479f9df), C(3bdccf69ece16792), C(18ebf45c4fecfdc9),
-     C(16818ee9d38c6664), C(5519fa9a1e35a329), C(cbd0001e4b08ed8),
-     C(41a965e37a0c731b), C(16818ee9d38c6664), C(5519fa9a1e35a329),
-     C(cbd0001e4b08ed8), C(41a965e37a0c731b), C(66e7b5dcca1ca28f),
-     C(963b2d993614347d), C(9b6fc6f41d411106), C(aaaecaccf7848c0c),
      C(8d0e4ed2)},
-    {C(4ca56a348b6c4d3), C(60618537c3872514), C(2fbb9f0e65871b09),
-     C(30278016830ddd43), C(f046646d9012e074), C(c62a5804f6e7c9da),
-     C(98d51f5830e2bc1e), C(30278016830ddd43), C(f046646d9012e074),
-     C(c62a5804f6e7c9da), C(98d51f5830e2bc1e), C(7b2cbe5d37e3f29e),
-     C(7b8c3ed50bda4aa0), C(3ea60cc24639e038), C(f7706de9fb0b5801),
-     C(1bf31347)},
+    {C(4ca56a348b6c4d3), C(60618537c3872514), C(2fbb9f0e65871b09), C(1bf31347)},
     {C(ebd22d4b70946401), C(6863602bf7139017), C(c0b1ac4e11b00666),
-     C(7d2782b82bd494b6), C(97159ba1c26b304b), C(42b3b0fd431b2ac2),
-     C(faa81f82691c830c), C(7d2782b82bd494b6), C(97159ba1c26b304b),
-     C(42b3b0fd431b2ac2), C(faa81f82691c830c), C(7cc6449234c7e185),
-     C(aeaa6fa643ca86a5), C(1412db1c0f2e0133), C(4df2fe3e4072934f),
      C(1ae3fc5b)},
-    {C(3cc4693d6cbcb0c), C(501689ea1c70ffa), C(10a4353e9c89e364),
-     C(58c8aba7475e2d95), C(3e2f291698c9427a), C(e8710d19c9de9e41),
-     C(65dda22eb04cf953), C(58c8aba7475e2d95), C(3e2f291698c9427a),
-     C(e8710d19c9de9e41), C(65dda22eb04cf953), C(d7729c48c250cffa),
-     C(ef76162b2ddfba4b), C(52371e17f4d51f6d), C(ddd002112ff0c833),
-     C(459c3930)},
+    {C(3cc4693d6cbcb0c), C(501689ea1c70ffa), C(10a4353e9c89e364), C(459c3930)},
     {C(38908e43f7ba5ef0), C(1ab035d4e7781e76), C(41d133e8c0a68ff7),
-     C(d1090893afaab8bc), C(96c4fe6922772807), C(4522426c2b4205eb),
-     C(efad99a1262e7e0d), C(d1090893afaab8bc), C(96c4fe6922772807),
-     C(4522426c2b4205eb), C(efad99a1262e7e0d), C(c7696029abdb465e),
-     C(4e18eaf03d517651), C(d006bced54c86ac8), C(4330326d1021860c),
      C(e00c4184)},
-    {C(34983ccc6aa40205), C(21802cad34e72bc4), C(1943e8fb3c17bb8),
-     C(fc947167f69c0da5), C(ae79cfdb91b6f6c1), C(7b251d04c26cbda3),
-     C(128a33a79060d25e), C(fc947167f69c0da5), C(ae79cfdb91b6f6c1),
-     C(7b251d04c26cbda3), C(128a33a79060d25e), C(1eca842dbfe018dd),
-     C(50a4cd2ee0ba9c63), C(c2f5c97d8399682f), C(3f929fc7cbe8ecbb),
-     C(ffc7a781)},
+    {C(34983ccc6aa40205), C(21802cad34e72bc4), C(1943e8fb3c17bb8), C(ffc7a781)},
     {C(86215c45dcac9905), C(ea546afe851cae4b), C(d85b6457e489e374),
-     C(b7609c8e70386d66), C(36e6ccc278d1636d), C(2f873307c08e6a1c),
-     C(10f252a758505289), C(b7609c8e70386d66), C(36e6ccc278d1636d),
-     C(2f873307c08e6a1c), C(10f252a758505289), C(c8977646e81ab4b6),
-     C(8017b745cd80213b), C(960687db359bea0), C(ef4a470660799488), C(6a125480)},
+     C(6a125480)},
     {C(420fc255c38db175), C(d503cd0f3c1208d1), C(d4684e74c825a0bc),
-     C(4c10537443152f3d), C(720451d3c895e25d), C(aff60c4d11f513fd),
-     C(881e8d6d2d5fb953), C(4c10537443152f3d), C(720451d3c895e25d),
-     C(aff60c4d11f513fd), C(881e8d6d2d5fb953), C(9dec034a043f1f55),
-     C(e27a0c22e7bfb39d), C(2220b959128324), C(53240272152dbd8b), C(88a1512b)},
+     C(88a1512b)},
     {C(1d7a31f5bc8fe2f9), C(4763991092dcf836), C(ed695f55b97416f4),
-     C(f265edb0c1c411d7), C(30e1e9ec5262b7e6), C(c2c3ba061ce7957a),
-     C(d975f93b89a16409), C(f265edb0c1c411d7), C(30e1e9ec5262b7e6),
-     C(c2c3ba061ce7957a), C(d975f93b89a16409), C(e9d703123f43450a),
-     C(41383fedfed67c82), C(6e9f43ecbbbd6004), C(c7ccd23a24e77b8), C(549bbbe5)},
+     C(549bbbe5)},
     {C(94129a84c376a26e), C(c245e859dc231933), C(1b8f74fecf917453),
-     C(e9369d2e9007e74b), C(b1375915d1136052), C(926c2021fe1d2351),
-     C(1d943addaaa2e7e6), C(e9369d2e9007e74b), C(b1375915d1136052),
-     C(926c2021fe1d2351), C(1d943addaaa2e7e6), C(f5f515869c246738),
-     C(7e309cd0e1c0f2a0), C(153c3c36cf523e3b), C(4931c66872ea6758),
      C(c133d38c)},
-    {C(1d3a9809dab05c8d), C(adddeb4f71c93e8), C(ef342eb36631edb),
-     C(301d7a61c4b3dbca), C(861336c3f0552d61), C(12c6db947471300f),
-     C(a679ef0ed761deb9), C(301d7a61c4b3dbca), C(861336c3f0552d61),
-     C(12c6db947471300f), C(a679ef0ed761deb9), C(5f713b720efcd147),
-     C(37ac330a333aa6b), C(3309dc9ec1616eef), C(52301d7a908026b5), C(fcace348)},
+    {C(1d3a9809dab05c8d), C(adddeb4f71c93e8), C(ef342eb36631edb), C(fcace348)},
     {C(90fa3ccbd60848da), C(dfa6e0595b569e11), C(e585d067a1f5135d),
-     C(6cef866ec295abea), C(c486c0d9214beb2d), C(d6e490944d5fe100),
-     C(59df3175d72c9f38), C(6cef866ec295abea), C(c486c0d9214beb2d),
-     C(d6e490944d5fe100), C(59df3175d72c9f38), C(3f23aeb4c04d1443),
-     C(9bf0515cd8d24770), C(958554f60ccaade2), C(5182863c90132fe8),
      C(ed7b6f9a)},
     {C(2dbb4fc71b554514), C(9650e04b86be0f82), C(60f2304fba9274d3),
-     C(fcfb9443e997cab), C(f13310d96dec2772), C(709cad2045251af2),
-     C(afd0d30cc6376dad), C(fcfb9443e997cab), C(f13310d96dec2772),
-     C(709cad2045251af2), C(afd0d30cc6376dad), C(59d4bed30d550d0d),
-     C(58006d4e22d8aad1), C(eee12d2362d1f13b), C(35cf1d7faaf1d228),
      C(6d907dda)},
     {C(b98bf4274d18374a), C(1b669fd4c7f9a19a), C(b1f5972b88ba2b7a),
-     C(73119c99e6d508be), C(5d4036a187735385), C(8fa66e192fd83831),
-     C(2abf64b6b592ed57), C(73119c99e6d508be), C(5d4036a187735385),
-     C(8fa66e192fd83831), C(2abf64b6b592ed57), C(d4501f95dd84b08c),
-     C(bf1552439c8bea02), C(4f56fe753ba7e0ba), C(4ca8d35cc058cfcd),
      C(7a4d48d5)},
     {C(d6781d0b5e18eb68), C(b992913cae09b533), C(58f6021caaee3a40),
-     C(aafcb77497b5a20b), C(411819e5e79b77a3), C(bd779579c51c77ce),
-     C(58d11f5dcf5d075d), C(aafcb77497b5a20b), C(411819e5e79b77a3),
-     C(bd779579c51c77ce), C(58d11f5dcf5d075d), C(9eae76cde1cb4233),
-     C(32fe25a9bf657970), C(1c0c807948edb06a), C(b8f29a3dfaee254d),
      C(e686f3db)},
-    {C(226651cf18f4884c), C(595052a874f0f51c), C(c9b75162b23bab42),
-     C(3f44f873be4812ec), C(427662c1dbfaa7b2), C(a207ff9638fb6558),
-     C(a738d919e45f550f), C(3f44f873be4812ec), C(427662c1dbfaa7b2),
-     C(a207ff9638fb6558), C(a738d919e45f550f), C(cb186ea05717e7d6),
-     C(1ca7d68a5871fdc1), C(5d4c119ea8ef3750), C(72b6a10fa2ff9406), C(cce7c55)},
-    {C(a734fb047d3162d6), C(e523170d240ba3a5), C(125a6972809730e8),
-     C(d396a297799c24a1), C(8fee992e3069bad5), C(2e3a01b0697ccf57),
-     C(ee9c7390bd901cfa), C(d396a297799c24a1), C(8fee992e3069bad5),
-     C(2e3a01b0697ccf57), C(ee9c7390bd901cfa), C(56f2d9da0af28af2),
-     C(3fdd37b2fe8437cb), C(3d13eeeb60d6aec0), C(2432ae62e800a5ce), C(f58b96b)},
+    {C(226651cf18f4884c), C(595052a874f0f51c), C(c9b75162b23bab42), C(cce7c55)},
+    {C(a734fb047d3162d6), C(e523170d240ba3a5), C(125a6972809730e8), C(f58b96b)},
     {C(c6df6364a24f75a3), C(c294e2c84c4f5df8), C(a88df65c6a89313b),
-     C(895fe8443183da74), C(c7f2f6f895a67334), C(a0d6b6a506691d31),
-     C(24f51712b459a9f0), C(895fe8443183da74), C(c7f2f6f895a67334),
-     C(a0d6b6a506691d31), C(24f51712b459a9f0), C(173a699481b9e088),
-     C(1dee9b77bcbf45d3), C(32b98a646a8667d0), C(3adcd4ee28f42a0e),
      C(1bbf6f60)},
-    {C(d8d1364c1fbcd10), C(2d7cc7f54832deaa), C(4e22c876a7c57625),
-     C(a3d5d1137d30c4bd), C(1e7d706a49bdfb9e), C(c63282b20ad86db2),
-     C(aec97fa07916bfd6), C(a3d5d1137d30c4bd), C(1e7d706a49bdfb9e),
-     C(c63282b20ad86db2), C(aec97fa07916bfd6), C(7c9ba3e52d44f73e),
-     C(af62fd245811185d), C(8a9d2dacd8737652), C(bd2cce277d5fbec0),
-     C(ce5e0cc2)},
+    {C(d8d1364c1fbcd10), C(2d7cc7f54832deaa), C(4e22c876a7c57625), C(ce5e0cc2)},
     {C(aae06f9146db885f), C(3598736441e280d9), C(fba339b117083e55),
-     C(b22bf08d9f8aecf7), C(c182730de337b922), C(2b9adc87a0450a46),
-     C(192c29a9cfc00aad), C(b22bf08d9f8aecf7), C(c182730de337b922),
-     C(2b9adc87a0450a46), C(192c29a9cfc00aad), C(9fd733f1d84a59d9),
-     C(d86bd5c9839ace15), C(af20b57303172876), C(9f63cb7161b5364c),
      C(584cfd6f)},
     {C(8955ef07631e3bcc), C(7d70965ea3926f83), C(39aed4134f8b2db6),
-     C(882efc2561715a9c), C(ef8132a18a540221), C(b20a3c87a8c257c1),
-     C(f541b8628fad6c23), C(882efc2561715a9c), C(ef8132a18a540221),
-     C(b20a3c87a8c257c1), C(f541b8628fad6c23), C(9552aed57a6e0467),
-     C(4d9fdd56867611a7), C(c330279bf23b9eab), C(44dbbaea2fcb8eba),
      C(8f9bbc33)},
     {C(ad611c609cfbe412), C(d3c00b18bf253877), C(90b2172e1f3d0bfd),
-     C(371a98b2cb084883), C(33a2886ee9f00663), C(be9568818ed6e6bd),
-     C(f244a0fa2673469a), C(371a98b2cb084883), C(33a2886ee9f00663),
-     C(be9568818ed6e6bd), C(f244a0fa2673469a), C(b447050bd3e559e9),
-     C(d3b695dae7a13383), C(ded0bb65be471188), C(ca3c7a2b78922cae),
      C(d7640d95)},
-    {C(d5339adc295d5d69), C(b633cc1dcb8b586a), C(ee84184cf5b1aeaf),
-     C(89f3aab99afbd636), C(f420e004f8148b9a), C(6818073faa797c7c),
-     C(dd3b4e21cbbf42ca), C(89f3aab99afbd636), C(f420e004f8148b9a),
-     C(6818073faa797c7c), C(dd3b4e21cbbf42ca), C(6a2b7db261164844),
-     C(cbead63d1895852a), C(93d37e1eae05e2f9), C(5d06db2703fbc3ae), C(3d12a2b)},
+    {C(d5339adc295d5d69), C(b633cc1dcb8b586a), C(ee84184cf5b1aeaf), C(3d12a2b)},
     {C(40d0aeff521375a8), C(77ba1ad7ecebd506), C(547c6f1a7d9df427),
-     C(21c2be098327f49b), C(7e035065ac7bbef5), C(6d7348e63023fb35),
-     C(9d427dc1b67c3830), C(21c2be098327f49b), C(7e035065ac7bbef5),
-     C(6d7348e63023fb35), C(9d427dc1b67c3830), C(4e3d018a43858341),
-     C(cf924bb44d6b43c5), C(4618b6a26e3446ae), C(54d3013fac3ed469),
      C(aaeafed0)},
     {C(8b2d54ae1a3df769), C(11e7adaee3216679), C(3483781efc563e03),
-     C(9d097dd3152ab107), C(51e21d24126e8563), C(cba56cac884a1354),
-     C(39abb1b595f0a977), C(9d097dd3152ab107), C(51e21d24126e8563),
-     C(cba56cac884a1354), C(39abb1b595f0a977), C(81e6dd1c1109848f),
-     C(1644b209826d7b15), C(6ac67e4e4b4812f0), C(b3a9f5622c935bf7),
      C(95b9b814)},
     {C(99c175819b4eae28), C(932e8ff9f7a40043), C(ec78dcab07ca9f7c),
-     C(c1a78b82ba815b74), C(458cbdfc82eb322a), C(17f4a192376ed8d7),
-     C(6f9e92968bc8ccef), C(c1a78b82ba815b74), C(458cbdfc82eb322a),
-     C(17f4a192376ed8d7), C(6f9e92968bc8ccef), C(93e098c333b39905),
-     C(d59b1cace44b7fdc), C(f7a64ed78c64c7c5), C(7c6eca5dd87ec1ce),
      C(45fbe66e)},
     {C(2a418335779b82fc), C(af0295987849a76b), C(c12bc5ff0213f46e),
-     C(5aeead8d6cb25bb9), C(739315f7743ec3ff), C(9ab48d27111d2dcc),
-     C(5b87bd35a975929b), C(5aeead8d6cb25bb9), C(739315f7743ec3ff),
-     C(9ab48d27111d2dcc), C(5b87bd35a975929b), C(c3dd8d6d95a46bb3),
-     C(7bf9093215a4f483), C(cb557d6ed84285bd), C(daf58422f261fdb5),
      C(b4baa7a8)},
-    {C(3b1fc6a3d279e67d), C(70ea1e49c226396), C(25505adcf104697c),
-     C(ba1ffba29f0367aa), C(a20bec1dd15a8b6c), C(e9bf61d2dab0f774),
-     C(f4f35bf5870a049c), C(ba1ffba29f0367aa), C(a20bec1dd15a8b6c),
-     C(e9bf61d2dab0f774), C(f4f35bf5870a049c), C(26787efa5b92385),
-     C(3d9533590ce30b59), C(a4da3e40530a01d4), C(6395deaefb70067c),
-     C(83e962fe)},
-    {C(d97eacdf10f1c3c9), C(b54f4654043a36e0), C(b128f6eb09d1234),
-     C(d8ad7ec84a9c9aa2), C(e256cffed11f69e6), C(2cf65e4958ad5bda),
-     C(cfbf9b03245989a7), C(d8ad7ec84a9c9aa2), C(e256cffed11f69e6),
-     C(2cf65e4958ad5bda), C(cfbf9b03245989a7), C(9fa51e6686cf4444),
-     C(9425c117a34609d5), C(b25f7e2c6f30e96), C(ea5477c3f2b5afd1), C(aac3531c)},
+    {C(3b1fc6a3d279e67d), C(70ea1e49c226396), C(25505adcf104697c), C(83e962fe)},
+    {C(d97eacdf10f1c3c9), C(b54f4654043a36e0), C(b128f6eb09d1234), C(aac3531c)},
     {C(293a5c1c4e203cd4), C(6b3329f1c130cefe), C(f2e32f8ec76aac91),
-     C(361e0a62c8187bff), C(6089971bb84d7133), C(93df7741588dd50b),
-     C(c2a9b6abcd1d80b1), C(361e0a62c8187bff), C(6089971bb84d7133),
-     C(93df7741588dd50b), C(c2a9b6abcd1d80b1), C(4d2f86869d79bc59),
-     C(85cd24d8aa570ff), C(b0dcf6ef0e94bbb5), C(2037c69aa7a78421), C(2b1db7cc)},
+     C(2b1db7cc)},
     {C(4290e018ffaedde7), C(a14948545418eb5e), C(72d851b202284636),
-     C(4ec02f3d2f2b23f2), C(ab3580708aa7c339), C(cdce066fbab3f65),
-     C(d8ed3ecf3c7647b9), C(4ec02f3d2f2b23f2), C(ab3580708aa7c339),
-     C(cdce066fbab3f65), C(d8ed3ecf3c7647b9), C(6d2204b3e31f344a),
-     C(61a4d87f80ee61d7), C(446c43dbed4b728f), C(73130ac94f58747e),
      C(cf00cd31)},
     {C(f919a59cbde8bf2f), C(a56d04203b2dc5a5), C(38b06753ac871e48),
-     C(c2c9fc637dbdfcfa), C(292ab8306d149d75), C(7f436b874b9ffc07),
-     C(a5b56b0129218b80), C(c2c9fc637dbdfcfa), C(292ab8306d149d75),
-     C(7f436b874b9ffc07), C(a5b56b0129218b80), C(9188f7bdc47ec050),
-     C(cfe9345d03a15ade), C(40b520fb2750c49e), C(c2e83d343968af2e),
      C(7d3c43b8)},
     {C(1d70a3f5521d7fa4), C(fb97b3fdc5891965), C(299d49bbbe3535af),
-     C(e1a8286a7d67946e), C(52bd956f047b298), C(cbd74332dd4204ac),
-     C(12b5be7752721976), C(e1a8286a7d67946e), C(52bd956f047b298),
-     C(cbd74332dd4204ac), C(12b5be7752721976), C(278426e27f6204b6),
-     C(932ca7a7cd610181), C(41647321f0a5914d), C(48f4aa61a0ae80db),
      C(cbd5fac6)},
     {C(6af98d7b656d0d7c), C(d2e99ae96d6b5c0c), C(f63bd1603ef80627),
-     C(bde51033ac0413f8), C(bc0272f691aec629), C(6204332651bebc44),
-     C(1cbf00de026ea9bd), C(bde51033ac0413f8), C(bc0272f691aec629),
-     C(6204332651bebc44), C(1cbf00de026ea9bd), C(b9c7ed6a75f3ff1e),
-     C(7e310b76a5808e4f), C(acbbd1aad5531885), C(fc245f2473adeb9c),
      C(76d0fec4)},
-    {C(395b7a8adb96ab75), C(582df7165b20f4a), C(e52bd30e9ff657f9),
-     C(6c71064996cbec8b), C(352c535edeefcb89), C(ac7f0aba15cd5ecd),
-     C(3aba1ca8353e5c60), C(6c71064996cbec8b), C(352c535edeefcb89),
-     C(ac7f0aba15cd5ecd), C(3aba1ca8353e5c60), C(5c30a288a80ce646),
-     C(c2940488b6617674), C(925f8cc66b370575), C(aa65d1283b9bb0ef),
-     C(405e3402)},
+    {C(395b7a8adb96ab75), C(582df7165b20f4a), C(e52bd30e9ff657f9), C(405e3402)},
     {C(3822dd82c7df012f), C(b9029b40bd9f122b), C(fd25b988468266c4),
-     C(43e47bd5bab1e0ef), C(4a71f363421f282f), C(880b2f32a2b4e289),
-     C(1299d4eda9d3eadf), C(43e47bd5bab1e0ef), C(4a71f363421f282f),
-     C(880b2f32a2b4e289), C(1299d4eda9d3eadf), C(d713a40226f5564),
-     C(4d8d34fedc769406), C(a85001b29cd9cac3), C(cae92352a41fd2b0),
      C(c732c481)},
     {C(79f7efe4a80b951a), C(dd3a3fddfc6c9c41), C(ab4c812f9e27aa40),
-     C(832954ec9d0de333), C(94c390aa9bcb6b8a), C(f3b32afdc1f04f82),
-     C(d229c3b72e4b9a74), C(832954ec9d0de333), C(94c390aa9bcb6b8a),
-     C(f3b32afdc1f04f82), C(d229c3b72e4b9a74), C(1d11860d7ed624a6),
-     C(cadee20b3441b984), C(75307079bf306f7b), C(87902aa3b9753ba4),
      C(a8d123c9)},
-    {C(ae6e59f5f055921a), C(e9d9b7bf68e82), C(5ce4e4a5b269cc59),
-     C(4960111789727567), C(149b8a37c7125ab6), C(78c7a13ab9749382),
-     C(1c61131260ca151a), C(4960111789727567), C(149b8a37c7125ab6),
-     C(78c7a13ab9749382), C(1c61131260ca151a), C(1e93276b35c309a0),
-     C(2618f56230acde58), C(af61130a18e4febf), C(7145deb18e89befe),
-     C(1e80ad7d)},
+    {C(ae6e59f5f055921a), C(e9d9b7bf68e82), C(5ce4e4a5b269cc59), C(1e80ad7d)},
     {C(8959dbbf07387d36), C(b4658afce48ea35d), C(8f3f82437d8cb8d6),
-     C(6566d74954986ba5), C(99d5235cc82519a7), C(257a23805c2d825),
-     C(ad75ccb968e93403), C(6566d74954986ba5), C(99d5235cc82519a7),
-     C(257a23805c2d825), C(ad75ccb968e93403), C(b45bd4cf78e11f7f),
-     C(80c5536bdc487983), C(a4fd76ecbf018c8a), C(3b9dac78a7a70d43),
      C(52aeb863)},
     {C(4739613234278a49), C(99ea5bcd340bf663), C(258640912e712b12),
-     C(c8a2827404991402), C(7ee5e78550f02675), C(2ec53952db5ac662),
-     C(1526405a9df6794b), C(c8a2827404991402), C(7ee5e78550f02675),
-     C(2ec53952db5ac662), C(1526405a9df6794b), C(eddc6271170c5e1f),
-     C(f5a85f986001d9d6), C(95427c677bf58d58), C(53ed666dfa85cb29),
      C(ef7c0c18)},
     {C(420e6c926bc54841), C(96dbbf6f4e7c75cd), C(d8d40fa70c3c67bb),
-     C(3edbc10e4bfee91b), C(f0d681304c28ef68), C(77ea602029aaaf9c),
-     C(90f070bd24c8483c), C(3edbc10e4bfee91b), C(f0d681304c28ef68),
-     C(77ea602029aaaf9c), C(90f070bd24c8483c), C(28bc8e41e08ceb86),
-     C(1eb56e48a65691ef), C(9fea5301c9202f0e), C(3fcb65091aa9f135),
      C(b6ad4b68)},
     {C(c8601bab561bc1b7), C(72b26272a0ff869a), C(56fdfc986d6bc3c4),
-     C(83707730cad725d4), C(c9ca88c3a779674a), C(e1c696fbbd9aa933),
-     C(723f3baab1c17a45), C(83707730cad725d4), C(c9ca88c3a779674a),
-     C(e1c696fbbd9aa933), C(723f3baab1c17a45), C(f82abc7a1d851682),
-     C(30683836818e857d), C(78bfa3e89a5ab23f), C(6928234482b31817),
      C(c1e46b17)},
-    {C(b2d294931a0e20eb), C(284ffd9a0815bc38), C(1f8a103aac9bbe6),
-     C(1ef8e98e1ea57269), C(5971116272f45a8b), C(187ad68ce95d8eac),
-     C(e94e93ee4e8ecaa6), C(1ef8e98e1ea57269), C(5971116272f45a8b),
-     C(187ad68ce95d8eac), C(e94e93ee4e8ecaa6), C(a0ff2a58611838b5),
-     C(b01e03849bfbae6f), C(d081e202e28ea3ab), C(51836bcee762bf13),
-     C(57b8df25)},
+    {C(b2d294931a0e20eb), C(284ffd9a0815bc38), C(1f8a103aac9bbe6), C(57b8df25)},
     {C(7966f53c37b6c6d7), C(8e6abcfb3aa2b88f), C(7f2e5e0724e5f345),
-     C(3eeb60c3f5f8143d), C(a25aec05c422a24f), C(b026b03ad3cca4db),
-     C(e6e030028cc02a02), C(3eeb60c3f5f8143d), C(a25aec05c422a24f),
-     C(b026b03ad3cca4db), C(e6e030028cc02a02), C(16fe679338b34bfc),
-     C(c1be385b5c8a9de4), C(65af5df6567530eb), C(ed3b303df4dc6335),
      C(e9fa36d6)},
     {C(be9bb0abd03b7368), C(13bca93a3031be55), C(e864f4f52b55b472),
-     C(36a8d13a2cbb0939), C(254ac73907413230), C(73520d1522315a70),
-     C(8c9fdb5cf1e1a507), C(36a8d13a2cbb0939), C(254ac73907413230),
-     C(73520d1522315a70), C(8c9fdb5cf1e1a507), C(b3640570b926886),
-     C(fba2344ee87f7bab), C(de57341ab448df05), C(385612ee094fa977),
      C(8f8daefc)},
-    {C(a08d128c5f1649be), C(a8166c3dbbe19aad), C(cb9f914f829ec62c),
-     C(5b2b7ca856fad1c3), C(8093022d682e375d), C(ea5d163ba7ea231f),
-     C(d6181d012c0de641), C(5b2b7ca856fad1c3), C(8093022d682e375d),
-     C(ea5d163ba7ea231f), C(d6181d012c0de641), C(e7d40d0ab8b08159),
-     C(2e82320f51b3a67e), C(27c2e356ea0b63a3), C(58842d01a2b1d077), C(6e1bb7e)},
+    {C(a08d128c5f1649be), C(a8166c3dbbe19aad), C(cb9f914f829ec62c), C(6e1bb7e)},
     {C(7c386f0ffe0465ac), C(530419c9d843dbf3), C(7450e3a4f72b8d8c),
-     C(48b218e3b721810d), C(d3757ac8609bc7fc), C(111ba02a88aefc8),
-     C(e86343137d3bfc2a), C(48b218e3b721810d), C(d3757ac8609bc7fc),
-     C(111ba02a88aefc8), C(e86343137d3bfc2a), C(44ad26b51661b507),
-     C(db1268670274f51e), C(62a5e75beae875f3), C(e266e7a44c5f28c6),
      C(fd0076f0)},
-    {C(bb362094e7ef4f8), C(ff3c2a48966f9725), C(55152803acd4a7fe),
-     C(15747d8c505ffd00), C(438a15f391312cd6), C(e46ca62c26d821f5),
-     C(be78d74c9f79cb44), C(15747d8c505ffd00), C(438a15f391312cd6),
-     C(e46ca62c26d821f5), C(be78d74c9f79cb44), C(a8aa19f3aa59f09a),
-     C(effb3cddab2c9267), C(d78e41ad97cb16a5), C(ace6821513527d32),
-     C(899b17b6)},
+    {C(bb362094e7ef4f8), C(ff3c2a48966f9725), C(55152803acd4a7fe), C(899b17b6)},
     {C(cd80dea24321eea4), C(52b4fdc8130c2b15), C(f3ea100b154bfb82),
-     C(d9ccef1d4be46988), C(5ede0c4e383a5e66), C(da69683716a54d1e),
-     C(bfc3fdf02d242d24), C(d9ccef1d4be46988), C(5ede0c4e383a5e66),
-     C(da69683716a54d1e), C(bfc3fdf02d242d24), C(20ed30274651b3f5),
-     C(4c659824169e86c6), C(637226dae5b52a0e), C(7e050dbd1c71dc7f),
      C(e3e84e31)},
     {C(d599a04125372c3a), C(313136c56a56f363), C(1e993c3677625832),
-     C(2870a99c76a587a4), C(99f74cc0b182dda4), C(8a5e895b2f0ca7b6),
-     C(3d78882d5e0bb1dc), C(2870a99c76a587a4), C(99f74cc0b182dda4),
-     C(8a5e895b2f0ca7b6), C(3d78882d5e0bb1dc), C(f466123732a3e25e),
-     C(aca5e59716a40e50), C(261d2e7383d0e686), C(ce9362d6a42c15a7),
      C(eef79b6b)},
-    {C(dbbf541e9dfda0a), C(1479fceb6db4f844), C(31ab576b59062534),
-     C(a3335c417687cf3a), C(92ff114ac45cda75), C(c3b8a627384f13b5),
-     C(c4f25de33de8b3f7), C(a3335c417687cf3a), C(92ff114ac45cda75),
-     C(c3b8a627384f13b5), C(c4f25de33de8b3f7), C(eacbf520578c5964),
-     C(4cb19c5ab24f3215), C(e7d8a6f67f0c6e7), C(325c2413eb770ada), C(868e3315)},
-    {C(c2ee3288be4fe2bf), C(c65d2f5ddf32b92), C(af6ecdf121ba5485),
-     C(c7cd48f7abf1fe59), C(ce600656ace6f53a), C(8a94a4381b108b34),
-     C(f9d1276c64bf59fb), C(c7cd48f7abf1fe59), C(ce600656ace6f53a),
-     C(8a94a4381b108b34), C(f9d1276c64bf59fb), C(219ce70ff5a112a5),
-     C(e6026c576e2d28d7), C(b8e467f25015e3a6), C(950cb904f37af710),
-     C(4639a426)},
+    {C(dbbf541e9dfda0a), C(1479fceb6db4f844), C(31ab576b59062534), C(868e3315)},
+    {C(c2ee3288be4fe2bf), C(c65d2f5ddf32b92), C(af6ecdf121ba5485), C(4639a426)},
     {C(d86603ced1ed4730), C(f9de718aaada7709), C(db8b9755194c6535),
-     C(d803e1eead47604c), C(ad00f7611970a71b), C(bc50036b16ce71f5),
-     C(afba96210a2ca7d6), C(d803e1eead47604c), C(ad00f7611970a71b),
-     C(bc50036b16ce71f5), C(afba96210a2ca7d6), C(28f7a7be1d6765f0),
-     C(97bd888b93938c68), C(6ad41d1b407ded49), C(b9bfec098dc543e4),
      C(f3213646)},
     {C(915263c671b28809), C(a815378e7ad762fd), C(abec6dc9b669f559),
-     C(d17c928c5342477f), C(745130b795254ad5), C(8c5db926fe88f8ba),
-     C(742a95c953e6d974), C(d17c928c5342477f), C(745130b795254ad5),
-     C(8c5db926fe88f8ba), C(742a95c953e6d974), C(279db8057b5d3e96),
-     C(98168411565b4ec4), C(50a72c54fa1125fa), C(27766a635db73638),
      C(17f148e9)},
-    {C(2b67cdd38c307a5e), C(cb1d45bb5c9fe1c), C(800baf2a02ec18ad),
-     C(6531c1fe32bcb417), C(8c970d8df8cdbeb4), C(917ba5fc67e72b40),
-     C(4b65e4e263e0a426), C(6531c1fe32bcb417), C(8c970d8df8cdbeb4),
-     C(917ba5fc67e72b40), C(4b65e4e263e0a426), C(e0de33ce88a8b3a9),
-     C(f8ef98a437e16b08), C(a5162c0c7c5f7b62), C(dbdac43361b2b881),
-     C(bfd94880)},
+    {C(2b67cdd38c307a5e), C(cb1d45bb5c9fe1c), C(800baf2a02ec18ad), C(bfd94880)},
     {C(2d107419073b9cd0), C(a96db0740cef8f54), C(ec41ee91b3ecdc1b),
-     C(ffe319654c8e7ebc), C(6a67b8f13ead5a72), C(6dd10a34f80d532f),
-     C(6e9cfaece9fbca4), C(ffe319654c8e7ebc), C(6a67b8f13ead5a72),
-     C(6dd10a34f80d532f), C(6e9cfaece9fbca4), C(b4468eb6a30aa7e9),
-     C(e87995bee483222a), C(d036c2c90c609391), C(853306e82fa32247),
      C(bb1fa7f3)},
-    {C(f3e9487ec0e26dfc), C(1ab1f63224e837fa), C(119983bb5a8125d8),
-     C(8950cfcf4bdf622c), C(8847dca82efeef2f), C(646b75b026708169),
-     C(21cab4b1687bd8b), C(8950cfcf4bdf622c), C(8847dca82efeef2f),
-     C(646b75b026708169), C(21cab4b1687bd8b), C(243b489a9eae6231),
-     C(5f3e634c4b779876), C(ff8abd1548eaf646), C(c7962f5f0151914b), C(88816b1)},
+    {C(f3e9487ec0e26dfc), C(1ab1f63224e837fa), C(119983bb5a8125d8), C(88816b1)},
     {C(1160987c8fe86f7d), C(879e6db1481eb91b), C(d7dcb802bfe6885d),
-     C(14453b5cc3d82396), C(4ef700c33ed278bc), C(1639c72ffc00d12e),
-     C(fb140ee6155f700d), C(14453b5cc3d82396), C(4ef700c33ed278bc),
-     C(1639c72ffc00d12e), C(fb140ee6155f700d), C(2e6b5c96a6620862),
-     C(a1f136998cbe19c), C(74e058a3b6c5a712), C(93dcf6bd33928b17), C(5c2faeb3)},
+     C(5c2faeb3)},
     {C(eab8112c560b967b), C(97f550b58e89dbae), C(846ed506d304051f),
-     C(276aa37744b5a028), C(8c10800ee90ea573), C(e6e57d2b33a1e0b7),
-     C(91f83563cd3b9dda), C(276aa37744b5a028), C(8c10800ee90ea573),
-     C(e6e57d2b33a1e0b7), C(91f83563cd3b9dda), C(afbb4739570738a1),
-     C(440ba98da5d8f69), C(fde4e9b0eda20350), C(e67dfa5a2138fa1), C(51b5fc6f)},
+     C(51b5fc6f)},
     {C(1addcf0386d35351), C(b5f436561f8f1484), C(85d38e22181c9bb1),
-     C(ff5c03f003c1fefe), C(e1098670afe7ff6), C(ea445030cf86de19),
-     C(f155c68b5c2967f8), C(ff5c03f003c1fefe), C(e1098670afe7ff6),
-     C(ea445030cf86de19), C(f155c68b5c2967f8), C(95d31b145dbb2e9e),
-     C(914fe1ca3deb3265), C(6066020b1358ccc1), C(c74bb7e2dee15036),
      C(33d94752)},
     {C(d445ba84bf803e09), C(1216c2497038f804), C(2293216ea2237207),
-     C(e2164451c651adfb), C(b2534e65477f9823), C(4d70691a69671e34),
-     C(15be4963dbde8143), C(e2164451c651adfb), C(b2534e65477f9823),
-     C(4d70691a69671e34), C(15be4963dbde8143), C(762e75c406c5e9a3),
-     C(7b7579f7e0356841), C(480533eb066dfce5), C(90ae14ea6bfeb4ae),
      C(b0c92948)},
     {C(37235a096a8be435), C(d9b73130493589c2), C(3b1024f59378d3be),
-     C(ad159f542d81f04e), C(49626a97a946096), C(d8d3998bf09fd304),
-     C(d127a411eae69459), C(ad159f542d81f04e), C(49626a97a946096),
-     C(d8d3998bf09fd304), C(d127a411eae69459), C(8f3253c4eb785a7b),
-     C(4049062f37e62397), C(b9fa04d3b670e5c1), C(1211a7967ac9350f),
      C(c7171590)},
     {C(763ad6ea2fe1c99d), C(cf7af5368ac1e26b), C(4d5e451b3bb8d3d4),
-     C(3712eb913d04e2f2), C(2f9500d319c84d89), C(4ac6eb21a8cf06f9),
-     C(7d1917afcde42744), C(3712eb913d04e2f2), C(2f9500d319c84d89),
-     C(4ac6eb21a8cf06f9), C(7d1917afcde42744), C(6b58604b5dd10903),
-     C(c4288dfbc1e319fc), C(230f75ca96817c6e), C(8894cba3b763756c),
      C(240a67fb)},
     {C(ea627fc84cd1b857), C(85e372494520071f), C(69ec61800845780b),
-     C(a3c1c5ca1b0367), C(eb6933997272bb3d), C(76a72cb62692a655),
-     C(140bb5531edf756e), C(a3c1c5ca1b0367), C(eb6933997272bb3d),
-     C(76a72cb62692a655), C(140bb5531edf756e), C(8d0d8067d1c925f4),
-     C(7b3fa56d8d77a10c), C(2bd00287b0946d88), C(f08c8e4bd65b8970),
      C(e1843cd5)},
     {C(1f2ffd79f2cdc0c8), C(726a1bc31b337aaa), C(678b7f275ef96434),
-     C(5aa82bfaa99d3978), C(c18f96cade5ce18d), C(38404491f9e34c03),
-     C(891fb8926ba0418c), C(5aa82bfaa99d3978), C(c18f96cade5ce18d),
-     C(38404491f9e34c03), C(891fb8926ba0418c), C(e5f69a6398114c15),
-     C(7b8ded3623bc6b1d), C(2f3e5c5da5ff70e8), C(1ab142addea6a9ec),
      C(fda1452b)},
     {C(39a9e146ec4b3210), C(f63f75802a78b1ac), C(e2e22539c94741c3),
-     C(8b305d532e61226e), C(caeae80da2ea2e), C(88a6289a76ac684e),
-     C(8ce5b5f9df1cbd85), C(8b305d532e61226e), C(caeae80da2ea2e),
-     C(88a6289a76ac684e), C(8ce5b5f9df1cbd85), C(8ae1fc4798e00d57),
-     C(e7164b8fb364fc46), C(6a978c9bd3a66943), C(ef10d5ae4dd08dc), C(a2cad330)},
+     C(a2cad330)},
     {C(74cba303e2dd9d6d), C(692699b83289fad1), C(dfb9aa7874678480),
-     C(751390a8a5c41bdc), C(6ee5fbf87605d34), C(6ca73f610f3a8f7c),
-     C(e898b3c996570ad), C(751390a8a5c41bdc), C(6ee5fbf87605d34),
-     C(6ca73f610f3a8f7c), C(e898b3c996570ad), C(98168a5858fc7110),
-     C(6f987fa27aa0daa2), C(f25e3e180d4b36a3), C(d0b03495aeb1be8a),
      C(53467e16)},
     {C(4cbc2b73a43071e0), C(56c5db4c4ca4e0b7), C(1b275a162f46bd3d),
-     C(b87a326e413604bf), C(d8f9a5fa214b03ab), C(8a8bb8265771cf88),
-     C(a655319054f6e70f), C(b87a326e413604bf), C(d8f9a5fa214b03ab),
-     C(8a8bb8265771cf88), C(a655319054f6e70f), C(b499cb8e65a9af44),
-     C(bee7fafcc8307491), C(5d2e55fa9b27cda2), C(63b120f5fb2d6ee5),
      C(da14a8d0)},
     {C(875638b9715d2221), C(d9ba0615c0c58740), C(616d4be2dfe825aa),
-     C(5df25f13ea7bc284), C(165edfaafd2598fb), C(af7215c5c718c696),
-     C(e9f2f9ca655e769), C(5df25f13ea7bc284), C(165edfaafd2598fb),
-     C(af7215c5c718c696), C(e9f2f9ca655e769), C(e459cfcb565d3d2d),
-     C(41d032631be2418a), C(c505db05fd946f60), C(54990394a714f5de),
      C(67333551)},
     {C(fb686b2782994a8d), C(edee60693756bb48), C(e6bc3cae0ded2ef5),
-     C(58eb4d03b2c3ddf5), C(6d2542995f9189f1), C(c0beec58a5f5fea2),
-     C(ed67436f42e2a78b), C(58eb4d03b2c3ddf5), C(6d2542995f9189f1),
-     C(c0beec58a5f5fea2), C(ed67436f42e2a78b), C(dfec763cdb2b5193),
-     C(724a8d5345bd2d6), C(94d4fd1b81457c23), C(28e87c50cdede453), C(a0ebd66e)},
+     C(a0ebd66e)},
     {C(ab21d81a911e6723), C(4c31b07354852f59), C(835da384c9384744),
-     C(7f759dddc6e8549a), C(616dd0ca022c8735), C(94717ad4bc15ceb3),
-     C(f66c7be808ab36e), C(7f759dddc6e8549a), C(616dd0ca022c8735),
-     C(94717ad4bc15ceb3), C(f66c7be808ab36e), C(af8286b550b2f4b7),
-     C(745bd217d20a9f40), C(c73bfb9c5430f015), C(55e65922666e3fc2),
      C(4b769593)},
     {C(33d013cc0cd46ecf), C(3de726423aea122c), C(116af51117fe21a9),
-     C(f271ba474edc562d), C(e6596e67f9dd3ebd), C(c0a288edf808f383),
-     C(b3def70681c6babc), C(f271ba474edc562d), C(e6596e67f9dd3ebd),
-     C(c0a288edf808f383), C(b3def70681c6babc), C(7da7864e9989b095),
-     C(bf2f8718693cd8a1), C(264a9144166da776), C(61ad90676870beb6),
      C(6aa75624)},
-    {C(8ca92c7cd39fae5d), C(317e620e1bf20f1), C(4f0b33bf2194b97f),
-     C(45744afcf131dbee), C(97222392c2559350), C(498a19b280c6d6ed),
-     C(83ac2c36acdb8d49), C(45744afcf131dbee), C(97222392c2559350),
-     C(498a19b280c6d6ed), C(83ac2c36acdb8d49), C(7a69645c294daa62),
-     C(abe9d2be8275b3d2), C(39542019de371085), C(7f4efac8488cd6ad),
-     C(602a3f96)},
-    {C(fdde3b03f018f43e), C(38f932946c78660), C(c84084ce946851ee),
-     C(b6dd09ba7851c7af), C(570de4e1bb13b133), C(c4e784eb97211642),
-     C(8285a7fcdcc7c58d), C(b6dd09ba7851c7af), C(570de4e1bb13b133),
-     C(c4e784eb97211642), C(8285a7fcdcc7c58d), C(d421f47990da899b),
-     C(8aed409c997eaa13), C(7a045929c2e29ccf), C(b373682a6202c86b),
-     C(cd183c4d)},
+    {C(8ca92c7cd39fae5d), C(317e620e1bf20f1), C(4f0b33bf2194b97f), C(602a3f96)},
+    {C(fdde3b03f018f43e), C(38f932946c78660), C(c84084ce946851ee), C(cd183c4d)},
     {C(9c8502050e9c9458), C(d6d2a1a69964beb9), C(1675766f480229b5),
-     C(216e1d6c86cb524c), C(d01cf6fd4f4065c0), C(fffa4ec5b482ea0f),
-     C(a0e20ee6a5404ac1), C(216e1d6c86cb524c), C(d01cf6fd4f4065c0),
-     C(fffa4ec5b482ea0f), C(a0e20ee6a5404ac1), C(c1b037e4eebaf85e),
-     C(634e3d7c3ebf89eb), C(bcda972358c67d1), C(fd1352181e5b8578), C(960a4d07)},
+     C(960a4d07)},
     {C(348176ca2fa2fdd2), C(3a89c514cc360c2d), C(9f90b8afb318d6d0),
-     C(bceee07c11a9ac30), C(2e2d47dff8e77eb7), C(11a394cd7b6d614a),
-     C(1d7c41d54e15cb4a), C(bceee07c11a9ac30), C(2e2d47dff8e77eb7),
-     C(11a394cd7b6d614a), C(1d7c41d54e15cb4a), C(15baa5ae7312b0fc),
-     C(f398f596cc984635), C(8ab8fdf87a6788e8), C(b2b5c1234ab47e2), C(9ae998c4)},
+     C(9ae998c4)},
     {C(4a3d3dfbbaea130b), C(4e221c920f61ed01), C(553fd6cd1304531f),
-     C(bd2b31b5608143fe), C(ab717a10f2554853), C(293857f04d194d22),
-     C(d51be8fa86f254f0), C(bd2b31b5608143fe), C(ab717a10f2554853),
-     C(293857f04d194d22), C(d51be8fa86f254f0), C(1eee39e07686907e),
-     C(639039fe0e8d3052), C(d6ec1470cef97ff), C(370c82b860034f0f), C(74e2179d)},
+     C(74e2179d)},
     {C(b371f768cdf4edb9), C(bdef2ace6d2de0f0), C(e05b4100f7f1baec),
-     C(b9e0d415b4ebd534), C(c97c2a27efaa33d7), C(591cdb35f84ef9da),
-     C(a57d02d0e8e3756c), C(b9e0d415b4ebd534), C(c97c2a27efaa33d7),
-     C(591cdb35f84ef9da), C(a57d02d0e8e3756c), C(23f55f12d7c5c87b),
-     C(4c7ca0fe23221101), C(dbc3020480334564), C(d985992f32c236b1),
      C(ee9bae25)},
-    {C(7a1d2e96934f61f), C(eb1760ae6af7d961), C(887eb0da063005df),
-     C(2228d6725e31b8ab), C(9b98f7e4d0142e70), C(b6a8c2115b8e0fe7),
-     C(b591e2f5ab9b94b1), C(2228d6725e31b8ab), C(9b98f7e4d0142e70),
-     C(b6a8c2115b8e0fe7), C(b591e2f5ab9b94b1), C(6c1feaa8065318e0),
-     C(4e7e2ca21c2e81fb), C(e9fe5d8ce7993c45), C(ee411fa2f12cf8df),
-     C(b66edf10)},
+    {C(7a1d2e96934f61f), C(eb1760ae6af7d961), C(887eb0da063005df), C(b66edf10)},
     {C(8be53d466d4728f2), C(86a5ac8e0d416640), C(984aa464cdb5c8bb),
-     C(87049e68f5d38e59), C(7d8ce44ec6bd7751), C(cc28d08ab414839c),
-     C(6c8f0bd34fe843e3), C(87049e68f5d38e59), C(7d8ce44ec6bd7751),
-     C(cc28d08ab414839c), C(6c8f0bd34fe843e3), C(b8496dcdc01f3e47),
-     C(2f03125c282ac26), C(82a8797ba3f5ef07), C(7c977a4d10bf52b8), C(d6209737)},
-    {C(829677eb03abf042), C(43cad004b6bc2c0), C(f2f224756803971a),
-     C(98d0dbf796480187), C(fbcb5f3e1bef5742), C(5af2a0463bf6e921),
-     C(ad9555bf0120b3a3), C(98d0dbf796480187), C(fbcb5f3e1bef5742),
-     C(5af2a0463bf6e921), C(ad9555bf0120b3a3), C(283e39b3dc99f447),
-     C(bedaa1a4a0250c28), C(9d50546624ff9a57), C(4abaf523d1c090f6), C(b994a88)},
-    {C(754435bae3496fc), C(5707fc006f094dcf), C(8951c86ab19d8e40),
-     C(57c5208e8f021a77), C(f7653fbb69cd9276), C(a484410af21d75cb),
-     C(f19b6844b3d627e8), C(57c5208e8f021a77), C(f7653fbb69cd9276),
-     C(a484410af21d75cb), C(f19b6844b3d627e8), C(f37400fc3ffd9514),
-     C(36ae0d821734edfd), C(5f37820af1f1f306), C(be637d40e6a5ad0), C(a05d43c0)},
+     C(d6209737)},
+    {C(829677eb03abf042), C(43cad004b6bc2c0), C(f2f224756803971a), C(b994a88)},
+    {C(754435bae3496fc), C(5707fc006f094dcf), C(8951c86ab19d8e40), C(a05d43c0)},
     {C(fda9877ea8e3805f), C(31e868b6ffd521b7), C(b08c90681fb6a0fd),
-     C(68110a7f83f5d3ff), C(6d77e045901b85a8), C(84ef681113036d8b),
-     C(3b9f8e3928f56160), C(68110a7f83f5d3ff), C(6d77e045901b85a8),
-     C(84ef681113036d8b), C(3b9f8e3928f56160), C(fc8b7f56c130835),
-     C(a11f3e800638e841), C(d9572267f5cf28c1), C(7897c8149803f2aa),
      C(c79f73a8)},
     {C(2e36f523ca8f5eb5), C(8b22932f89b27513), C(331cd6ecbfadc1bb),
-     C(d1bfe4df12b04cbf), C(f58c17243fd63842), C(3a453cdba80a60af),
-     C(5737b2ca7470ea95), C(d1bfe4df12b04cbf), C(f58c17243fd63842),
-     C(3a453cdba80a60af), C(5737b2ca7470ea95), C(54d44a3f4477030c),
-     C(8168e02d4869aa7f), C(77f383a17778559d), C(95e1737d77a268fc),
      C(a490aff5)},
     {C(21a378ef76828208), C(a5c13037fa841da2), C(506d22a53fbe9812),
-     C(61c9c95d91017da5), C(16f7c83ba68f5279), C(9c0619b0808d05f7),
-     C(83c117ce4e6b70a3), C(61c9c95d91017da5), C(16f7c83ba68f5279),
-     C(9c0619b0808d05f7), C(83c117ce4e6b70a3), C(cfb4c8af7fd01413),
-     C(fdef04e602e72296), C(ed6124d337889b1), C(4919c86707b830da), C(dfad65b4)},
-    {C(ccdd5600054b16ca), C(f78846e84204cb7b), C(1f9faec82c24eac9),
-     C(58634004c7b2d19a), C(24bb5f51ed3b9073), C(46409de018033d00),
-     C(4a9805eed5ac802e), C(58634004c7b2d19a), C(24bb5f51ed3b9073),
-     C(46409de018033d00), C(4a9805eed5ac802e), C(e18de8db306baf82),
-     C(46bbf75f1fa025ff), C(5faf2fb09be09487), C(3fbc62bd4e558fb3), C(1d07dfb)},
+     C(dfad65b4)},
+    {C(ccdd5600054b16ca), C(f78846e84204cb7b), C(1f9faec82c24eac9), C(1d07dfb)},
     {C(7854468f4e0cabd0), C(3a3f6b4f098d0692), C(ae2423ec7799d30d),
-     C(29c3529eb165eeba), C(443de3703b657c35), C(66acbce31ae1bc8d),
-     C(1acc99effe1d547e), C(29c3529eb165eeba), C(443de3703b657c35),
-     C(66acbce31ae1bc8d), C(1acc99effe1d547e), C(cf07f8a57906573d),
-     C(31bafb0bbb9a86e7), C(40c69492702a9346), C(7df61fdaa0b858af),
      C(416df9a0)},
     {C(7f88db5346d8f997), C(88eac9aacc653798), C(68a4d0295f8eefa1),
-     C(ae59ca86f4c3323d), C(25906c09906d5c4c), C(8dd2aa0c0a6584ae),
-     C(232a7d96b38f40e9), C(ae59ca86f4c3323d), C(25906c09906d5c4c),
-     C(8dd2aa0c0a6584ae), C(232a7d96b38f40e9), C(8986ee00a2ed0042),
-     C(c49ae7e428c8a7d1), C(b7dd8280713ac9c2), C(e018720aed1ebc28),
      C(1f8fb9cc)},
     {C(bb3fb5fb01d60fcf), C(1b7cc0847a215eb6), C(1246c994437990a1),
-     C(d4edc954c07cd8f3), C(224f47e7c00a30ab), C(d5ad7ad7f41ef0c6),
-     C(59e089281d869fd7), C(d4edc954c07cd8f3), C(224f47e7c00a30ab),
-     C(d5ad7ad7f41ef0c6), C(59e089281d869fd7), C(f29340d07a14b6f1),
-     C(c87c5ef76d9c4ef3), C(463118794193a9a), C(2922dcb0540f0dbc), C(7abf48e3)},
+     C(7abf48e3)},
     {C(2e783e1761acd84d), C(39158042bac975a0), C(1cd21c5a8071188d),
-     C(b1b7ec44f9302176), C(5cb476450dc0c297), C(dc5ef652521ef6a2),
-     C(3cc79a9e334e1f84), C(b1b7ec44f9302176), C(5cb476450dc0c297),
-     C(dc5ef652521ef6a2), C(3cc79a9e334e1f84), C(769e2a283dbcc651),
-     C(9f24b105c8511d3f), C(c31c15575de2f27e), C(ecfecf32c3ae2d66),
      C(dea4e3dd)},
     {C(392058251cf22acc), C(944ec4475ead4620), C(b330a10b5cb94166),
-     C(54bc9bee7cbe1767), C(485820bdbe442431), C(54d6120ea2972e90),
-     C(f437a0341f29b72a), C(54bc9bee7cbe1767), C(485820bdbe442431),
-     C(54d6120ea2972e90), C(f437a0341f29b72a), C(8f30885c784d5704),
-     C(aa95376b16c7906a), C(e826928cfaf93dc3), C(20e8f54d1c16d7d8),
      C(c6064f22)},
-    {C(adf5c1e5d6419947), C(2a9747bc659d28aa), C(95c5b8cb1f5d62c),
-     C(80973ea532b0f310), C(a471829aa9c17dd9), C(c2ff3479394804ab),
-     C(6bf44f8606753636), C(80973ea532b0f310), C(a471829aa9c17dd9),
-     C(c2ff3479394804ab), C(6bf44f8606753636), C(5184d2973e6dd827),
-     C(121b96369a332d9a), C(5c25d3475ab69e50), C(26d2961d62884168),
-     C(743bed9c)},
+    {C(adf5c1e5d6419947), C(2a9747bc659d28aa), C(95c5b8cb1f5d62c), C(743bed9c)},
     {C(6bc1db2c2bee5aba), C(e63b0ed635307398), C(7b2eca111f30dbbc),
-     C(230d2b3e47f09830), C(ec8624a821c1caf4), C(ea6ec411cdbf1cb1),
-     C(5f38ae82af364e27), C(230d2b3e47f09830), C(ec8624a821c1caf4),
-     C(ea6ec411cdbf1cb1), C(5f38ae82af364e27), C(a519ef515ea7187c),
-     C(6bad5efa7ebae05f), C(748abacb11a74a63), C(a28eef963d1396eb),
      C(fce254d5)},
     {C(b00f898229efa508), C(83b7590ad7f6985c), C(2780e70a0592e41d),
-     C(7122413bdbc94035), C(e7f90fae33bf7763), C(4b6bd0fb30b12387),
-     C(557359c0c44f48ca), C(7122413bdbc94035), C(e7f90fae33bf7763),
-     C(4b6bd0fb30b12387), C(557359c0c44f48ca), C(d5656c3d6bc5f0d),
-     C(983ff8e5e784da99), C(628479671b445bf), C(e179a1e27ce68f5d), C(e47ec9d1)},
+     C(e47ec9d1)},
     {C(b56eb769ce0d9a8c), C(ce196117bfbcaf04), C(b26c3c3797d66165),
-     C(5ed12338f630ab76), C(fab19fcb319116d), C(167f5f42b521724b),
-     C(c4aa56c409568d74), C(5ed12338f630ab76), C(fab19fcb319116d),
-     C(167f5f42b521724b), C(c4aa56c409568d74), C(75fff4b42f8e9778),
-     C(94218f94710c1ea3), C(b7b05efb738b06a6), C(83fff2deabf9cd3), C(334a145c)},
+     C(334a145c)},
     {C(70c0637675b94150), C(259e1669305b0a15), C(46e1dd9fd387a58d),
-     C(fca4e5bc9292788e), C(cd509dc1facce41c), C(bbba575a59d82fe),
-     C(4e2e71c15b45d4d3), C(fca4e5bc9292788e), C(cd509dc1facce41c),
-     C(bbba575a59d82fe), C(4e2e71c15b45d4d3), C(5dc54582ead999c),
-     C(72612d1571963c6f), C(30318a9d2d3d1829), C(785dd00f4cc9c9a0),
      C(adec1e3c)},
     {C(74c0b8a6821faafe), C(abac39d7491370e7), C(faf0b2a48a4e6aed),
-     C(967e970df9673d2a), C(d465247cffa415c0), C(33a1df0ca1107722),
-     C(49fc2a10adce4a32), C(967e970df9673d2a), C(d465247cffa415c0),
-     C(33a1df0ca1107722), C(49fc2a10adce4a32), C(c5707e079a284308),
-     C(573028266635dda6), C(f786f5eee6127fa0), C(b30d79cebfb51266),
      C(f6a9fbf8)},
     {C(5fb5e48ac7b7fa4f), C(a96170f08f5acbc7), C(bbf5c63d4f52a1e5),
-     C(6cc09e60700563e9), C(d18f23221e964791), C(ffc23eeef7af26eb),
-     C(693a954a3622a315), C(815308a32a9b0daf), C(efb2ab27bf6fd0bd),
-     C(9f1ffc0986111118), C(f9a3aa1778ea3985), C(698fe54b2b93933b),
-     C(dacc2b28404d0f10), C(815308a32a9b0daf), C(efb2ab27bf6fd0bd),
      C(5398210c)},
 };
 
 void TestUnchanging(const uint64_t* expected, int offset, int len) {
-  const uint128 u = CityHash128(data + offset, len);
-  const uint128 v = CityHash128WithSeed(data + offset, len, kSeed128);
   EXPECT_EQ(expected[0], CityHash64(data + offset, len));
-  EXPECT_EQ(expected[15], CityHash32(data + offset, len));
+  EXPECT_EQ(expected[3], CityHash32(data + offset, len));
   EXPECT_EQ(expected[1], CityHash64WithSeed(data + offset, len, kSeed0));
   EXPECT_EQ(expected[2],
             CityHash64WithSeeds(data + offset, len, kSeed0, kSeed1));
-  EXPECT_EQ(expected[3], Uint128Low64(u));
-  EXPECT_EQ(expected[4], Uint128High64(u));
-  EXPECT_EQ(expected[5], Uint128Low64(v));
-  EXPECT_EQ(expected[6], Uint128High64(v));
-#ifdef __SSE4_2__
-  const uint128 y = CityHashCrc128(data + offset, len);
-  const uint128 z = CityHashCrc128WithSeed(data + offset, len, kSeed128);
-  uint64_t crc256_results[4];
-  CityHashCrc256(data + offset, len, crc256_results);
-  EXPECT_EQ(expected[7], Uint128Low64(y));
-  EXPECT_EQ(expected[8], Uint128High64(y));
-  EXPECT_EQ(expected[9], Uint128Low64(z));
-  EXPECT_EQ(expected[10], Uint128High64(z));
-  for (int i = 0; i < 4; i++) {
-    EXPECT_EQ(expected[11 + i], crc256_results[i]);
-  }
-#endif
 }
 
 TEST(CityHashTest, Unchanging) {
diff --git a/absl/hash/internal/hash.cc b/absl/hash/internal/hash.cc
index 4bf6409..4ab7a9f 100644
--- a/absl/hash/internal/hash.cc
+++ b/absl/hash/internal/hash.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
diff --git a/absl/hash/internal/hash.h b/absl/hash/internal/hash.h
index 4543d67..9ab9890 100644
--- a/absl/hash/internal/hash.h
+++ b/absl/hash/internal/hash.h
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -221,7 +221,9 @@
 }
 // AbslHashValue() for hashing floating-point values
 template <typename H, typename Float>
-typename std::enable_if<std::is_floating_point<Float>::value, H>::type
+typename std::enable_if<std::is_same<Float, float>::value ||
+                            std::is_same<Float, double>::value,
+                        H>::type
 AbslHashValue(H hash_state, Float value) {
   return hash_internal::hash_bytes(std::move(hash_state),
                                    value == 0 ? 0 : value);
@@ -231,8 +233,9 @@
 // For example, in x86 sizeof(long double)==16 but it only really uses 80-bits
 // of it. This means we can't use hash_bytes on a long double and have to
 // convert it to something else first.
-template <typename H>
-H AbslHashValue(H hash_state, long double value) {
+template <typename H, typename LongDouble>
+typename std::enable_if<std::is_same<LongDouble, long double>::value, H>::type
+AbslHashValue(H hash_state, LongDouble value) {
   const int category = std::fpclassify(value);
   switch (category) {
     case FP_INFINITE:
@@ -264,7 +267,12 @@
 // AbslHashValue() for hashing pointers
 template <typename H, typename T>
 H AbslHashValue(H hash_state, T* ptr) {
-  return hash_internal::hash_bytes(std::move(hash_state), ptr);
+  auto v = reinterpret_cast<uintptr_t>(ptr);
+  // Due to alignment, pointers tend to have low bits as zero, and the next few
+  // bits follow a pattern since they are also multiples of some base value.
+  // Mixing the pointer twice helps prevent stuck low bits for certain alignment
+  // values.
+  return H::combine(std::move(hash_state), v, v);
 }
 
 // AbslHashValue() for hashing nullptr_t
@@ -303,13 +311,13 @@
 
 // AbslHashValue for hashing tuples
 template <typename H, typename... Ts>
-#if _MSC_VER
+#if defined(_MSC_VER)
 // This SFINAE gets MSVC confused under some conditions. Let's just disable it
 // for now.
 H
-#else
+#else  // _MSC_VER
 typename std::enable_if<absl::conjunction<is_hashable<Ts>...>::value, H>::type
-#endif
+#endif  // _MSC_VER
 AbslHashValue(H hash_state, const std::tuple<Ts...>& t) {
   return hash_internal::hash_tuple(std::move(hash_state), t,
                                    absl::make_index_sequence<sizeof...(Ts)>());
@@ -494,6 +502,15 @@
   }
   return H::combine(std::move(hash_state), v.index());
 }
+
+// -----------------------------------------------------------------------------
+// AbslHashValue for Other Types
+// -----------------------------------------------------------------------------
+
+// AbslHashValue for hashing std::bitset is not defined, for the same reason as
+// for vector<bool> (see std::vector above): It does not expose the raw bytes,
+// and a fallback to std::hash<> is most likely faster.
+
 // -----------------------------------------------------------------------------
 
 // hash_range_or_bytes()
@@ -518,51 +535,22 @@
   return hash_state;
 }
 
-// InvokeHashTag
-//
-// InvokeHash(H, const T&) invokes the appropriate hash implementation for a
-// hasher of type `H` and a value of type `T`. If `T` is not hashable, there
-// will be no matching overload of InvokeHash().
-// Note: Some platforms (eg MSVC) do not support the detect idiom on
-// std::hash. In those platforms the last fallback will be std::hash and
-// InvokeHash() will always have a valid overload even if std::hash<T> is not
-// valid.
-//
-// We try the following options in order:
-//   * If is_uniquely_represented, hash bytes directly.
-//   * ADL AbslHashValue(H, const T&) call.
-//   * std::hash<T>
-
-// In MSVC we can't probe std::hash or stdext::hash because it triggers a
-// static_assert instead of failing substitution.
-#if defined(_MSC_VER)
-#undef ABSL_HASH_INTERNAL_CAN_POISON_
-#else   // _MSC_VER
-#define ABSL_HASH_INTERNAL_CAN_POISON_ 1
-#endif  // _MSC_VER
-
 #if defined(ABSL_INTERNAL_LEGACY_HASH_NAMESPACE) && \
-    ABSL_HASH_INTERNAL_CAN_POISON_
+    ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_
 #define ABSL_HASH_INTERNAL_SUPPORT_LEGACY_HASH_ 1
+#else
+#define ABSL_HASH_INTERNAL_SUPPORT_LEGACY_HASH_ 0
 #endif
 
-enum class InvokeHashTag {
-  kUniquelyRepresented,
-  kHashValue,
-#if ABSL_HASH_INTERNAL_SUPPORT_LEGACY_HASH_
-  kLegacyHash,
-#endif  // ABSL_HASH_INTERNAL_SUPPORT_LEGACY_HASH_
-  kStdHash,
-  kNone
-};
-
 // HashSelect
 //
 // Type trait to select the appropriate hash implementation to use.
-// HashSelect<T>::value is an instance of InvokeHashTag that indicates the best
-// available hashing mechanism.
-// See `Note` above about MSVC.
-template <typename T>
+// HashSelect::type<T> will give the proper hash implementation, to be invoked
+// as:
+//   HashSelect::type<T>::Invoke(state, value)
+// Also, HashSelect::type<T>::value is a boolean equal to `true` if there is a
+// valid `Invoke` function. Types that are not hashable will have a ::value of
+// `false`.
 struct HashSelect {
  private:
   struct State : HashStateBase<State> {
@@ -571,95 +559,75 @@
     using State::HashStateBase::combine_contiguous;
   };
 
-  // `Probe<V, Tag>::value` evaluates to `V<T>::value` if it is a valid
-  // expression, and `false` otherwise.
-  // `Probe<V, Tag>::tag` always evaluates to `Tag`.
-  template <template <typename> class V, InvokeHashTag Tag>
-  struct Probe {
+  struct UniquelyRepresentedProbe {
+    template <typename H, typename T>
+    static auto Invoke(H state, const T& value)
+        -> absl::enable_if_t<is_uniquely_represented<T>::value, H> {
+      return hash_internal::hash_bytes(std::move(state), value);
+    }
+  };
+
+  struct HashValueProbe {
+    template <typename H, typename T>
+    static auto Invoke(H state, const T& value) -> absl::enable_if_t<
+        std::is_same<H,
+                     decltype(AbslHashValue(std::move(state), value))>::value,
+        H> {
+      return AbslHashValue(std::move(state), value);
+    }
+  };
+
+  struct LegacyHashProbe {
+#if ABSL_HASH_INTERNAL_SUPPORT_LEGACY_HASH_
+    template <typename H, typename T>
+    static auto Invoke(H state, const T& value) -> absl::enable_if_t<
+        std::is_convertible<
+            decltype(ABSL_INTERNAL_LEGACY_HASH_NAMESPACE::hash<T>()(value)),
+            size_t>::value,
+        H> {
+      return hash_internal::hash_bytes(
+          std::move(state),
+          ABSL_INTERNAL_LEGACY_HASH_NAMESPACE::hash<T>{}(value));
+    }
+#endif  // ABSL_HASH_INTERNAL_SUPPORT_LEGACY_HASH_
+  };
+
+  struct StdHashProbe {
+    template <typename H, typename T>
+    static auto Invoke(H state, const T& value)
+        -> absl::enable_if_t<type_traits_internal::IsHashable<T>::value, H> {
+      return hash_internal::hash_bytes(std::move(state), std::hash<T>{}(value));
+    }
+  };
+
+  template <typename Hash, typename T>
+  struct Probe : Hash {
    private:
-    template <typename U, typename std::enable_if<V<U>::value, int>::type = 0>
+    template <typename H, typename = decltype(H::Invoke(
+                              std::declval<State>(), std::declval<const T&>()))>
     static std::true_type Test(int);
     template <typename U>
     static std::false_type Test(char);
 
    public:
-    static constexpr InvokeHashTag kTag = Tag;
-    static constexpr bool value = decltype(
-        Test<absl::remove_const_t<absl::remove_reference_t<T>>>(0))::value;
+    static constexpr bool value = decltype(Test<Hash>(0))::value;
   };
 
-  template <typename U>
-  using ProbeUniquelyRepresented = is_uniquely_represented<U>;
-
-  template <typename U>
-  using ProbeHashValue =
-      std::is_same<State, decltype(AbslHashValue(std::declval<State>(),
-                                                 std::declval<const U&>()))>;
-
-#if ABSL_HASH_INTERNAL_SUPPORT_LEGACY_HASH_
-  template <typename U>
-  using ProbeLegacyHash =
-      std::is_convertible<decltype(ABSL_INTERNAL_LEGACY_HASH_NAMESPACE::hash<
-                                   U>()(std::declval<const U&>())),
-                          size_t>;
-#endif  // ABSL_HASH_INTERNAL_SUPPORT_LEGACY_HASH_
-
-  template <typename U>
-  using ProbeStdHash =
-#if ABSL_HASH_INTERNAL_CAN_POISON_
-      std::is_convertible<decltype(std::hash<U>()(std::declval<const U&>())),
-                          size_t>;
-#else   // ABSL_HASH_INTERNAL_CAN_POISON_
-      std::true_type;
-#endif  // ABSL_HASH_INTERNAL_CAN_POISON_
-
-  template <typename U>
-  using ProbeNone = std::true_type;
-
  public:
   // Probe each implementation in order.
   // disjunction provides short circuting wrt instantiation.
-  static constexpr InvokeHashTag value = absl::disjunction<
-      Probe<ProbeUniquelyRepresented, InvokeHashTag::kUniquelyRepresented>,
-      Probe<ProbeHashValue, InvokeHashTag::kHashValue>,
-#if ABSL_HASH_INTERNAL_SUPPORT_LEGACY_HASH_
-      Probe<ProbeLegacyHash, InvokeHashTag::kLegacyHash>,
-#endif  // ABSL_HASH_INTERNAL_SUPPORT_LEGACY_HASH_
-      Probe<ProbeStdHash, InvokeHashTag::kStdHash>,
-      Probe<ProbeNone, InvokeHashTag::kNone>>::kTag;
+  template <typename T>
+  using Apply = absl::disjunction<         //
+      Probe<UniquelyRepresentedProbe, T>,  //
+      Probe<HashValueProbe, T>,            //
+      Probe<LegacyHashProbe, T>,           //
+      Probe<StdHashProbe, T>,              //
+      std::false_type>;
 };
 
 template <typename T>
-struct is_hashable : std::integral_constant<bool, HashSelect<T>::value !=
-                                                      InvokeHashTag::kNone> {};
-
-template <typename H, typename T>
-absl::enable_if_t<HashSelect<T>::value == InvokeHashTag::kUniquelyRepresented,
-                  H>
-InvokeHash(H state, const T& value) {
-  return hash_internal::hash_bytes(std::move(state), value);
-}
-
-template <typename H, typename T>
-absl::enable_if_t<HashSelect<T>::value == InvokeHashTag::kHashValue, H>
-InvokeHash(H state, const T& value) {
-  return AbslHashValue(std::move(state), value);
-}
-
-#if ABSL_HASH_INTERNAL_SUPPORT_LEGACY_HASH_
-template <typename H, typename T>
-absl::enable_if_t<HashSelect<T>::value == InvokeHashTag::kLegacyHash, H>
-InvokeHash(H state, const T& value) {
-  return hash_internal::hash_bytes(
-      std::move(state), ABSL_INTERNAL_LEGACY_HASH_NAMESPACE::hash<T>{}(value));
-}
-#endif  // ABSL_HASH_INTERNAL_SUPPORT_LEGACY_HASH_
-
-template <typename H, typename T>
-absl::enable_if_t<HashSelect<T>::value == InvokeHashTag::kStdHash, H>
-InvokeHash(H state, const T& value) {
-  return hash_internal::hash_bytes(std::move(state), std::hash<T>{}(value));
-}
+struct is_hashable
+    : std::integral_constant<bool, HashSelect::template Apply<T>::value> {};
 
 // CityHashState
 class CityHashState : public HashStateBase<CityHashState> {
@@ -869,7 +837,8 @@
 template <typename H>
 template <typename T, typename... Ts>
 H HashStateBase<H>::combine(H state, const T& value, const Ts&... values) {
-  return H::combine(hash_internal::InvokeHash(std::move(state), value),
+  return H::combine(hash_internal::HashSelect::template Apply<T>::Invoke(
+                        std::move(state), value),
                     values...);
 }
 
diff --git a/absl/hash/internal/print_hash_of.cc b/absl/hash/internal/print_hash_of.cc
index b6df31c..c392125 100644
--- a/absl/hash/internal/print_hash_of.cc
+++ b/absl/hash/internal/print_hash_of.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
diff --git a/absl/hash/internal/spy_hash_state.h b/absl/hash/internal/spy_hash_state.h
index 03d795b..c4cc8d0 100644
--- a/absl/hash/internal/spy_hash_state.h
+++ b/absl/hash/internal/spy_hash_state.h
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -39,8 +39,7 @@
 template <typename T>
 class SpyHashStateImpl : public HashStateBase<SpyHashStateImpl<T>> {
  public:
-  SpyHashStateImpl()
-      : error_(std::make_shared<absl::optional<std::string>>()) {
+  SpyHashStateImpl() : error_(std::make_shared<absl::optional<std::string>>()) {
     static_assert(std::is_void<T>::value, "");
   }
 
@@ -170,7 +169,6 @@
   // AbslHashValue directly (because the hash state type does not match).
   static bool direct_absl_hash_value_error_;
 
-
   std::vector<std::string> hash_representation_;
   // This is a shared_ptr because we want all instances of the particular
   // SpyHashState run to share the field. This way we can set the error for
@@ -200,7 +198,7 @@
 template <
     typename T, typename U,
     // Only trigger for when (T != U),
-    absl::enable_if_t<!std::is_same<T, U>::value, int> = 0,
+    typename = absl::enable_if_t<!std::is_same<T, U>::value>,
     // This statement works in two ways:
     //  - First, it instantiates RunOnStartup and forces the initialization of
     //    `run`, which set the global variable.
diff --git a/absl/memory/BUILD.bazel b/absl/memory/BUILD.bazel
index 89a312e..7c6366f 100644
--- a/absl/memory/BUILD.bazel
+++ b/absl/memory/BUILD.bazel
@@ -5,7 +5,7 @@
 # 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
+#      https://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,
@@ -15,7 +15,7 @@
 #
 
 load(
-    "//absl:copts.bzl",
+    "//absl:copts/configure_copts.bzl",
     "ABSL_DEFAULT_COPTS",
     "ABSL_TEST_COPTS",
     "ABSL_EXCEPTIONS_FLAG",
diff --git a/absl/memory/CMakeLists.txt b/absl/memory/CMakeLists.txt
index 5958f5c..0a81220 100644
--- a/absl/memory/CMakeLists.txt
+++ b/absl/memory/CMakeLists.txt
@@ -5,7 +5,7 @@
 # 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
+#      https://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,
@@ -14,58 +14,45 @@
 # limitations under the License.
 #
 
-list(APPEND MEMORY_PUBLIC_HEADERS
-  "memory.h"
-)
-
-
-absl_header_library(
-  TARGET
-    absl_memory
-  EXPORT_NAME
+absl_cc_library(
+  NAME
     memory
+  HDRS
+    "memory.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::core_headers
+    absl::meta
+  PUBLIC
 )
 
-#
-## TESTS
-#
-
-# test memory_test
-list(APPEND MEMORY_TEST_SRC
-  "memory_test.cc"
-  ${MEMORY_PUBLIC_HEADERS}
-)
-set(MEMORY_TEST_PUBLIC_LIBRARIES absl::base absl::memory)
-
-
-
-absl_test(
-  TARGET
+absl_cc_test(
+  NAME
     memory_test
-  SOURCES
-    ${MEMORY_TEST_SRC}
-  PUBLIC_LIBRARIES
-    ${MEMORY_TEST_PUBLIC_LIBRARIES}
+  SRCS
+    "memory_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::memory
+    absl::base
+    absl::core_headers
+    gmock_main
 )
 
-
-# test memory_exception_safety_test
-set(MEMORY_EXCEPTION_SAFETY_TEST_SRC "memory_exception_safety_test.cc")
-set(MEMORY_EXCEPTION_SAFETY_TEST_PUBLIC_LIBRARIES
-  absl::memory
-  absl_base_internal_exception_safety_testing
-)
-
-absl_test(
-  TARGET
+absl_cc_test(
+  NAME
     memory_exception_safety_test
-  SOURCES
-    ${MEMORY_EXCEPTION_SAFETY_TEST_SRC}
-  PUBLIC_LIBRARIES
-    ${MEMORY_EXCEPTION_SAFETY_TEST_PUBLIC_LIBRARIES}
-  PRIVATE_COMPILE_FLAGS
+  SRCS
+    "memory_exception_safety_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
     ${ABSL_EXCEPTIONS_FLAG}
+  LINKOPTS
+    ${ABSL_EXCEPTIONS_FLAG_LINKOPTS}
+  DEPS
+    absl::memory
+    absl::exception_safety_testing
+    gmock_main
 )
-
-
-
diff --git a/absl/memory/memory.h b/absl/memory/memory.h
index 1eaec0f..5a4a1a1 100644
--- a/absl/memory/memory.h
+++ b/absl/memory/memory.h
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -47,19 +47,14 @@
 //   X* NewX(int, int);
 //   auto x = WrapUnique(NewX(1, 2));  // 'x' is std::unique_ptr<X>.
 //
-// The purpose of WrapUnique is to automatically deduce the pointer type. If you
-// wish to make the type explicit, for readability reasons or because you prefer
-// to use a base-class pointer rather than a derived one, just use
+// Do not call WrapUnique with an explicit type, as in
+// `WrapUnique<X>(NewX(1, 2))`.  The purpose of WrapUnique is to automatically
+// deduce the pointer type. If you wish to make the type explicit, just use
 // `std::unique_ptr` directly.
 //
-// Example:
-//   X* Factory(int, int);
-//   auto x = std::unique_ptr<X>(Factory(1, 2));
+//   auto x = std::unique_ptr<X>(NewX(1, 2));
 //                  - or -
-//   std::unique_ptr<X> x(Factory(1, 2));
-//
-// This has the added advantage of working whether Factory returns a raw
-// pointer or a `std::unique_ptr`.
+//   std::unique_ptr<X> x(NewX(1, 2));
 //
 // While `absl::WrapUnique` is useful for capturing the output of a raw
 // pointer factory, prefer 'absl::make_unique<T>(args...)' over
@@ -120,7 +115,7 @@
 //
 // For more background on why `std::unique_ptr<T>(new T(a,b))` is problematic,
 // see Herb Sutter's explanation on
-// (Exception-Safe Function Calls)[http://herbsutter.com/gotw/_102/].
+// (Exception-Safe Function Calls)[https://herbsutter.com/gotw/_102/].
 // (In general, reviewers should treat `new T(a,b)` with scrutiny.)
 //
 // Example usage:
@@ -599,7 +594,7 @@
     return a.max_size();
   }
   static size_type max_size_impl(char, const Alloc&) {
-    return std::numeric_limits<size_type>::max() / sizeof(value_type);
+    return (std::numeric_limits<size_type>::max)() / sizeof(value_type);
   }
 
   template <typename A>
@@ -646,7 +641,7 @@
     : memory_internal::ExtractOrT<memory_internal::GetIsNothrow, Alloc,
                                   std::false_type> {};
 
-#if ABSL_ALLOCATOR_NOTHROW
+#if defined(ABSL_ALLOCATOR_NOTHROW) && ABSL_ALLOCATOR_NOTHROW
 template <typename T>
 struct allocator_is_nothrow<std::allocator<T>> : std::true_type {};
 struct default_allocator_is_nothrow : std::true_type {};
@@ -655,59 +650,42 @@
 #endif
 
 namespace memory_internal {
-#ifdef ABSL_HAVE_EXCEPTIONS  // ConstructRange
 template <typename Allocator, typename Iterator, typename... Args>
 void ConstructRange(Allocator& alloc, Iterator first, Iterator last,
                     const Args&... args) {
   for (Iterator cur = first; cur != last; ++cur) {
-    try {
-      std::allocator_traits<Allocator>::construct(alloc, cur, args...);
-    } catch (...) {
+    ABSL_INTERNAL_TRY {
+      std::allocator_traits<Allocator>::construct(alloc, std::addressof(*cur),
+                                                  args...);
+    }
+    ABSL_INTERNAL_CATCH_ANY {
       while (cur != first) {
         --cur;
-        std::allocator_traits<Allocator>::destroy(alloc, cur);
+        std::allocator_traits<Allocator>::destroy(alloc, std::addressof(*cur));
       }
-      throw;
+      ABSL_INTERNAL_RETHROW;
     }
   }
 }
-#else   // ABSL_HAVE_EXCEPTIONS  // ConstructRange
-template <typename Allocator, typename Iterator, typename... Args>
-void ConstructRange(Allocator& alloc, Iterator first, Iterator last,
-                    const Args&... args) {
-  for (; first != last; ++first) {
-    std::allocator_traits<Allocator>::construct(alloc, first, args...);
-  }
-}
-#endif  // ABSL_HAVE_EXCEPTIONS  // ConstructRange
 
-#ifdef ABSL_HAVE_EXCEPTIONS  // CopyRange
 template <typename Allocator, typename Iterator, typename InputIterator>
 void CopyRange(Allocator& alloc, Iterator destination, InputIterator first,
                InputIterator last) {
   for (Iterator cur = destination; first != last;
        static_cast<void>(++cur), static_cast<void>(++first)) {
-    try {
-      std::allocator_traits<Allocator>::construct(alloc, cur, *first);
-    } catch (...) {
+    ABSL_INTERNAL_TRY {
+      std::allocator_traits<Allocator>::construct(alloc, std::addressof(*cur),
+                                                  *first);
+    }
+    ABSL_INTERNAL_CATCH_ANY {
       while (cur != destination) {
         --cur;
-        std::allocator_traits<Allocator>::destroy(alloc, cur);
+        std::allocator_traits<Allocator>::destroy(alloc, std::addressof(*cur));
       }
-      throw;
+      ABSL_INTERNAL_RETHROW;
     }
   }
 }
-#else   // ABSL_HAVE_EXCEPTIONS  // CopyRange
-template <typename Allocator, typename Iterator, typename InputIterator>
-void CopyRange(Allocator& alloc, Iterator destination, InputIterator first,
-               InputIterator last) {
-  for (; first != last;
-       static_cast<void>(++destination), static_cast<void>(++first)) {
-    std::allocator_traits<Allocator>::construct(alloc, destination, *first);
-  }
-}
-#endif  // ABSL_HAVE_EXCEPTIONS  // CopyRange
 }  // namespace memory_internal
 }  // namespace absl
 
diff --git a/absl/memory/memory_exception_safety_test.cc b/absl/memory/memory_exception_safety_test.cc
index 00d2b19..a1c3970 100644
--- a/absl/memory/memory_exception_safety_test.cc
+++ b/absl/memory/memory_exception_safety_test.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
diff --git a/absl/memory/memory_test.cc b/absl/memory/memory_test.cc
index 2e453e2..8905433 100644
--- a/absl/memory/memory_test.cc
+++ b/absl/memory/memory_test.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -69,6 +69,45 @@
   EXPECT_EQ("hi", *p);
 }
 
+// InitializationVerifier fills in a pattern when allocated so we can
+// distinguish between its default and value initialized states (without
+// accessing truly uninitialized memory).
+struct InitializationVerifier {
+  static constexpr int kDefaultScalar = 0x43;
+  static constexpr int kDefaultArray = 0x4B;
+
+  static void* operator new(size_t n) {
+    void* ret = ::operator new(n);
+    memset(ret, kDefaultScalar, n);
+    return ret;
+  }
+
+  static void* operator new[](size_t n) {
+    void* ret = ::operator new[](n);
+    memset(ret, kDefaultArray, n);
+    return ret;
+  }
+
+  int a;
+  int b;
+};
+
+TEST(Initialization, MakeUnique) {
+  auto p = absl::make_unique<InitializationVerifier>();
+
+  EXPECT_EQ(0, p->a);
+  EXPECT_EQ(0, p->b);
+}
+
+TEST(Initialization, MakeUniqueArray) {
+  auto p = absl::make_unique<InitializationVerifier[]>(2);
+
+  EXPECT_EQ(0, p[0].a);
+  EXPECT_EQ(0, p[0].b);
+  EXPECT_EQ(0, p[1].a);
+  EXPECT_EQ(0, p[1].b);
+}
+
 struct MoveOnly {
   MoveOnly() = default;
   explicit MoveOnly(int i1) : ip1{new int{i1}} {}
@@ -145,7 +184,7 @@
     explicit TakesStdType(const std::vector<int> &vec) {}
   };
   using absl::make_unique;
-  make_unique<TakesStdType>(std::vector<int>());
+  (void)make_unique<TakesStdType>(std::vector<int>());
 }
 
 #if 0
diff --git a/absl/meta/BUILD.bazel b/absl/meta/BUILD.bazel
index dbc9717..1c39fa9 100644
--- a/absl/meta/BUILD.bazel
+++ b/absl/meta/BUILD.bazel
@@ -1,5 +1,5 @@
 load(
-    "//absl:copts.bzl",
+    "//absl:copts/configure_copts.bzl",
     "ABSL_DEFAULT_COPTS",
     "ABSL_TEST_COPTS",
 )
diff --git a/absl/meta/CMakeLists.txt b/absl/meta/CMakeLists.txt
index adb0ceb..74d4a54 100644
--- a/absl/meta/CMakeLists.txt
+++ b/absl/meta/CMakeLists.txt
@@ -5,7 +5,7 @@
 # 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
+#      https://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,
@@ -14,39 +14,37 @@
 # limitations under the License.
 #
 
-list(APPEND META_PUBLIC_HEADERS
-  "type_traits.h"
+absl_cc_library(
+  NAME
+    type_traits
+  HDRS
+    "type_traits.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::config
+  PUBLIC
 )
 
-
-#
-## TESTS
-#
-
-# test type_traits_test
-list(APPEND TYPE_TRAITS_TEST_SRC
-  "type_traits_test.cc"
-  ${META_PUBLIC_HEADERS}
-)
-
-absl_header_library(
-  TARGET
-    absl_meta
-  PUBLIC_LIBRARIES
-    absl::base
-  EXPORT_NAME
-    meta
- )
-
-absl_test(
-  TARGET
+absl_cc_test(
+  NAME
     type_traits_test
-  SOURCES
-    ${TYPE_TRAITS_TEST_SRC}
-  PUBLIC_LIBRARIES
+  SRCS
+    "type_traits_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::type_traits
     absl::base
-    absl::meta
+    absl::core_headers
+    gmock_main
 )
 
-
-
+# component target
+absl_cc_library(
+  NAME
+    meta
+  DEPS
+    absl::type_traits
+  PUBLIC
+)
diff --git a/absl/meta/type_traits.h b/absl/meta/type_traits.h
index 23ebd6e..fbdc921 100644
--- a/absl/meta/type_traits.h
+++ b/absl/meta/type_traits.h
@@ -5,7 +5,7 @@
 // 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
+//      https://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,
@@ -22,7 +22,7 @@
 // support type inference, classification, and transformation, as well as
 // make it easier to write templates based on generic type behavior.
 //
-// See http://en.cppreference.com/w/cpp/header/type_traits
+// See https://en.cppreference.com/w/cpp/header/type_traits
 //
 // WARNING: use of many of the constructs in this header will count as "complex
 // template metaprogramming", so before proceeding, please carefully consider
@@ -246,7 +246,7 @@
 // For the purposes of this check, the call to std::declval is considered
 // trivial."
 //
-// Notes from http://en.cppreference.com/w/cpp/types/is_constructible:
+// Notes from https://en.cppreference.com/w/cpp/types/is_constructible:
 // In many implementations, is_nothrow_constructible also checks if the
 // destructor throws because it is effectively noexcept(T(arg)). Same
 // applies to is_trivially_constructible, which, in these implementations, also
@@ -413,24 +413,139 @@
 using result_of_t = typename std::result_of<T>::type;
 
 namespace type_traits_internal {
+// In MSVC we can't probe std::hash or stdext::hash because it triggers a
+// static_assert instead of failing substitution. Libc++ prior to 4.0
+// also used a static_assert.
+//
+#if defined(_MSC_VER) || (defined(_LIBCPP_VERSION) && \
+                          _LIBCPP_VERSION < 4000 && _LIBCPP_STD_VER > 11)
+#define ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_ 0
+#else
+#define ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_ 1
+#endif
+
+#if !ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_
 template <typename Key, typename = size_t>
+struct IsHashable : std::true_type {};
+#else   // ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_
+template <typename Key, typename = void>
 struct IsHashable : std::false_type {};
 
 template <typename Key>
-struct IsHashable<Key,
-                  decltype(std::declval<std::hash<Key>>()(std::declval<Key>()))>
-    : std::true_type {};
+struct IsHashable<
+    Key,
+    absl::enable_if_t<std::is_convertible<
+        decltype(std::declval<std::hash<Key>&>()(std::declval<Key const&>())),
+        std::size_t>::value>> : std::true_type {};
+#endif  // !ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_
 
-template <typename Key>
-struct IsHashEnabled
-    : absl::conjunction<std::is_default_constructible<std::hash<Key>>,
-                        std::is_copy_constructible<std::hash<Key>>,
-                        std::is_destructible<std::hash<Key>>,
-                        absl::is_copy_assignable<std::hash<Key>>,
-                        IsHashable<Key>> {};
+struct AssertHashEnabledHelper {
+ private:
+  static void Sink(...) {}
+  struct NAT {};
+
+  template <class Key>
+  static auto GetReturnType(int)
+      -> decltype(std::declval<std::hash<Key>>()(std::declval<Key const&>()));
+  template <class Key>
+  static NAT GetReturnType(...);
+
+  template <class Key>
+  static std::nullptr_t DoIt() {
+    static_assert(IsHashable<Key>::value,
+                  "std::hash<Key> does not provide a call operator");
+    static_assert(
+        std::is_default_constructible<std::hash<Key>>::value,
+        "std::hash<Key> must be default constructible when it is enabled");
+    static_assert(
+        std::is_copy_constructible<std::hash<Key>>::value,
+        "std::hash<Key> must be copy constructible when it is enabled");
+    static_assert(absl::is_copy_assignable<std::hash<Key>>::value,
+                  "std::hash<Key> must be copy assignable when it is enabled");
+    // is_destructible is unchecked as it's implied by each of the
+    // is_constructible checks.
+    using ReturnType = decltype(GetReturnType<Key>(0));
+    static_assert(std::is_same<ReturnType, NAT>::value ||
+                      std::is_same<ReturnType, size_t>::value,
+                  "std::hash<Key> must return size_t");
+    return nullptr;
+  }
+
+  template <class... Ts>
+  friend void AssertHashEnabled();
+};
+
+template <class... Ts>
+inline void AssertHashEnabled() {
+  using Helper = AssertHashEnabledHelper;
+  Helper::Sink(Helper::DoIt<Ts>()...);
+}
 
 }  // namespace type_traits_internal
 
+// An internal namespace that is required to implement the C++17 swap traits.
+// It is not further nested in type_traits_internal to avoid long symbol names.
+namespace swap_internal {
+
+// Necessary for the traits.
+using std::swap;
+
+// This declaration prevents global `swap` and `absl::swap` overloads from being
+// considered unless ADL picks them up.
+void swap();
+
+template <class T>
+using IsSwappableImpl = decltype(swap(std::declval<T&>(), std::declval<T&>()));
+
+// NOTE: This dance with the default template parameter is for MSVC.
+template <class T,
+          class IsNoexcept = std::integral_constant<
+              bool, noexcept(swap(std::declval<T&>(), std::declval<T&>()))>>
+using IsNothrowSwappableImpl = typename std::enable_if<IsNoexcept::value>::type;
+
+// IsSwappable
+//
+// Determines whether the standard swap idiom is a valid expression for
+// arguments of type `T`.
+template <class T>
+struct IsSwappable
+    : absl::type_traits_internal::is_detected<IsSwappableImpl, T> {};
+
+// IsNothrowSwappable
+//
+// Determines whether the standard swap idiom is a valid expression for
+// arguments of type `T` and is noexcept.
+template <class T>
+struct IsNothrowSwappable
+    : absl::type_traits_internal::is_detected<IsNothrowSwappableImpl, T> {};
+
+// Swap()
+//
+// Performs the swap idiom from a namespace where valid candidates may only be
+// found in `std` or via ADL.
+template <class T, absl::enable_if_t<IsSwappable<T>::value, int> = 0>
+void Swap(T& lhs, T& rhs) noexcept(IsNothrowSwappable<T>::value) {
+  swap(lhs, rhs);
+}
+
+// StdSwapIsUnconstrained
+//
+// Some standard library implementations are broken in that they do not
+// constrain `std::swap`. This will effectively tell us if we are dealing with
+// one of those implementations.
+using StdSwapIsUnconstrained = IsSwappable<void()>;
+
+}  // namespace swap_internal
+
+namespace type_traits_internal {
+
+// Make the swap-related traits/function accessible from this namespace.
+using swap_internal::IsNothrowSwappable;
+using swap_internal::IsSwappable;
+using swap_internal::Swap;
+using swap_internal::StdSwapIsUnconstrained;
+
+}  // namespace type_traits_internal
 }  // namespace absl
 
 #endif  // ABSL_META_TYPE_TRAITS_H_
diff --git a/absl/meta/type_traits_test.cc b/absl/meta/type_traits_test.cc
index f51f5de..912336e 100644
--- a/absl/meta/type_traits_test.cc
+++ b/absl/meta/type_traits_test.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -953,4 +953,85 @@
 #endif  // _LIBCPP_VERSION
 }
 
+namespace adl_namespace {
+
+struct DeletedSwap {
+};
+
+void swap(DeletedSwap&, DeletedSwap&) = delete;
+
+struct SpecialNoexceptSwap {
+  SpecialNoexceptSwap(SpecialNoexceptSwap&&) {}
+  SpecialNoexceptSwap& operator=(SpecialNoexceptSwap&&) { return *this; }
+  ~SpecialNoexceptSwap() = default;
+};
+
+void swap(SpecialNoexceptSwap&, SpecialNoexceptSwap&) noexcept {}
+
+}  // namespace adl_namespace
+
+TEST(TypeTraitsTest, IsSwappable) {
+  using absl::type_traits_internal::IsSwappable;
+  using absl::type_traits_internal::StdSwapIsUnconstrained;
+
+  EXPECT_TRUE(IsSwappable<int>::value);
+
+  struct S {};
+  EXPECT_TRUE(IsSwappable<S>::value);
+
+  struct NoConstruct {
+    NoConstruct(NoConstruct&&) = delete;
+    NoConstruct& operator=(NoConstruct&&) { return *this; }
+    ~NoConstruct() = default;
+  };
+
+  EXPECT_EQ(IsSwappable<NoConstruct>::value, StdSwapIsUnconstrained::value);
+  struct NoAssign {
+    NoAssign(NoAssign&&) {}
+    NoAssign& operator=(NoAssign&&) = delete;
+    ~NoAssign() = default;
+  };
+
+  EXPECT_EQ(IsSwappable<NoAssign>::value, StdSwapIsUnconstrained::value);
+
+  EXPECT_FALSE(IsSwappable<adl_namespace::DeletedSwap>::value);
+
+  EXPECT_TRUE(IsSwappable<adl_namespace::SpecialNoexceptSwap>::value);
+}
+
+TEST(TypeTraitsTest, IsNothrowSwappable) {
+  using absl::type_traits_internal::IsNothrowSwappable;
+  using absl::type_traits_internal::StdSwapIsUnconstrained;
+
+  EXPECT_TRUE(IsNothrowSwappable<int>::value);
+
+  struct NonNoexceptMoves {
+    NonNoexceptMoves(NonNoexceptMoves&&) {}
+    NonNoexceptMoves& operator=(NonNoexceptMoves&&) { return *this; }
+    ~NonNoexceptMoves() = default;
+  };
+
+  EXPECT_FALSE(IsNothrowSwappable<NonNoexceptMoves>::value);
+
+  struct NoConstruct {
+    NoConstruct(NoConstruct&&) = delete;
+    NoConstruct& operator=(NoConstruct&&) { return *this; }
+    ~NoConstruct() = default;
+  };
+
+  EXPECT_FALSE(IsNothrowSwappable<NoConstruct>::value);
+
+  struct NoAssign {
+    NoAssign(NoAssign&&) {}
+    NoAssign& operator=(NoAssign&&) = delete;
+    ~NoAssign() = default;
+  };
+
+  EXPECT_FALSE(IsNothrowSwappable<NoAssign>::value);
+
+  EXPECT_FALSE(IsNothrowSwappable<adl_namespace::DeletedSwap>::value);
+
+  EXPECT_TRUE(IsNothrowSwappable<adl_namespace::SpecialNoexceptSwap>::value);
+}
+
 }  // namespace
diff --git a/absl/numeric/BUILD.bazel b/absl/numeric/BUILD.bazel
index 324ce66..7cd7ee1 100644
--- a/absl/numeric/BUILD.bazel
+++ b/absl/numeric/BUILD.bazel
@@ -4,7 +4,7 @@
 # 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
+#      https://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,
@@ -13,7 +13,7 @@
 # limitations under the License.
 
 load(
-    "//absl:copts.bzl",
+    "//absl:copts/configure_copts.bzl",
     "ABSL_DEFAULT_COPTS",
     "ABSL_TEST_COPTS",
 )
diff --git a/absl/numeric/CMakeLists.txt b/absl/numeric/CMakeLists.txt
index 3360b2e..d26141c 100644
--- a/absl/numeric/CMakeLists.txt
+++ b/absl/numeric/CMakeLists.txt
@@ -5,7 +5,7 @@
 # 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
+#      https://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,
@@ -14,49 +14,45 @@
 # limitations under the License.
 #
 
-list(APPEND NUMERIC_PUBLIC_HEADERS
-  "int128.h"
-)
-
-
-# library 128
-list(APPEND INT128_SRC
-  "int128.cc"
-  ${NUMERIC_PUBLIC_HEADERS}
-)
-absl_library(
-  TARGET
-    absl_int128
-  SOURCES
-    ${INT128_SRC}
-  PUBLIC_LIBRARIES
-    ${INT128_PUBLIC_LIBRARIES}
-  EXPORT_NAME
+absl_cc_library(
+  NAME
     int128
+  HDRS
+    "int128.h"
+  SRCS
+    "int128.cc"
+    "int128_have_intrinsic.inc"
+    "int128_no_intrinsic.inc"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::config
+    absl::core_headers
+  PUBLIC
 )
 
-
-absl_header_library(
-  TARGET
-    absl_numeric
-  PUBLIC_LIBRARIES
-    absl::int128
-  EXPORT_NAME
-    numeric
-)
-
-# test int128_test
-set(INT128_TEST_SRC "int128_test.cc")
-set(INT128_TEST_PUBLIC_LIBRARIES absl::numeric absl::base)
-
-absl_test(
-  TARGET
+absl_cc_test(
+  NAME
     int128_test
-  SOURCES
-    ${INT128_TEST_SRC}
-  PUBLIC_LIBRARIES
-    ${INT128_TEST_PUBLIC_LIBRARIES}
+  SRCS
+    "int128_stream_test.cc"
+    "int128_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::int128
+    absl::base
+    absl::core_headers
+    absl::hash_testing
+    absl::type_traits
+    gmock_main
 )
 
-
-
+# component target
+absl_cc_library(
+  NAME
+    numeric
+  DEPS
+    absl::int128
+  PUBLIC
+)
diff --git a/absl/numeric/int128.cc b/absl/numeric/int128.cc
index cd79534..93b62c5 100644
--- a/absl/numeric/int128.cc
+++ b/absl/numeric/int128.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -17,7 +17,7 @@
 #include <stddef.h>
 #include <cassert>
 #include <iomanip>
-#include <iostream>  // NOLINT(readability/streams)
+#include <ostream>  // NOLINT(readability/streams)
 #include <sstream>
 #include <string>
 #include <type_traits>
@@ -65,7 +65,7 @@
 
 // Long division/modulo for uint128 implemented using the shift-subtract
 // division algorithm adapted from:
-// http://stackoverflow.com/questions/5386377/division-without-using
+// https://stackoverflow.com/questions/5386377/division-without-using
 void DivModImpl(uint128 dividend, uint128 divisor, uint128* quotient_ret,
                 uint128* remainder_ret) {
   assert(divisor != 0);
@@ -123,6 +123,28 @@
 
   return MakeUint128(0, static_cast<uint64_t>(v));
 }
+
+#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.
+// It is more work, so only use when we need the workaround.
+uint128 MakeUint128FromFloat(long double v) {
+  // Go 50 bits at a time, that fits in a double
+  static_assert(std::numeric_limits<double>::digits >= 50, "");
+  static_assert(std::numeric_limits<long double>::digits <= 150, "");
+  // Undefined behavior if v is not finite or cannot fit into uint128.
+  assert(std::isfinite(v) && v > -1 && v < std::ldexp(1.0L, 128));
+
+  v = std::ldexp(v, -100);
+  uint64_t w0 = static_cast<uint64_t>(static_cast<double>(std::trunc(v)));
+  v = std::ldexp(v - static_cast<double>(w0), 50);
+  uint64_t w1 = static_cast<uint64_t>(static_cast<double>(std::trunc(v)));
+  v = std::ldexp(v - static_cast<double>(w1), 50);
+  uint64_t w2 = static_cast<uint64_t>(static_cast<double>(std::trunc(v)));
+  return (static_cast<uint128>(w0) << 100) | (static_cast<uint128>(w1) << 50) |
+         static_cast<uint128>(w2);
+}
+#endif  // __clang__ && !__SSE3__
 }  // namespace
 
 uint128::uint128(float v) : uint128(MakeUint128FromFloat(v)) {}
diff --git a/absl/numeric/int128.h b/absl/numeric/int128.h
index 79b62a7..2f5b8ad 100644
--- a/absl/numeric/int128.h
+++ b/absl/numeric/int128.h
@@ -5,7 +5,7 @@
 // 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
+//      https://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,
@@ -37,8 +37,21 @@
 #include "absl/base/macros.h"
 #include "absl/base/port.h"
 
-namespace absl {
+#if defined(_MSC_VER)
+// In very old versions of MSVC and when the /Zc:wchar_t flag is off, wchar_t is
+// a typedef for unsigned short.  Otherwise wchar_t is mapped to the __wchar_t
+// builtin type.  We need to make sure not to define operator wchar_t()
+// alongside operator unsigned short() in these instances.
+#define ABSL_INTERNAL_WCHAR_T __wchar_t
+#if defined(_M_X64)
+#include <intrin.h>
+#pragma intrinsic(_umul128)
+#endif  // defined(_M_X64)
+#else   // defined(_MSC_VER)
+#define ABSL_INTERNAL_WCHAR_T wchar_t
+#endif  // defined(_MSC_VER)
 
+namespace absl {
 
 // uint128
 //
@@ -126,7 +139,7 @@
   constexpr explicit operator unsigned char() const;
   constexpr explicit operator char16_t() const;
   constexpr explicit operator char32_t() const;
-  constexpr explicit operator wchar_t() const;
+  constexpr explicit operator ABSL_INTERNAL_WCHAR_T() const;
   constexpr explicit operator short() const;  // NOLINT(runtime/int)
   // NOLINTNEXTLINE(runtime/int)
   constexpr explicit operator unsigned short() const;
@@ -227,8 +240,8 @@
 // TODO(strel) add operator>>(std::istream&, uint128)
 
 constexpr uint128 Uint128Max() {
-  return uint128(std::numeric_limits<uint64_t>::max(),
-                 std::numeric_limits<uint64_t>::max());
+  return uint128((std::numeric_limits<uint64_t>::max)(),
+                 (std::numeric_limits<uint64_t>::max)());
 }
 
 }  // namespace absl
@@ -266,9 +279,9 @@
 #endif  // ABSL_HAVE_INTRINSIC_INT128
   static constexpr bool tinyness_before = false;
 
-  static constexpr absl::uint128 min() { return 0; }
+  static constexpr absl::uint128 (min)() { return 0; }
   static constexpr absl::uint128 lowest() { return 0; }
-  static constexpr absl::uint128 max() { return absl::Uint128Max(); }
+  static constexpr absl::uint128 (max)() { return absl::Uint128Max(); }
   static constexpr absl::uint128 epsilon() { return 0; }
   static constexpr absl::uint128 round_error() { return 0; }
   static constexpr absl::uint128 infinity() { return 0; }
@@ -384,13 +397,13 @@
 
 constexpr uint128::uint128(int v)
     : lo_{static_cast<uint64_t>(v)},
-      hi_{v < 0 ? std::numeric_limits<uint64_t>::max() : 0} {}
+      hi_{v < 0 ? (std::numeric_limits<uint64_t>::max)() : 0} {}
 constexpr uint128::uint128(long v)  // NOLINT(runtime/int)
     : lo_{static_cast<uint64_t>(v)},
-      hi_{v < 0 ? std::numeric_limits<uint64_t>::max() : 0} {}
+      hi_{v < 0 ? (std::numeric_limits<uint64_t>::max)() : 0} {}
 constexpr uint128::uint128(long long v)  // NOLINT(runtime/int)
     : lo_{static_cast<uint64_t>(v)},
-      hi_{v < 0 ? std::numeric_limits<uint64_t>::max() : 0} {}
+      hi_{v < 0 ? (std::numeric_limits<uint64_t>::max)() : 0} {}
 
 constexpr uint128::uint128(unsigned int v) : lo_{v}, hi_{0} {}
 // NOLINTNEXTLINE(runtime/int)
@@ -413,13 +426,13 @@
     : hi_{high}, lo_{low} {}
 
 constexpr uint128::uint128(int v)
-    : hi_{v < 0 ? std::numeric_limits<uint64_t>::max() : 0},
+    : hi_{v < 0 ? (std::numeric_limits<uint64_t>::max)() : 0},
       lo_{static_cast<uint64_t>(v)} {}
 constexpr uint128::uint128(long v)  // NOLINT(runtime/int)
-    : hi_{v < 0 ? std::numeric_limits<uint64_t>::max() : 0},
+    : hi_{v < 0 ? (std::numeric_limits<uint64_t>::max)() : 0},
       lo_{static_cast<uint64_t>(v)} {}
 constexpr uint128::uint128(long long v)  // NOLINT(runtime/int)
-    : hi_{v < 0 ? std::numeric_limits<uint64_t>::max() : 0},
+    : hi_{v < 0 ? (std::numeric_limits<uint64_t>::max)() : 0},
       lo_{static_cast<uint64_t>(v)} {}
 
 constexpr uint128::uint128(unsigned int v) : hi_{0}, lo_{v} {}
@@ -463,8 +476,8 @@
   return static_cast<char32_t>(lo_);
 }
 
-constexpr uint128::operator wchar_t() const {
-  return static_cast<wchar_t>(lo_);
+constexpr uint128::operator ABSL_INTERNAL_WCHAR_T() const {
+  return static_cast<ABSL_INTERNAL_WCHAR_T>(lo_);
 }
 
 // NOLINTNEXTLINE(runtime/int)
@@ -661,6 +674,12 @@
   // can be used for uint128 storage.
   return static_cast<unsigned __int128>(lhs) *
          static_cast<unsigned __int128>(rhs);
+#elif defined(_MSC_VER) && defined(_M_X64)
+  uint64_t carry;
+  uint64_t low = _umul128(Uint128Low64(lhs), Uint128Low64(rhs), &carry);
+  return MakeUint128(Uint128Low64(lhs) * Uint128High64(rhs) +
+                         Uint128High64(lhs) * Uint128Low64(rhs) + carry,
+                     low);
 #else   // ABSL_HAVE_INTRINSIC128
   uint64_t a32 = Uint128Low64(lhs) >> 32;
   uint64_t a00 = Uint128Low64(lhs) & 0xffffffff;
@@ -708,4 +727,6 @@
 
 }  // namespace absl
 
+#undef ABSL_INTERNAL_WCHAR_T
+
 #endif  // ABSL_NUMERIC_INT128_H_
diff --git a/absl/numeric/int128_benchmark.cc b/absl/numeric/int128_benchmark.cc
index 1cb7d0e..a5502d9 100644
--- a/absl/numeric/int128_benchmark.cc
+++ b/absl/numeric/int128_benchmark.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
diff --git a/absl/numeric/int128_have_intrinsic.inc b/absl/numeric/int128_have_intrinsic.inc
index ee2a093..c7ea683 100644
--- a/absl/numeric/int128_have_intrinsic.inc
+++ b/absl/numeric/int128_have_intrinsic.inc
@@ -5,7 +5,7 @@
 // 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
+//      https://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,
@@ -15,4 +15,4 @@
 
 // This file contains :int128 implementation details that depend on internal
 // representation when ABSL_HAVE_INTRINSIC_INT128 is defined. This file is
-// included by int128.h.
+// included by int128.h and relies on ABSL_INTERNAL_WCHAR_T being defined.
diff --git a/absl/numeric/int128_no_intrinsic.inc b/absl/numeric/int128_no_intrinsic.inc
index 0d0b3cf..046cb9b 100644
--- a/absl/numeric/int128_no_intrinsic.inc
+++ b/absl/numeric/int128_no_intrinsic.inc
@@ -5,7 +5,7 @@
 // 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
+//      https://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,
@@ -15,4 +15,4 @@
 
 // This file contains :int128 implementation details that depend on internal
 // representation when ABSL_HAVE_INTRINSIC_INT128 is *not* defined. This file
-// is included by int128.h.
+// is included by int128.h and relies on ABSL_INTERNAL_WCHAR_T being defined.
diff --git a/absl/numeric/int128_stream_test.cc b/absl/numeric/int128_stream_test.cc
index 09efaad..3cfa9dc 100644
--- a/absl/numeric/int128_stream_test.cc
+++ b/absl/numeric/int128_stream_test.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
diff --git a/absl/numeric/int128_test.cc b/absl/numeric/int128_test.cc
index dfe3475..5e1b5ec 100644
--- a/absl/numeric/int128_test.cc
+++ b/absl/numeric/int128_test.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -51,7 +51,7 @@
 class Uint128FloatTraitsTest : public ::testing::Test {};
 typedef ::testing::Types<float, double, long double> FloatingPointTypes;
 
-TYPED_TEST_CASE(Uint128IntegerTraitsTest, IntegerTypes);
+TYPED_TEST_SUITE(Uint128IntegerTraitsTest, IntegerTypes);
 
 TYPED_TEST(Uint128IntegerTraitsTest, ConstructAssignTest) {
   static_assert(std::is_constructible<absl::uint128, TypeParam>::value,
@@ -62,7 +62,7 @@
                 "TypeParam must not be assignable from absl::uint128");
 }
 
-TYPED_TEST_CASE(Uint128FloatTraitsTest, FloatingPointTypes);
+TYPED_TEST_SUITE(Uint128FloatTraitsTest, FloatingPointTypes);
 
 TYPED_TEST(Uint128FloatTraitsTest, ConstructAssignTest) {
   static_assert(std::is_constructible<absl::uint128, TypeParam>::value,
@@ -271,6 +271,20 @@
   EXPECT_EQ(static_cast<absl::uint128>(round_to_zero), 0);
   EXPECT_EQ(static_cast<absl::uint128>(round_to_five), 5);
   EXPECT_EQ(static_cast<absl::uint128>(round_to_nine), 9);
+
+  absl::uint128 highest_precision_in_long_double =
+      ~absl::uint128{} >> (128 - std::numeric_limits<long double>::digits);
+  EXPECT_EQ(highest_precision_in_long_double,
+            static_cast<absl::uint128>(
+                static_cast<long double>(highest_precision_in_long_double)));
+  // Apply a mask just to make sure all the bits are the right place.
+  const absl::uint128 arbitrary_mask =
+      absl::MakeUint128(0xa29f622677ded751, 0xf8ca66add076f468);
+  EXPECT_EQ(highest_precision_in_long_double & arbitrary_mask,
+            static_cast<absl::uint128>(static_cast<long double>(
+                highest_precision_in_long_double & arbitrary_mask)));
+
+  EXPECT_EQ(static_cast<absl::uint128>(-0.1L), 0);
 }
 
 TEST(Uint128, OperatorAssignReturnRef) {
@@ -440,4 +454,29 @@
   EXPECT_EQ(absl::Uint128Max(), std::numeric_limits<absl::uint128>::max());
 }
 
+TEST(Uint128, Hash) {
+  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly({
+      // Some simple values
+      absl::uint128{0},
+      absl::uint128{1},
+      ~absl::uint128{},
+      // 64 bit limits
+      absl::uint128{std::numeric_limits<int64_t>::max()},
+      absl::uint128{std::numeric_limits<uint64_t>::max()} + 0,
+      absl::uint128{std::numeric_limits<uint64_t>::max()} + 1,
+      absl::uint128{std::numeric_limits<uint64_t>::max()} + 2,
+      // Keeping high same
+      absl::uint128{1} << 62,
+      absl::uint128{1} << 63,
+      // Keeping low same
+      absl::uint128{1} << 64,
+      absl::uint128{1} << 65,
+      // 128 bit limits
+      std::numeric_limits<absl::uint128>::max(),
+      std::numeric_limits<absl::uint128>::max() - 1,
+      std::numeric_limits<absl::uint128>::min() + 1,
+      std::numeric_limits<absl::uint128>::min(),
+  }));
+}
+
 }  // namespace
diff --git a/absl/strings/BUILD.bazel b/absl/strings/BUILD.bazel
index 6d7c261..9640ff4 100644
--- a/absl/strings/BUILD.bazel
+++ b/absl/strings/BUILD.bazel
@@ -5,17 +5,16 @@
 # 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
+#      https://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.
-#
 
 load(
-    "//absl:copts.bzl",
+    "//absl:copts/configure_copts.bzl",
     "ABSL_DEFAULT_COPTS",
     "ABSL_TEST_COPTS",
     "ABSL_EXCEPTIONS_FLAG",
@@ -413,6 +412,7 @@
     copts = ABSL_TEST_COPTS,
     visibility = ["//visibility:private"],
     deps = [
+        ":pow10_helper",
         ":strings",
         "//absl/base",
         "//absl/base:core_headers",
@@ -471,6 +471,8 @@
     srcs = ["charconv_test.cc"],
     copts = ABSL_TEST_COPTS,
     deps = [
+        ":pow10_helper",
+        ":str_format",
         ":strings",
         "//absl/base",
         "@com_google_googletest//:gtest_main",
@@ -659,3 +661,23 @@
         "@com_google_googletest//:gtest_main",
     ],
 )
+
+cc_library(
+    name = "pow10_helper",
+    testonly = True,
+    srcs = ["internal/pow10_helper.cc"],
+    hdrs = ["internal/pow10_helper.h"],
+    visibility = ["//visibility:private"],
+)
+
+cc_test(
+    name = "pow10_helper_test",
+    srcs = ["internal/pow10_helper_test.cc"],
+    copts = ABSL_TEST_COPTS,
+    visibility = ["//visibility:private"],
+    deps = [
+        ":pow10_helper",
+        ":str_format",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
diff --git a/absl/strings/BUILD.gn b/absl/strings/BUILD.gn
index 20af83c..6f5cef6 100644
--- a/absl/strings/BUILD.gn
+++ b/absl/strings/BUILD.gn
@@ -144,3 +144,21 @@
     "../types:span",
   ]
 }
+
+source_set("pow10_helper") {
+  testonly = true
+  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" ]
+  sources = [
+    "internal/pow10_helper.cc",
+  ]
+  public = [
+    "internal/pow10_helper.h",
+  ]
+  visibility = []
+  visibility += [ ":*" ]
+}
diff --git a/absl/strings/CMakeLists.txt b/absl/strings/CMakeLists.txt
index f3e4162..d3393a3 100644
--- a/absl/strings/CMakeLists.txt
+++ b/absl/strings/CMakeLists.txt
@@ -5,7 +5,7 @@
 # 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
+#      https://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,
@@ -14,93 +14,359 @@
 # limitations under the License.
 #
 
-
-list(APPEND STRINGS_PUBLIC_HEADERS
-  "ascii.h"
-  "charconv.h"
-  "escaping.h"
-  "match.h"
-  "numbers.h"
-  "str_cat.h"
-  "string_view.h"
-  "strip.h"
-  "str_join.h"
-  "str_replace.h"
-  "str_split.h"
-  "substitute.h"
-)
-
-
-list(APPEND STRINGS_INTERNAL_HEADERS
-  "internal/char_map.h"
-  "internal/charconv_bigint.h"
-  "internal/charconv_parse.h"
-  "internal/memutil.h"
-  "internal/ostringstream.h"
-  "internal/resize_uninitialized.h"
-  "internal/stl_type_traits.h"
-  "internal/str_join_internal.h"
-  "internal/str_split_internal.h"
-  "internal/utf8.h"
-)
-
-
-
-# add string library
-list(APPEND STRINGS_SRC
-  "ascii.cc"
-  "charconv.cc"
-  "escaping.cc"
-  "internal/charconv_bigint.cc"
-  "internal/charconv_parse.cc"
-  "internal/memutil.cc"
-  "internal/memutil.h"
-  "internal/utf8.cc"
-  "internal/ostringstream.cc"
-  "match.cc"
-  "numbers.cc"
-  "str_cat.cc"
-  "str_replace.cc"
-  "str_split.cc"
-  "string_view.cc"
-  "substitute.cc"
-  ${STRINGS_PUBLIC_HEADERS}
-  ${STRINGS_INTERNAL_HEADERS}
-)
-set(STRINGS_PUBLIC_LIBRARIES absl::base absl_throw_delegate)
-
-absl_library(
-  TARGET
-    absl_strings
-  SOURCES
-    ${STRINGS_SRC}
-  PUBLIC_LIBRARIES
-    ${STRINGS_PUBLIC_LIBRARIES}
-  EXPORT_NAME
+absl_cc_library(
+  NAME
     strings
+  HDRS
+    "ascii.h"
+    "charconv.h"
+    "escaping.h"
+    "match.h"
+    "numbers.h"
+    "str_cat.h"
+    "str_join.h"
+    "str_replace.h"
+    "str_split.h"
+    "string_view.h"
+    "strip.h"
+    "substitute.h"
+  SRCS
+    "ascii.cc"
+    "charconv.cc"
+    "escaping.cc"
+    "internal/charconv_bigint.cc"
+    "internal/charconv_bigint.h"
+    "internal/charconv_parse.cc"
+    "internal/charconv_parse.h"
+    "internal/memutil.cc"
+    "internal/memutil.h"
+    "internal/stl_type_traits.h"
+    "internal/str_join_internal.h"
+    "internal/str_split_internal.h"
+    "match.cc"
+    "numbers.cc"
+    "str_cat.cc"
+    "str_replace.cc"
+    "str_split.cc"
+    "string_view.cc"
+    "substitute.cc"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::strings_internal
+    absl::base
+    absl::bits
+    absl::config
+    absl::core_headers
+    absl::endian
+    absl::throw_delegate
+    absl::memory
+    absl::type_traits
+    absl::int128
+  PUBLIC
 )
 
-# add str_format library
-absl_header_library(
-  TARGET
-    absl_str_format
-  PUBLIC_LIBRARIES
-    str_format_internal
-  EXPORT_NAME
+absl_cc_library(
+  NAME
+    strings_internal
+  HDRS
+    "internal/char_map.h"
+    "internal/ostringstream.h"
+    "internal/resize_uninitialized.h"
+    "internal/utf8.h"
+  SRCS
+    "internal/ostringstream.cc"
+    "internal/utf8.cc"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::core_headers
+    absl::endian
+    absl::type_traits
+)
+
+absl_cc_test(
+  NAME
+    match_test
+  SRCS
+    "match_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::strings
+    absl::base
+    gmock_main
+)
+
+absl_cc_test(
+  NAME
+    escaping_test
+  SRCS
+    "escaping_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::strings
+    absl::core_headers
+    absl::fixed_array
+    gmock_main
+)
+
+absl_cc_test(
+  NAME
+    ascii_test
+  SRCS
+    "ascii_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::strings
+    absl::core_headers
+    gmock_main
+)
+
+absl_cc_test(
+  NAME
+    memutil_test
+  SRCS
+    "internal/memutil.h"
+    "internal/memutil_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::strings
+    absl::core_headers
+    gmock_main
+)
+
+absl_cc_test(
+  NAME
+    utf8_test
+  SRCS
+    "internal/utf8_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::strings_internal
+    absl::base
+    absl::core_headers
+    gmock_main
+)
+
+absl_cc_test(
+  NAME
+    string_view_test
+  SRCS
+    "string_view_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+    ${ABSL_EXCEPTIONS_FLAG}
+  LINKOPTS
+    ${ABSL_EXCEPTIONS_FLAG_LINKOPTS}
+  DEPS
+    absl::strings
+    absl::config
+    absl::core_headers
+    absl::dynamic_annotations
+    gmock_main
+)
+
+absl_cc_test(
+  NAME
+    substitute_test
+  SRCS
+    "substitute_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::strings
+    absl::core_headers
+    gmock_main
+)
+
+absl_cc_test(
+  NAME
+    str_replace_test
+  SRCS
+    "str_replace_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::strings
+    gmock_main
+)
+
+absl_cc_test(
+  NAME
+    str_split_test
+  SRCS
+    "str_split_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::strings
+    absl::base
+    absl::core_headers
+    absl::dynamic_annotations
+    gmock_main
+)
+
+absl_cc_test(
+  NAME
+    ostringstream_test
+  SRCS
+    "internal/ostringstream_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::strings_internal
+    gmock_main
+)
+
+absl_cc_test(
+  NAME
+    resize_uninitialized_test
+  SRCS
+    "internal/resize_uninitialized.h"
+    "internal/resize_uninitialized_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::base
+    absl::core_headers
+    absl::type_traits
+    gmock_main
+)
+
+absl_cc_test(
+  NAME
+    str_join_test
+  SRCS
+    "str_join_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::strings
+    absl::base
+    absl::core_headers
+    absl::memory
+    gmock_main
+)
+
+absl_cc_test(
+  NAME
+    str_cat_test
+  SRCS
+    "str_cat_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::strings
+    absl::core_headers
+    gmock_main
+)
+
+absl_cc_test(
+  NAME
+    numbers_test
+  SRCS
+    "internal/numbers_test_common.h"
+    "numbers_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::strings
+    absl::base
+    absl::core_headers
+    absl::pow10_helper
+    gmock_main
+)
+
+absl_cc_test(
+  NAME
+    strip_test
+  SRCS
+    "strip_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::strings
+    absl::base
+    gmock_main
+)
+
+absl_cc_test(
+  NAME
+    char_map_test
+  SRCS
+    "internal/char_map_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::strings_internal
+    gmock_main
+)
+
+absl_cc_test(
+  NAME
+    charconv_test
+  SRCS
+    "charconv_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::strings
+    absl::str_format
+    absl::base
+    absl::pow10_helper
+    gmock_main
+)
+
+absl_cc_test(
+  NAME
+    charconv_parse_test
+  SRCS
+    "internal/charconv_parse.h"
+    "internal/charconv_parse_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::strings
+    absl::base
+    gmock_main
+)
+
+absl_cc_test(
+  NAME
+    charconv_bigint_test
+  SRCS
+    "internal/charconv_bigint.h"
+    "internal/charconv_bigint_test.cc"
+    "internal/charconv_parse.h"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::strings
+    absl::base
+    gmock_main
+)
+
+absl_cc_library(
+  NAME
     str_format
+  HDRS
+    "str_format.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::str_format_internal
+  PUBLIC
 )
 
-# str_format_internal
-absl_library(
-  TARGET
+absl_cc_library(
+  NAME
     str_format_internal
-  SOURCES
-    "internal/str_format/arg.cc"
-    "internal/str_format/bind.cc"
-    "internal/str_format/extension.cc"
-    "internal/str_format/float_conversion.cc"
-    "internal/str_format/output.cc"
-    "internal/str_format/parser.cc"
+  HDRS
     "internal/str_format/arg.h"
     "internal/str_format/bind.h"
     "internal/str_format/checker.h"
@@ -108,356 +374,145 @@
     "internal/str_format/float_conversion.h"
     "internal/str_format/output.h"
     "internal/str_format/parser.h"
-  PUBLIC_LIBRARIES
-    str_format_extension_internal
+  SRCS
+    "internal/str_format/arg.cc"
+    "internal/str_format/bind.cc"
+    "internal/str_format/extension.cc"
+    "internal/str_format/float_conversion.cc"
+    "internal/str_format/output.cc"
+    "internal/str_format/parser.cc"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
     absl::strings
-    absl::base
-    absl::numeric
-    absl::container
+    absl::core_headers
+    absl::inlined_vector
+    absl::type_traits
+    absl::int128
     absl::span
 )
 
-# str_format_extension_internal
-absl_library(
-  TARGET
-    str_format_extension_internal
-  SOURCES
-    "internal/str_format/extension.cc"
-    "internal/str_format/extension.h"
-    "internal/str_format/output.cc"
-    "internal/str_format/output.h"
-  PUBLIC_LIBRARIES
-    absl::base
-    absl::strings
-)
-
-#
-## TESTS
-#
-
-# test match_test
-set(MATCH_TEST_SRC "match_test.cc")
-set(MATCH_TEST_PUBLIC_LIBRARIES absl::strings)
-
-absl_test(
-  TARGET
-    match_test
-  SOURCES
-    ${MATCH_TEST_SRC}
-  PUBLIC_LIBRARIES
-    ${MATCH_TEST_PUBLIC_LIBRARIES}
-)
-
-
-# test escaping_test
-set(ESCAPING_TEST_SRC "escaping_test.cc")
-set(ESCAPING_TEST_PUBLIC_LIBRARIES absl::strings absl::base)
-
-absl_test(
-  TARGET
-    escaping_test
-  SOURCES
-    ${ESCAPING_TEST_SRC}
-  PUBLIC_LIBRARIES
-    ${ESCAPING_TEST_PUBLIC_LIBRARIES}
-)
-
-
-# test ascii_test
-set(ASCII_TEST_SRC "ascii_test.cc")
-set(ASCII_TEST_PUBLIC_LIBRARIES absl::strings)
-
-absl_test(
-  TARGET
-    ascii_test
-  SOURCES
-    ${ASCII_TEST_SRC}
-  PUBLIC_LIBRARIES
-    ${ASCII_TEST_PUBLIC_LIBRARIES}
-)
-
-
-# test memutil_test
-set(MEMUTIL_TEST_SRC "internal/memutil_test.cc")
-set(MEMUTIL_TEST_PUBLIC_LIBRARIES absl::strings)
-
-absl_test(
-  TARGET
-    memutil_test
-  SOURCES
-    ${MEMUTIL_TEST_SRC}
-  PUBLIC_LIBRARIES
-    ${MEMUTIL_TEST_PUBLIC_LIBRARIES}
-)
-
-
-# test utf8_test
-set(UTF8_TEST_SRC "internal/utf8_test.cc")
-set(UTF8_TEST_PUBLIC_LIBRARIES absl::strings absl::base)
-
-absl_test(
-  TARGET
-    utf8_test
-  SOURCES
-    ${UTF8_TEST_SRC}
-  PUBLIC_LIBRARIES
-    ${UTF8_TEST_PUBLIC_LIBRARIES}
-)
-
-
-# test string_view_test
-set(STRING_VIEW_TEST_SRC "string_view_test.cc")
-set(STRING_VIEW_TEST_PUBLIC_LIBRARIES absl::strings absl_throw_delegate absl::base)
-
-absl_test(
-  TARGET
-    string_view_test
-  SOURCES
-    ${STRING_VIEW_TEST_SRC}
-  PUBLIC_LIBRARIES
-    ${STRING_VIEW_TEST_PUBLIC_LIBRARIES}
-)
-
-
-# test substitute_test
-set(SUBSTITUTE_TEST_SRC "substitute_test.cc")
-set(SUBSTITUTE_TEST_PUBLIC_LIBRARIES absl::strings absl::base)
-
-absl_test(
-  TARGET
-    substitute_test
-  SOURCES
-    ${SUBSTITUTE_TEST_SRC}
-  PUBLIC_LIBRARIES
-    ${SUBSTITUTE_TEST_PUBLIC_LIBRARIES}
-)
-
-
-# test str_replace_test
-set(STR_REPLACE_TEST_SRC "str_replace_test.cc")
-set(STR_REPLACE_TEST_PUBLIC_LIBRARIES absl::strings absl::base absl_throw_delegate)
-
-absl_test(
-  TARGET
-    str_replace_test
-  SOURCES
-    ${STR_REPLACE_TEST_SRC}
-  PUBLIC_LIBRARIES
-    ${STR_REPLACE_TEST_PUBLIC_LIBRARIES}
-)
-
-
-# test str_split_test
-set(STR_SPLIT_TEST_SRC "str_split_test.cc")
-set(STR_SPLIT_TEST_PUBLIC_LIBRARIES absl::strings absl::base absl_throw_delegate)
-
-absl_test(
-  TARGET
-    str_split_test
-  SOURCES
-    ${STR_SPLIT_TEST_SRC}
-  PUBLIC_LIBRARIES
-    ${STR_SPLIT_TEST_PUBLIC_LIBRARIES}
-)
-
-
-# test ostringstream_test
-set(OSTRINGSTREAM_TEST_SRC "internal/ostringstream_test.cc")
-set(OSTRINGSTREAM_TEST_PUBLIC_LIBRARIES absl::strings)
-
-absl_test(
-  TARGET
-    ostringstream_test
-  SOURCES
-    ${OSTRINGSTREAM_TEST_SRC}
-  PUBLIC_LIBRARIES
-    ${OSTRINGSTREAM_TEST_PUBLIC_LIBRARIES}
-)
-
-
-# test resize_uninitialized_test
-set(RESIZE_UNINITIALIZED_TEST_SRC "internal/resize_uninitialized_test.cc")
-
-absl_test(
-  TARGET
-    resize_uninitialized_test
-  SOURCES
-    ${RESIZE_UNINITIALIZED_TEST_SRC}
-)
-
-
-# test str_join_test
-set(STR_JOIN_TEST_SRC "str_join_test.cc")
-set(STR_JOIN_TEST_PUBLIC_LIBRARIES absl::strings)
-
-absl_test(
-  TARGET
-    str_join_test
-  SOURCES
-    ${STR_JOIN_TEST_SRC}
-  PUBLIC_LIBRARIES
-    ${STR_JOIN_TEST_PUBLIC_LIBRARIES}
-)
-
-
-# test str_cat_test
-set(STR_CAT_TEST_SRC "str_cat_test.cc")
-set(STR_CAT_TEST_PUBLIC_LIBRARIES absl::strings)
-
-absl_test(
-  TARGET
-    str_cat_test
-  SOURCES
-    ${STR_CAT_TEST_SRC}
-  PUBLIC_LIBRARIES
-    ${STR_CAT_TEST_PUBLIC_LIBRARIES}
-)
-
-
-# test numbers_test
-set(NUMBERS_TEST_SRC "numbers_test.cc")
-set(NUMBERS_TEST_PUBLIC_LIBRARIES absl::strings)
-
-absl_test(
-  TARGET
-    numbers_test
-  SOURCES
-    ${NUMBERS_TEST_SRC}
-  PUBLIC_LIBRARIES
-    ${NUMBERS_TEST_PUBLIC_LIBRARIES}
-)
-
-
-# test strip_test
-set(STRIP_TEST_SRC "strip_test.cc")
-set(STRIP_TEST_PUBLIC_LIBRARIES absl::strings)
-
-absl_test(
-  TARGET
-    strip_test
-  SOURCES
-    ${STRIP_TEST_SRC}
-  PUBLIC_LIBRARIES
-    ${STRIP_TEST_PUBLIC_LIBRARIES}
-)
-
-
-# test char_map_test
-set(CHAR_MAP_TEST_SRC "internal/char_map_test.cc")
-set(CHAR_MAP_TEST_PUBLIC_LIBRARIES absl::strings)
-
-absl_test(
-  TARGET
-    char_map_test
-  SOURCES
-    ${CHAR_MAP_TEST_SRC}
-  PUBLIC_LIBRARIES
-    ${CHAR_MAP_TEST_PUBLIC_LIBRARIES}
-)
-
-
-# test charconv_test
-set(CHARCONV_TEST_SRC "charconv_test.cc")
-set(CHARCONV_TEST_PUBLIC_LIBRARIES absl::strings)
-
-absl_test(
-  TARGET
-    charconv_test
-  SOURCES
-    ${CHARCONV_TEST_SRC}
-  PUBLIC_LIBRARIES
-    ${CHARCONV_TEST_PUBLIC_LIBRARIES}
-)
-
-
-# test charconv_parse_test
-set(CHARCONV_PARSE_TEST_SRC "internal/charconv_parse_test.cc")
-set(CHARCONV_PARSE_TEST_PUBLIC_LIBRARIES absl::strings)
-
-absl_test(
-  TARGET
-    charconv_parse_test
-  SOURCES
-    ${CHARCONV_PARSE_TEST_SRC}
-  PUBLIC_LIBRARIES
-    ${CHARCONV_PARSE_TEST_PUBLIC_LIBRARIES}
-)
-
-
-# test charconv_bigint_test
-set(CHARCONV_BIGINT_TEST_SRC "internal/charconv_bigint_test.cc")
-set(CHARCONV_BIGINT_TEST_PUBLIC_LIBRARIES absl::strings)
-
-absl_test(
-  TARGET
-    charconv_bigint_test
-  SOURCES
-    ${CHARCONV_BIGINT_TEST_SRC}
-  PUBLIC_LIBRARIES
-    ${CHARCONV_BIGINT_TEST_PUBLIC_LIBRARIES}
-)
-# test str_format_test
-absl_test(
-  TARGET
+absl_cc_test(
+  NAME
     str_format_test
-  SOURCES
+  SRCS
     "str_format_test.cc"
-  PUBLIC_LIBRARIES
-    absl::base
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
     absl::str_format
     absl::strings
+    absl::core_headers
+    gmock_main
 )
 
-# test str_format_bind_test
-absl_test(
-  TARGET
-    str_format_bind_test
-  SOURCES
-    "internal/str_format/bind_test.cc"
-  PUBLIC_LIBRARIES
-    str_format_internal
-)
-
-# test str_format_checker_test
-absl_test(
-  TARGET
-    str_format_checker_test
-  SOURCES
-    "internal/str_format/checker_test.cc"
-  PUBLIC_LIBRARIES
+absl_cc_test(
+  NAME
+    str_format_extension_test
+  SRCS
+    "internal/str_format/extension_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
     absl::str_format
+    absl::str_format_internal
+    gmock_main
 )
 
-# test str_format_convert_test
-absl_test(
-  TARGET
+absl_cc_test(
+  NAME
+    str_format_arg_test
+  SRCS
+    "internal/str_format/arg_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::str_format
+    absl::str_format_internal
+    gmock_main
+)
+
+absl_cc_test(
+  NAME
+    str_format_bind_test
+  SRCS
+    "internal/str_format/bind_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::str_format_internal
+    gmock_main
+)
+
+absl_cc_test(
+  NAME
+    str_format_checker_test
+  SRCS
+    "internal/str_format/checker_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::str_format
+    gmock_main
+)
+
+absl_cc_test(
+  NAME
     str_format_convert_test
-  SOURCES
+  SRCS
     "internal/str_format/convert_test.cc"
-  PUBLIC_LIBRARIES
-    str_format_internal
-    absl::numeric
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::str_format_internal
+    absl::int128
+    gmock_main
 )
 
-# test str_format_output_test
-absl_test(
-  TARGET
+absl_cc_test(
+  NAME
     str_format_output_test
-  SOURCES
+  SRCS
     "internal/str_format/output_test.cc"
-  PUBLIC_LIBRARIES
-    str_format_extension_internal
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::str_format_internal
+    gmock_main
 )
 
-# test str_format_parser_test
-absl_test(
-  TARGET
+absl_cc_test(
+  NAME
     str_format_parser_test
-  SOURCES
+  SRCS
     "internal/str_format/parser_test.cc"
-  PUBLIC_LIBRARIES
-    str_format_internal
-    absl::base
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::str_format_internal
+    absl::core_headers
+    gmock_main
 )
 
+absl_cc_library(
+  NAME
+    pow10_helper
+  HDRS
+    "internal/pow10_helper.h"
+  SRCS
+    "internal/pow10_helper.cc"
+  TESTONLY
+)
 
+absl_cc_test(
+  NAME
+    pow10_helper_test
+  SRCS
+    "internal/pow10_helper_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::pow10_helper
+    absl::str_format
+    gmock_main
+)
diff --git a/absl/strings/ascii.cc b/absl/strings/ascii.cc
index c9481e8..3f7c581 100644
--- a/absl/strings/ascii.cc
+++ b/absl/strings/ascii.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
diff --git a/absl/strings/ascii.h b/absl/strings/ascii.h
index 48a9da2..f9e4fd1 100644
--- a/absl/strings/ascii.h
+++ b/absl/strings/ascii.h
@@ -5,7 +5,7 @@
 // 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
+//      https://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,
diff --git a/absl/strings/ascii_benchmark.cc b/absl/strings/ascii_benchmark.cc
index 8dea4b8..aca458c 100644
--- a/absl/strings/ascii_benchmark.cc
+++ b/absl/strings/ascii_benchmark.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
diff --git a/absl/strings/ascii_test.cc b/absl/strings/ascii_test.cc
index 9903b04..5ecd23f 100644
--- a/absl/strings/ascii_test.cc
+++ b/absl/strings/ascii_test.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
diff --git a/absl/strings/charconv.cc b/absl/strings/charconv.cc
index c7b8c98..bc07e7a 100644
--- a/absl/strings/charconv.cc
+++ b/absl/strings/charconv.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -551,9 +551,10 @@
   int binary_exponent = Power10Exponent(parsed_decimal.exponent);
 
   // Discard bits that are inaccurate due to truncation error.  The magic
-  // `mantissa_width` constants below are justified in charconv_algorithm.md.
-  // They represent the number of bits in `wide_binary_mantissa` that are
-  // guaranteed to be unaffected by error propagation.
+  // `mantissa_width` constants below are justified in
+  // https://abseil.io/about/design/charconv. They represent the number of bits
+  // in `wide_binary_mantissa` that are guaranteed to be unaffected by error
+  // propagation.
   bool mantissa_exact;
   int mantissa_width;
   if (parsed_decimal.subrange_begin) {
diff --git a/absl/strings/charconv.h b/absl/strings/charconv.h
index 0735382..59f74bf 100644
--- a/absl/strings/charconv.h
+++ b/absl/strings/charconv.h
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
diff --git a/absl/strings/charconv_benchmark.cc b/absl/strings/charconv_benchmark.cc
index fd83f44..644b2ab 100644
--- a/absl/strings/charconv_benchmark.cc
+++ b/absl/strings/charconv_benchmark.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
diff --git a/absl/strings/charconv_test.cc b/absl/strings/charconv_test.cc
index 89418fe..b58fad2 100644
--- a/absl/strings/charconv_test.cc
+++ b/absl/strings/charconv_test.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -19,7 +19,9 @@
 
 #include "gmock/gmock.h"
 #include "gtest/gtest.h"
+#include "absl/strings/internal/pow10_helper.h"
 #include "absl/strings/str_cat.h"
+#include "absl/strings/str_format.h"
 
 #ifdef _MSC_FULL_VER
 #define ABSL_COMPILER_DOES_EXACT_ROUNDING 0
@@ -31,6 +33,8 @@
 
 namespace {
 
+using absl::strings_internal::Pow10;
+
 #if ABSL_COMPILER_DOES_EXACT_ROUNDING
 
 // Tests that the given string is accepted by absl::from_chars, and that it
@@ -275,7 +279,8 @@
   absl::from_chars(low_rep.data(), low_rep.data() + low_rep.size(), actual_low);
   EXPECT_EQ(expected_low, actual_low);
 
-  std::string high_rep = absl::StrCat(mantissa, std::string(1000, '0'), "1e", exponent);
+  std::string high_rep =
+      absl::StrCat(mantissa, std::string(1000, '0'), "1e", exponent);
   FloatType actual_high = 0;
   absl::from_chars(high_rep.data(), high_rep.data() + high_rep.size(),
                    actual_high);
@@ -678,7 +683,8 @@
     auto result =
         absl::from_chars(input.data(), input.data() + input.size(), actual);
     EXPECT_EQ(result.ec, std::errc());
-    EXPECT_EQ(expected, actual);
+    EXPECT_EQ(expected, actual)
+        << absl::StrFormat("%a vs %a", expected, actual);
   }
   // test legal values near upper_bound
   for (index = upper_bound, step = 1; index > lower_bound;
@@ -690,7 +696,8 @@
     auto result =
         absl::from_chars(input.data(), input.data() + input.size(), actual);
     EXPECT_EQ(result.ec, std::errc());
-    EXPECT_EQ(expected, actual);
+    EXPECT_EQ(expected, actual)
+        << absl::StrFormat("%a vs %a", expected, actual);
   }
   // Test underflow values below lower_bound
   for (index = lower_bound - 1, step = 1; index > -1000000;
@@ -747,7 +754,7 @@
 // acceptable exponents in this test.
 TEST(FromChars, DecimalDoubleLimits) {
   auto input_gen = [](int index) { return absl::StrCat("1.0e", index); };
-  auto expected_gen = [](int index) { return std::pow(10.0, index); };
+  auto expected_gen = [](int index) { return Pow10(index); };
   TestOverflowAndUnderflow<double>(input_gen, expected_gen, -323, 308);
 }
 
@@ -759,7 +766,7 @@
 // acceptable exponents in this test.
 TEST(FromChars, DecimalFloatLimits) {
   auto input_gen = [](int index) { return absl::StrCat("1.0e", index); };
-  auto expected_gen = [](int index) { return std::pow(10.0, index); };
+  auto expected_gen = [](int index) { return Pow10(index); };
   TestOverflowAndUnderflow<float>(input_gen, expected_gen, -45, 38);
 }
 
diff --git a/absl/strings/escaping.cc b/absl/strings/escaping.cc
index 8d8b00b..bc8307e 100644
--- a/absl/strings/escaping.cc
+++ b/absl/strings/escaping.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -179,7 +179,8 @@
             ch = (ch << 4) + hex_digit_to_int(*++p);
           if (ch > 0xFF) {
             if (error) {
-              *error = "Value of \\" + std::string(hex_start, p + 1 - hex_start) +
+              *error = "Value of \\" +
+                       std::string(hex_start, p + 1 - hex_start) +
                        " exceeds 0xff";
             }
             return false;
@@ -294,7 +295,7 @@
 // ----------------------------------------------------------------------
 // CUnescapeInternal()
 //
-//    Same as above but uses a C++ string for output. 'source' and 'dest'
+//    Same as above but uses a std::string for output. 'source' and 'dest'
 //    may be the same.
 // ----------------------------------------------------------------------
 bool CUnescapeInternal(absl::string_view source, bool leave_nulls_escaped,
@@ -324,7 +325,8 @@
 //
 //    Escaped chars: \n, \r, \t, ", ', \, and !absl::ascii_isprint().
 // ----------------------------------------------------------------------
-std::string CEscapeInternal(absl::string_view src, bool use_hex, bool utf8_safe) {
+std::string CEscapeInternal(absl::string_view src, bool use_hex,
+                            bool utf8_safe) {
   std::string dest;
   bool last_hex_escape = false;  // true if last output char was \xNN.
 
@@ -786,7 +788,7 @@
   // Base64 encodes three bytes of input at a time. If the input is not
   // divisible by three, we pad as appropriate.
   //
-  // (from http://tools.ietf.org/html/rfc3548)
+  // (from https://tools.ietf.org/html/rfc3548)
   // Special processing is performed if fewer than 24 bits are available
   // at the end of the data being encoded.  A full encoding quantum is
   // always completed at the end of a quantity.  When fewer than 24 input
@@ -800,12 +802,12 @@
   size_t len = (input_len / 3) * 4;
 
   if (input_len % 3 == 0) {
-    // (from http://tools.ietf.org/html/rfc3548)
+    // (from https://tools.ietf.org/html/rfc3548)
     // (1) the final quantum of encoding input is an integral multiple of 24
     // bits; here, the final unit of encoded output will be an integral
     // multiple of 4 characters with no "=" padding,
   } else if (input_len % 3 == 1) {
-    // (from http://tools.ietf.org/html/rfc3548)
+    // (from https://tools.ietf.org/html/rfc3548)
     // (2) the final quantum of encoding input is exactly 8 bits; here, the
     // final unit of encoded output will be two characters followed by two
     // "=" padding characters, or
@@ -814,7 +816,7 @@
       len += 2;
     }
   } else {  // (input_len % 3 == 2)
-    // (from http://tools.ietf.org/html/rfc3548)
+    // (from https://tools.ietf.org/html/rfc3548)
     // (3) the final quantum of encoding input is exactly 16 bits; here, the
     // final unit of encoded output will be three characters followed by one
     // "=" padding character.
@@ -843,8 +845,8 @@
 
   // Three bytes of data encodes to four characters of cyphertext.
   // So we can pump through three-byte chunks atomically.
-  if (szsrc >= 3) {  // "limit_src - 3" is UB if szsrc < 3
-    while (cur_src < limit_src - 3) {  // as long as we have >= 32 bits
+  if (szsrc >= 3) {  // "limit_src - 3" is UB if szsrc < 3.
+    while (cur_src < limit_src - 3) {  // While we have >= 32 bits.
       uint32_t in = absl::big_endian::Load32(cur_src) >> 8;
 
       cur_dest[0] = base64[in >> 18];
@@ -1011,7 +1013,8 @@
   }
 }
 
-// This is a templated function so that T can be either a char* or a string.
+// This is a templated function so that T can be either a char* or a
+// std::string.
 template <typename T>
 void BytesToHexStringInternal(const unsigned char* src, T dest, ptrdiff_t num) {
   auto dest_ptr = &dest[0];
@@ -1028,7 +1031,8 @@
 //
 // See CUnescapeInternal() for implementation details.
 // ----------------------------------------------------------------------
-bool CUnescape(absl::string_view source, std::string* dest, std::string* error) {
+bool CUnescape(absl::string_view source, std::string* dest,
+               std::string* error) {
   return CUnescapeInternal(source, kUnescapeNulls, dest, error);
 }
 
diff --git a/absl/strings/escaping.h b/absl/strings/escaping.h
index 2965973..fd9be78 100644
--- a/absl/strings/escaping.h
+++ b/absl/strings/escaping.h
@@ -5,7 +5,7 @@
 // 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
+//      https://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,
@@ -19,7 +19,6 @@
 //
 // This header file contains string utilities involved in escaping and
 // unescaping strings in various ways.
-//
 
 #ifndef ABSL_STRINGS_ESCAPING_H_
 #define ABSL_STRINGS_ESCAPING_H_
@@ -38,7 +37,7 @@
 // CUnescape()
 //
 // Unescapes a `source` string and copies it into `dest`, rewriting C-style
-// escape sequences (http://en.cppreference.com/w/cpp/language/escape) into
+// escape sequences (https://en.cppreference.com/w/cpp/language/escape) into
 // their proper code point equivalents, returning `true` if successful.
 //
 // The following unescape sequences can be handled:
@@ -56,7 +55,6 @@
 //     UTF-8. (E.g., `\u2019` unescapes to the three bytes 0xE2, 0x80, and
 //     0x99).
 //
-//
 // If any errors are encountered, this function returns `false`, leaving the
 // `dest` output parameter in an unspecified state, and stores the first
 // encountered error in `error`. To disable error reporting, set `error` to
@@ -80,7 +78,7 @@
 // CEscape()
 //
 // Escapes a 'src' string using C-style escapes sequences
-// (http://en.cppreference.com/w/cpp/language/escape), escaping other
+// (https://en.cppreference.com/w/cpp/language/escape), escaping other
 // non-printable/non-whitespace bytes as octal sequences (e.g. "\377").
 //
 // Example:
diff --git a/absl/strings/escaping_benchmark.cc b/absl/strings/escaping_benchmark.cc
index 0f791f4..10d5b03 100644
--- a/absl/strings/escaping_benchmark.cc
+++ b/absl/strings/escaping_benchmark.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
diff --git a/absl/strings/escaping_test.cc b/absl/strings/escaping_test.cc
index 9dc27f3..d433b4c 100644
--- a/absl/strings/escaping_test.cc
+++ b/absl/strings/escaping_test.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -36,18 +36,19 @@
 
 TEST(CEscape, EscapeAndUnescape) {
   const std::string inputs[] = {
-    std::string("foo\nxx\r\b\0023"),
-    std::string(""),
-    std::string("abc"),
-    std::string("\1chad_rules"),
-    std::string("\1arnar_drools"),
-    std::string("xxxx\r\t'\"\\"),
-    std::string("\0xx\0", 4),
-    std::string("\x01\x31"),
-    std::string("abc\xb\x42\141bc"),
-    std::string("123\1\x31\x32\x33"),
-    std::string("\xc1\xca\x1b\x62\x19o\xcc\x04"),
-    std::string("\\\"\xe8\xb0\xb7\xe6\xad\x8c\\\" is Google\\\'s Chinese name"),
+      std::string("foo\nxx\r\b\0023"),
+      std::string(""),
+      std::string("abc"),
+      std::string("\1chad_rules"),
+      std::string("\1arnar_drools"),
+      std::string("xxxx\r\t'\"\\"),
+      std::string("\0xx\0", 4),
+      std::string("\x01\x31"),
+      std::string("abc\xb\x42\141bc"),
+      std::string("123\1\x31\x32\x33"),
+      std::string("\xc1\xca\x1b\x62\x19o\xcc\x04"),
+      std::string(
+          "\\\"\xe8\xb0\xb7\xe6\xad\x8c\\\" is Google\\\'s Chinese name"),
   };
   // Do this twice, once for octal escapes and once for hex escapes.
   for (int kind = 0; kind < 4; kind++) {
@@ -159,15 +160,14 @@
     EXPECT_TRUE(absl::CUnescape(val.escaped, &out));
     EXPECT_EQ(out, val.unescaped);
   }
-  std::string bad[] =
-     {"\\u1",         // too short
-      "\\U1",         // too short
-      "\\Uffffff",    // exceeds 0x10ffff (largest Unicode)
-      "\\U00110000",  // exceeds 0x10ffff (largest Unicode)
-      "\\uD835",      // surrogate character (D800-DFFF)
-      "\\U0000DD04",  // surrogate character (D800-DFFF)
-      "\\777",        // exceeds 0xff
-      "\\xABCD"};     // exceeds 0xff
+  std::string bad[] = {"\\u1",         // too short
+                       "\\U1",         // too short
+                       "\\Uffffff",    // exceeds 0x10ffff (largest Unicode)
+                       "\\U00110000",  // exceeds 0x10ffff (largest Unicode)
+                       "\\uD835",      // surrogate character (D800-DFFF)
+                       "\\U0000DD04",  // surrogate character (D800-DFFF)
+                       "\\777",        // exceeds 0xff
+                       "\\xABCD"};     // exceeds 0xff
   for (const std::string& e : bad) {
     std::string error;
     std::string out;
@@ -258,9 +258,11 @@
   // All escapes, including newlines and null escapes, should have been
   // converted to the equivalent characters.
   EXPECT_EQ(std::string("\0\n"
-                   "0\n"
-                   "\0\n"
-                   "\0", 7), result_string_);
+                        "0\n"
+                        "\0\n"
+                        "\0",
+                        7),
+            result_string_);
 }
 
 
@@ -268,17 +270,21 @@
   std::string original_string(kStringWithMultipleHexNulls);
   EXPECT_TRUE(absl::CUnescape(original_string, &result_string_));
   EXPECT_EQ(std::string("\0\n"
-                   "0\n"
-                   "\0\n"
-                   "\0", 7), result_string_);
+                        "0\n"
+                        "\0\n"
+                        "\0",
+                        7),
+            result_string_);
 }
 
 TEST_F(CUnescapeTest, UnescapesMultipleUnicodeNulls) {
   std::string original_string(kStringWithMultipleUnicodeNulls);
   EXPECT_TRUE(absl::CUnescape(original_string, &result_string_));
   EXPECT_EQ(std::string("\0\n"
-                   "0\n"
-                   "\0", 5), result_string_);
+                        "0\n"
+                        "\0",
+                        5),
+            result_string_);
 }
 
 static struct {
diff --git a/absl/strings/internal/char_map.h b/absl/strings/internal/char_map.h
index 8d92963..b9108b8 100644
--- a/absl/strings/internal/char_map.h
+++ b/absl/strings/internal/char_map.h
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
diff --git a/absl/strings/internal/char_map_benchmark.cc b/absl/strings/internal/char_map_benchmark.cc
index c45f315..5cef967 100644
--- a/absl/strings/internal/char_map_benchmark.cc
+++ b/absl/strings/internal/char_map_benchmark.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
diff --git a/absl/strings/internal/char_map_test.cc b/absl/strings/internal/char_map_test.cc
index c3601e1..d330624 100644
--- a/absl/strings/internal/char_map_test.cc
+++ b/absl/strings/internal/char_map_test.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
diff --git a/absl/strings/internal/charconv_bigint.cc b/absl/strings/internal/charconv_bigint.cc
index 3e7296e..95d471d 100644
--- a/absl/strings/internal/charconv_bigint.cc
+++ b/absl/strings/internal/charconv_bigint.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
diff --git a/absl/strings/internal/charconv_bigint.h b/absl/strings/internal/charconv_bigint.h
index aa70af2..7da9a7e 100644
--- a/absl/strings/internal/charconv_bigint.h
+++ b/absl/strings/internal/charconv_bigint.h
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -57,17 +57,10 @@
                 "unsupported max_words value");
 
   BigUnsigned() : size_(0), words_{} {}
-  explicit BigUnsigned(uint32_t v) : size_(v > 0 ? 1 : 0), words_{v} {}
-  explicit BigUnsigned(uint64_t v)
-      : size_(0),
-        words_{static_cast<uint32_t>(v & 0xffffffff),
-               static_cast<uint32_t>(v >> 32)} {
-    if (words_[1]) {
-      size_ = 2;
-    } else if (words_[0]) {
-      size_ = 1;
-    }
-  }
+  explicit constexpr BigUnsigned(uint64_t v)
+      : size_((v >> 32) ? 2 : v ? 1 : 0),
+        words_{static_cast<uint32_t>(v & 0xffffffffu),
+               static_cast<uint32_t>(v >> 32)} {}
 
   // Constructs a BigUnsigned from the given string_view containing a decimal
   // value.  If the input std::string is not a decimal integer, constructs a 0
@@ -110,12 +103,12 @@
         SetToZero();
         return;
       }
-      size_ = std::min(size_ + word_shift, max_words);
+      size_ = (std::min)(size_ + word_shift, max_words);
       count %= 32;
       if (count == 0) {
         std::copy_backward(words_, words_ + size_ - word_shift, words_ + size_);
       } else {
-        for (int i = std::min(size_, max_words - 1); i > word_shift; --i) {
+        for (int i = (std::min)(size_, max_words - 1); i > word_shift; --i) {
           words_[i] = (words_[i - word_shift] << count) |
                       (words_[i - word_shift - 1] >> (32 - count));
         }
@@ -274,7 +267,7 @@
   void MultiplyBy(int other_size, const uint32_t* other_words) {
     const int original_size = size_;
     const int first_step =
-        std::min(original_size + other_size - 2, max_words - 1);
+        (std::min)(original_size + other_size - 2, max_words - 1);
     for (int step = first_step; step >= 0; --step) {
       MultiplyStep(original_size, other_words, other_size, step);
     }
@@ -293,7 +286,7 @@
           value = 0;
         }
       }
-      size_ = std::min(max_words, std::max(index + 1, size_));
+      size_ = (std::min)(max_words, (std::max)(index + 1, size_));
     }
   }
 
@@ -316,7 +309,7 @@
       } else {
         // Normally 32-bit AddWithCarry() sets size_, but since we don't call
         // it when `high` is 0, do it ourselves here.
-        size_ = std::min(max_words, std::max(index + 1, size_));
+        size_ = (std::min)(max_words, (std::max)(index + 1, size_));
       }
     }
   }
@@ -355,7 +348,7 @@
 // Returns -1 if lhs < rhs, 0 if lhs == rhs, and 1 if lhs > rhs.
 template <int N, int M>
 int Compare(const BigUnsigned<N>& lhs, const BigUnsigned<M>& rhs) {
-  int limit = std::max(lhs.size(), rhs.size());
+  int limit = (std::max)(lhs.size(), rhs.size());
   for (int i = limit - 1; i >= 0; --i) {
     const uint32_t lhs_word = lhs.GetWord(i);
     const uint32_t rhs_word = rhs.GetWord(i);
@@ -370,7 +363,7 @@
 
 template <int N, int M>
 bool operator==(const BigUnsigned<N>& lhs, const BigUnsigned<M>& rhs) {
-  int limit = std::max(lhs.size(), rhs.size());
+  int limit = (std::max)(lhs.size(), rhs.size());
   for (int i = 0; i < limit; ++i) {
     if (lhs.GetWord(i) != rhs.GetWord(i)) {
       return false;
diff --git a/absl/strings/internal/charconv_bigint_test.cc b/absl/strings/internal/charconv_bigint_test.cc
index 9b63578..745714a 100644
--- a/absl/strings/internal/charconv_bigint_test.cc
+++ b/absl/strings/internal/charconv_bigint_test.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
diff --git a/absl/strings/internal/charconv_parse.cc b/absl/strings/internal/charconv_parse.cc
index 7e4dabc..f3c7232 100644
--- a/absl/strings/internal/charconv_parse.cc
+++ b/absl/strings/internal/charconv_parse.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
diff --git a/absl/strings/internal/charconv_parse.h b/absl/strings/internal/charconv_parse.h
index 7a5c087..44d06b2 100644
--- a/absl/strings/internal/charconv_parse.h
+++ b/absl/strings/internal/charconv_parse.h
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
diff --git a/absl/strings/internal/charconv_parse_test.cc b/absl/strings/internal/charconv_parse_test.cc
index f48b9ae..9511c98 100644
--- a/absl/strings/internal/charconv_parse_test.cc
+++ b/absl/strings/internal/charconv_parse_test.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
diff --git a/absl/strings/internal/escaping_test_common.h b/absl/strings/internal/escaping_test_common.h
index cc41f43..bd80303 100644
--- a/absl/strings/internal/escaping_test_common.h
+++ b/absl/strings/internal/escaping_test_common.h
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
diff --git a/absl/strings/internal/memutil.cc b/absl/strings/internal/memutil.cc
index a0de70d..77aa63c 100644
--- a/absl/strings/internal/memutil.cc
+++ b/absl/strings/internal/memutil.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
diff --git a/absl/strings/internal/memutil.h b/absl/strings/internal/memutil.h
index 7de383b..7c071a8 100644
--- a/absl/strings/internal/memutil.h
+++ b/absl/strings/internal/memutil.h
@@ -5,7 +5,7 @@
 // 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
+//      https://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,
diff --git a/absl/strings/internal/memutil_benchmark.cc b/absl/strings/internal/memutil_benchmark.cc
index 77915ad..dc95c3e 100644
--- a/absl/strings/internal/memutil_benchmark.cc
+++ b/absl/strings/internal/memutil_benchmark.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
diff --git a/absl/strings/internal/memutil_test.cc b/absl/strings/internal/memutil_test.cc
index 09424de..d8681dd 100644
--- a/absl/strings/internal/memutil_test.cc
+++ b/absl/strings/internal/memutil_test.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
diff --git a/absl/strings/internal/numbers_test_common.h b/absl/strings/internal/numbers_test_common.h
index 20e3af5..2824720 100644
--- a/absl/strings/internal/numbers_test_common.h
+++ b/absl/strings/internal/numbers_test_common.h
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -64,11 +64,11 @@
 
 inline const std::array<uint32_test_case, 27>& strtouint32_test_cases() {
   static const std::array<uint32_test_case, 27> test_cases{{
-      {"0xffffffff", true, 16, std::numeric_limits<uint32_t>::max()},
+      {"0xffffffff", true, 16, (std::numeric_limits<uint32_t>::max)()},
       {"0x34234324", true, 16, 0x34234324},
       {"34234324", true, 16, 0x34234324},
       {"0", true, 16, 0},
-      {" \t\n 0xffffffff", true, 16, std::numeric_limits<uint32_t>::max()},
+      {" \t\n 0xffffffff", true, 16, (std::numeric_limits<uint32_t>::max)()},
       {" \f\v 46", true, 10, 46},  // must accept weird whitespace
       {" \t\n 72717222", true, 8, 072717222},
       {" \t\n 072717222", true, 8, 072717222},
@@ -77,7 +77,7 @@
 
       // Base-10 version.
       {"34234324", true, 0, 34234324},
-      {"4294967295", true, 0, std::numeric_limits<uint32_t>::max()},
+      {"4294967295", true, 0, (std::numeric_limits<uint32_t>::max)()},
       {"34234324 \n\t", true, 10, 34234324},
 
       // Unusual base
@@ -96,8 +96,8 @@
       {" \t\n -123", false, 0, 0},
 
       // Out of bounds.
-      {"4294967296", false, 0, std::numeric_limits<uint32_t>::max()},
-      {"0x100000000", false, 0, std::numeric_limits<uint32_t>::max()},
+      {"4294967296", false, 0, (std::numeric_limits<uint32_t>::max)()},
+      {"0x100000000", false, 0, (std::numeric_limits<uint32_t>::max)()},
       {nullptr, false, 0, 0},
   }};
   return test_cases;
@@ -119,7 +119,7 @@
       {"000", true, 0, 0},
       {"0", true, 0, 0},
       {" \t\n 0xffffffffffffffff", true, 16,
-       std::numeric_limits<uint64_t>::max()},
+       (std::numeric_limits<uint64_t>::max)()},
 
       {"012345670123456701234", true, 8, int64_t{012345670123456701234}},
       {"12345670123456701234", true, 8, int64_t{012345670123456701234}},
@@ -130,7 +130,7 @@
       {"34234324487834466", true, 0, int64_t{34234324487834466}},
 
       {" \t\n 18446744073709551615", true, 0,
-       std::numeric_limits<uint64_t>::max()},
+       (std::numeric_limits<uint64_t>::max)()},
 
       {"34234324487834466 \n\t ", true, 0, int64_t{34234324487834466}},
 
@@ -156,12 +156,13 @@
       // Out of bounds.
       {"18446744073709551616", false, 10, 0},
       {"18446744073709551616", false, 0, 0},
-      {"0x10000000000000000", false, 16, std::numeric_limits<uint64_t>::max()},
+      {"0x10000000000000000", false, 16,
+       (std::numeric_limits<uint64_t>::max)()},
       {"0X10000000000000000", false, 16,
-       std::numeric_limits<uint64_t>::max()},  // 0X versus 0x.
-      {"0x10000000000000000", false, 0, std::numeric_limits<uint64_t>::max()},
+       (std::numeric_limits<uint64_t>::max)()},  // 0X versus 0x.
+      {"0x10000000000000000", false, 0, (std::numeric_limits<uint64_t>::max)()},
       {"0X10000000000000000", false, 0,
-       std::numeric_limits<uint64_t>::max()},  // 0X versus 0x.
+       (std::numeric_limits<uint64_t>::max)()},  // 0X versus 0x.
 
       {"0x1234", true, 16, 0x1234},
 
diff --git a/absl/strings/internal/ostringstream.cc b/absl/strings/internal/ostringstream.cc
index 6ee2b10..d0f0f84 100644
--- a/absl/strings/internal/ostringstream.cc
+++ b/absl/strings/internal/ostringstream.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
diff --git a/absl/strings/internal/ostringstream.h b/absl/strings/internal/ostringstream.h
index e81a89a..2079201 100644
--- a/absl/strings/internal/ostringstream.h
+++ b/absl/strings/internal/ostringstream.h
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -25,18 +25,18 @@
 namespace absl {
 namespace strings_internal {
 
-// The same as std::ostringstream but appends to a user-specified string,
+// The same as std::ostringstream but appends to a user-specified std::string,
 // and is faster. It is ~70% faster to create, ~50% faster to write to, and
-// completely free to extract the result string.
+// completely free to extract the result std::string.
 //
-//   string s;
+//   std::string s;
 //   OStringStream strm(&s);
 //   strm << 42 << ' ' << 3.14;  // appends to `s`
 //
 // The stream object doesn't have to be named. Starting from C++11 operator<<
 // works with rvalues of std::ostream.
 //
-//   string s;
+//   std::string s;
 //   OStringStream(&s) << 42 << ' ' << 3.14;  // appends to `s`
 //
 // OStringStream is faster to create than std::ostringstream but it's still
@@ -45,14 +45,14 @@
 //
 // Creates unnecessary instances of OStringStream: slow.
 //
-//   string s;
+//   std::string s;
 //   OStringStream(&s) << 42;
 //   OStringStream(&s) << ' ';
 //   OStringStream(&s) << 3.14;
 //
 // Creates a single instance of OStringStream and reuses it: fast.
 //
-//   string s;
+//   std::string s;
 //   OStringStream strm(&s);
 //   strm << 42;
 //   strm << ' ';
@@ -64,8 +64,8 @@
   // The argument can be null, in which case you'll need to call str(p) with a
   // non-null argument before you can write to the stream.
   //
-  // The destructor of OStringStream doesn't use the std::string. It's OK to destroy
-  // the std::string before the stream.
+  // The destructor of OStringStream doesn't use the std::string. It's OK to
+  // destroy the std::string before the stream.
   explicit OStringStream(std::string* s) : std::ostream(this), s_(s) {}
 
   std::string* str() { return s_; }
diff --git a/absl/strings/internal/ostringstream_benchmark.cc b/absl/strings/internal/ostringstream_benchmark.cc
index c93f969..5979f18 100644
--- a/absl/strings/internal/ostringstream_benchmark.cc
+++ b/absl/strings/internal/ostringstream_benchmark.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
diff --git a/absl/strings/internal/ostringstream_test.cc b/absl/strings/internal/ostringstream_test.cc
index 069a0e1..2879e50 100644
--- a/absl/strings/internal/ostringstream_test.cc
+++ b/absl/strings/internal/ostringstream_test.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
diff --git a/absl/strings/internal/pow10_helper.cc b/absl/strings/internal/pow10_helper.cc
new file mode 100644
index 0000000..03ed8d0
--- /dev/null
+++ b/absl/strings/internal/pow10_helper.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
+//
+//      https://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/internal/pow10_helper.h"
+
+#include <cmath>
+
+namespace absl {
+namespace strings_internal {
+
+namespace {
+
+// The exact value of 1e23 falls precisely halfway between two representable
+// doubles. Furthermore, the rounding rules we prefer (break ties by rounding
+// to the nearest even) dictate in this case that the number should be rounded
+// down, but this is not completely specified for floating-point literals in
+// C++. (It just says to use the default rounding mode of the standard
+// library.) We ensure the result we want by using a number that has an
+// unambiguous correctly rounded answer.
+constexpr double k1e23 = 9999999999999999e7;
+
+constexpr double kPowersOfTen[] = {
+    0.0,    1e-323, 1e-322, 1e-321, 1e-320, 1e-319, 1e-318, 1e-317, 1e-316,
+    1e-315, 1e-314, 1e-313, 1e-312, 1e-311, 1e-310, 1e-309, 1e-308, 1e-307,
+    1e-306, 1e-305, 1e-304, 1e-303, 1e-302, 1e-301, 1e-300, 1e-299, 1e-298,
+    1e-297, 1e-296, 1e-295, 1e-294, 1e-293, 1e-292, 1e-291, 1e-290, 1e-289,
+    1e-288, 1e-287, 1e-286, 1e-285, 1e-284, 1e-283, 1e-282, 1e-281, 1e-280,
+    1e-279, 1e-278, 1e-277, 1e-276, 1e-275, 1e-274, 1e-273, 1e-272, 1e-271,
+    1e-270, 1e-269, 1e-268, 1e-267, 1e-266, 1e-265, 1e-264, 1e-263, 1e-262,
+    1e-261, 1e-260, 1e-259, 1e-258, 1e-257, 1e-256, 1e-255, 1e-254, 1e-253,
+    1e-252, 1e-251, 1e-250, 1e-249, 1e-248, 1e-247, 1e-246, 1e-245, 1e-244,
+    1e-243, 1e-242, 1e-241, 1e-240, 1e-239, 1e-238, 1e-237, 1e-236, 1e-235,
+    1e-234, 1e-233, 1e-232, 1e-231, 1e-230, 1e-229, 1e-228, 1e-227, 1e-226,
+    1e-225, 1e-224, 1e-223, 1e-222, 1e-221, 1e-220, 1e-219, 1e-218, 1e-217,
+    1e-216, 1e-215, 1e-214, 1e-213, 1e-212, 1e-211, 1e-210, 1e-209, 1e-208,
+    1e-207, 1e-206, 1e-205, 1e-204, 1e-203, 1e-202, 1e-201, 1e-200, 1e-199,
+    1e-198, 1e-197, 1e-196, 1e-195, 1e-194, 1e-193, 1e-192, 1e-191, 1e-190,
+    1e-189, 1e-188, 1e-187, 1e-186, 1e-185, 1e-184, 1e-183, 1e-182, 1e-181,
+    1e-180, 1e-179, 1e-178, 1e-177, 1e-176, 1e-175, 1e-174, 1e-173, 1e-172,
+    1e-171, 1e-170, 1e-169, 1e-168, 1e-167, 1e-166, 1e-165, 1e-164, 1e-163,
+    1e-162, 1e-161, 1e-160, 1e-159, 1e-158, 1e-157, 1e-156, 1e-155, 1e-154,
+    1e-153, 1e-152, 1e-151, 1e-150, 1e-149, 1e-148, 1e-147, 1e-146, 1e-145,
+    1e-144, 1e-143, 1e-142, 1e-141, 1e-140, 1e-139, 1e-138, 1e-137, 1e-136,
+    1e-135, 1e-134, 1e-133, 1e-132, 1e-131, 1e-130, 1e-129, 1e-128, 1e-127,
+    1e-126, 1e-125, 1e-124, 1e-123, 1e-122, 1e-121, 1e-120, 1e-119, 1e-118,
+    1e-117, 1e-116, 1e-115, 1e-114, 1e-113, 1e-112, 1e-111, 1e-110, 1e-109,
+    1e-108, 1e-107, 1e-106, 1e-105, 1e-104, 1e-103, 1e-102, 1e-101, 1e-100,
+    1e-99,  1e-98,  1e-97,  1e-96,  1e-95,  1e-94,  1e-93,  1e-92,  1e-91,
+    1e-90,  1e-89,  1e-88,  1e-87,  1e-86,  1e-85,  1e-84,  1e-83,  1e-82,
+    1e-81,  1e-80,  1e-79,  1e-78,  1e-77,  1e-76,  1e-75,  1e-74,  1e-73,
+    1e-72,  1e-71,  1e-70,  1e-69,  1e-68,  1e-67,  1e-66,  1e-65,  1e-64,
+    1e-63,  1e-62,  1e-61,  1e-60,  1e-59,  1e-58,  1e-57,  1e-56,  1e-55,
+    1e-54,  1e-53,  1e-52,  1e-51,  1e-50,  1e-49,  1e-48,  1e-47,  1e-46,
+    1e-45,  1e-44,  1e-43,  1e-42,  1e-41,  1e-40,  1e-39,  1e-38,  1e-37,
+    1e-36,  1e-35,  1e-34,  1e-33,  1e-32,  1e-31,  1e-30,  1e-29,  1e-28,
+    1e-27,  1e-26,  1e-25,  1e-24,  1e-23,  1e-22,  1e-21,  1e-20,  1e-19,
+    1e-18,  1e-17,  1e-16,  1e-15,  1e-14,  1e-13,  1e-12,  1e-11,  1e-10,
+    1e-9,   1e-8,   1e-7,   1e-6,   1e-5,   1e-4,   1e-3,   1e-2,   1e-1,
+    1e+0,   1e+1,   1e+2,   1e+3,   1e+4,   1e+5,   1e+6,   1e+7,   1e+8,
+    1e+9,   1e+10,  1e+11,  1e+12,  1e+13,  1e+14,  1e+15,  1e+16,  1e+17,
+    1e+18,  1e+19,  1e+20,  1e+21,  1e+22,  k1e23,  1e+24,  1e+25,  1e+26,
+    1e+27,  1e+28,  1e+29,  1e+30,  1e+31,  1e+32,  1e+33,  1e+34,  1e+35,
+    1e+36,  1e+37,  1e+38,  1e+39,  1e+40,  1e+41,  1e+42,  1e+43,  1e+44,
+    1e+45,  1e+46,  1e+47,  1e+48,  1e+49,  1e+50,  1e+51,  1e+52,  1e+53,
+    1e+54,  1e+55,  1e+56,  1e+57,  1e+58,  1e+59,  1e+60,  1e+61,  1e+62,
+    1e+63,  1e+64,  1e+65,  1e+66,  1e+67,  1e+68,  1e+69,  1e+70,  1e+71,
+    1e+72,  1e+73,  1e+74,  1e+75,  1e+76,  1e+77,  1e+78,  1e+79,  1e+80,
+    1e+81,  1e+82,  1e+83,  1e+84,  1e+85,  1e+86,  1e+87,  1e+88,  1e+89,
+    1e+90,  1e+91,  1e+92,  1e+93,  1e+94,  1e+95,  1e+96,  1e+97,  1e+98,
+    1e+99,  1e+100, 1e+101, 1e+102, 1e+103, 1e+104, 1e+105, 1e+106, 1e+107,
+    1e+108, 1e+109, 1e+110, 1e+111, 1e+112, 1e+113, 1e+114, 1e+115, 1e+116,
+    1e+117, 1e+118, 1e+119, 1e+120, 1e+121, 1e+122, 1e+123, 1e+124, 1e+125,
+    1e+126, 1e+127, 1e+128, 1e+129, 1e+130, 1e+131, 1e+132, 1e+133, 1e+134,
+    1e+135, 1e+136, 1e+137, 1e+138, 1e+139, 1e+140, 1e+141, 1e+142, 1e+143,
+    1e+144, 1e+145, 1e+146, 1e+147, 1e+148, 1e+149, 1e+150, 1e+151, 1e+152,
+    1e+153, 1e+154, 1e+155, 1e+156, 1e+157, 1e+158, 1e+159, 1e+160, 1e+161,
+    1e+162, 1e+163, 1e+164, 1e+165, 1e+166, 1e+167, 1e+168, 1e+169, 1e+170,
+    1e+171, 1e+172, 1e+173, 1e+174, 1e+175, 1e+176, 1e+177, 1e+178, 1e+179,
+    1e+180, 1e+181, 1e+182, 1e+183, 1e+184, 1e+185, 1e+186, 1e+187, 1e+188,
+    1e+189, 1e+190, 1e+191, 1e+192, 1e+193, 1e+194, 1e+195, 1e+196, 1e+197,
+    1e+198, 1e+199, 1e+200, 1e+201, 1e+202, 1e+203, 1e+204, 1e+205, 1e+206,
+    1e+207, 1e+208, 1e+209, 1e+210, 1e+211, 1e+212, 1e+213, 1e+214, 1e+215,
+    1e+216, 1e+217, 1e+218, 1e+219, 1e+220, 1e+221, 1e+222, 1e+223, 1e+224,
+    1e+225, 1e+226, 1e+227, 1e+228, 1e+229, 1e+230, 1e+231, 1e+232, 1e+233,
+    1e+234, 1e+235, 1e+236, 1e+237, 1e+238, 1e+239, 1e+240, 1e+241, 1e+242,
+    1e+243, 1e+244, 1e+245, 1e+246, 1e+247, 1e+248, 1e+249, 1e+250, 1e+251,
+    1e+252, 1e+253, 1e+254, 1e+255, 1e+256, 1e+257, 1e+258, 1e+259, 1e+260,
+    1e+261, 1e+262, 1e+263, 1e+264, 1e+265, 1e+266, 1e+267, 1e+268, 1e+269,
+    1e+270, 1e+271, 1e+272, 1e+273, 1e+274, 1e+275, 1e+276, 1e+277, 1e+278,
+    1e+279, 1e+280, 1e+281, 1e+282, 1e+283, 1e+284, 1e+285, 1e+286, 1e+287,
+    1e+288, 1e+289, 1e+290, 1e+291, 1e+292, 1e+293, 1e+294, 1e+295, 1e+296,
+    1e+297, 1e+298, 1e+299, 1e+300, 1e+301, 1e+302, 1e+303, 1e+304, 1e+305,
+    1e+306, 1e+307, 1e+308,
+};
+
+}  // namespace
+
+double Pow10(int exp) {
+  if (exp < -324) {
+    return 0.0;
+  } else if (exp > 308) {
+    return INFINITY;
+  } else {
+    return kPowersOfTen[exp + 324];
+  }
+}
+
+}  // namespace strings_internal
+}  // namespace absl
diff --git a/absl/strings/internal/pow10_helper.h b/absl/strings/internal/pow10_helper.h
new file mode 100644
index 0000000..9d1aa71
--- /dev/null
+++ b/absl/strings/internal/pow10_helper.h
@@ -0,0 +1,36 @@
+//
+// 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
+//
+//      https://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.
+//
+// This test helper library contains a table of powers of 10, to guarantee
+// precise values are computed across the full range of doubles. We can't rely
+// on the pow() function, because not all standard libraries ship a version
+// that is precise.
+#ifndef ABSL_STRINGS_INTERNAL_POW10_HELPER_H_
+#define ABSL_STRINGS_INTERNAL_POW10_HELPER_H_
+
+#include <vector>
+
+namespace absl {
+namespace strings_internal {
+
+// Computes the precise value of 10^exp. (I.e. the nearest representable
+// double to the exact value, rounding to nearest-even in the (single) case of
+// being exactly halfway between.)
+double Pow10(int exp);
+
+}  // namespace strings_internal
+}  // namespace absl
+
+#endif  // ABSL_STRINGS_INTERNAL_POW10_HELPER_H_
diff --git a/absl/strings/internal/pow10_helper_test.cc b/absl/strings/internal/pow10_helper_test.cc
new file mode 100644
index 0000000..a4a68b5
--- /dev/null
+++ b/absl/strings/internal/pow10_helper_test.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
+//
+//      https://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/internal/pow10_helper.h"
+
+#include <cmath>
+
+#include "gtest/gtest.h"
+#include "absl/strings/str_format.h"
+
+namespace absl {
+namespace strings_internal {
+
+namespace {
+
+struct TestCase {
+  int power;           // Testing Pow10(power)
+  uint64_t significand;  // Raw bits of the expected value
+  int radix;           // significand is adjusted by 2^radix
+};
+
+TEST(Pow10HelperTest, Works) {
+  // The logic in pow10_helper.cc is so simple that theoretically we don't even
+  // need a test. However, we're paranoid and believe that there may be
+  // compilers that don't round floating-point literals correctly, even though
+  // it is specified by the standard. We check various edge cases, just to be
+  // sure.
+  constexpr TestCase kTestCases[] = {
+      // Subnormals
+      {-323, 0x2, -1074},
+      {-322, 0x14, -1074},
+      {-321, 0xca, -1074},
+      {-320, 0x7e8, -1074},
+      {-319, 0x4f10, -1074},
+      {-318, 0x316a2, -1074},
+      {-317, 0x1ee257, -1074},
+      {-316, 0x134d761, -1074},
+      {-315, 0xc1069cd, -1074},
+      {-314, 0x78a42205, -1074},
+      {-313, 0x4b6695433, -1074},
+      {-312, 0x2f201d49fb, -1074},
+      {-311, 0x1d74124e3d1, -1074},
+      {-310, 0x12688b70e62b, -1074},
+      {-309, 0xb8157268fdaf, -1074},
+      {-308, 0x730d67819e8d2, -1074},
+      // Values that are very close to rounding the other way.
+      // Comment shows difference of significand from the true value.
+      {-307, 0x11fa182c40c60d, -1072},  // -.4588
+      {-290, 0x18f2b061aea072, -1016},  //  .4854
+      {-276, 0x11BA03F5B21000, -969},   //  .4709
+      {-259, 0x1899C2F6732210, -913},   //  .4830
+      {-252, 0x1D53844EE47DD1, -890},   // -.4743
+      {-227, 0x1E5297287C2F45, -807},   // -.4708
+      {-198, 0x1322E220A5B17E, -710},   // -.4714
+      {-195, 0x12B010D3E1CF56, -700},   //  .4928
+      {-192, 0x123FF06EEA847A, -690},   //  .4968
+      {-163, 0x1708D0F84D3DE7, -594},   // -.4977
+      {-145, 0x13FAAC3E3FA1F3, -534},   // -.4785
+      {-111, 0x133D4032C2C7F5, -421},   //  .4774
+      {-106, 0x1D5B561574765B, -405},   // -.4869
+      {-104, 0x16EF5B40C2FC77, -398},   // -.4741
+      {-88, 0x197683DF2F268D, -345},    // -.4738
+      {-86, 0x13E497065CD61F, -338},    //  .4736
+      {-76, 0x17288E1271F513, -305},    // -.4761
+      {-63, 0x1A53FC9631D10D, -262},    //  .4929
+      {-30, 0x14484BFEEBC2A0, -152},    //  .4758
+      {-21, 0x12E3B40A0E9B4F, -122},    // -.4916
+      {-5, 0x14F8B588E368F1, -69},      //  .4829
+      {23, 0x152D02C7E14AF6, 24},       // -.5000 (exactly, round-to-even)
+      {29, 0x1431E0FAE6D721, 44},       // -.4870
+      {34, 0x1ED09BEAD87C03, 60},       // -.4721
+      {70, 0x172EBAD6DDC73D, 180},      //  .4733
+      {105, 0x1BE7ABD3781ECA, 296},     // -.4850
+      {126, 0x17A2ECC414A03F, 366},     // -.4999
+      {130, 0x1CDA62055B2D9E, 379},     //  .4855
+      {165, 0x115D847AD00087, 496},     // -.4913
+      {172, 0x14B378469B6732, 519},     //  .4818
+      {187, 0x1262DFEEBBB0F9, 569},     // -.4805
+      {210, 0x18557F31326BBB, 645},     // -.4992
+      {212, 0x1302CB5E6F642A, 652},     // -.4838
+      {215, 0x1290BA9A38C7D1, 662},     // -.4881
+      {236, 0x1F736F9B3494E9, 731},     //  .4707
+      {244, 0x176EC98994F489, 758},     //  .4924
+      {250, 0x1658E3AB795204, 778},     // -.4963
+      {252, 0x117571DDF6C814, 785},     //  .4873
+      {254, 0x1B4781EAD1989E, 791},     // -.4887
+      {260, 0x1A03FDE214CAF1, 811},     //  .4784
+      {284, 0x1585041B2C477F, 891},     //  .4798
+      {304, 0x1D2A1BE4048F90, 957},     // -.4987
+      // Out-of-range values
+      {-324, 0x0, 0},
+      {-325, 0x0, 0},
+      {-326, 0x0, 0},
+      {309, 1, 2000},
+      {310, 1, 2000},
+      {311, 1, 2000},
+  };
+  for (const TestCase& test_case : kTestCases) {
+    EXPECT_EQ(Pow10(test_case.power),
+              std::ldexp(test_case.significand, test_case.radix))
+        << absl::StrFormat("Failure for Pow10(%d): %a vs %a", test_case.power,
+                           Pow10(test_case.power),
+                           std::ldexp(test_case.significand, test_case.radix));
+  }
+}
+
+}  // namespace
+}  // namespace strings_internal
+}  // namespace absl
diff --git a/absl/strings/internal/resize_uninitialized.h b/absl/strings/internal/resize_uninitialized.h
index a94e054..469962b 100644
--- a/absl/strings/internal/resize_uninitialized.h
+++ b/absl/strings/internal/resize_uninitialized.h
@@ -5,7 +5,7 @@
 // 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
+//      https://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,
@@ -18,6 +18,7 @@
 #define ABSL_STRINGS_INTERNAL_RESIZE_UNINITIALIZED_H_
 
 #include <string>
+#include <type_traits>
 #include <utility>
 
 #include "absl/base/port.h"
@@ -27,40 +28,42 @@
 namespace strings_internal {
 
 // Is a subclass of true_type or false_type, depending on whether or not
-// T has a resize_uninitialized member.
-template <typename T, typename = void>
-struct HasResizeUninitialized : std::false_type {};
-template <typename T>
-struct HasResizeUninitialized<
-    T, absl::void_t<decltype(std::declval<T>().resize_uninitialized(237))>>
-    : std::true_type {};
+// T has a __resize_default_init member.
+template <typename string_type, typename = void>
+struct ResizeUninitializedTraits {
+  using HasMember = std::false_type;
+  static void Resize(string_type* s, size_t new_size) { s->resize(new_size); }
+};
 
+// __resize_default_init is provided by libc++ >= 8.0 and by Google's internal
+// ::string implementation.
 template <typename string_type>
-void ResizeUninit(string_type* s, size_t new_size, std::true_type) {
-  s->resize_uninitialized(new_size);
-}
-template <typename string_type>
-void ResizeUninit(string_type* s, size_t new_size, std::false_type) {
-  s->resize(new_size);
-}
+struct ResizeUninitializedTraits<
+    string_type, absl::void_t<decltype(std::declval<string_type&>()
+                                           .__resize_default_init(237))> > {
+  using HasMember = std::true_type;
+  static void Resize(string_type* s, size_t new_size) {
+    s->__resize_default_init(new_size);
+  }
+};
 
-// Returns true if the string implementation supports a resize where
-// the new characters added to the string are left untouched.
+// Returns true if the std::string implementation supports a resize where
+// the new characters added to the std::string are left untouched.
 //
 // (A better name might be "STLStringSupportsUninitializedResize", alluding to
 // the previous function.)
 template <typename string_type>
 inline constexpr bool STLStringSupportsNontrashingResize(string_type*) {
-  return HasResizeUninitialized<string_type>();
+  return ResizeUninitializedTraits<string_type>::HasMember::value;
 }
 
 // Like str->resize(new_size), except any new characters added to "*str" as a
 // result of resizing may be left uninitialized, rather than being filled with
 // '0' bytes. Typically used when code is then going to overwrite the backing
-// store of the string with known data. Uses a Google extension to ::string.
+// store of the std::string with known data.
 template <typename string_type, typename = void>
 inline void STLStringResizeUninitialized(string_type* s, size_t new_size) {
-  ResizeUninit(s, new_size, HasResizeUninitialized<string_type>());
+  ResizeUninitializedTraits<string_type>::Resize(s, new_size);
 }
 
 }  // namespace strings_internal
diff --git a/absl/strings/internal/resize_uninitialized_test.cc b/absl/strings/internal/resize_uninitialized_test.cc
index ad282ef..c5be0b1 100644
--- a/absl/strings/internal/resize_uninitialized_test.cc
+++ b/absl/strings/internal/resize_uninitialized_test.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -24,44 +24,44 @@
   void resize(size_t) { resize_call_count += 1; }
 };
 
-int resize_uninitialized_call_count = 0;
+int resize_default_init_call_count = 0;
 
-struct resize_uninitializable_string {
+struct resize_default_init_string {
   void resize(size_t) { resize_call_count += 1; }
-  void resize_uninitialized(size_t) { resize_uninitialized_call_count += 1; }
+  void __resize_default_init(size_t) { resize_default_init_call_count += 1; }
 };
 
 TEST(ResizeUninit, WithAndWithout) {
   resize_call_count = 0;
-  resize_uninitialized_call_count = 0;
+  resize_default_init_call_count = 0;
   {
     resizable_string rs;
 
     EXPECT_EQ(resize_call_count, 0);
-    EXPECT_EQ(resize_uninitialized_call_count, 0);
+    EXPECT_EQ(resize_default_init_call_count, 0);
     EXPECT_FALSE(
         absl::strings_internal::STLStringSupportsNontrashingResize(&rs));
     EXPECT_EQ(resize_call_count, 0);
-    EXPECT_EQ(resize_uninitialized_call_count, 0);
+    EXPECT_EQ(resize_default_init_call_count, 0);
     absl::strings_internal::STLStringResizeUninitialized(&rs, 237);
     EXPECT_EQ(resize_call_count, 1);
-    EXPECT_EQ(resize_uninitialized_call_count, 0);
+    EXPECT_EQ(resize_default_init_call_count, 0);
   }
 
   resize_call_count = 0;
-  resize_uninitialized_call_count = 0;
+  resize_default_init_call_count = 0;
   {
-    resize_uninitializable_string rus;
+    resize_default_init_string rus;
 
     EXPECT_EQ(resize_call_count, 0);
-    EXPECT_EQ(resize_uninitialized_call_count, 0);
+    EXPECT_EQ(resize_default_init_call_count, 0);
     EXPECT_TRUE(
         absl::strings_internal::STLStringSupportsNontrashingResize(&rus));
     EXPECT_EQ(resize_call_count, 0);
-    EXPECT_EQ(resize_uninitialized_call_count, 0);
+    EXPECT_EQ(resize_default_init_call_count, 0);
     absl::strings_internal::STLStringResizeUninitialized(&rus, 237);
     EXPECT_EQ(resize_call_count, 0);
-    EXPECT_EQ(resize_uninitialized_call_count, 1);
+    EXPECT_EQ(resize_default_init_call_count, 1);
   }
 }
 
diff --git a/absl/strings/internal/stl_type_traits.h b/absl/strings/internal/stl_type_traits.h
index 04c4a53..202ab37 100644
--- a/absl/strings/internal/stl_type_traits.h
+++ b/absl/strings/internal/stl_type_traits.h
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
diff --git a/absl/strings/internal/str_format/arg.h b/absl/strings/internal/str_format/arg.h
index 3376d48..4d48af0 100644
--- a/absl/strings/internal/str_format/arg.h
+++ b/absl/strings/internal/str_format/arg.h
@@ -35,12 +35,14 @@
     T, void_t<decltype(AbslFormatConvert(
            std::declval<const T&>(), std::declval<ConversionSpec>(),
            std::declval<FormatSink*>()))>> : std::true_type {};
+
 template <typename T>
 class StreamedWrapper;
 
 // If 'v' can be converted (in the printf sense) according to 'conv',
 // then convert it, appending to `sink` and return `true`.
 // Otherwise fail and return `false`.
+
 // Raw pointers.
 struct VoidPtr {
   VoidPtr() = default;
@@ -54,7 +56,8 @@
                                          FormatSinkImpl* sink);
 
 // Strings.
-ConvertResult<Conv::s> FormatConvertImpl(const std::string& v, ConversionSpec conv,
+ConvertResult<Conv::s> FormatConvertImpl(const std::string& v,
+                                         ConversionSpec conv,
                                          FormatSinkImpl* sink);
 ConvertResult<Conv::s> FormatConvertImpl(string_view v, ConversionSpec conv,
                                          FormatSinkImpl* sink);
@@ -80,7 +83,7 @@
 
   int precision = conv.precision();
   if (precision >= 0)
-    to_write = std::min(to_write, static_cast<size_t>(precision));
+    to_write = (std::min)(to_write, static_cast<size_t>(precision));
 
   space_remaining = Excess(to_write, space_remaining);
 
@@ -335,12 +338,12 @@
     using CommonType = typename std::conditional<std::is_signed<T>::value,
                                                  int64_t, uint64_t>::type;
     if (static_cast<CommonType>(val) >
-        static_cast<CommonType>(std::numeric_limits<int>::max())) {
-      return std::numeric_limits<int>::max();
+        static_cast<CommonType>((std::numeric_limits<int>::max)())) {
+      return (std::numeric_limits<int>::max)();
     } else if (std::is_signed<T>::value &&
                static_cast<CommonType>(val) <
-                   static_cast<CommonType>(std::numeric_limits<int>::min())) {
-      return std::numeric_limits<int>::min();
+                   static_cast<CommonType>((std::numeric_limits<int>::min)())) {
+      return (std::numeric_limits<int>::min)();
     }
     return static_cast<int>(val);
   }
@@ -409,7 +412,7 @@
   ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(double, __VA_ARGS__);             \
   ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(long double, __VA_ARGS__);        \
   ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(const char*, __VA_ARGS__);        \
-  ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(std::string, __VA_ARGS__);             \
+  ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(std::string, __VA_ARGS__);        \
   ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(string_view, __VA_ARGS__)
 
 ABSL_INTERNAL_FORMAT_DISPATCH_OVERLOADS_EXPAND_(extern);
diff --git a/absl/strings/internal/str_format/arg_test.cc b/absl/strings/internal/str_format/arg_test.cc
index 83d5904..3421fac 100644
--- a/absl/strings/internal/str_format/arg_test.cc
+++ b/absl/strings/internal/str_format/arg_test.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://www.apache.org/licenses/LICENSE-2.0
 //
 #include "absl/strings/internal/str_format/arg.h"
 
diff --git a/absl/strings/internal/str_format/bind.cc b/absl/strings/internal/str_format/bind.cc
index c4eddd1..a31859e 100644
--- a/absl/strings/internal/str_format/bind.cc
+++ b/absl/strings/internal/str_format/bind.cc
@@ -25,12 +25,12 @@
   explicit ArgContext(absl::Span<const FormatArgImpl> pack) : pack_(pack) {}
 
   // Fill 'bound' with the results of applying the context's argument pack
-  // to the specified 'props'. We synthesize a BoundConversion by
+  // to the specified 'unbound'. We synthesize a BoundConversion by
   // lining up a UnboundConversion with a user argument. We also
   // resolve any '*' specifiers for width and precision, so after
   // this call, 'bound' has all the information it needs to be formatted.
   // Returns false on failure.
-  bool Bind(const UnboundConversion *props, BoundConversion *bound);
+  bool Bind(const UnboundConversion* unbound, BoundConversion* bound);
 
  private:
   absl::Span<const FormatArgImpl> pack_;
@@ -53,7 +53,8 @@
         // "A negative field width is taken as a '-' flag followed by a
         // positive field width."
         force_left = true;
-        width = -width;
+        // Make sure we don't overflow the width when negating it.
+        width = -std::max(width, -std::numeric_limits<int>::max());
       }
     }
 
@@ -159,7 +160,7 @@
 }
 
 std::string Summarize(const UntypedFormatSpecImpl format,
-                 absl::Span<const FormatArgImpl> args) {
+                      absl::Span<const FormatArgImpl> args) {
   typedef SummarizingConverter Converter;
   std::string out;
   {
@@ -187,7 +188,7 @@
 }
 
 std::string& AppendPack(std::string* out, const UntypedFormatSpecImpl format,
-                   absl::Span<const FormatArgImpl> args) {
+                        absl::Span<const FormatArgImpl> args) {
   size_t orig = out->size();
   if (ABSL_PREDICT_FALSE(!FormatUntyped(out, format, args))) {
     out->erase(orig);
diff --git a/absl/strings/internal/str_format/bind.h b/absl/strings/internal/str_format/bind.h
index 1b52df9..4f78295 100644
--- a/absl/strings/internal/str_format/bind.h
+++ b/absl/strings/internal/str_format/bind.h
@@ -153,7 +153,7 @@
 
 // for testing
 std::string Summarize(UntypedFormatSpecImpl format,
-                 absl::Span<const FormatArgImpl> args);
+                      absl::Span<const FormatArgImpl> args);
 bool BindWithPack(const UnboundConversion* props,
                   absl::Span<const FormatArgImpl> pack, BoundConversion* bound);
 
@@ -162,10 +162,10 @@
                    absl::Span<const FormatArgImpl> args);
 
 std::string& AppendPack(std::string* out, UntypedFormatSpecImpl format,
-                   absl::Span<const FormatArgImpl> args);
+                        absl::Span<const FormatArgImpl> args);
 
 inline std::string FormatPack(const UntypedFormatSpecImpl format,
-                         absl::Span<const FormatArgImpl> args) {
+                              absl::Span<const FormatArgImpl> args) {
   std::string out;
   AppendPack(&out, format, args);
   return out;
@@ -176,7 +176,7 @@
 int SnprintF(char* output, size_t size, UntypedFormatSpecImpl format,
              absl::Span<const FormatArgImpl> args);
 
-// Returned by Streamed(v). Converts via '%s' to the string created
+// Returned by Streamed(v). Converts via '%s' to the std::string created
 // by std::ostream << v.
 template <typename T>
 class StreamedWrapper {
diff --git a/absl/strings/internal/str_format/bind_test.cc b/absl/strings/internal/str_format/bind_test.cc
index 4757573..ba6470e 100644
--- a/absl/strings/internal/str_format/bind_test.cc
+++ b/absl/strings/internal/str_format/bind_test.cc
@@ -1,6 +1,7 @@
 #include "absl/strings/internal/str_format/bind.h"
 
 #include <string.h>
+#include <limits>
 
 #include "gtest/gtest.h"
 
@@ -91,6 +92,20 @@
   }
 }
 
+TEST_F(FormatBindTest, WidthUnderflowRegression) {
+  UnboundConversion props;
+  BoundConversion bound;
+  int next = 0;
+  const int args_i[] = {std::numeric_limits<int>::min(), 17};
+  const FormatArgImpl args[] = {FormatArgImpl(args_i[0]),
+                                FormatArgImpl(args_i[1])};
+  ASSERT_TRUE(Extract("*d", &props, &next));
+  ASSERT_TRUE(BindWithPack(&props, args, &bound));
+
+  EXPECT_EQ(bound.width(), std::numeric_limits<int>::max());
+  EXPECT_EQ(bound.arg(), args + 1);
+}
+
 TEST_F(FormatBindTest, FormatPack) {
   struct Expectation {
     int line;
diff --git a/absl/strings/internal/str_format/checker_test.cc b/absl/strings/internal/str_format/checker_test.cc
index 14d11ea..c1d8c76 100644
--- a/absl/strings/internal/str_format/checker_test.cc
+++ b/absl/strings/internal/str_format/checker_test.cc
@@ -62,32 +62,32 @@
       ValidFormat<int>("%% %d"),                        //
       ValidFormat<int>("%ld"),                          //
       ValidFormat<int>("%lld"),                         //
-      ValidFormat<std::string>("%s"),                        //
-      ValidFormat<std::string>("%10s"),                      //
+      ValidFormat<std::string>("%s"),                   //
+      ValidFormat<std::string>("%10s"),                 //
       ValidFormat<int>("%.10x"),                        //
       ValidFormat<int, int>("%*.3x"),                   //
       ValidFormat<int>("%1.d"),                         //
       ValidFormat<int>("%.d"),                          //
       ValidFormat<int, double>("%d %g"),                //
-      ValidFormat<int, std::string>("%*s"),                  //
+      ValidFormat<int, std::string>("%*s"),             //
       ValidFormat<int, double>("%.*f"),                 //
       ValidFormat<void (*)(), volatile int*>("%p %p"),  //
       ValidFormat<string_view, const char*, double, void*>(
           "string_view=%s const char*=%s double=%f void*=%p)"),
 
-      ValidFormat<int>("%% %1$d"),            //
-      ValidFormat<int>("%1$ld"),              //
-      ValidFormat<int>("%1$lld"),             //
-      ValidFormat<std::string>("%1$s"),            //
-      ValidFormat<std::string>("%1$10s"),          //
-      ValidFormat<int>("%1$.10x"),            //
-      ValidFormat<int>("%1$*1$.*1$d"),        //
-      ValidFormat<int, int>("%1$*2$.3x"),     //
-      ValidFormat<int>("%1$1.d"),             //
-      ValidFormat<int>("%1$.d"),              //
-      ValidFormat<double, int>("%2$d %1$g"),  //
-      ValidFormat<int, std::string>("%2$*1$s"),    //
-      ValidFormat<int, double>("%2$.*1$f"),   //
+      ValidFormat<int>("%% %1$d"),               //
+      ValidFormat<int>("%1$ld"),                 //
+      ValidFormat<int>("%1$lld"),                //
+      ValidFormat<std::string>("%1$s"),          //
+      ValidFormat<std::string>("%1$10s"),        //
+      ValidFormat<int>("%1$.10x"),               //
+      ValidFormat<int>("%1$*1$.*1$d"),           //
+      ValidFormat<int, int>("%1$*2$.3x"),        //
+      ValidFormat<int>("%1$1.d"),                //
+      ValidFormat<int>("%1$.d"),                 //
+      ValidFormat<double, int>("%2$d %1$g"),     //
+      ValidFormat<int, std::string>("%2$*1$s"),  //
+      ValidFormat<int, double>("%2$.*1$f"),      //
       ValidFormat<void*, string_view, const char*, double>(
           "string_view=%2$s const char*=%3$s double=%4$f void*=%1$p "
           "repeat=%3$s)")};
@@ -99,25 +99,25 @@
   constexpr Case falses[] = {
       ValidFormat<int>(""),  //
 
-      ValidFormat<e>("%s"),             //
-      ValidFormat<e2>("%s"),            //
-      ValidFormat<>("%s"),              //
-      ValidFormat<>("%r"),              //
-      ValidFormat<int>("%s"),           //
-      ValidFormat<int>("%.1.d"),        //
-      ValidFormat<int>("%*1d"),         //
-      ValidFormat<int>("%1-d"),         //
+      ValidFormat<e>("%s"),                  //
+      ValidFormat<e2>("%s"),                 //
+      ValidFormat<>("%s"),                   //
+      ValidFormat<>("%r"),                   //
+      ValidFormat<int>("%s"),                //
+      ValidFormat<int>("%.1.d"),             //
+      ValidFormat<int>("%*1d"),              //
+      ValidFormat<int>("%1-d"),              //
       ValidFormat<std::string, int>("%*s"),  //
-      ValidFormat<int>("%*d"),          //
+      ValidFormat<int>("%*d"),               //
       ValidFormat<std::string>("%p"),        //
-      ValidFormat<int (*)(int)>("%d"),  //
+      ValidFormat<int (*)(int)>("%d"),       //
 
-      ValidFormat<>("%3$d"),                //
-      ValidFormat<>("%1$r"),                //
-      ValidFormat<int>("%1$s"),             //
-      ValidFormat<int>("%1$.1.d"),          //
-      ValidFormat<int>("%1$*2$1d"),         //
-      ValidFormat<int>("%1$1-d"),           //
+      ValidFormat<>("%3$d"),                     //
+      ValidFormat<>("%1$r"),                     //
+      ValidFormat<int>("%1$s"),                  //
+      ValidFormat<int>("%1$.1.d"),               //
+      ValidFormat<int>("%1$*2$1d"),              //
+      ValidFormat<int>("%1$1-d"),                //
       ValidFormat<std::string, int>("%2$*1$s"),  //
       ValidFormat<std::string>("%1$p"),
 
diff --git a/absl/strings/internal/str_format/convert_test.cc b/absl/strings/internal/str_format/convert_test.cc
index 32f8a0f..99cc0af 100644
--- a/absl/strings/internal/str_format/convert_test.cc
+++ b/absl/strings/internal/str_format/convert_test.cc
@@ -232,7 +232,7 @@
 template <typename T>
 class TypedFormatConvertTest : public FormatConvertTest { };
 
-TYPED_TEST_CASE_P(TypedFormatConvertTest);
+TYPED_TEST_SUITE_P(TypedFormatConvertTest);
 
 std::vector<std::string> AllFlagCombinations() {
   const char kFlags[] = {'-', '#', '0', '+', ' '};
@@ -363,6 +363,7 @@
     AllIntTypes;
 INSTANTIATE_TYPED_TEST_CASE_P(TypedFormatConvertTestWithAllIntTypes,
                               TypedFormatConvertTest, AllIntTypes);
+
 TEST_F(FormatConvertTest, Uint128) {
   absl::uint128 v = static_cast<absl::uint128>(0x1234567890abcdef) * 1979;
   absl::uint128 max = absl::Uint128Max();
diff --git a/absl/strings/internal/str_format/extension.cc b/absl/strings/internal/str_format/extension.cc
index c217470..d7f5815 100644
--- a/absl/strings/internal/str_format/extension.cc
+++ b/absl/strings/internal/str_format/extension.cc
@@ -5,7 +5,7 @@
 // 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
+//      https://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,
diff --git a/absl/strings/internal/str_format/extension.h b/absl/strings/internal/str_format/extension.h
index 11b996a..eb81f8a 100644
--- a/absl/strings/internal/str_format/extension.h
+++ b/absl/strings/internal/str_format/extension.h
@@ -5,7 +5,7 @@
 // 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
+//      https://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,
@@ -13,7 +13,6 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 //
-//
 #ifndef ABSL_STRINGS_INTERNAL_STR_FORMAT_EXTENSION_H_
 #define ABSL_STRINGS_INTERNAL_STR_FORMAT_EXTENSION_H_
 
@@ -360,7 +359,7 @@
   integral = d | i | u | o | x | X,
   floating = a | e | f | g | A | E | F | G,
   numeric = integral | floating,
-  string = s,  // absl:ignore(std::string)
+  string = s,
   pointer = p
 };
 
@@ -409,4 +408,4 @@
 
 }  // namespace absl
 
-#endif  // ABSL_STRINGS_STR_FORMAT_EXTENSION_H_
+#endif  // ABSL_STRINGS_INTERNAL_STR_FORMAT_EXTENSION_H_
diff --git a/absl/strings/internal/str_format/extension_test.cc b/absl/strings/internal/str_format/extension_test.cc
index 224fc92..4e23fef 100644
--- a/absl/strings/internal/str_format/extension_test.cc
+++ b/absl/strings/internal/str_format/extension_test.cc
@@ -5,7 +5,7 @@
 // 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
+//      https://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,
@@ -18,6 +18,7 @@
 
 #include <random>
 #include <string>
+
 #include "absl/strings/str_format.h"
 
 #include "gtest/gtest.h"
diff --git a/absl/strings/internal/str_format/output.cc b/absl/strings/internal/str_format/output.cc
index 5c3795b..38987b6 100644
--- a/absl/strings/internal/str_format/output.cc
+++ b/absl/strings/internal/str_format/output.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -20,6 +20,16 @@
 namespace absl {
 namespace str_format_internal {
 
+namespace {
+struct ClearErrnoGuard {
+  ClearErrnoGuard() : old_value(errno) { errno = 0; }
+  ~ClearErrnoGuard() {
+    if (!errno) errno = old_value;
+  }
+  int old_value;
+};
+}  // namespace
+
 void BufferRawSink::Write(string_view v) {
   size_t to_write = std::min(v.size(), size_);
   std::memcpy(buffer_, v.data(), to_write);
@@ -30,14 +40,27 @@
 
 void FILERawSink::Write(string_view v) {
   while (!v.empty() && !error_) {
+    // Reset errno to zero in case the libc implementation doesn't set errno
+    // when a failure occurs.
+    ClearErrnoGuard guard;
+
     if (size_t result = std::fwrite(v.data(), 1, v.size(), output_)) {
       // Some progress was made.
       count_ += result;
       v.remove_prefix(result);
     } else {
-      // Some error occurred.
-      if (errno != EINTR) {
+      if (errno == EINTR) {
+        continue;
+      } else if (errno) {
         error_ = errno;
+      } else if (std::ferror(output_)) {
+        // Non-POSIX compliant libc implementations may not set errno, so we
+        // have check the streams error indicator.
+        error_ = EBADF;
+      } else {
+        // We're likely on a non-POSIX system that encountered EINTR but had no
+        // way of reporting it.
+        continue;
       }
     }
   }
diff --git a/absl/strings/internal/str_format/output.h b/absl/strings/internal/str_format/output.h
index 12ecd99..42da641 100644
--- a/absl/strings/internal/str_format/output.h
+++ b/absl/strings/internal/str_format/output.h
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
diff --git a/absl/strings/internal/str_format/output_test.cc b/absl/strings/internal/str_format/output_test.cc
index cc3c615..6e04abe 100644
--- a/absl/strings/internal/str_format/output_test.cc
+++ b/absl/strings/internal/str_format/output_test.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -17,7 +17,6 @@
 #include <sstream>
 #include <string>
 
-
 #include "gmock/gmock.h"
 #include "gtest/gtest.h"
 
@@ -28,12 +27,6 @@
   std::string str = "ABC";
   str_format_internal::InvokeFlush(&str, "DEF");
   EXPECT_EQ(str, "ABCDEF");
-
-#if UTIL_FORMAT_HAS_GLOBAL_STRING
-  std::string str2 = "ABC";
-  str_format_internal::InvokeFlush(&str2, "DEF");
-  EXPECT_EQ(str2, "ABCDEF");
-#endif  // UTIL_FORMAT_HAS_GLOBAL_STRING
 }
 
 TEST(InvokeFlush, Stream) {
diff --git a/absl/strings/internal/str_format/parser.cc b/absl/strings/internal/str_format/parser.cc
index 5e3d0d0..10487f2 100644
--- a/absl/strings/internal/str_format/parser.cc
+++ b/absl/strings/internal/str_format/parser.cc
@@ -99,10 +99,11 @@
     // digit doesn't match the expected characters.
     int num_digits = std::numeric_limits<int>::digits10;
     for (;;) {
-      if (ABSL_PREDICT_FALSE(pos == end || !num_digits)) break;
+      if (ABSL_PREDICT_FALSE(pos == end)) break;
       c = *pos++;
       if (!std::isdigit(c)) break;
       --num_digits;
+      if (ABSL_PREDICT_FALSE(!num_digits)) break;
       digits = 10 * digits + c - '0';
     }
     return digits;
diff --git a/absl/strings/internal/str_format/parser_test.cc b/absl/strings/internal/str_format/parser_test.cc
index ae40203..ff70575 100644
--- a/absl/strings/internal/str_format/parser_test.cc
+++ b/absl/strings/internal/str_format/parser_test.cc
@@ -246,6 +246,8 @@
 
   EXPECT_FALSE(Run("1000000000.999999999d"));
   EXPECT_FALSE(Run("999999999.1000000000d"));
+  EXPECT_FALSE(Run("9999999999d"));
+  EXPECT_FALSE(Run(".9999999999d"));
 }
 
 TEST_F(ConsumeUnboundConversionTest, Flags) {
diff --git a/absl/strings/internal/str_join_internal.h b/absl/strings/internal/str_join_internal.h
index 0058fc8..7c35f4d 100644
--- a/absl/strings/internal/str_join_internal.h
+++ b/absl/strings/internal/str_join_internal.h
@@ -5,7 +5,7 @@
 // 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
+//      https://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,
@@ -193,7 +193,7 @@
 // and formats each element using the provided Formatter object.
 template <typename Iterator, typename Formatter>
 std::string JoinAlgorithm(Iterator start, Iterator end, absl::string_view s,
-                     Formatter&& f) {
+                          Formatter&& f) {
   std::string result;
   absl::string_view sep("");
   for (Iterator it = start; it != end; ++it) {
@@ -212,7 +212,7 @@
 // This is an overload of the previous JoinAlgorithm() function. Here the
 // Formatter argument is of type NoFormatter. Since NoFormatter is an internal
 // type, this overload is only invoked when strings::Join() is called with a
-// range of string-like objects (e.g., string, absl::string_view), and an
+// range of string-like objects (e.g., std::string, absl::string_view), and an
 // explicit Formatter argument was NOT specified.
 //
 // The optimization is that the needed space will be reserved in the output
@@ -224,7 +224,7 @@
               typename std::iterator_traits<Iterator>::iterator_category,
               std::forward_iterator_tag>::value>::type>
 std::string JoinAlgorithm(Iterator start, Iterator end, absl::string_view s,
-                     NoFormatter) {
+                          NoFormatter) {
   std::string result;
   if (start != end) {
     // Sums size
@@ -276,14 +276,15 @@
 
 template <typename... T, typename Formatter>
 std::string JoinAlgorithm(const std::tuple<T...>& tup, absl::string_view sep,
-                     Formatter&& fmt) {
+                          Formatter&& fmt) {
   std::string result;
   JoinTupleLoop<0, sizeof...(T)>()(&result, tup, sep, fmt);
   return result;
 }
 
 template <typename Iterator>
-std::string JoinRange(Iterator first, Iterator last, absl::string_view separator) {
+std::string JoinRange(Iterator first, Iterator last,
+                      absl::string_view separator) {
   // No formatter was explicitly given, so a default must be chosen.
   typedef typename std::iterator_traits<Iterator>::value_type ValueType;
   typedef typename DefaultFormatter<ValueType>::Type Formatter;
@@ -292,7 +293,7 @@
 
 template <typename Range, typename Formatter>
 std::string JoinRange(const Range& range, absl::string_view separator,
-                 Formatter&& fmt) {
+                      Formatter&& fmt) {
   using std::begin;
   using std::end;
   return JoinAlgorithm(begin(range), end(range), separator, fmt);
diff --git a/absl/strings/internal/str_split_internal.h b/absl/strings/internal/str_split_internal.h
index 81e8d55..52f6222 100644
--- a/absl/strings/internal/str_split_internal.h
+++ b/absl/strings/internal/str_split_internal.h
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -96,8 +96,8 @@
     }
   }
 
-  // Holds the data moved from temporary std::string arguments. Declared first so
-  // that 'value' can refer to 'copy_'.
+  // Holds the data moved from temporary std::string arguments. Declared first
+  // so that 'value' can refer to 'copy_'.
   std::string copy_;
   absl::string_view value_;
 };
@@ -376,10 +376,10 @@
 
   // Partial specialization for a std::vector<std::string>.
   //
-  // Optimized for the common case of splitting to a std::vector<std::string>. In
-  // this case we first split the results to a std::vector<absl::string_view> so
-  // the returned std::vector<std::string> can have space reserved to avoid std::string
-  // moves.
+  // Optimized for the common case of splitting to a std::vector<std::string>.
+  // In this case we first split the results to a std::vector<absl::string_view>
+  // so the returned std::vector<std::string> can have space reserved to avoid
+  // std::string moves.
   template <typename A>
   struct ConvertToContainer<std::vector<std::string, A>, std::string, false> {
     std::vector<std::string, A> operator()(const Splitter& splitter) const {
diff --git a/absl/strings/internal/utf8.cc b/absl/strings/internal/utf8.cc
index 2415c2c..82d36c2 100644
--- a/absl/strings/internal/utf8.cc
+++ b/absl/strings/internal/utf8.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
diff --git a/absl/strings/internal/utf8.h b/absl/strings/internal/utf8.h
index d2c3c0b..0423630 100644
--- a/absl/strings/internal/utf8.h
+++ b/absl/strings/internal/utf8.h
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -13,7 +13,6 @@
 // limitations under the License.
 //
 // UTF8 utilities, implemented to reduce dependencies.
-//
 
 #ifndef ABSL_STRINGS_INTERNAL_UTF8_H_
 #define ABSL_STRINGS_INTERNAL_UTF8_H_
diff --git a/absl/strings/internal/utf8_test.cc b/absl/strings/internal/utf8_test.cc
index 64cec70..88dd503 100644
--- a/absl/strings/internal/utf8_test.cc
+++ b/absl/strings/internal/utf8_test.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -22,12 +22,17 @@
 
 namespace {
 
+#if !defined(__cpp_char8_t)
+#if defined(__clang__)
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wc++2a-compat"
+#endif
 TEST(EncodeUTF8Char, BasicFunction) {
   std::pair<char32_t, std::string> tests[] = {{0x0030, u8"\u0030"},
-                                         {0x00A3, u8"\u00A3"},
-                                         {0x00010000, u8"\U00010000"},
-                                         {0x0000FFFF, u8"\U0000FFFF"},
-                                         {0x0010FFFD, u8"\U0010FFFD"}};
+                                              {0x00A3, u8"\u00A3"},
+                                              {0x00010000, u8"\U00010000"},
+                                              {0x0000FFFF, u8"\U0000FFFF"},
+                                              {0x0010FFFD, u8"\U0010FFFD"}};
   for (auto &test : tests) {
     char buf0[7] = {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'};
     char buf1[7] = {'\xFF', '\xFF', '\xFF', '\xFF', '\xFF', '\xFF', '\xFF'};
@@ -53,5 +58,9 @@
   EXPECT_LE(absl::strings_internal::EncodeUTF8Char(buf2, -1),
             absl::strings_internal::kMaxEncodedUTF8Size);
 }
+#if defined(__clang__)
+#pragma clang diagnostic pop
+#endif
+#endif  // !defined(__cpp_char8_t)
 
 }  // namespace
diff --git a/absl/strings/match.cc b/absl/strings/match.cc
index 3d10c57..7b24241 100644
--- a/absl/strings/match.cc
+++ b/absl/strings/match.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -18,15 +18,6 @@
 
 namespace absl {
 
-namespace {
-bool CaseEqual(absl::string_view piece1, absl::string_view piece2) {
-  return (piece1.size() == piece2.size() &&
-          0 == strings_internal::memcasecmp(piece1.data(), piece2.data(),
-                                            piece1.size()));
-  // memcasecmp uses ascii_tolower().
-}
-}  // namespace
-
 bool EqualsIgnoreCase(absl::string_view piece1, absl::string_view piece2) {
   return (piece1.size() == piece2.size() &&
           0 == absl::strings_internal::memcasecmp(piece1.data(), piece2.data(),
@@ -36,12 +27,12 @@
 
 bool StartsWithIgnoreCase(absl::string_view text, absl::string_view prefix) {
   return (text.size() >= prefix.size()) &&
-         CaseEqual(text.substr(0, prefix.size()), prefix);
+         EqualsIgnoreCase(text.substr(0, prefix.size()), prefix);
 }
 
 bool EndsWithIgnoreCase(absl::string_view text, absl::string_view suffix) {
   return (text.size() >= suffix.size()) &&
-         CaseEqual(text.substr(text.size() - suffix.size()), suffix);
+         EqualsIgnoreCase(text.substr(text.size() - suffix.size()), suffix);
 }
 
 }  // namespace absl
diff --git a/absl/strings/match.h b/absl/strings/match.h
index 6e8ed10..5251b7f 100644
--- a/absl/strings/match.h
+++ b/absl/strings/match.h
@@ -5,7 +5,7 @@
 // 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
+//      https://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,
@@ -74,13 +74,13 @@
 
 // StartsWithIgnoreCase()
 //
-// Returns whether a given ASCII string `text` starts with `starts_with`,
+// Returns whether a given ASCII string `text` starts with `prefix`,
 // ignoring case in the comparison.
 bool StartsWithIgnoreCase(absl::string_view text, absl::string_view prefix);
 
 // EndsWithIgnoreCase()
 //
-// Returns whether a given ASCII string `text` ends with `ends_with`, ignoring
+// Returns whether a given ASCII string `text` ends with `suffix`, ignoring
 // case in the comparison.
 bool EndsWithIgnoreCase(absl::string_view text, absl::string_view suffix);
 
diff --git a/absl/strings/match_test.cc b/absl/strings/match_test.cc
index c21e00b..4c313dd 100644
--- a/absl/strings/match_test.cc
+++ b/absl/strings/match_test.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -19,7 +19,7 @@
 namespace {
 
 TEST(MatchTest, StartsWith) {
-  const std::string s1("123" "\0" "456", 7);
+  const std::string s1("123\0abc", 7);
   const absl::string_view a("foobar");
   const absl::string_view b(s1);
   const absl::string_view e;
@@ -36,7 +36,7 @@
 }
 
 TEST(MatchTest, EndsWith) {
-  const std::string s1("123" "\0" "456", 7);
+  const std::string s1("123\0abc", 7);
   const absl::string_view a("foobar");
   const absl::string_view b(s1);
   const absl::string_view e;
diff --git a/absl/strings/numbers.cc b/absl/strings/numbers.cc
index 9309f9d..558c339 100644
--- a/absl/strings/numbers.cc
+++ b/absl/strings/numbers.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -35,17 +35,18 @@
 #include "absl/strings/ascii.h"
 #include "absl/strings/charconv.h"
 #include "absl/strings/internal/memutil.h"
+#include "absl/strings/match.h"
 #include "absl/strings/str_cat.h"
 
 namespace absl {
 
-bool SimpleAtof(absl::string_view str, float* value) {
-  *value = 0.0;
+bool SimpleAtof(absl::string_view str, float* out) {
+  *out = 0.0;
   str = StripAsciiWhitespace(str);
   if (!str.empty() && str[0] == '+') {
     str.remove_prefix(1);
   }
-  auto result = absl::from_chars(str.data(), str.data() + str.size(), *value);
+  auto result = absl::from_chars(str.data(), str.data() + str.size(), *out);
   if (result.ec == std::errc::invalid_argument) {
     return false;
   }
@@ -56,22 +57,22 @@
   // from_chars() with DR 3801's current wording will return max() on
   // overflow.  SimpleAtof returns infinity instead.
   if (result.ec == std::errc::result_out_of_range) {
-    if (*value > 1.0) {
-      *value = std::numeric_limits<float>::infinity();
-    } else if (*value < -1.0) {
-      *value = -std::numeric_limits<float>::infinity();
+    if (*out > 1.0) {
+      *out = std::numeric_limits<float>::infinity();
+    } else if (*out < -1.0) {
+      *out = -std::numeric_limits<float>::infinity();
     }
   }
   return true;
 }
 
-bool SimpleAtod(absl::string_view str, double* value) {
-  *value = 0.0;
+bool SimpleAtod(absl::string_view str, double* out) {
+  *out = 0.0;
   str = StripAsciiWhitespace(str);
   if (!str.empty() && str[0] == '+') {
     str.remove_prefix(1);
   }
-  auto result = absl::from_chars(str.data(), str.data() + str.size(), *value);
+  auto result = absl::from_chars(str.data(), str.data() + str.size(), *out);
   if (result.ec == std::errc::invalid_argument) {
     return false;
   }
@@ -82,10 +83,10 @@
   // from_chars() with DR 3801's current wording will return max() on
   // overflow.  SimpleAtod returns infinity instead.
   if (result.ec == std::errc::result_out_of_range) {
-    if (*value > 1.0) {
-      *value = std::numeric_limits<double>::infinity();
-    } else if (*value < -1.0) {
-      *value = -std::numeric_limits<double>::infinity();
+    if (*out > 1.0) {
+      *out = std::numeric_limits<double>::infinity();
+    } else if (*out < -1.0) {
+      *out = -std::numeric_limits<double>::infinity();
     }
   }
   return true;
@@ -93,14 +94,6 @@
 
 namespace {
 
-// TODO(rogeeff): replace with the real released thing once we figure out what
-// it is.
-inline bool CaseEqual(absl::string_view piece1, absl::string_view piece2) {
-  return (piece1.size() == piece2.size() &&
-          0 == strings_internal::memcasecmp(piece1.data(), piece2.data(),
-                                            piece1.size()));
-}
-
 // Writes a two-character representation of 'i' to 'buf'. 'i' must be in the
 // range 0 <= i < 100, and buf must have space for two characters. Example:
 //   char buf[2];
@@ -136,18 +129,18 @@
 
 }  // namespace
 
-bool SimpleAtob(absl::string_view str, bool* value) {
-  ABSL_RAW_CHECK(value != nullptr, "Output pointer must not be nullptr.");
-  if (CaseEqual(str, "true") || CaseEqual(str, "t") ||
-      CaseEqual(str, "yes") || CaseEqual(str, "y") ||
-      CaseEqual(str, "1")) {
-    *value = true;
+bool SimpleAtob(absl::string_view str, bool* out) {
+  ABSL_RAW_CHECK(out != nullptr, "Output pointer must not be nullptr.");
+  if (EqualsIgnoreCase(str, "true") || EqualsIgnoreCase(str, "t") ||
+      EqualsIgnoreCase(str, "yes") || EqualsIgnoreCase(str, "y") ||
+      EqualsIgnoreCase(str, "1")) {
+    *out = true;
     return true;
   }
-  if (CaseEqual(str, "false") || CaseEqual(str, "f") ||
-      CaseEqual(str, "no") || CaseEqual(str, "n") ||
-      CaseEqual(str, "0")) {
-    *value = false;
+  if (EqualsIgnoreCase(str, "false") || EqualsIgnoreCase(str, "f") ||
+      EqualsIgnoreCase(str, "no") || EqualsIgnoreCase(str, "n") ||
+      EqualsIgnoreCase(str, "0")) {
+    *out = false;
     return true;
   }
   return false;
diff --git a/absl/strings/numbers.h b/absl/strings/numbers.h
index f9b2cce..e0f96df 100644
--- a/absl/strings/numbers.h
+++ b/absl/strings/numbers.h
@@ -5,7 +5,7 @@
 // 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
+//      https://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,
@@ -44,7 +44,8 @@
 // Converts the given string into an integer value, returning `true` if
 // successful. The string must reflect a base-10 integer (optionally followed or
 // preceded by ASCII whitespace) whose value falls within the range of the
-// integer type.
+// integer type. If any errors are encountered, this function returns `false`,
+// leaving `out` in an unspecified state.
 template <typename int_type>
 ABSL_MUST_USE_RESULT bool SimpleAtoi(absl::string_view s, int_type* out);
 
@@ -52,25 +53,29 @@
 //
 // Converts the given string (optionally followed or preceded by ASCII
 // whitespace) into a float, which may be rounded on overflow or underflow.
-// See http://en.cppreference.com/w/c/string/byte/strtof for details about the
-// allowed formats for `str`.
-ABSL_MUST_USE_RESULT bool SimpleAtof(absl::string_view str, float* value);
+// See https://en.cppreference.com/w/c/string/byte/strtof for details about the
+// allowed formats for `str`. If any errors are encountered, this function
+// returns `false`, leaving `out` in an unspecified state.
+ABSL_MUST_USE_RESULT bool SimpleAtof(absl::string_view str, float* out);
 
 // SimpleAtod()
 //
 // Converts the given string (optionally followed or preceded by ASCII
 // whitespace) into a double, which may be rounded on overflow or underflow.
-// See http://en.cppreference.com/w/c/string/byte/strtof for details about the
-// allowed formats for `str`.
-ABSL_MUST_USE_RESULT bool SimpleAtod(absl::string_view str, double* value);
+// See https://en.cppreference.com/w/c/string/byte/strtof for details about the
+// allowed formats for `str`. If any errors are encountered, this function
+// returns `false`, leaving `out` in an unspecified state.
+ABSL_MUST_USE_RESULT bool SimpleAtod(absl::string_view str, double* out);
 
 // SimpleAtob()
 //
 // Converts the given string into a boolean, returning `true` if successful.
 // The following case-insensitive strings are interpreted as boolean `true`:
 // "true", "t", "yes", "y", "1". The following case-insensitive strings
-// are interpreted as boolean `false`: "false", "f", "no", "n", "0".
-ABSL_MUST_USE_RESULT bool SimpleAtob(absl::string_view str, bool* value);
+// are interpreted as boolean `false`: "false", "f", "no", "n", "0". If any
+// errors are encountered, this function returns `false`, leaving `out` in an
+// unspecified state.
+ABSL_MUST_USE_RESULT bool SimpleAtob(absl::string_view str, bool* out);
 
 }  // namespace absl
 
diff --git a/absl/strings/numbers_benchmark.cc b/absl/strings/numbers_benchmark.cc
index 0570b75..54dbedd 100644
--- a/absl/strings/numbers_benchmark.cc
+++ b/absl/strings/numbers_benchmark.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
diff --git a/absl/strings/numbers_test.cc b/absl/strings/numbers_test.cc
index 36fc0d6..ca2ee48 100644
--- a/absl/strings/numbers_test.cc
+++ b/absl/strings/numbers_test.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -39,6 +39,7 @@
 #include "absl/strings/str_cat.h"
 
 #include "absl/strings/internal/numbers_test_common.h"
+#include "absl/strings/internal/pow10_helper.h"
 
 namespace {
 
@@ -190,7 +191,8 @@
   EXPECT_EQ(expected, std::string(&buffer[1], actual)) << " Input " << x;
 
   char* generic_actual = absl::numbers_internal::FastIntToBuffer(x, &buffer[1]);
-  EXPECT_EQ(expected, std::string(&buffer[1], generic_actual)) << " Input " << x;
+  EXPECT_EQ(expected, std::string(&buffer[1], generic_actual))
+      << " Input " << x;
 
   char* my_actual =
       absl::numbers_internal::FastIntToBuffer(MyUInt64(x), &buffer[1]);
@@ -783,7 +785,7 @@
   if (iters_per_float == 0) iters_per_float = 1;
   for (float f : floats) {
     if (f == last) continue;
-    float testf = nextafter(last, std::numeric_limits<float>::max());
+    float testf = std::nextafter(last, std::numeric_limits<float>::max());
     runnable(testf);
     runnable(-testf);
     last = testf;
@@ -797,7 +799,7 @@
         last = testf;
       }
     }
-    testf = nextafter(f, 0.0f);
+    testf = std::nextafter(f, 0.0f);
     if (testf > last) {
       runnable(testf);
       runnable(-testf);
@@ -871,15 +873,15 @@
     }
 
     for (int exponent = -324; exponent <= 308; ++exponent) {
-      double powten = pow(10.0, exponent);
+      double powten = absl::strings_internal::Pow10(exponent);
       if (powten == 0) powten = 5e-324;
       if (kFloatNumCases >= 1e9) {
         // The exhaustive test takes a very long time, so log progress.
         char buf[kSixDigitsToBufferSize];
         ABSL_RAW_LOG(
             INFO, "%s",
-            absl::StrCat("Exp ", exponent, " powten=", powten, "(",
-                         powten, ") (",
+            absl::StrCat("Exp ", exponent, " powten=", powten, "(", powten,
+                         ") (",
                          std::string(buf, SixDigitsToBuffer(powten, buf)), ")")
                 .c_str());
       }
diff --git a/absl/strings/str_cat.cc b/absl/strings/str_cat.cc
index efa4fd7..2667976 100644
--- a/absl/strings/str_cat.cc
+++ b/absl/strings/str_cat.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -78,9 +78,9 @@
 
 // ----------------------------------------------------------------------
 // StrCat()
-//    This merges the given strings or integers, with no delimiter.  This
+//    This merges the given strings or integers, with no delimiter. This
 //    is designed to be the fastest possible way to construct a string out
-//    of a mix of raw C strings, StringPieces, strings, and integer values.
+//    of a mix of raw C strings, string_views, strings, and integer values.
 // ----------------------------------------------------------------------
 
 // Append is merely a version of memcpy that returns the address of the byte
@@ -119,7 +119,7 @@
 }
 
 std::string StrCat(const AlphaNum& a, const AlphaNum& b, const AlphaNum& c,
-              const AlphaNum& d) {
+                   const AlphaNum& d) {
   std::string result;
   strings_internal::STLStringResizeUninitialized(
       &result, a.size() + b.size() + c.size() + d.size());
diff --git a/absl/strings/str_cat.h b/absl/strings/str_cat.h
index da9ed9a..cba8ceb 100644
--- a/absl/strings/str_cat.h
+++ b/absl/strings/str_cat.h
@@ -5,7 +5,7 @@
 // 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
+//      https://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,
@@ -42,7 +42,6 @@
 // Floating point numbers are formatted with six-digit precision, which is
 // the default for "std::cout <<" or printf "%g" (the same as "%.6g").
 //
-//
 // You can convert to hexadecimal output rather than decimal output using the
 // `Hex` type contained here. To do so, pass `Hex(my_int)` as a parameter to
 // `StrCat()` or `StrAppend()`. You may specify a minimum hex field width using
@@ -78,8 +77,8 @@
 
 // Enum that specifies the number of significant digits to return in a `Hex` or
 // `Dec` conversion and fill character to use. A `kZeroPad2` value, for example,
-// would produce hexadecimal strings such as "0A","0F" and a 'kSpacePad5' value
-// would produce hexadecimal strings such as "    A","    F".
+// would produce hexadecimal strings such as "0a","0f" and a 'kSpacePad5' value
+// would produce hexadecimal strings such as "    a","    f".
 enum PadSpec : uint8_t {
   kNoPad = 1,
   kZeroPad2,
@@ -97,6 +96,10 @@
   kZeroPad14,
   kZeroPad15,
   kZeroPad16,
+  kZeroPad17,
+  kZeroPad18,
+  kZeroPad19,
+  kZeroPad20,
 
   kSpacePad2 = kZeroPad2 + 64,
   kSpacePad3,
@@ -113,6 +116,10 @@
   kSpacePad14,
   kSpacePad15,
   kSpacePad16,
+  kSpacePad17,
+  kSpacePad18,
+  kSpacePad19,
+  kSpacePad20,
 };
 
 // -----------------------------------------------------------------------------
@@ -237,6 +244,7 @@
 
   AlphaNum(const char* c_str) : piece_(c_str) {}  // NOLINT(runtime/explicit)
   AlphaNum(absl::string_view pc) : piece_(pc) {}  // NOLINT(runtime/explicit)
+
   template <typename Allocator>
   AlphaNum(  // NOLINT(runtime/explicit)
       const std::basic_string<char, std::char_traits<char>, Allocator>& str)
@@ -309,16 +317,15 @@
 
 ABSL_MUST_USE_RESULT std::string StrCat(const AlphaNum& a, const AlphaNum& b);
 ABSL_MUST_USE_RESULT std::string StrCat(const AlphaNum& a, const AlphaNum& b,
-                                   const AlphaNum& c);
+                                        const AlphaNum& c);
 ABSL_MUST_USE_RESULT std::string StrCat(const AlphaNum& a, const AlphaNum& b,
-                                   const AlphaNum& c, const AlphaNum& d);
+                                        const AlphaNum& c, const AlphaNum& d);
 
 // Support 5 or more arguments
 template <typename... AV>
-ABSL_MUST_USE_RESULT inline std::string StrCat(const AlphaNum& a, const AlphaNum& b,
-                                          const AlphaNum& c, const AlphaNum& d,
-                                          const AlphaNum& e,
-                                          const AV&... args) {
+ABSL_MUST_USE_RESULT inline std::string StrCat(
+    const AlphaNum& a, const AlphaNum& b, const AlphaNum& c, const AlphaNum& d,
+    const AlphaNum& e, const AV&... args) {
   return strings_internal::CatPieces(
       {a.Piece(), b.Piece(), c.Piece(), d.Piece(), e.Piece(),
        static_cast<const AlphaNum&>(args).Piece()...});
@@ -336,18 +343,18 @@
 // not try to check each of its input arguments to be sure that they are not
 // a subset of the string being appended to. That is, while this will work:
 //
-//   string s = "foo";
+//   std::string s = "foo";
 //   s += s;
 //
 // This output is undefined:
 //
-//   string s = "foo";
+//   std::string s = "foo";
 //   StrAppend(&s, s);
 //
 // This output is undefined as well, since `absl::string_view` does not own its
 // data:
 //
-//   string s = "foobar";
+//   std::string s = "foobar";
 //   absl::string_view p = s;
 //   StrAppend(&s, p);
 
diff --git a/absl/strings/str_cat_benchmark.cc b/absl/strings/str_cat_benchmark.cc
index b6df9e3..14c63b3 100644
--- a/absl/strings/str_cat_benchmark.cc
+++ b/absl/strings/str_cat_benchmark.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
diff --git a/absl/strings/str_cat_test.cc b/absl/strings/str_cat_test.cc
index 555d8db..beb15fa 100644
--- a/absl/strings/str_cat_test.cc
+++ b/absl/strings/str_cat_test.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -106,11 +106,7 @@
 TEST(StrCat, Basics) {
   std::string result;
 
-  std::string strs[] = {
-    "Hello",
-    "Cruel",
-    "World"
-  };
+  std::string strs[] = {"Hello", "Cruel", "World"};
 
   std::string stdstrs[] = {
     "std::Hello",
@@ -164,9 +160,10 @@
   result = absl::StrCat(ui64s[0], ", ", ui64s[1], "!");
   EXPECT_EQ(result, "12345678910, 10987654321!");
 
-  std::string one = "1";  // Actually, it's the size of this std::string that we want; a
-                     // 64-bit build distinguishes between size_t and uint64_t,
-                     // even though they're both unsigned 64-bit values.
+  std::string one =
+      "1";  // Actually, it's the size of this std::string that we want; a
+            // 64-bit build distinguishes between size_t and uint64_t,
+            // even though they're both unsigned 64-bit values.
   result = absl::StrCat("And a ", one.size(), " and a ",
                         &result[2] - &result[0], " and a ", one, " 2 3 4", "!");
   EXPECT_EQ(result, "And a 1 and a 2 and a 1 2 3 4!");
@@ -306,11 +303,7 @@
 TEST(StrAppend, Basics) {
   std::string result = "existing text";
 
-  std::string strs[] = {
-    "Hello",
-    "Cruel",
-    "World"
-  };
+  std::string strs[] = {"Hello", "Cruel", "World"};
 
   std::string stdstrs[] = {
     "std::Hello",
@@ -365,9 +358,10 @@
   absl::StrAppend(&result, ui64s[0], ", ", ui64s[1], "!");
   EXPECT_EQ(result.substr(old_size), "12345678910, 10987654321!");
 
-  std::string one = "1";  // Actually, it's the size of this std::string that we want; a
-                     // 64-bit build distinguishes between size_t and uint64_t,
-                     // even though they're both unsigned 64-bit values.
+  std::string one =
+      "1";  // Actually, it's the size of this std::string that we want; a
+            // 64-bit build distinguishes between size_t and uint64_t,
+            // even though they're both unsigned 64-bit values.
   old_size = result.size();
   absl::StrAppend(&result, "And a ", one.size(), " and a ",
                   &result[2] - &result[0], " and a ", one, " 2 3 4", "!");
@@ -427,7 +421,7 @@
   snprintf(expected, sizeof(expected), nopad_format, v);
   EXPECT_EQ(expected, actual) << " decimal value " << v;
 
-  for (int spec = absl::kZeroPad2; spec <= absl::kZeroPad16; ++spec) {
+  for (int spec = absl::kZeroPad2; spec <= absl::kZeroPad20; ++spec) {
     std::string actual =
         absl::StrCat(absl::Hex(v, static_cast<absl::PadSpec>(spec)));
     snprintf(expected, sizeof(expected), zeropad_format,
@@ -435,7 +429,7 @@
     EXPECT_EQ(expected, actual) << " decimal value " << v;
   }
 
-  for (int spec = absl::kSpacePad2; spec <= absl::kSpacePad16; ++spec) {
+  for (int spec = absl::kSpacePad2; spec <= absl::kSpacePad20; ++spec) {
     std::string actual =
         absl::StrCat(absl::Hex(v, static_cast<absl::PadSpec>(spec)));
     snprintf(expected, sizeof(expected), spacepad_format,
@@ -453,7 +447,7 @@
   snprintf(expected, sizeof(expected), nopad_format, v);
   EXPECT_EQ(expected, actual) << " decimal value " << v;
 
-  for (int spec = absl::kZeroPad2; spec <= absl::kZeroPad16; ++spec) {
+  for (int spec = absl::kZeroPad2; spec <= absl::kZeroPad20; ++spec) {
     std::string actual =
         absl::StrCat(absl::Dec(v, static_cast<absl::PadSpec>(spec)));
     snprintf(expected, sizeof(expected), zeropad_format,
@@ -463,7 +457,7 @@
         << "' digits " << (spec - absl::kZeroPad2 + 2);
   }
 
-  for (int spec = absl::kSpacePad2; spec <= absl::kSpacePad16; ++spec) {
+  for (int spec = absl::kSpacePad2; spec <= absl::kSpacePad20; ++spec) {
     std::string actual =
         absl::StrCat(absl::Dec(v, static_cast<absl::PadSpec>(spec)));
     snprintf(expected, sizeof(expected), spacepad_format,
diff --git a/absl/strings/str_format.h b/absl/strings/str_format.h
index 2d07725..539d951 100644
--- a/absl/strings/str_format.h
+++ b/absl/strings/str_format.h
@@ -5,7 +5,7 @@
 // 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
+//      https://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,
@@ -24,7 +24,8 @@
 //
 // Example:
 //
-//   string s = absl::StrFormat("%s %s You have $%d!", "Hello", name, dollars);
+//   std::string s = absl::StrFormat(
+//                      "%s %s You have $%d!", "Hello", name, dollars);
 //
 // The library consists of the following basic utilities:
 //
@@ -89,7 +90,7 @@
 // Example:
 //
 //   absl::UntypedFormatSpec format("%d");
-//   string out;
+//   std::string out;
 //   CHECK(absl::FormatUntyped(&out, format, {absl::FormatArg(1)}));
 class UntypedFormatSpec {
  public:
@@ -135,8 +136,8 @@
 // Example:
 //
 //   int n = 0;
-//   string s = absl::StrFormat("%s%d%n", "hello", 123,
-//                   absl::FormatCountCapture(&n));
+//   std::string s = absl::StrFormat("%s%d%n", "hello", 123,
+//                       absl::FormatCountCapture(&n));
 //   EXPECT_EQ(8, n);
 class FormatCountCapture {
  public:
@@ -186,7 +187,7 @@
 // A format string generally follows the POSIX syntax as used within the POSIX
 // `printf` specification.
 //
-// (See http://pubs.opengroup.org/onlinepubs/9699919799/utilities/printf.html.)
+// (See http://pubs.opengroup.org/onlinepubs/9699919799/functions/fprintf.html.)
 //
 // In specific, the `FormatSpec` supports the following type specifiers:
 //   * `c` for characters
@@ -223,7 +224,7 @@
 //     "%p", *int               -> "0x7ffdeb6ad2a4"
 //
 //     int n = 0;
-//     string s = absl::StrFormat(
+//     std::string s = absl::StrFormat(
 //         "%s%d%n", "hello", 123, absl::FormatCountCapture(&n));
 //     EXPECT_EQ(8, n);
 //
@@ -290,14 +291,14 @@
 //
 // Example:
 //
-//   string s = absl::StrFormat(
+//   std::string s = absl::StrFormat(
 //       "Welcome to %s, Number %d!", "The Village", 6);
 //   EXPECT_EQ("Welcome to The Village, Number 6!", s);
 //
 // Returns an empty string in case of error.
 template <typename... Args>
 ABSL_MUST_USE_RESULT std::string StrFormat(const FormatSpec<Args...>& format,
-                                      const Args&... args) {
+                                           const Args&... args) {
   return str_format_internal::FormatPack(
       str_format_internal::UntypedFormatSpecImpl::Extract(format),
       {str_format_internal::FormatArgImpl(args)...});
@@ -311,11 +312,12 @@
 //
 // Example:
 //
-//   string orig("For example PI is approximately ");
+//   std::string orig("For example PI is approximately ");
 //   std::cout << StrAppendFormat(&orig, "%12.6f", 3.14);
 template <typename... Args>
-std::string& StrAppendFormat(std::string* dst, const FormatSpec<Args...>& format,
-                        const Args&... args) {
+std::string& StrAppendFormat(std::string* dst,
+                             const FormatSpec<Args...>& format,
+                             const Args&... args) {
   return str_format_internal::AppendPack(
       dst, str_format_internal::UntypedFormatSpecImpl::Extract(format),
       {str_format_internal::FormatArgImpl(args)...});
@@ -434,7 +436,8 @@
 // `absl::FormatRawSink` interface), using a format string and zero or more
 // additional arguments.
 //
-// By default, `string` and `std::ostream` are supported as destination objects.
+// By default, `std::string` and `std::ostream` are supported as destination
+// objects.
 //
 // `absl::Format()` is a generic version of `absl::StrFormat(), for custom
 // sinks. The format string, like format strings for `StrFormat()`, is checked
@@ -483,9 +486,10 @@
 //
 // Example:
 //
-//   std::optional<string> FormatDynamic(const string& in_format,
-//                                       const vector<string>& in_args) {
-//     string out;
+//   std::optional<std::string> FormatDynamic(
+//       const std::string& in_format,
+//       const vector<std::string>& in_args) {
+//     std::string out;
 //     std::vector<absl::FormatArg> args;
 //     for (const auto& v : in_args) {
 //       // It is important that 'v' is a reference to the objects in in_args.
@@ -509,4 +513,5 @@
 }
 
 }  // namespace absl
+
 #endif  // ABSL_STRINGS_STR_FORMAT_H_
diff --git a/absl/strings/str_format_test.cc b/absl/strings/str_format_test.cc
index aa14e21..d4cffa0 100644
--- a/absl/strings/str_format_test.cc
+++ b/absl/strings/str_format_test.cc
@@ -242,6 +242,7 @@
   std::string ReadFile() {
     std::fseek(file_, 0, SEEK_END);
     int size = std::ftell(file_);
+    EXPECT_GT(size, 0);
     std::rewind(file_);
     std::string str(2 * size, ' ');
     int read_bytes = std::fread(&str[0], 1, str.size(), file_);
@@ -270,7 +271,7 @@
   EXPECT_EQ(errno, EBADF);
 }
 
-#if __GNUC__
+#if __GLIBC__
 TEST_F(FormatEntryPointTest, FprintfTooLarge) {
   std::FILE* f = std::fopen("/dev/null", "w");
   int width = 2000000000;
@@ -297,7 +298,7 @@
   EXPECT_EQ(result, 30);
   EXPECT_EQ(tmp.ReadFile(), "STRING: ABC NUMBER: -000000019");
 }
-#endif  // __GNUC__
+#endif  // __GLIBC__
 
 TEST_F(FormatEntryPointTest, SNPrintF) {
   char buffer[16];
@@ -340,7 +341,7 @@
   EXPECT_EQ(StrFormat("%c", int{'a'}), "a");
   EXPECT_EQ(StrFormat("%c", long{'a'}), "a");  // NOLINT
   EXPECT_EQ(StrFormat("%c", uint64_t{'a'}), "a");
-  //     "s" - std::string                  Eg: "C" -> "C", std::string("C++") -> "C++"
+  //     "s" - std::string       Eg: "C" -> "C", std::string("C++") -> "C++"
   //           Formats std::string, char*, string_view, and Cord.
   EXPECT_EQ(StrFormat("%s", "C"), "C");
   EXPECT_EQ(StrFormat("%s", std::string("C++")), "C++");
@@ -605,35 +606,21 @@
 // Some codegen thunks that we can use to easily dump the generated assembly for
 // different StrFormat calls.
 
-inline std::string CodegenAbslStrFormatInt(int i) {
+std::string CodegenAbslStrFormatInt(int i) {  // NOLINT
   return absl::StrFormat("%d", i);
 }
 
-inline std::string CodegenAbslStrFormatIntStringInt64(int i, const std::string& s,
-                                                 int64_t i64) {
+std::string CodegenAbslStrFormatIntStringInt64(int i, const std::string& s,
+                                               int64_t i64) {  // NOLINT
   return absl::StrFormat("%d %s %d", i, s, i64);
 }
 
-inline void CodegenAbslStrAppendFormatInt(std::string* out, int i) {
+void CodegenAbslStrAppendFormatInt(std::string* out, int i) {  // NOLINT
   absl::StrAppendFormat(out, "%d", i);
 }
 
-inline void CodegenAbslStrAppendFormatIntStringInt64(std::string* out, int i,
-                                                     const std::string& s,
-                                                     int64_t i64) {
+void CodegenAbslStrAppendFormatIntStringInt64(std::string* out, int i,
+                                              const std::string& s,
+                                              int64_t i64) {  // NOLINT
   absl::StrAppendFormat(out, "%d %s %d", i, s, i64);
 }
-
-auto absl_internal_str_format_force_codegen_funcs = std::make_tuple(
-    CodegenAbslStrFormatInt, CodegenAbslStrFormatIntStringInt64,
-    CodegenAbslStrAppendFormatInt, CodegenAbslStrAppendFormatIntStringInt64);
-
-bool absl_internal_str_format_force_codegen_always_false;
-// Force the compiler to generate the functions by making it look like we
-// escape the function pointers.
-// It can't statically know that
-// absl_internal_str_format_force_codegen_always_false is not changed by someone
-// else.
-bool absl_internal_str_format_force_codegen =
-    absl_internal_str_format_force_codegen_always_false &&
-    printf("%p", &absl_internal_str_format_force_codegen_funcs) == 0;
diff --git a/absl/strings/str_join.h b/absl/strings/str_join.h
index f9611ad..7345b96 100644
--- a/absl/strings/str_join.h
+++ b/absl/strings/str_join.h
@@ -5,7 +5,7 @@
 // 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
+//      https://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,
@@ -18,13 +18,13 @@
 // -----------------------------------------------------------------------------
 //
 // This header file contains functions for joining a range of elements and
-// returning the result as a string. StrJoin operations are specified by passing
-// a range, a separator string to use between the elements joined, and an
-// optional Formatter responsible for converting each argument in the range to a
-// string. If omitted, a default `AlphaNumFormatter()` is called on the elements
-// to be joined, using the same formatting that `absl::StrCat()` uses. This
-// package defines a number of default formatters, and you can define your own
-// implementations.
+// returning the result as a std::string. StrJoin operations are specified by
+// passing a range, a separator string to use between the elements joined, and
+// an optional Formatter responsible for converting each argument in the range
+// to a string. If omitted, a default `AlphaNumFormatter()` is called on the
+// elements to be joined, using the same formatting that `absl::StrCat()` uses.
+// This package defines a number of default formatters, and you can define your
+// own implementations.
 //
 // Ranges are specified by passing a container with `std::begin()` and
 // `std::end()` iterators, container-specific `begin()` and `end()` iterators, a
@@ -37,8 +37,8 @@
 //
 // Example:
 //
-//   std::vector<string> v = {"foo", "bar", "baz"};
-//   string s = absl::StrJoin(v, "-");
+//   std::vector<std::string> v = {"foo", "bar", "baz"};
+//   std::string s = absl::StrJoin(v, "-");
 //   EXPECT_EQ("foo-bar-baz", s);
 //
 // See comments on the `absl::StrJoin()` function for more examples.
@@ -66,16 +66,16 @@
 // -----------------------------------------------------------------------------
 //
 // A Formatter is a function object that is responsible for formatting its
-// argument as a string and appending it to a given output string. Formatters
-// may be implemented as function objects, lambdas, or normal functions. You may
-// provide your own Formatter to enable `absl::StrJoin()` to work with arbitrary
-// types.
+// argument as a string and appending it to a given output std::string.
+// Formatters may be implemented as function objects, lambdas, or normal
+// functions. You may provide your own Formatter to enable `absl::StrJoin()` to
+// work with arbitrary types.
 //
 // The following is an example of a custom Formatter that simply uses
-// `std::to_string()` to format an integer as a string.
+// `std::to_string()` to format an integer as a std::string.
 //
 //   struct MyFormatter {
-//     void operator()(string* out, int i) const {
+//     void operator()(std::string* out, int i) const {
 //       out->append(std::to_string(i));
 //     }
 //   };
@@ -84,7 +84,7 @@
 // argument to `absl::StrJoin()`:
 //
 //   std::vector<int> v = {1, 2, 3, 4};
-//   string s = absl::StrJoin(v, "-", MyFormatter());
+//   std::string s = absl::StrJoin(v, "-", MyFormatter());
 //   EXPECT_EQ("1-2-3-4", s);
 //
 // The following standard formatters are provided within this file:
@@ -156,7 +156,7 @@
 // StrJoin()
 // -----------------------------------------------------------------------------
 //
-// Joins a range of elements and returns the result as a string.
+// Joins a range of elements and returns the result as a std::string.
 // `absl::StrJoin()` takes a range, a separator string to use between the
 // elements joined, and an optional Formatter responsible for converting each
 // argument in the range to a string.
@@ -167,22 +167,22 @@
 // Example 1:
 //   // Joins a collection of strings. This pattern also works with a collection
 //   // of `absl::string_view` or even `const char*`.
-//   std::vector<string> v = {"foo", "bar", "baz"};
-//   string s = absl::StrJoin(v, "-");
+//   std::vector<std::string> v = {"foo", "bar", "baz"};
+//   std::string s = absl::StrJoin(v, "-");
 //   EXPECT_EQ("foo-bar-baz", s);
 //
 // Example 2:
 //   // Joins the values in the given `std::initializer_list<>` specified using
 //   // brace initialization. This pattern also works with an initializer_list
 //   // of ints or `absl::string_view` -- any `AlphaNum`-compatible type.
-//   string s = absl::StrJoin({"foo", "bar", "baz"}, "-");
+//   std::string s = absl::StrJoin({"foo", "bar", "baz"}, "-");
 //   EXPECT_EQ("foo-bar-baz", s);
 //
 // Example 3:
 //   // Joins a collection of ints. This pattern also works with floats,
 //   // doubles, int64s -- any `StrCat()`-compatible type.
 //   std::vector<int> v = {1, 2, 3, -4};
-//   string s = absl::StrJoin(v, "-");
+//   std::string s = absl::StrJoin(v, "-");
 //   EXPECT_EQ("1-2-3--4", s);
 //
 // Example 4:
@@ -193,7 +193,7 @@
 //   // `std::vector<int*>`.
 //   int x = 1, y = 2, z = 3;
 //   std::vector<int*> v = {&x, &y, &z};
-//   string s = absl::StrJoin(v, "-");
+//   std::string s = absl::StrJoin(v, "-");
 //   EXPECT_EQ("1-2-3", s);
 //
 // Example 5:
@@ -202,53 +202,53 @@
 //   v.emplace_back(new int(1));
 //   v.emplace_back(new int(2));
 //   v.emplace_back(new int(3));
-//   string s = absl::StrJoin(v, "-");
+//   std::string s = absl::StrJoin(v, "-");
 //   EXPECT_EQ("1-2-3", s);
 //
 // Example 6:
 //   // Joins a `std::map`, with each key-value pair separated by an equals
 //   // sign. This pattern would also work with, say, a
 //   // `std::vector<std::pair<>>`.
-//   std::map<string, int> m = {
+//   std::map<std::string, int> m = {
 //       std::make_pair("a", 1),
 //       std::make_pair("b", 2),
 //       std::make_pair("c", 3)};
-//   string s = absl::StrJoin(m, ",", absl::PairFormatter("="));
+//   std::string s = absl::StrJoin(m, ",", absl::PairFormatter("="));
 //   EXPECT_EQ("a=1,b=2,c=3", s);
 //
 // Example 7:
 //   // These examples show how `absl::StrJoin()` handles a few common edge
 //   // cases:
-//   std::vector<string> v_empty;
+//   std::vector<std::string> v_empty;
 //   EXPECT_EQ("", absl::StrJoin(v_empty, "-"));
 //
-//   std::vector<string> v_one_item = {"foo"};
+//   std::vector<std::string> v_one_item = {"foo"};
 //   EXPECT_EQ("foo", absl::StrJoin(v_one_item, "-"));
 //
-//   std::vector<string> v_empty_string = {""};
+//   std::vector<std::string> v_empty_string = {""};
 //   EXPECT_EQ("", absl::StrJoin(v_empty_string, "-"));
 //
-//   std::vector<string> v_one_item_empty_string = {"a", ""};
+//   std::vector<std::string> v_one_item_empty_string = {"a", ""};
 //   EXPECT_EQ("a-", absl::StrJoin(v_one_item_empty_string, "-"));
 //
-//   std::vector<string> v_two_empty_string = {"", ""};
+//   std::vector<std::string> v_two_empty_string = {"", ""};
 //   EXPECT_EQ("-", absl::StrJoin(v_two_empty_string, "-"));
 //
 // Example 8:
 //   // Joins a `std::tuple<T...>` of heterogeneous types, converting each to
-//   // a string using the `absl::AlphaNum` class.
-//   string s = absl::StrJoin(std::make_tuple(123, "abc", 0.456), "-");
+//   // a std::string using the `absl::AlphaNum` class.
+//   std::string s = absl::StrJoin(std::make_tuple(123, "abc", 0.456), "-");
 //   EXPECT_EQ("123-abc-0.456", s);
 
 template <typename Iterator, typename Formatter>
 std::string StrJoin(Iterator start, Iterator end, absl::string_view sep,
-               Formatter&& fmt) {
+                    Formatter&& fmt) {
   return strings_internal::JoinAlgorithm(start, end, sep, fmt);
 }
 
 template <typename Range, typename Formatter>
 std::string StrJoin(const Range& range, absl::string_view separator,
-               Formatter&& fmt) {
+                    Formatter&& fmt) {
   return strings_internal::JoinRange(range, separator, fmt);
 }
 
@@ -260,7 +260,7 @@
 
 template <typename... T, typename Formatter>
 std::string StrJoin(const std::tuple<T...>& value, absl::string_view separator,
-               Formatter&& fmt) {
+                    Formatter&& fmt) {
   return strings_internal::JoinAlgorithm(value, separator, fmt);
 }
 
@@ -280,7 +280,8 @@
 }
 
 template <typename... T>
-std::string StrJoin(const std::tuple<T...>& value, absl::string_view separator) {
+std::string StrJoin(const std::tuple<T...>& value,
+                    absl::string_view separator) {
   return strings_internal::JoinAlgorithm(value, separator, AlphaNumFormatter());
 }
 
diff --git a/absl/strings/str_join_benchmark.cc b/absl/strings/str_join_benchmark.cc
index 7fb0e49..d6f689f 100644
--- a/absl/strings/str_join_benchmark.cc
+++ b/absl/strings/str_join_benchmark.cc
@@ -5,7 +5,7 @@
 // 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
+//      https://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,
@@ -58,7 +58,8 @@
   const int string_len = state.range(0);
   const int num_pairs = state.range(1);
   const std::string s(string_len, 'x');
-  const std::vector<std::pair<std::string, int>> v(num_pairs, std::make_pair(s, 42));
+  const std::vector<std::pair<std::string, int>> v(num_pairs,
+                                                   std::make_pair(s, 42));
   for (auto _ : state) {
     std::string s = absl::StrJoin(v, ",", absl::PairFormatter("="));
     benchmark::DoNotOptimize(s);
diff --git a/absl/strings/str_join_test.cc b/absl/strings/str_join_test.cc
index c941f9c..921d9c2 100644
--- a/absl/strings/str_join_test.cc
+++ b/absl/strings/str_join_test.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -118,7 +118,7 @@
 
   {
     // A std::map, which is a collection of std::pair<>s.
-    std::map<std::string, int> m = { {"a", 1}, {"b", 2}, {"c", 3} };
+    std::map<std::string, int> m = {{"a", 1}, {"b", 2}, {"c", 3}};
     EXPECT_EQ("a=1,b=2,c=3", absl::StrJoin(m, ",", absl::PairFormatter("=")));
   }
 
@@ -140,7 +140,8 @@
   }
 
   {
-    // A range of 1 element gives a std::string with that element but no separator.
+    // A range of 1 element gives a std::string with that element but no
+    // separator.
     std::vector<std::string> v = {"foo"};
     EXPECT_EQ("foo", absl::StrJoin(v, "-"));
   }
@@ -173,9 +174,10 @@
 TEST(StrJoin, CustomFormatter) {
   std::vector<std::string> v{"One", "Two", "Three"};
   {
-    std::string joined = absl::StrJoin(v, "", [](std::string* out, const std::string& in) {
-      absl::StrAppend(out, "(", in, ")");
-    });
+    std::string joined =
+        absl::StrJoin(v, "", [](std::string* out, const std::string& in) {
+          absl::StrAppend(out, "(", in, ")");
+        });
     EXPECT_EQ("(One)(Two)(Three)", joined);
   }
   {
diff --git a/absl/strings/str_replace.cc b/absl/strings/str_replace.cc
index 69efa35..280f63d 100644
--- a/absl/strings/str_replace.cc
+++ b/absl/strings/str_replace.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -68,11 +68,12 @@
 // aren't inlined.
 
 std::string StrReplaceAll(absl::string_view s,
-                     strings_internal::FixedMapping replacements) {
+                          strings_internal::FixedMapping replacements) {
   return StrReplaceAll<strings_internal::FixedMapping>(s, replacements);
 }
 
-int StrReplaceAll(strings_internal::FixedMapping replacements, std::string* target) {
+int StrReplaceAll(strings_internal::FixedMapping replacements,
+                  std::string* target) {
   return StrReplaceAll<strings_internal::FixedMapping>(replacements, target);
 }
 
diff --git a/absl/strings/str_replace.h b/absl/strings/str_replace.h
index 3bfe4c6..30540d0 100644
--- a/absl/strings/str_replace.h
+++ b/absl/strings/str_replace.h
@@ -5,7 +5,7 @@
 // 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
+//      https://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,
@@ -29,12 +29,12 @@
 //
 // Example:
 //
-// string html_escaped = absl::StrReplaceAll(user_input, {
-//                                           {"&", "&amp;"},
-//                                           {"<", "&lt;"},
-//                                           {">", "&gt;"},
-//                                           {"\"", "&quot;"},
-//                                           {"'", "&#39;"}});
+// std::string html_escaped = absl::StrReplaceAll(user_input, {
+//                                                {"&", "&amp;"},
+//                                                {"<", "&lt;"},
+//                                                {">", "&gt;"},
+//                                                {"\"", "&quot;"},
+//                                                {"'", "&#39;"}});
 #ifndef ABSL_STRINGS_STR_REPLACE_H_
 #define ABSL_STRINGS_STR_REPLACE_H_
 
@@ -58,10 +58,11 @@
 //
 // Example:
 //
-//   string s = absl::StrReplaceAll("$who bought $count #Noun. Thanks $who!",
-//                                  {{"$count", absl::StrCat(5)},
-//                                   {"$who", "Bob"},
-//                                   {"#Noun", "Apples"}});
+//   std::string s = absl::StrReplaceAll(
+//       "$who bought $count #Noun. Thanks $who!",
+//       {{"$count", absl::StrCat(5)},
+//        {"$who", "Bob"},
+//        {"#Noun", "Apples"}});
 //   EXPECT_EQ("Bob bought 5 Apples. Thanks Bob!", s);
 ABSL_MUST_USE_RESULT std::string StrReplaceAll(
     absl::string_view s,
@@ -78,20 +79,22 @@
 //   replacements["$who"] = "Bob";
 //   replacements["$count"] = "5";
 //   replacements["#Noun"] = "Apples";
-//   string s = absl::StrReplaceAll("$who bought $count #Noun. Thanks $who!",
-//                                  replacements);
+//   std::string s = absl::StrReplaceAll(
+//       "$who bought $count #Noun. Thanks $who!",
+//       replacements);
 //   EXPECT_EQ("Bob bought 5 Apples. Thanks Bob!", s);
 //
 //   // A std::vector of std::pair elements can be more efficient.
-//   std::vector<std::pair<const absl::string_view, string>> replacements;
+//   std::vector<std::pair<const absl::string_view, std::string>> replacements;
 //   replacements.push_back({"&", "&amp;"});
 //   replacements.push_back({"<", "&lt;"});
 //   replacements.push_back({">", "&gt;"});
-//   string s = absl::StrReplaceAll("if (ptr < &foo)",
+//   std::string s = absl::StrReplaceAll("if (ptr < &foo)",
 //                                  replacements);
 //   EXPECT_EQ("if (ptr &lt; &amp;foo)", s);
 template <typename StrToStrMapping>
-std::string StrReplaceAll(absl::string_view s, const StrToStrMapping& replacements);
+std::string StrReplaceAll(absl::string_view s,
+                          const StrToStrMapping& replacements);
 
 // Overload of `StrReplaceAll()` to replace character sequences within a given
 // output string *in place* with replacements provided within an initializer
@@ -99,7 +102,7 @@
 //
 // Example:
 //
-//   string s = std::string("$who bought $count #Noun. Thanks $who!");
+//   std::string s = std::string("$who bought $count #Noun. Thanks $who!");
 //   int count;
 //   count = absl::StrReplaceAll({{"$count", absl::StrCat(5)},
 //                               {"$who", "Bob"},
@@ -117,7 +120,7 @@
 //
 // Example:
 //
-//   string s = std::string("if (ptr < &foo)");
+//   std::string s = std::string("if (ptr < &foo)");
 //   int count = absl::StrReplaceAll({{"&", "&amp;"},
 //                                    {"<", "&lt;"},
 //                                    {">", "&gt;"}}, &s);
@@ -187,7 +190,8 @@
 }  // namespace strings_internal
 
 template <typename StrToStrMapping>
-std::string StrReplaceAll(absl::string_view s, const StrToStrMapping& replacements) {
+std::string StrReplaceAll(absl::string_view s,
+                          const StrToStrMapping& replacements) {
   auto subs = strings_internal::FindSubstitutions(s, replacements);
   std::string result;
   result.reserve(s.size());
diff --git a/absl/strings/str_replace_benchmark.cc b/absl/strings/str_replace_benchmark.cc
index 8386f2e..95b2dc1 100644
--- a/absl/strings/str_replace_benchmark.cc
+++ b/absl/strings/str_replace_benchmark.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -54,7 +54,7 @@
     size_t r = 0;
     big_string = new std::string(1000 * 1000, ' ');
     for (std::string phrase : {"the quick brown fox jumped over the lazy dogs",
-                          "pack my box with the five dozen liquor jugs"}) {
+                               "pack my box with the five dozen liquor jugs"}) {
       for (int i = 0; i < 10 * 1000; ++i) {
         r = r * 237 + 41;  // not very random.
         memcpy(&(*big_string)[r % (big_string->size() - phrase.size())],
@@ -108,11 +108,11 @@
   std::string src = *big_string;
   for (auto _ : state) {
     std::string dest = absl::StrReplaceAll(src, {{"the", "box"},
-                                            {"brown", "quick"},
-                                            {"jumped", "liquored"},
-                                            {"dozen", "brown"},
-                                            {"lazy", "pack"},
-                                            {"liquor", "shakes"}});
+                                                 {"brown", "quick"},
+                                                 {"jumped", "liquored"},
+                                                 {"dozen", "brown"},
+                                                 {"lazy", "pack"},
+                                                 {"liquor", "shakes"}});
     ABSL_RAW_CHECK(dest == *after_replacing_many,
                    "not benchmarking intended behavior");
   }
diff --git a/absl/strings/str_replace_test.cc b/absl/strings/str_replace_test.cc
index 5d003a2..1ca23af 100644
--- a/absl/strings/str_replace_test.cc
+++ b/absl/strings/str_replace_test.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -148,7 +148,7 @@
   replacements["$count"] = "5";
   replacements["#Noun"] = "Apples";
   std::string s = absl::StrReplaceAll("$who bought $count #Noun. Thanks $who!",
-                                 replacements);
+                                      replacements);
   EXPECT_EQ("Bob bought 5 Apples. Thanks Bob!", s);
 }
 
diff --git a/absl/strings/str_split.cc b/absl/strings/str_split.cc
index 0a68c52..2593130 100644
--- a/absl/strings/str_split.cc
+++ b/absl/strings/str_split.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
diff --git a/absl/strings/str_split.h b/absl/strings/str_split.h
index c7eb280..7333078 100644
--- a/absl/strings/str_split.h
+++ b/absl/strings/str_split.h
@@ -5,7 +5,7 @@
 // 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
+//      https://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,
@@ -71,23 +71,23 @@
 //   - `ByLength`
 //   - `MaxSplits`
 //
+// A Delimiter's `Find()` member function will be passed an input `text` that is
+// to be split and a position (`pos`) to begin searching for the next delimiter
+// in `text`. The returned absl::string_view should refer to the next occurrence
+// (after `pos`) of the represented delimiter; this returned absl::string_view
+// represents the next location where the input `text` should be broken.
 //
-// A Delimiter's Find() member function will be passed the input text that is to
-// be split and the position to begin searching for the next delimiter in the
-// input text. The returned absl::string_view should refer to the next
-// occurrence (after pos) of the represented delimiter; this returned
-// absl::string_view represents the next location where the input string should
-// be broken. The returned absl::string_view may be zero-length if the Delimiter
-// does not represent a part of the string (e.g., a fixed-length delimiter). If
-// no delimiter is found in the given text, a zero-length absl::string_view
-// referring to text.end() should be returned (e.g.,
-// absl::string_view(text.end(), 0)). It is important that the returned
-// absl::string_view always be within the bounds of input text given as an
+// The returned absl::string_view may be zero-length if the Delimiter does not
+// represent a part of the string (e.g., a fixed-length delimiter). If no
+// delimiter is found in the input `text`, a zero-length absl::string_view
+// referring to `text.end()` should be returned (e.g.,
+// `text.substr(text.size())`). It is important that the returned
+// absl::string_view always be within the bounds of the input `text` given as an
 // argument--it must not refer to a string that is physically located outside of
 // the given string.
 //
 // The following example is a simple Delimiter object that is created with a
-// single char and will look for that char in the text passed to the Find()
+// single char and will look for that char in the text passed to the `Find()`
 // function:
 //
 //   struct SimpleDelimiter {
@@ -96,9 +96,9 @@
 //     absl::string_view Find(absl::string_view text, size_t pos) {
 //       auto found = text.find(c_, pos);
 //       if (found == absl::string_view::npos)
-//         return absl::string_view(text.end(), 0);
+//         return text.substr(text.size());
 //
-//       return absl::string_view(text, found, 1);
+//       return text.substr(found, 1);
 //     }
 //   };
 
@@ -131,8 +131,7 @@
 // ByChar
 //
 // A single character delimiter. `ByChar` is functionally equivalent to a
-// 1-char string within a `ByString` delimiter, but slightly more
-// efficient.
+// 1-char string within a `ByString` delimiter, but slightly more efficient.
 //
 // Example:
 //
@@ -413,10 +412,10 @@
 //
 // The `StrSplit()` function adapts the returned collection to the collection
 // specified by the caller (e.g. `std::vector` above). The returned collections
-// may contain `string`, `absl::string_view` (in which case the original string
-// being split must ensure that it outlives the collection), or any object that
-// can be explicitly created from an `absl::string_view`. This behavior works
-// for:
+// may contain `std::string`, `absl::string_view` (in which case the original
+// string being split must ensure that it outlives the collection), or any
+// object that can be explicitly created from an `absl::string_view`. This
+// behavior works for:
 //
 // 1) All standard STL containers including `std::vector`, `std::list`,
 //    `std::deque`, `std::set`,`std::multiset`, 'std::map`, and `std::multimap`
@@ -460,7 +459,7 @@
 // Example:
 //
 //   // Stores first two split strings as the members in a std::pair.
-//   std::pair<string, string> p = absl::StrSplit("a,b,c", ',');
+//   std::pair<std::string, std::string> p = absl::StrSplit("a,b,c", ',');
 //   // p.first == "a", p.second == "b"       // "c" is omitted.
 //
 // The `StrSplit()` function can be used multiple times to perform more
@@ -470,7 +469,7 @@
 //
 //   // The input string "a=b=c,d=e,f=,g" becomes
 //   // { "a" => "b=c", "d" => "e", "f" => "", "g" => "" }
-//   std::map<string, string> m;
+//   std::map<std::string, std::string> m;
 //   for (absl::string_view sp : absl::StrSplit("a=b=c,d=e,f=,g", ',')) {
 //     m.insert(absl::StrSplit(sp, absl::MaxSplits('=', 1)));
 //   }
diff --git a/absl/strings/str_split_benchmark.cc b/absl/strings/str_split_benchmark.cc
index 326ff74..28c25e8 100644
--- a/absl/strings/str_split_benchmark.cc
+++ b/absl/strings/str_split_benchmark.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -35,16 +35,16 @@
   return test;
 }
 
-void BM_Split2StringPiece(benchmark::State& state) {
+void BM_Split2StringView(benchmark::State& state) {
   std::string test = MakeTestString(state.range(0));
   for (auto _ : state) {
     std::vector<absl::string_view> result = absl::StrSplit(test, ';');
     benchmark::DoNotOptimize(result);
   }
 }
-BENCHMARK_RANGE(BM_Split2StringPiece, 0, 1 << 20);
+BENCHMARK_RANGE(BM_Split2StringView, 0, 1 << 20);
 
-void BM_Split2StringPieceLifted(benchmark::State& state) {
+void BM_Split2StringViewLifted(benchmark::State& state) {
   std::string test = MakeTestString(state.range(0));
   std::vector<absl::string_view> result;
   for (auto _ : state) {
@@ -52,7 +52,7 @@
   }
   benchmark::DoNotOptimize(result);
 }
-BENCHMARK_RANGE(BM_Split2StringPieceLifted, 0, 1 << 20);
+BENCHMARK_RANGE(BM_Split2StringViewLifted, 0, 1 << 20);
 
 void BM_Split2String(benchmark::State& state) {
   std::string test = MakeTestString(state.range(0));
@@ -69,7 +69,8 @@
 void BM_Split2SplitStringUsing(benchmark::State& state) {
   std::string test = MakeTestString(state.range(0));
   for (auto _ : state) {
-    std::vector<std::string> result = absl::StrSplit(test, ';', absl::SkipEmpty());
+    std::vector<std::string> result =
+        absl::StrSplit(test, ';', absl::SkipEmpty());
     benchmark::DoNotOptimize(result);
   }
 }
diff --git a/absl/strings/str_split_test.cc b/absl/strings/str_split_test.cc
index 413ad31..ef6400e 100644
--- a/absl/strings/str_split_test.cc
+++ b/absl/strings/str_split_test.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -40,8 +40,8 @@
 TEST(Split, TraitsTest) {
   static_assert(!absl::strings_internal::SplitterIsConvertibleTo<int>::value,
                 "");
-  static_assert(!absl::strings_internal::SplitterIsConvertibleTo<std::string>::value,
-                "");
+  static_assert(
+      !absl::strings_internal::SplitterIsConvertibleTo<std::string>::value, "");
   static_assert(absl::strings_internal::SplitterIsConvertibleTo<
                     std::vector<std::string>>::value,
                 "");
@@ -182,7 +182,8 @@
   {
     // Uses the SkipWhitespace predicate.
     using absl::SkipWhitespace;
-    std::vector<std::string> v = absl::StrSplit(" a , ,,b,", ',', SkipWhitespace());
+    std::vector<std::string> v =
+        absl::StrSplit(" a , ,,b,", ',', SkipWhitespace());
     EXPECT_THAT(v, ElementsAre(" a ", "b"));
   }
 
@@ -215,7 +216,8 @@
 
   {
     // Results stored in a std::multimap.
-    std::multimap<std::string, std::string> m = absl::StrSplit("a,1,b,2,a,3", ',');
+    std::multimap<std::string, std::string> m =
+        absl::StrSplit("a,1,b,2,a,3", ',');
     EXPECT_EQ(3, m.size());
     auto it = m.find("a");
     EXPECT_EQ("1", it->second);
@@ -271,7 +273,8 @@
   EXPECT_EQ("a", *it);  // tests dereference
   ++it;                 // tests preincrement
   EXPECT_NE(it, end);
-  EXPECT_EQ("b", std::string(it->data(), it->size()));  // tests dereference as ptr
+  EXPECT_EQ("b",
+            std::string(it->data(), it->size()));  // tests dereference as ptr
   it++;                                            // tests postincrement
   EXPECT_EQ(it, end);
 }
@@ -295,7 +298,8 @@
   EXPECT_EQ("a", *it);  // tests dereference
   ++it;                 // tests preincrement -- "b" should be skipped here.
   EXPECT_NE(it, end);
-  EXPECT_EQ("c", std::string(it->data(), it->size()));  // tests dereference as ptr
+  EXPECT_EQ("c",
+            std::string(it->data(), it->size()));  // tests dereference as ptr
   it++;                                            // tests postincrement
   EXPECT_EQ(it, end);
 }
@@ -421,10 +425,13 @@
   TestMapConversionOperator<std::map<std::string, std::string>>(splitter);
   TestMapConversionOperator<
       std::multimap<absl::string_view, absl::string_view>>(splitter);
-  TestMapConversionOperator<std::multimap<absl::string_view, std::string>>(splitter);
-  TestMapConversionOperator<std::multimap<std::string, absl::string_view>>(splitter);
+  TestMapConversionOperator<std::multimap<absl::string_view, std::string>>(
+      splitter);
+  TestMapConversionOperator<std::multimap<std::string, absl::string_view>>(
+      splitter);
   TestMapConversionOperator<std::multimap<std::string, std::string>>(splitter);
-  TestMapConversionOperator<std::unordered_map<std::string, std::string>>(splitter);
+  TestMapConversionOperator<std::unordered_map<std::string, std::string>>(
+      splitter);
 
   // Tests conversion to std::pair
 
@@ -568,10 +575,9 @@
 }
 
 TEST(Split, Temporary) {
-  // Use a std::string longer than the small-std::string-optimization length, so that when
-  // the temporary is destroyed, if the splitter keeps a reference to the
-  // std::string's contents, it'll reference freed memory instead of just dead
-  // on-stack memory.
+  // Use a std::string longer than the SSO length, so that when the temporary is
+  // destroyed, if the splitter keeps a reference to the std::string's contents,
+  // it'll reference freed memory instead of just dead on-stack memory.
   const char input[] = "a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u";
   EXPECT_LT(sizeof(std::string), ABSL_ARRAYSIZE(input))
       << "Input should be larger than fits on the stack.";
@@ -647,6 +653,11 @@
   }
 }
 
+#if !defined(__cpp_char8_t)
+#if defined(__clang__)
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wc++2a-compat"
+#endif
 TEST(Split, UTF8) {
   // Tests splitting utf8 strings and utf8 delimiters.
   std::string utf8_string = u8"\u03BA\u1F79\u03C3\u03BC\u03B5";
@@ -673,6 +684,10 @@
     EXPECT_THAT(v, ElementsAre("Foo", u8"h\u00E4llo", u8"th\u4E1Ere"));
   }
 }
+#if defined(__clang__)
+#pragma clang diagnostic pop
+#endif
+#endif  // !defined(__cpp_char8_t)
 
 TEST(Split, EmptyStringDelimiter) {
   {
diff --git a/absl/strings/string_view.cc b/absl/strings/string_view.cc
index 4ceeb6b..cb79d5d 100644
--- a/absl/strings/string_view.cc
+++ b/absl/strings/string_view.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -228,7 +228,7 @@
 // member definitions that are required by the C++ standard, resulting in
 // LNK1169 "multiply defined" errors at link time. __declspec(selectany) asks
 // MSVC to choose only one definition for the symbol it decorates. See details
-// at http://msdn.microsoft.com/en-us/library/34h23df8(v=vs.100).aspx
+// at https://msdn.microsoft.com/en-us/library/34h23df8(v=vs.100).aspx
 #ifdef _MSC_VER
 #define ABSL_STRING_VIEW_SELECTANY __declspec(selectany)
 #else
diff --git a/absl/strings/string_view.h b/absl/strings/string_view.h
index 6bcd3c4..f8b2001 100644
--- a/absl/strings/string_view.h
+++ b/absl/strings/string_view.h
@@ -5,7 +5,7 @@
 // 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
+//      https://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,
@@ -32,7 +32,7 @@
 
 #ifdef ABSL_HAVE_STD_STRING_VIEW
 
-#include <string_view>
+#include <string_view>  // IWYU pragma: export
 
 namespace absl {
 using std::string_view;
@@ -101,7 +101,6 @@
 // example, when splitting a string, `std::vector<absl::string_view>` is a
 // natural data type for the output.
 //
-//
 // When constructed from a source which is nul-terminated, the `string_view`
 // itself will not include the nul-terminator unless a specific size (including
 // the nul) is passed to the constructor. As a result, common idioms that work
@@ -277,7 +276,7 @@
   // Checks if the `string_view` is empty (refers to no characters).
   constexpr bool empty() const noexcept { return length_ == 0; }
 
-  // std::string:view::operator[]
+  // string_view::operator[]
   //
   // Returns the ith element of an `string_view` using the array operator.
   // Note that this operator does not perform any bounds checking.
@@ -355,7 +354,7 @@
   string_view substr(size_type pos, size_type n = npos) const {
     if (ABSL_PREDICT_FALSE(pos > length_))
       base_internal::ThrowStdOutOfRange("absl::string_view::substr");
-    n = std::min(n, length_ - pos);
+    n = (std::min)(n, length_ - pos);
     return string_view(ptr_ + pos, n);
   }
 
@@ -368,7 +367,7 @@
   // on the respective sizes of the two `string_view`s to determine which is
   // smaller, equal, or greater.
   int compare(string_view x) const noexcept {
-    auto min_length = std::min(length_, x.length_);
+    auto min_length = (std::min)(length_, x.length_);
     if (min_length > 0) {
       int r = memcmp(ptr_, x.ptr_, min_length);
       if (r < 0) return -1;
@@ -490,7 +489,7 @@
 
  private:
   static constexpr size_type kMaxSize =
-      std::numeric_limits<difference_type>::max();
+      (std::numeric_limits<difference_type>::max)();
 
   static constexpr size_type CheckLengthInternal(size_type len) {
     return ABSL_ASSERT(len <= kMaxSize), len;
@@ -508,6 +507,7 @@
   if (len != y.size()) {
     return false;
   }
+
   return x.data() == y.data() || len <= 0 ||
          memcmp(x.data(), y.data(), len) == 0;
 }
@@ -517,7 +517,7 @@
 }
 
 inline bool operator<(string_view x, string_view y) noexcept {
-  auto min_size = std::min(x.size(), y.size());
+  auto min_size = (std::min)(x.size(), y.size());
   const int r = min_size == 0 ? 0 : memcmp(x.data(), y.data(), min_size);
   return (r < 0) || (r == 0 && x.size() < y.size());
 }
@@ -547,7 +547,7 @@
 // Provided because std::string_view::substr throws if `pos > size()`
 inline string_view ClippedSubstr(string_view s, size_t pos,
                                  size_t n = string_view::npos) {
-  pos = std::min(pos, static_cast<size_t>(s.size()));
+  pos = (std::min)(pos, static_cast<size_t>(s.size()));
   return s.substr(pos, n);
 }
 
diff --git a/absl/strings/string_view_benchmark.cc b/absl/strings/string_view_benchmark.cc
index fb46db1..46909cb 100644
--- a/absl/strings/string_view_benchmark.cc
+++ b/absl/strings/string_view_benchmark.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -151,7 +151,7 @@
   std::string haystack(state.range(0), '0');
   absl::string_view s(haystack);
   for (auto _ : state) {
-    s.find("x");  // not present; length 1
+    benchmark::DoNotOptimize(s.find("x"));  // not present; length 1
   }
 }
 BENCHMARK(BM_find_string_view_len_one)->Range(1, 1 << 20);
@@ -160,7 +160,7 @@
   std::string haystack(state.range(0), '0');
   absl::string_view s(haystack);
   for (auto _ : state) {
-    s.find("xx");  // not present; length 2
+    benchmark::DoNotOptimize(s.find("xx"));  // not present; length 2
   }
 }
 BENCHMARK(BM_find_string_view_len_two)->Range(1, 1 << 20);
@@ -169,7 +169,7 @@
   std::string haystack(state.range(0), '0');
   absl::string_view s(haystack);
   for (auto _ : state) {
-    s.find('x');  // not present
+    benchmark::DoNotOptimize(s.find('x'));  // not present
   }
 }
 BENCHMARK(BM_find_one_char)->Range(1, 1 << 20);
@@ -178,7 +178,7 @@
   std::string haystack(state.range(0), '0');
   absl::string_view s(haystack);
   for (auto _ : state) {
-    s.rfind('x');  // not present
+    benchmark::DoNotOptimize(s.rfind('x'));  // not present
   }
 }
 BENCHMARK(BM_rfind_one_char)->Range(1, 1 << 20);
@@ -193,7 +193,7 @@
 
   absl::string_view s(haystack);
   for (auto _ : state) {
-    s.find_first_of(needle);
+    benchmark::DoNotOptimize(s.find_first_of(needle));
   }
 }
 
diff --git a/absl/strings/string_view_test.cc b/absl/strings/string_view_test.cc
index a94e822..f5acf1d 100644
--- a/absl/strings/string_view_test.cc
+++ b/absl/strings/string_view_test.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -284,9 +284,10 @@
 }
 #undef COMPARE
 
-// Sadly, our users often confuse string::npos with absl::string_view::npos;
-// So much so that we test here that they are the same.  They need to
-// both be unsigned, and both be the maximum-valued integer of their type.
+// Sadly, our users often confuse std::string::npos with
+// absl::string_view::npos; So much so that we test here that they are the same.
+// They need to both be unsigned, and both be the maximum-valued integer of
+// their type.
 
 template <typename T>
 struct is_type {
@@ -678,9 +679,9 @@
   EXPECT_EQ(a.substr(23, absl::string_view::npos), c);
   // throw exception
 #ifdef ABSL_HAVE_EXCEPTIONS
-  EXPECT_THROW(a.substr(99, 2), std::out_of_range);
+  EXPECT_THROW((void)a.substr(99, 2), std::out_of_range);
 #else
-  EXPECT_DEATH(a.substr(99, 2), "absl::string_view::substr");
+  EXPECT_DEATH((void)a.substr(99, 2), "absl::string_view::substr");
 #endif
 }
 
@@ -755,7 +756,6 @@
   std::string s1("123");
   s1 += '\0';
   s1 += "456";
-  absl::string_view b(s1);
   absl::string_view e;
   std::string s2;
 
@@ -995,8 +995,8 @@
 TEST(StringViewTest, Noexcept) {
   EXPECT_TRUE((std::is_nothrow_constructible<absl::string_view,
                                              const std::string&>::value));
-  EXPECT_TRUE(
-      (std::is_nothrow_constructible<absl::string_view, const std::string&>::value));
+  EXPECT_TRUE((std::is_nothrow_constructible<absl::string_view,
+                                             const std::string&>::value));
   EXPECT_TRUE(std::is_nothrow_constructible<absl::string_view>::value);
   constexpr absl::string_view sp;
   EXPECT_TRUE(noexcept(sp.begin()));
diff --git a/absl/strings/strip.h b/absl/strings/strip.h
index 8d0d7c6..e1341e0 100644
--- a/absl/strings/strip.h
+++ b/absl/strings/strip.h
@@ -5,7 +5,7 @@
 // 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
+//      https://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,
diff --git a/absl/strings/strip_test.cc b/absl/strings/strip_test.cc
index 40c4c60..e4e00cb 100644
--- a/absl/strings/strip_test.cc
+++ b/absl/strings/strip_test.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -27,9 +27,6 @@
 
 namespace {
 
-using testing::ElementsAre;
-using testing::IsEmpty;
-
 TEST(Strip, ConsumePrefixOneChar) {
   absl::string_view input("abc");
   EXPECT_TRUE(absl::ConsumePrefix(&input, "a"));
diff --git a/absl/strings/substitute.cc b/absl/strings/substitute.cc
index 3b20059..bc17695 100644
--- a/absl/strings/substitute.cc
+++ b/absl/strings/substitute.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
diff --git a/absl/strings/substitute.h b/absl/strings/substitute.h
index 4de7b4e..507bc4f 100644
--- a/absl/strings/substitute.h
+++ b/absl/strings/substitute.h
@@ -5,7 +5,7 @@
 // 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
+//      https://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,
@@ -36,18 +36,17 @@
 // use at that location within the format string.
 //
 // Example 1:
-//   string s = Substitute("$1 purchased $0 $2. Thanks $1!",
-//                         5, "Bob", "Apples");
+//   std::string s = Substitute("$1 purchased $0 $2. Thanks $1!",
+//                              5, "Bob", "Apples");
 //   EXPECT_EQ("Bob purchased 5 Apples. Thanks Bob!", s);
 //
 // Example 2:
-//   string s = "Hi. ";
+//   std::string s = "Hi. ";
 //   SubstituteAndAppend(&s, "My name is $0 and I am $1 years old.", "Bob", 5);
 //   EXPECT_EQ("Hi. My name is Bob and I am 5 years old.", s);
 //
-//
 // Supported types:
-//   * absl::string_view, string, const char* (null is equivalent to "")
+//   * absl::string_view, std::string, const char* (null is equivalent to "")
 //   * int32_t, int64_t, uint32_t, uint64
 //   * float, double
 //   * bool (Printed as "true" or "false")
@@ -456,7 +455,7 @@
 // Example:
 //  template <typename... Args>
 //  void VarMsg(absl::string_view format, const Args&... args) {
-//    string s = absl::Substitute(format, args...);
+//    std::string s = absl::Substitute(format, args...);
 
 ABSL_MUST_USE_RESULT inline std::string Substitute(absl::string_view format) {
   std::string result;
@@ -574,70 +573,70 @@
                      "contains one of $1-$9");
 
 std::string Substitute(const char* format, const substitute_internal::Arg& a0,
-                  const substitute_internal::Arg& a1)
+                       const substitute_internal::Arg& a1)
     ABSL_BAD_CALL_IF(substitute_internal::PlaceholderBitmask(format) != 3,
                      "There were 2 substitution arguments given, but "
                      "this format std::string is either missing its $0/$1, or "
                      "contains one of $2-$9");
 
 std::string Substitute(const char* format, const substitute_internal::Arg& a0,
-                  const substitute_internal::Arg& a1,
-                  const substitute_internal::Arg& a2)
+                       const substitute_internal::Arg& a1,
+                       const substitute_internal::Arg& a2)
     ABSL_BAD_CALL_IF(substitute_internal::PlaceholderBitmask(format) != 7,
                      "There were 3 substitution arguments given, but "
                      "this format std::string is either missing its $0/$1/$2, or "
                      "contains one of $3-$9");
 
 std::string Substitute(const char* format, const substitute_internal::Arg& a0,
-                  const substitute_internal::Arg& a1,
-                  const substitute_internal::Arg& a2,
-                  const substitute_internal::Arg& a3)
+                       const substitute_internal::Arg& a1,
+                       const substitute_internal::Arg& a2,
+                       const substitute_internal::Arg& a3)
     ABSL_BAD_CALL_IF(substitute_internal::PlaceholderBitmask(format) != 15,
                      "There were 4 substitution arguments given, but "
                      "this format std::string is either missing its $0-$3, or "
                      "contains one of $4-$9");
 
 std::string Substitute(const char* format, const substitute_internal::Arg& a0,
-                  const substitute_internal::Arg& a1,
-                  const substitute_internal::Arg& a2,
-                  const substitute_internal::Arg& a3,
-                  const substitute_internal::Arg& a4)
+                       const substitute_internal::Arg& a1,
+                       const substitute_internal::Arg& a2,
+                       const substitute_internal::Arg& a3,
+                       const substitute_internal::Arg& a4)
     ABSL_BAD_CALL_IF(substitute_internal::PlaceholderBitmask(format) != 31,
                      "There were 5 substitution arguments given, but "
                      "this format std::string is either missing its $0-$4, or "
                      "contains one of $5-$9");
 
 std::string Substitute(const char* format, const substitute_internal::Arg& a0,
-                  const substitute_internal::Arg& a1,
-                  const substitute_internal::Arg& a2,
-                  const substitute_internal::Arg& a3,
-                  const substitute_internal::Arg& a4,
-                  const substitute_internal::Arg& a5)
+                       const substitute_internal::Arg& a1,
+                       const substitute_internal::Arg& a2,
+                       const substitute_internal::Arg& a3,
+                       const substitute_internal::Arg& a4,
+                       const substitute_internal::Arg& a5)
     ABSL_BAD_CALL_IF(substitute_internal::PlaceholderBitmask(format) != 63,
                      "There were 6 substitution arguments given, but "
                      "this format std::string is either missing its $0-$5, or "
                      "contains one of $6-$9");
 
 std::string Substitute(const char* format, const substitute_internal::Arg& a0,
-                  const substitute_internal::Arg& a1,
-                  const substitute_internal::Arg& a2,
-                  const substitute_internal::Arg& a3,
-                  const substitute_internal::Arg& a4,
-                  const substitute_internal::Arg& a5,
-                  const substitute_internal::Arg& a6)
+                       const substitute_internal::Arg& a1,
+                       const substitute_internal::Arg& a2,
+                       const substitute_internal::Arg& a3,
+                       const substitute_internal::Arg& a4,
+                       const substitute_internal::Arg& a5,
+                       const substitute_internal::Arg& a6)
     ABSL_BAD_CALL_IF(substitute_internal::PlaceholderBitmask(format) != 127,
                      "There were 7 substitution arguments given, but "
                      "this format std::string is either missing its $0-$6, or "
                      "contains one of $7-$9");
 
 std::string Substitute(const char* format, const substitute_internal::Arg& a0,
-                  const substitute_internal::Arg& a1,
-                  const substitute_internal::Arg& a2,
-                  const substitute_internal::Arg& a3,
-                  const substitute_internal::Arg& a4,
-                  const substitute_internal::Arg& a5,
-                  const substitute_internal::Arg& a6,
-                  const substitute_internal::Arg& a7)
+                       const substitute_internal::Arg& a1,
+                       const substitute_internal::Arg& a2,
+                       const substitute_internal::Arg& a3,
+                       const substitute_internal::Arg& a4,
+                       const substitute_internal::Arg& a5,
+                       const substitute_internal::Arg& a6,
+                       const substitute_internal::Arg& a7)
     ABSL_BAD_CALL_IF(substitute_internal::PlaceholderBitmask(format) != 255,
                      "There were 8 substitution arguments given, but "
                      "this format std::string is either missing its $0-$7, or "
diff --git a/absl/strings/substitute_test.cc b/absl/strings/substitute_test.cc
index 144df01..f656890 100644
--- a/absl/strings/substitute_test.cc
+++ b/absl/strings/substitute_test.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
diff --git a/absl/synchronization/BUILD.bazel b/absl/synchronization/BUILD.bazel
index f52e9d4..5e69847 100644
--- a/absl/synchronization/BUILD.bazel
+++ b/absl/synchronization/BUILD.bazel
@@ -5,7 +5,7 @@
 # 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
+#      https://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,
@@ -15,7 +15,7 @@
 #
 
 load(
-    "//absl:copts.bzl",
+    "//absl:copts/configure_copts.bzl",
     "ABSL_DEFAULT_COPTS",
     "ABSL_TEST_COPTS",
 )
@@ -69,6 +69,10 @@
         "notification.h",
     ],
     copts = ABSL_DEFAULT_COPTS,
+    linkopts = select({
+        "//absl:windows": [],
+        "//conditions:default": ["-pthread"],
+    }),
     deps = [
         ":graphcycles_internal",
         "//absl/base",
@@ -170,18 +174,31 @@
     ],
 )
 
-cc_test(
-    name = "mutex_benchmark",
+cc_library(
+    name = "mutex_benchmark_common",
+    testonly = 1,
     srcs = ["mutex_benchmark.cc"],
     copts = ABSL_TEST_COPTS,
-    tags = ["benchmark"],
-    visibility = ["//visibility:private"],
+    visibility = [
+        "//absl/synchronization:__pkg__",
+    ],
     deps = [
         ":synchronization",
         ":thread_pool",
         "//absl/base",
         "@com_github_google_benchmark//:benchmark_main",
     ],
+    alwayslink = 1,
+)
+
+cc_binary(
+    name = "mutex_benchmark",
+    testonly = 1,
+    copts = ABSL_DEFAULT_COPTS,
+    visibility = ["//visibility:private"],
+    deps = [
+        ":mutex_benchmark_common",
+    ],
 )
 
 cc_test(
@@ -232,10 +249,6 @@
         "lifetime_test.cc",
     ],
     copts = ABSL_TEST_COPTS,
-    linkopts = select({
-        "//absl:windows": [],
-        "//conditions:default": ["-pthread"],
-    }),
     tags = ["no_test_ios_x86_64"],
     deps = [
         ":synchronization",
diff --git a/absl/synchronization/CMakeLists.txt b/absl/synchronization/CMakeLists.txt
index de0d7b7..68473b7 100644
--- a/absl/synchronization/CMakeLists.txt
+++ b/absl/synchronization/CMakeLists.txt
@@ -5,7 +5,7 @@
 # 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
+#      https://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,
@@ -14,142 +14,182 @@
 # limitations under the License.
 #
 
-list(APPEND SYNCHRONIZATION_PUBLIC_HEADERS
-  "barrier.h"
-  "blocking_counter.h"
-  "mutex.h"
-  "notification.h"
+absl_cc_library(
+  NAME
+    graphcycles_internal
+  HDRS
+    "internal/graphcycles.h"
+  SRCS
+    "internal/graphcycles.cc"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::base
+    absl::base_internal
+    absl::core_headers
+    absl::malloc_internal
 )
 
-
-list(APPEND SYNCHRONIZATION_INTERNAL_HEADERS
-  "internal/create_thread_identity.h"
-  "internal/graphcycles.h"
-  "internal/kernel_timeout.h"
-  "internal/per_thread_sem.h"
-  "internal/thread_pool.h"
-  "internal/waiter.h"
-)
-
-
-
-# synchronization library
-list(APPEND SYNCHRONIZATION_SRC
-  "barrier.cc"
-  "blocking_counter.cc"
-  "internal/create_thread_identity.cc"
-  "internal/per_thread_sem.cc"
-  "internal/waiter.cc"
-  "internal/graphcycles.cc"
-  "notification.cc"
-  "mutex.cc"
-)
-
-set(SYNCHRONIZATION_PUBLIC_LIBRARIES absl::base absl::stacktrace absl::symbolize absl::time)
-
-absl_library(
-  TARGET
-    absl_synchronization
-  SOURCES
-    ${SYNCHRONIZATION_SRC}
-  PUBLIC_LIBRARIES
-    ${SYNCHRONIZATION_PUBLIC_LIBRARIES}
-  EXPORT_NAME
+absl_cc_library(
+  NAME
     synchronization
+  HDRS
+    "barrier.h"
+    "blocking_counter.h"
+    "internal/create_thread_identity.h"
+    "internal/kernel_timeout.h"
+    "internal/mutex_nonprod.inc"
+    "internal/per_thread_sem.h"
+    "internal/waiter.h"
+    "mutex.h"
+    "notification.h"
+  SRCS
+    "barrier.cc"
+    "blocking_counter.cc"
+    "internal/create_thread_identity.cc"
+    "internal/per_thread_sem.cc"
+    "internal/waiter.cc"
+    "notification.cc"
+    "mutex.cc"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::graphcycles_internal
+    absl::base
+    absl::base_internal
+    absl::config
+    absl::core_headers
+    absl::dynamic_annotations
+    absl::malloc_internal
+    absl::stacktrace
+    absl::symbolize
+    absl::time
+  PUBLIC
 )
 
-
-#
-## TESTS
-#
-
-
-# test barrier_test
-set(BARRIER_TEST_SRC "barrier_test.cc")
-set(BARRIER_TEST_PUBLIC_LIBRARIES absl::synchronization)
-
-absl_test(
-  TARGET
+absl_cc_test(
+  NAME
     barrier_test
-  SOURCES
-    ${BARRIER_TEST_SRC}
-  PUBLIC_LIBRARIES
-    ${BARRIER_TEST_PUBLIC_LIBRARIES}
+  SRCS
+    "barrier_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::synchronization
+    absl::time
+    gmock_main
 )
 
-
-# test blocking_counter_test
-set(BLOCKING_COUNTER_TEST_SRC "blocking_counter_test.cc")
-set(BLOCKING_COUNTER_TEST_PUBLIC_LIBRARIES absl::synchronization)
-
-absl_test(
-  TARGET
+absl_cc_test(
+  NAME
     blocking_counter_test
-  SOURCES
-    ${BLOCKING_COUNTER_TEST_SRC}
-  PUBLIC_LIBRARIES
-    ${BLOCKING_COUNTER_TEST_PUBLIC_LIBRARIES}
+  SRCS
+    "blocking_counter_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::synchronization
+    absl::time
+    gmock_main
 )
 
-
-# test graphcycles_test
-set(GRAPHCYCLES_TEST_SRC "internal/graphcycles_test.cc")
-set(GRAPHCYCLES_TEST_PUBLIC_LIBRARIES absl::synchronization)
-
-absl_test(
-  TARGET
+absl_cc_test(
+  NAME
     graphcycles_test
-  SOURCES
-    ${GRAPHCYCLES_TEST_SRC}
-  PUBLIC_LIBRARIES
-    ${GRAPHCYCLES_TEST_PUBLIC_LIBRARIES}
+  SRCS
+    "internal/graphcycles_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::graphcycles_internal
+    absl::base
+    absl::core_headers
+    gmock_main
 )
 
+absl_cc_library(
+  NAME
+    thread_pool
+  HDRS
+    "internal/thread_pool.h"
+  DEPS
+    absl::synchronization
+    absl::core_headers
+  TESTONLY
+)
 
-# test mutex_test
-set(MUTEX_TEST_SRC "mutex_test.cc")
-set(MUTEX_TEST_PUBLIC_LIBRARIES absl::synchronization)
-
-absl_test(
-  TARGET
+absl_cc_test(
+  NAME
     mutex_test
-  SOURCES
-    ${MUTEX_TEST_SRC}
-  PUBLIC_LIBRARIES
-    ${MUTEX_TEST_PUBLIC_LIBRARIES}
+  SRCS
+    "mutex_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::synchronization
+    absl::thread_pool
+    absl::base
+    absl::core_headers
+    absl::memory
+    absl::time
+    gmock_main
 )
 
-
-# test notification_test
-set(NOTIFICATION_TEST_SRC "notification_test.cc")
-set(NOTIFICATION_TEST_PUBLIC_LIBRARIES absl::synchronization)
-
-absl_test(
-  TARGET
+absl_cc_test(
+  NAME
     notification_test
-  SOURCES
-    ${NOTIFICATION_TEST_SRC}
-  PUBLIC_LIBRARIES
-    ${NOTIFICATION_TEST_PUBLIC_LIBRARIES}
+  SRCS
+    "notification_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::synchronization
+    absl::time
+    gmock_main
 )
 
-
-# test per_thread_sem_test_common
-set(PER_THREAD_SEM_TEST_COMMON_SRC "internal/per_thread_sem_test.cc")
-set(PER_THREAD_SEM_TEST_COMMON_PUBLIC_LIBRARIES absl::synchronization absl::strings)
-
-absl_test(
-  TARGET
+absl_cc_library(
+  NAME
     per_thread_sem_test_common
-  SOURCES
-    ${PER_THREAD_SEM_TEST_COMMON_SRC}
-  PUBLIC_LIBRARIES
-    ${PER_THREAD_SEM_TEST_COMMON_PUBLIC_LIBRARIES}
+  SRCS
+    "internal/per_thread_sem_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::synchronization
+    absl::base
+    absl::strings
+    absl::time
+    gmock
+  TESTONLY
 )
 
+absl_cc_test(
+  NAME
+    per_thread_sem_test
+  SRCS
+    "internal/per_thread_sem_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::per_thread_sem_test_common
+    absl::synchronization
+    absl::base
+    absl::strings
+    absl::time
+    gmock_main
+)
 
-
-
-
-
-
+absl_cc_test(
+  NAME
+    lifetime_test
+  SRCS
+    "lifetime_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::synchronization
+    absl::base
+    absl::core_headers
+    Threads::Threads
+)
diff --git a/absl/synchronization/barrier.cc b/absl/synchronization/barrier.cc
index a1b3ad5..c2c539a 100644
--- a/absl/synchronization/barrier.cc
+++ b/absl/synchronization/barrier.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
diff --git a/absl/synchronization/barrier.h b/absl/synchronization/barrier.h
index f834fee..23bb2f5 100644
--- a/absl/synchronization/barrier.h
+++ b/absl/synchronization/barrier.h
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
diff --git a/absl/synchronization/barrier_test.cc b/absl/synchronization/barrier_test.cc
index d6cabab..bfc6cb1 100644
--- a/absl/synchronization/barrier_test.cc
+++ b/absl/synchronization/barrier_test.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
diff --git a/absl/synchronization/blocking_counter.cc b/absl/synchronization/blocking_counter.cc
index 7e68e96..481a06b 100644
--- a/absl/synchronization/blocking_counter.cc
+++ b/absl/synchronization/blocking_counter.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
diff --git a/absl/synchronization/blocking_counter.h b/absl/synchronization/blocking_counter.h
index 557ed02..4c66e0a 100644
--- a/absl/synchronization/blocking_counter.h
+++ b/absl/synchronization/blocking_counter.h
@@ -5,7 +5,7 @@
 // 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
+//      https://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,
diff --git a/absl/synchronization/blocking_counter_test.cc b/absl/synchronization/blocking_counter_test.cc
index e8223f8..c63e339 100644
--- a/absl/synchronization/blocking_counter_test.cc
+++ b/absl/synchronization/blocking_counter_test.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
diff --git a/absl/synchronization/internal/create_thread_identity.cc b/absl/synchronization/internal/create_thread_identity.cc
index e7a65cd..6e93605 100644
--- a/absl/synchronization/internal/create_thread_identity.cc
+++ b/absl/synchronization/internal/create_thread_identity.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -67,6 +67,30 @@
   return (addr + align - 1) & ~(align - 1);
 }
 
+static void ResetThreadIdentity(base_internal::ThreadIdentity* identity) {
+  base_internal::PerThreadSynch* pts = &identity->per_thread_synch;
+  pts->next = nullptr;
+  pts->skip = nullptr;
+  pts->may_skip = false;
+  pts->waitp = nullptr;
+  pts->suppress_fatal_errors = false;
+  pts->readers = 0;
+  pts->priority = 0;
+  pts->next_priority_read_cycles = 0;
+  pts->state.store(base_internal::PerThreadSynch::State::kAvailable,
+                   std::memory_order_relaxed);
+  pts->maybe_unlocking = false;
+  pts->wake = false;
+  pts->cond_waiter = false;
+  pts->all_locks = nullptr;
+  identity->waiter_state = {};
+  identity->blocked_count_ptr = nullptr;
+  identity->ticker.store(0, std::memory_order_relaxed);
+  identity->wait_start.store(0, std::memory_order_relaxed);
+  identity->is_idle.store(false, std::memory_order_relaxed);
+  identity->next = nullptr;
+}
+
 static base_internal::ThreadIdentity* NewThreadIdentity() {
   base_internal::ThreadIdentity* identity = nullptr;
 
@@ -90,7 +114,7 @@
         RoundUp(reinterpret_cast<intptr_t>(allocation),
                 base_internal::PerThreadSynch::kAlignment));
   }
-  memset(identity, 0, sizeof(*identity));
+  ResetThreadIdentity(identity);
 
   return identity;
 }
diff --git a/absl/synchronization/internal/create_thread_identity.h b/absl/synchronization/internal/create_thread_identity.h
index 1bb87de..ebb16c5 100644
--- a/absl/synchronization/internal/create_thread_identity.h
+++ b/absl/synchronization/internal/create_thread_identity.h
@@ -5,7 +5,7 @@
  * 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
+ *      https://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,
@@ -50,4 +50,5 @@
 
 }  // namespace synchronization_internal
 }  // namespace absl
+
 #endif  // ABSL_SYNCHRONIZATION_INTERNAL_CREATE_THREAD_IDENTITY_H_
diff --git a/absl/synchronization/internal/graphcycles.cc b/absl/synchronization/internal/graphcycles.cc
index d3878de..0c8c756 100644
--- a/absl/synchronization/internal/graphcycles.cc
+++ b/absl/synchronization/internal/graphcycles.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
diff --git a/absl/synchronization/internal/graphcycles.h b/absl/synchronization/internal/graphcycles.h
index 2e6686a..e5bde00 100644
--- a/absl/synchronization/internal/graphcycles.h
+++ b/absl/synchronization/internal/graphcycles.h
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
diff --git a/absl/synchronization/internal/graphcycles_benchmark.cc b/absl/synchronization/internal/graphcycles_benchmark.cc
index a239c25..54823e0 100644
--- a/absl/synchronization/internal/graphcycles_benchmark.cc
+++ b/absl/synchronization/internal/graphcycles_benchmark.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
diff --git a/absl/synchronization/internal/graphcycles_test.cc b/absl/synchronization/internal/graphcycles_test.cc
index 9a85b39..58e8477 100644
--- a/absl/synchronization/internal/graphcycles_test.cc
+++ b/absl/synchronization/internal/graphcycles_test.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
diff --git a/absl/synchronization/internal/kernel_timeout.h b/absl/synchronization/internal/kernel_timeout.h
index bb70800..61c72e7 100644
--- a/absl/synchronization/internal/kernel_timeout.h
+++ b/absl/synchronization/internal/kernel_timeout.h
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -53,6 +53,7 @@
 
   // We explicitly do not support other custom formats: timespec, int64_t nanos.
   // Unify on this and absl::Time, please.
+
   bool has_timeout() const { return ns_ != 0; }
 
  private:
@@ -76,7 +77,7 @@
     if (x <= 0) x = 1;
     // A time larger than what can be represented to the kernel is treated
     // as no timeout.
-    if (x == std::numeric_limits<int64_t>::max()) x = 0;
+    if (x == (std::numeric_limits<int64_t>::max)()) x = 0;
     return x;
   }
 
@@ -90,7 +91,7 @@
           ERROR,
           "Tried to create a timespec from a non-timeout; never do this.");
       // But we'll try to continue sanely.  no-timeout ~= saturated timeout.
-      n = std::numeric_limits<int64_t>::max();
+      n = (std::numeric_limits<int64_t>::max)();
     }
 
     // Kernel APIs validate timespecs as being at or after the epoch,
@@ -100,8 +101,8 @@
     if (n < 0) n = 0;
 
     struct timespec abstime;
-    int64_t seconds = std::min(n / kNanosPerSecond,
-                             int64_t{std::numeric_limits<time_t>::max()});
+    int64_t seconds = (std::min)(n / kNanosPerSecond,
+                               int64_t{(std::numeric_limits<time_t>::max)()});
     abstime.tv_sec = static_cast<time_t>(seconds);
     abstime.tv_nsec =
         static_cast<decltype(abstime.tv_nsec)>(n % kNanosPerSecond);
@@ -119,7 +120,7 @@
   // <intsafe.h> and <WinBase.h>.
   typedef unsigned long DWord;  // NOLINT
   DWord InMillisecondsFromNow() const {
-    constexpr DWord kInfinite = std::numeric_limits<DWord>::max();
+    constexpr DWord kInfinite = (std::numeric_limits<DWord>::max)();
     if (!has_timeout()) {
       return kInfinite;
     }
@@ -130,7 +131,7 @@
     if (ns_ >= now) {
       // Round up so that Now() + ms_from_now >= ns_.
       constexpr uint64_t max_nanos =
-          std::numeric_limits<int64_t>::max() - 999999u;
+          (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 > kInfinite) {
@@ -148,4 +149,5 @@
 
 }  // namespace synchronization_internal
 }  // namespace absl
+
 #endif  // ABSL_SYNCHRONIZATION_INTERNAL_KERNEL_TIMEOUT_H_
diff --git a/absl/synchronization/internal/mutex_nonprod.cc b/absl/synchronization/internal/mutex_nonprod.cc
index 45c6032..267deaf 100644
--- a/absl/synchronization/internal/mutex_nonprod.cc
+++ b/absl/synchronization/internal/mutex_nonprod.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
diff --git a/absl/synchronization/internal/mutex_nonprod.inc b/absl/synchronization/internal/mutex_nonprod.inc
index 0aab3d1..b8d5af7 100644
--- a/absl/synchronization/internal/mutex_nonprod.inc
+++ b/absl/synchronization/internal/mutex_nonprod.inc
@@ -214,6 +214,9 @@
   // stack) should use this constructor.
   explicit SynchronizationStorage(base_internal::LinkerInitialized) {}
 
+  constexpr explicit SynchronizationStorage(absl::ConstInitType)
+      : is_dynamic_(false), once_(), space_{{0}} {}
+
   SynchronizationStorage(SynchronizationStorage&) = delete;
   SynchronizationStorage& operator=(SynchronizationStorage&) = delete;
 
diff --git a/absl/synchronization/internal/per_thread_sem.cc b/absl/synchronization/internal/per_thread_sem.cc
index caa2baf..b7014fb 100644
--- a/absl/synchronization/internal/per_thread_sem.cc
+++ b/absl/synchronization/internal/per_thread_sem.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -89,6 +89,7 @@
   if (identity->blocked_count_ptr != nullptr) {
     identity->blocked_count_ptr->fetch_sub(1, std::memory_order_relaxed);
   }
+
   identity->is_idle.store(false, std::memory_order_relaxed);
   identity->wait_start.store(0, std::memory_order_relaxed);
   return !timeout;
diff --git a/absl/synchronization/internal/per_thread_sem.h b/absl/synchronization/internal/per_thread_sem.h
index 678b69e..e7da070 100644
--- a/absl/synchronization/internal/per_thread_sem.h
+++ b/absl/synchronization/internal/per_thread_sem.h
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -104,4 +104,5 @@
     absl::synchronization_internal::KernelTimeout t) {
   return AbslInternalPerThreadSemWait(t);
 }
+
 #endif  // ABSL_SYNCHRONIZATION_INTERNAL_PER_THREAD_SEM_H_
diff --git a/absl/synchronization/internal/per_thread_sem_test.cc b/absl/synchronization/internal/per_thread_sem_test.cc
index c29d840..dba7239 100644
--- a/absl/synchronization/internal/per_thread_sem_test.cc
+++ b/absl/synchronization/internal/per_thread_sem_test.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -114,10 +114,9 @@
       min_cycles = std::min(min_cycles, cycles);
       total_cycles += cycles;
     }
-    std::string out =
-        StrCat(msg, "min cycle count=", min_cycles, " avg cycle count=",
-               absl::SixDigits(static_cast<double>(total_cycles) /
-                               kNumIterations));
+    std::string out = StrCat(
+        msg, "min cycle count=", min_cycles, " avg cycle count=",
+        absl::SixDigits(static_cast<double>(total_cycles) / kNumIterations));
     printf("%s\n", out.c_str());
 
     partner_thread.join();
@@ -152,12 +151,16 @@
 }
 
 TEST_F(PerThreadSemTest, Timeouts) {
-  absl::Time timeout = absl::Now() + absl::Milliseconds(50);
+  const absl::Duration delay = absl::Milliseconds(50);
+  const absl::Time start = absl::Now();
+  EXPECT_FALSE(Wait(start + delay));
+  const absl::Duration elapsed = absl::Now() - start;
   // Allow for a slight early return, to account for quality of implementation
   // issues on various platforms.
   const absl::Duration slop = absl::Microseconds(200);
-  EXPECT_FALSE(Wait(timeout));
-  EXPECT_LE(timeout, absl::Now() + slop);
+  EXPECT_LE(delay - slop, elapsed)
+      << "Wait returned " << delay - elapsed
+      << " early (with " << slop << " slop), start time was " << start;
 
   absl::Time negative_timeout = absl::UnixEpoch() - absl::Milliseconds(100);
   EXPECT_FALSE(Wait(negative_timeout));
diff --git a/absl/synchronization/internal/thread_pool.h b/absl/synchronization/internal/thread_pool.h
index 8464042..7f458f5 100644
--- a/absl/synchronization/internal/thread_pool.h
+++ b/absl/synchronization/internal/thread_pool.h
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -16,6 +16,7 @@
 #define ABSL_SYNCHRONIZATION_INTERNAL_THREAD_POOL_H_
 
 #include <cassert>
+#include <cstddef>
 #include <functional>
 #include <queue>
 #include <thread>  // NOLINT(build/c++11)
@@ -42,7 +43,7 @@
   ~ThreadPool() {
     {
       absl::MutexLock l(&mu_);
-      for (int i = 0; i < threads_.size(); ++i) {
+      for (size_t i = 0; i < threads_.size(); i++) {
         queue_.push(nullptr);  // Shutdown signal.
       }
     }
diff --git a/absl/synchronization/internal/waiter.cc b/absl/synchronization/internal/waiter.cc
index 768c520..74b0965 100644
--- a/absl/synchronization/internal/waiter.cc
+++ b/absl/synchronization/internal/waiter.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -40,6 +40,7 @@
 #include <atomic>
 #include <cassert>
 #include <cstdint>
+
 #include "absl/base/internal/raw_logging.h"
 #include "absl/base/internal/thread_identity.h"
 #include "absl/base/optimization.h"
@@ -81,6 +82,7 @@
 #define FUTEX_BITSET_MATCH_ANY 0xFFFFFFFF
 #endif
 #endif
+
 class Futex {
  public:
   static int WaitUntil(std::atomic<int32_t> *v, int32_t val,
diff --git a/absl/synchronization/internal/waiter.h b/absl/synchronization/internal/waiter.h
index 23166f4..66b4beb 100644
--- a/absl/synchronization/internal/waiter.h
+++ b/absl/synchronization/internal/waiter.h
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
diff --git a/absl/synchronization/lifetime_test.cc b/absl/synchronization/lifetime_test.cc
index 90c9009..0279c8f 100644
--- a/absl/synchronization/lifetime_test.cc
+++ b/absl/synchronization/lifetime_test.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -17,6 +17,7 @@
 #include <type_traits>
 
 #include "absl/base/attributes.h"
+#include "absl/base/const_init.h"
 #include "absl/base/internal/raw_logging.h"
 #include "absl/base/thread_annotations.h"
 #include "absl/synchronization/mutex.h"
@@ -72,23 +73,19 @@
 // Launch thread 1 and thread 2, and block on their completion.
 // If any of 'mutex', 'condvar', or 'notification' is nullptr, use a locally
 // constructed instance instead.
-void RunTests(absl::Mutex* mutex, absl::CondVar* condvar,
-              absl::Notification* notification) {
+void RunTests(absl::Mutex* mutex, absl::CondVar* condvar) {
   absl::Mutex default_mutex;
   absl::CondVar default_condvar;
-  absl::Notification default_notification;
+  absl::Notification notification;
   if (!mutex) {
     mutex = &default_mutex;
   }
   if (!condvar) {
     condvar = &default_condvar;
   }
-  if (!notification) {
-    notification = &default_notification;
-  }
   bool state = false;
-  std::thread thread_one(ThreadOne, mutex, condvar, notification, &state);
-  std::thread thread_two(ThreadTwo, mutex, condvar, notification, &state);
+  std::thread thread_one(ThreadOne, mutex, condvar, &notification, &state);
+  std::thread thread_two(ThreadTwo, mutex, condvar, &notification, &state);
   thread_one.join();
   thread_two.join();
 }
@@ -96,10 +93,13 @@
 void TestLocals() {
   absl::Mutex mutex;
   absl::CondVar condvar;
-  absl::Notification notification;
-  RunTests(&mutex, &condvar, &notification);
+  RunTests(&mutex, &condvar);
 }
 
+// Normal kConstInit usage
+ABSL_CONST_INIT absl::Mutex const_init_mutex(absl::kConstInit);
+void TestConstInitGlobal() { RunTests(&const_init_mutex, nullptr); }
+
 // Global variables during start and termination
 //
 // In a translation unit, static storage duration variables are initialized in
@@ -122,10 +122,53 @@
   Function fn_;
 };
 
+// kConstInit
+// Test early usage.  (Declaration comes first; definitions must appear after
+// the test runner.)
+extern absl::Mutex early_const_init_mutex;
+// (Normally I'd write this +[], to make the cast-to-function-pointer explicit,
+// but in some MSVC setups we support, lambdas provide conversion operators to
+// different flavors of function pointers, making this trick ambiguous.)
+OnConstruction test_early_const_init([] {
+  RunTests(&early_const_init_mutex, nullptr);
+});
+// This definition appears before test_early_const_init, but it should be
+// initialized first (due to constant initialization).  Test that the object
+// actually works when constructed this way.
+ABSL_CONST_INIT absl::Mutex early_const_init_mutex(absl::kConstInit);
+
+// Furthermore, test that the const-init c'tor doesn't stomp over the state of
+// a Mutex.  Really, this is a test that the platform under test correctly
+// supports C++11 constant initialization.  (The constant-initialization
+// constructors of globals "happen at link time"; memory is pre-initialized,
+// before the constructors of either grab_lock or check_still_locked are run.)
+extern absl::Mutex const_init_sanity_mutex;
+OnConstruction grab_lock([]() NO_THREAD_SAFETY_ANALYSIS {
+  const_init_sanity_mutex.Lock();
+});
+ABSL_CONST_INIT absl::Mutex const_init_sanity_mutex(absl::kConstInit);
+OnConstruction check_still_locked([]() NO_THREAD_SAFETY_ANALYSIS {
+  const_init_sanity_mutex.AssertHeld();
+  const_init_sanity_mutex.Unlock();
+});
+
+// Test shutdown usage.  (Declarations come first; definitions must appear after
+// the test runner.)
+extern absl::Mutex late_const_init_mutex;
+// OnDestruction is being used here as a global variable, even though it has a
+// non-trivial destructor.  This is against the style guide.  We're violating
+// that rule here to check that the exception we allow for kConstInit is safe.
+// NOLINTNEXTLINE
+OnDestruction test_late_const_init([] {
+  RunTests(&late_const_init_mutex, nullptr);
+});
+ABSL_CONST_INIT absl::Mutex late_const_init_mutex(absl::kConstInit);
+
 }  // namespace
 
 int main() {
   TestLocals();
+  TestConstInitGlobal();
   // Explicitly call exit(0) here, to make it clear that we intend for the
   // above global object destructors to run.
   std::exit(0);
diff --git a/absl/synchronization/mutex.cc b/absl/synchronization/mutex.cc
index 9d59a79..97c5919 100644
--- a/absl/synchronization/mutex.cc
+++ b/absl/synchronization/mutex.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -118,6 +118,10 @@
 
 }  // namespace
 
+static inline bool EvalConditionAnnotated(const Condition *cond, Mutex *mu,
+                                          bool locking, bool trylock,
+                                          bool read_lock);
+
 void RegisterMutexProfiler(void (*fn)(int64_t wait_timestamp)) {
   submit_profile_data.Store(fn);
 }
@@ -233,15 +237,14 @@
   SYNCH_EV_SIGNALALL,
 };
 
-enum {                 // Event flags
-  SYNCH_F_R = 0x01,    // reader event
-  SYNCH_F_LCK = 0x02,  // PostSynchEvent called with mutex held
-  SYNCH_F_ACQ = 0x04,  // event is an acquire
+enum {                    // Event flags
+  SYNCH_F_R = 0x01,       // reader event
+  SYNCH_F_LCK = 0x02,     // PostSynchEvent called with mutex held
+  SYNCH_F_TRY = 0x04,     // TryLock or ReaderTryLock
+  SYNCH_F_UNLOCK = 0x08,  // Unlock or ReaderUnlock
 
   SYNCH_F_LCK_W = SYNCH_F_LCK,
   SYNCH_F_LCK_R = SYNCH_F_LCK | SYNCH_F_R,
-  SYNCH_F_ACQ_W = SYNCH_F_ACQ,
-  SYNCH_F_ACQ_R = SYNCH_F_ACQ | SYNCH_F_R,
 };
 }  // anonymous namespace
 
@@ -250,21 +253,22 @@
   int flags;
   const char *msg;
 } event_properties[] = {
-  { SYNCH_F_LCK_W|SYNCH_F_ACQ_W, "TryLock succeeded " },
-  { 0,                           "TryLock failed " },
-  { SYNCH_F_LCK_R|SYNCH_F_ACQ_R, "ReaderTryLock succeeded " },
-  { 0,                           "ReaderTryLock failed " },
-  {               SYNCH_F_ACQ_W, "Lock blocking " },
-  { SYNCH_F_LCK_W,               "Lock returning " },
-  {               SYNCH_F_ACQ_R, "ReaderLock blocking " },
-  { SYNCH_F_LCK_R,               "ReaderLock returning " },
-  { SYNCH_F_LCK_W,               "Unlock " },
-  { SYNCH_F_LCK_R,               "ReaderUnlock " },
-  { 0,                           "Wait on " },
-  { 0,                           "Wait unblocked " },
-  { 0,                           "Signal on " },
-  { 0,                           "SignalAll on " },
+    {SYNCH_F_LCK_W | SYNCH_F_TRY, "TryLock succeeded "},
+    {0, "TryLock failed "},
+    {SYNCH_F_LCK_R | SYNCH_F_TRY, "ReaderTryLock succeeded "},
+    {0, "ReaderTryLock failed "},
+    {0, "Lock blocking "},
+    {SYNCH_F_LCK_W, "Lock returning "},
+    {0, "ReaderLock blocking "},
+    {SYNCH_F_LCK_R, "ReaderLock returning "},
+    {SYNCH_F_LCK_W | SYNCH_F_UNLOCK, "Unlock "},
+    {SYNCH_F_LCK_R | SYNCH_F_UNLOCK, "ReaderUnlock "},
+    {0, "Wait on "},
+    {0, "Wait unblocked "},
+    {0, "Signal on "},
+    {0, "SignalAll on "},
 };
+
 static absl::base_internal::SpinLock synch_event_mu(
     absl::base_internal::kLinkerInitialized);
 // protects synch_event
@@ -414,9 +418,26 @@
     ABSL_RAW_LOG(INFO, "%s%p %s %s", event_properties[ev].msg, obj,
                  (e == nullptr ? "" : e->name), buffer);
   }
-  if ((event_properties[ev].flags & SYNCH_F_LCK) != 0 && e != nullptr &&
-      e->invariant != nullptr) {
-    (*e->invariant)(e->arg);
+  const int flags = event_properties[ev].flags;
+  if ((flags & SYNCH_F_LCK) != 0 && e != nullptr && e->invariant != nullptr) {
+    // Calling the invariant as is causes problems under ThreadSanitizer.
+    // We are currently inside of Mutex Lock/Unlock and are ignoring all
+    // memory accesses and synchronization. If the invariant transitively
+    // synchronizes something else and we ignore the synchronization, we will
+    // get false positive race reports later.
+    // Reuse EvalConditionAnnotated to properly call into user code.
+    struct local {
+      static bool pred(SynchEvent *ev) {
+        (*ev->invariant)(ev->arg);
+        return false;
+      }
+    };
+    Condition cond(&local::pred, e);
+    Mutex *mu = static_cast<Mutex *>(obj);
+    const bool locking = (flags & SYNCH_F_UNLOCK) == 0;
+    const bool trylock = (flags & SYNCH_F_TRY) != 0;
+    const bool read_lock = (flags & SYNCH_F_R) != 0;
+    EvalConditionAnnotated(&cond, mu, locking, trylock, read_lock);
   }
   UnrefSynchEvent(e);
 }
@@ -1079,7 +1100,7 @@
 // if the wait extends past the absolute time specified, even if "s" is still
 // on the mutex queue.  In this case, remove "s" from the queue and return
 // true, otherwise return false.
-void Mutex::Block(PerThreadSynch *s) {
+ABSL_XRAY_LOG_ARGS(1) void Mutex::Block(PerThreadSynch *s) {
   while (s->state.load(std::memory_order_acquire) == PerThreadSynch::kQueued) {
     if (!DecrementSynchSem(this, s, s->waitp->timeout)) {
       // After a timeout, we go into a spin loop until we remove ourselves
@@ -1552,7 +1573,7 @@
   ABSL_TSAN_MUTEX_PRE_LOCK(this, TsanFlags(how));
   this->LockSlowLoop(&waitp, flags);
   bool res = waitp.cond != nullptr ||  // => cond known true from LockSlowLoop
-             cond.Eval();
+             EvalConditionAnnotated(&cond, this, true, false, how == kShared);
   ABSL_TSAN_MUTEX_POST_LOCK(this, TsanFlags(how), 0);
   return res;
 }
@@ -1730,12 +1751,17 @@
 
 // Compute cond->Eval() and tell race detectors that we do it under mutex mu.
 static inline bool EvalConditionAnnotated(const Condition *cond, Mutex *mu,
-                                          bool locking, Mutex::MuHow how) {
+                                          bool locking, bool trylock,
+                                          bool read_lock) {
   // Delicate annotation dance.
   // We are currently inside of read/write lock/unlock operation.
   // All memory accesses are ignored inside of mutex operations + for unlock
   // operation tsan considers that we've already released the mutex.
   bool res = false;
+#ifdef THREAD_SANITIZER
+  const int flags = read_lock ? __tsan_mutex_read_lock : 0;
+  const int tryflags = flags | (trylock ? __tsan_mutex_try_lock : 0);
+#endif
   if (locking) {
     // For lock we pretend that we have finished the operation,
     // evaluate the predicate, then unlock the mutex and start locking it again
@@ -1743,24 +1769,26 @@
     // Note: we can't simply do POST_LOCK, Eval, PRE_LOCK, because then tsan
     // will think the lock acquisition is recursive which will trigger
     // deadlock detector.
-    ABSL_TSAN_MUTEX_POST_LOCK(mu, TsanFlags(how), 0);
+    ABSL_TSAN_MUTEX_POST_LOCK(mu, tryflags, 0);
     res = cond->Eval();
-    ABSL_TSAN_MUTEX_PRE_UNLOCK(mu, TsanFlags(how));
-    ABSL_TSAN_MUTEX_POST_UNLOCK(mu, TsanFlags(how));
-    ABSL_TSAN_MUTEX_PRE_LOCK(mu, TsanFlags(how));
+    // There is no "try" version of Unlock, so use flags instead of tryflags.
+    ABSL_TSAN_MUTEX_PRE_UNLOCK(mu, flags);
+    ABSL_TSAN_MUTEX_POST_UNLOCK(mu, flags);
+    ABSL_TSAN_MUTEX_PRE_LOCK(mu, tryflags);
   } else {
     // Similarly, for unlock we pretend that we have unlocked the mutex,
     // lock the mutex, evaluate the predicate, and start unlocking it again
     // to match the annotation at the end of outer unlock operation.
-    ABSL_TSAN_MUTEX_POST_UNLOCK(mu, TsanFlags(how));
-    ABSL_TSAN_MUTEX_PRE_LOCK(mu, TsanFlags(how));
-    ABSL_TSAN_MUTEX_POST_LOCK(mu, TsanFlags(how), 0);
+    ABSL_TSAN_MUTEX_POST_UNLOCK(mu, flags);
+    ABSL_TSAN_MUTEX_PRE_LOCK(mu, flags);
+    ABSL_TSAN_MUTEX_POST_LOCK(mu, flags, 0);
     res = cond->Eval();
-    ABSL_TSAN_MUTEX_PRE_UNLOCK(mu, TsanFlags(how));
+    ABSL_TSAN_MUTEX_PRE_UNLOCK(mu, flags);
   }
   // Prevent unused param warnings in non-TSAN builds.
   static_cast<void>(mu);
-  static_cast<void>(how);
+  static_cast<void>(trylock);
+  static_cast<void>(read_lock);
   return res;
 }
 
@@ -1806,7 +1834,8 @@
           v, (how->fast_or | (v & zap_desig_waker[flags & kMuHasBlocked])) +
                  how->fast_add,
           std::memory_order_acquire, std::memory_order_relaxed)) {
-    if (cond == nullptr || EvalConditionAnnotated(cond, this, true, how)) {
+    if (cond == nullptr ||
+        EvalConditionAnnotated(cond, this, true, false, how == kShared)) {
       return true;
     }
     unlock = true;
@@ -1824,7 +1853,8 @@
   }
   this->LockSlowLoop(&waitp, flags);
   return waitp.cond != nullptr ||  // => cond known true from LockSlowLoop
-         cond == nullptr || EvalConditionAnnotated(cond, this, true, how);
+         cond == nullptr ||
+         EvalConditionAnnotated(cond, this, true, false, how == kShared);
 }
 
 // RAW_CHECK_FMT() takes a condition, a printf-style format string, and
@@ -1841,7 +1871,7 @@
   // Test for either of two situations that should not occur in v:
   //   kMuWriter and kMuReader
   //   kMuWrWait and !kMuWait
-  const intptr_t w = v ^ kMuWait;
+  const uintptr_t w = v ^ kMuWait;
   // By flipping that bit, we can now test for:
   //   kMuWriter and kMuReader in w
   //   kMuWrWait and kMuWait in w
@@ -1880,7 +1910,8 @@
                      waitp->how->fast_add,
               std::memory_order_acquire, std::memory_order_relaxed)) {
         if (waitp->cond == nullptr ||
-            EvalConditionAnnotated(waitp->cond, this, true, waitp->how)) {
+            EvalConditionAnnotated(waitp->cond, this, true, false,
+                                   waitp->how == kShared)) {
           break;  // we timed out, or condition true, so return
         }
         this->UnlockSlow(waitp);  // got lock but condition false
@@ -1923,7 +1954,8 @@
                                               std::memory_order_release,
                                               std::memory_order_relaxed));
           if (waitp->cond == nullptr ||
-              EvalConditionAnnotated(waitp->cond, this, true, waitp->how)) {
+              EvalConditionAnnotated(waitp->cond, this, true, false,
+                                     waitp->how == kShared)) {
             break;  // we timed out, or condition true, so return
           }
           this->UnlockSlow(waitp);           // got lock but condition false
diff --git a/absl/synchronization/mutex.h b/absl/synchronization/mutex.h
index a378190..c38e356 100644
--- a/absl/synchronization/mutex.h
+++ b/absl/synchronization/mutex.h
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -61,6 +61,7 @@
 #include <cstdint>
 #include <string>
 
+#include "absl/base/const_init.h"
 #include "absl/base/internal/identity.h"
 #include "absl/base/internal/low_level_alloc.h"
 #include "absl/base/internal/thread_identity.h"
@@ -136,7 +137,27 @@
 
 class LOCKABLE Mutex {
  public:
+  // Creates a `Mutex` that is not held by anyone. This constructor is
+  // typically used for Mutexes allocated on the heap or the stack.
+  //
+  // To create `Mutex` instances with static storage duration
+  // (e.g. a namespace-scoped or global variable), see
+  // `Mutex::Mutex(absl::kConstInit)` below instead.
   Mutex();
+
+  // Creates a mutex with static storage duration.  A global variable
+  // constructed this way avoids the lifetime issues that can occur on program
+  // startup and shutdown.  (See absl/base/const_init.h.)
+  //
+  // For Mutexes allocated on the heap and stack, instead use the default
+  // constructor, which can interact more fully with the thread sanitizer.
+  //
+  // Example usage:
+  //   namespace foo {
+  //   ABSL_CONST_INIT Mutex mu(absl::kConstInit);
+  //   }
+  explicit constexpr Mutex(absl::ConstInitType);
+
   ~Mutex();
 
   // Mutex::Lock()
@@ -584,7 +605,7 @@
 // -----------------------------------------------------------------------------
 //
 // As noted above, `Mutex` contains a number of member functions which take a
-// `Condition` as a argument; clients can wait for conditions to become `true`
+// `Condition` as an argument; clients can wait for conditions to become `true`
 // before attempting to acquire the mutex. These sections are known as
 // "condition critical" sections. To use a `Condition`, you simply need to
 // construct it, and use within an appropriate `Mutex` member function;
@@ -879,11 +900,15 @@
 };
 
 #ifdef ABSL_INTERNAL_USE_NONPROD_MUTEX
+inline constexpr Mutex::Mutex(absl::ConstInitType) : impl_(absl::kConstInit) {}
+
 #else
 inline Mutex::Mutex() : mu_(0) {
   ABSL_TSAN_MUTEX_CREATE(this, __tsan_mutex_not_static);
 }
 
+inline constexpr Mutex::Mutex(absl::ConstInitType) : mu_(0) {}
+
 inline CondVar::CondVar() : cv_(0) {}
 #endif
 
@@ -1025,4 +1050,5 @@
 extern "C" {
 void AbslInternalMutexYield();
 }  // extern "C"
+
 #endif  // ABSL_SYNCHRONIZATION_MUTEX_H_
diff --git a/absl/synchronization/mutex_benchmark.cc b/absl/synchronization/mutex_benchmark.cc
index 1e019e0..ab18800 100644
--- a/absl/synchronization/mutex_benchmark.cc
+++ b/absl/synchronization/mutex_benchmark.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -12,16 +12,154 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+#include <cstdint>
+#include <mutex>  // NOLINT(build/c++11)
 #include <vector>
 
-#include "benchmark/benchmark.h"
-#include "absl/base/internal/sysinfo.h"
+#include "absl/base/internal/cycleclock.h"
+#include "absl/base/internal/spinlock.h"
 #include "absl/synchronization/blocking_counter.h"
 #include "absl/synchronization/internal/thread_pool.h"
 #include "absl/synchronization/mutex.h"
+#include "benchmark/benchmark.h"
 
 namespace {
 
+void BM_Mutex(benchmark::State& state) {
+  static absl::Mutex* mu = new absl::Mutex;
+  for (auto _ : state) {
+    absl::MutexLock lock(mu);
+  }
+}
+BENCHMARK(BM_Mutex)->UseRealTime()->Threads(1)->ThreadPerCpu();
+
+static void DelayNs(int64_t ns, int* data) {
+  int64_t end = absl::base_internal::CycleClock::Now() +
+                ns * absl::base_internal::CycleClock::Frequency() / 1e9;
+  while (absl::base_internal::CycleClock::Now() < end) {
+    ++(*data);
+    benchmark::DoNotOptimize(*data);
+  }
+}
+
+template <typename MutexType>
+class RaiiLocker {
+ public:
+  explicit RaiiLocker(MutexType* mu) : mu_(mu) { mu_->Lock(); }
+  ~RaiiLocker() { mu_->Unlock(); }
+ private:
+  MutexType* mu_;
+};
+
+template <>
+class RaiiLocker<std::mutex> {
+ public:
+  explicit RaiiLocker(std::mutex* mu) : mu_(mu) { mu_->lock(); }
+  ~RaiiLocker() { mu_->unlock(); }
+ private:
+  std::mutex* mu_;
+};
+
+template <typename MutexType>
+void BM_Contended(benchmark::State& state) {
+  struct Shared {
+    MutexType mu;
+    int data = 0;
+  };
+  static auto* shared = new Shared;
+  int local = 0;
+  for (auto _ : state) {
+    // Here we model both local work outside of the critical section as well as
+    // some work inside of the critical section. The idea is to capture some
+    // more or less realisitic contention levels.
+    // If contention is too low, the benchmark won't measure anything useful.
+    // If contention is unrealistically high, the benchmark will favor
+    // bad mutex implementations that block and otherwise distract threads
+    // from the mutex and shared state for as much as possible.
+    // To achieve this amount of local work is multiplied by number of threads
+    // to keep ratio between local work and critical section approximately
+    // equal regardless of number of threads.
+    DelayNs(100 * state.threads, &local);
+    RaiiLocker<MutexType> locker(&shared->mu);
+    DelayNs(state.range(0), &shared->data);
+  }
+}
+
+BENCHMARK_TEMPLATE(BM_Contended, absl::Mutex)
+    ->UseRealTime()
+    // ThreadPerCpu poorly handles non-power-of-two CPU counts.
+    ->Threads(1)
+    ->Threads(2)
+    ->Threads(4)
+    ->Threads(6)
+    ->Threads(8)
+    ->Threads(12)
+    ->Threads(16)
+    ->Threads(24)
+    ->Threads(32)
+    ->Threads(48)
+    ->Threads(64)
+    ->Threads(96)
+    ->Threads(128)
+    ->Threads(192)
+    ->Threads(256)
+    // Some empirically chosen amounts of work in critical section.
+    // 1 is low contention, 200 is high contention and few values in between.
+    ->Arg(1)
+    ->Arg(20)
+    ->Arg(50)
+    ->Arg(200);
+
+BENCHMARK_TEMPLATE(BM_Contended, absl::base_internal::SpinLock)
+    ->UseRealTime()
+    // ThreadPerCpu poorly handles non-power-of-two CPU counts.
+    ->Threads(1)
+    ->Threads(2)
+    ->Threads(4)
+    ->Threads(6)
+    ->Threads(8)
+    ->Threads(12)
+    ->Threads(16)
+    ->Threads(24)
+    ->Threads(32)
+    ->Threads(48)
+    ->Threads(64)
+    ->Threads(96)
+    ->Threads(128)
+    ->Threads(192)
+    ->Threads(256)
+    // Some empirically chosen amounts of work in critical section.
+    // 1 is low contention, 200 is high contention and few values in between.
+    ->Arg(1)
+    ->Arg(20)
+    ->Arg(50)
+    ->Arg(200);
+
+BENCHMARK_TEMPLATE(BM_Contended, std::mutex)
+    ->UseRealTime()
+    // ThreadPerCpu poorly handles non-power-of-two CPU counts.
+    ->Threads(1)
+    ->Threads(2)
+    ->Threads(4)
+    ->Threads(6)
+    ->Threads(8)
+    ->Threads(12)
+    ->Threads(16)
+    ->Threads(24)
+    ->Threads(32)
+    ->Threads(48)
+    ->Threads(64)
+    ->Threads(96)
+    ->Threads(128)
+    ->Threads(192)
+    ->Threads(256)
+    // Some empirically chosen amounts of work in critical section.
+    // 1 is low contention, 200 is high contention and few values in between.
+    ->Arg(1)
+    ->Arg(20)
+    ->Arg(50)
+    ->Arg(200);
+
 // Measure the overhead of conditions on mutex release (when they must be
 // evaluated).  Mutex has (some) support for equivalence classes allowing
 // Conditions with the same function/argument to potentially not be multiply
@@ -82,13 +220,4 @@
 #endif
 BENCHMARK(BM_ConditionWaiters)->RangePair(0, 2, 1, kMaxConditionWaiters);
 
-void BM_ContendedMutex(benchmark::State& state) {
-  static absl::Mutex* mu = new absl::Mutex;
-  for (auto _ : state) {
-    absl::MutexLock lock(mu);
-  }
-}
-BENCHMARK(BM_ContendedMutex)->Threads(1);
-BENCHMARK(BM_ContendedMutex)->ThreadPerCpu();
-
 }  // namespace
diff --git a/absl/synchronization/mutex_test.cc b/absl/synchronization/mutex_test.cc
index b2820e2..1021122 100644
--- a/absl/synchronization/mutex_test.cc
+++ b/absl/synchronization/mutex_test.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -610,9 +610,9 @@
   waiter2.reset();  // "join" waiter2
 }
 
-INSTANTIATE_TEST_CASE_P(CondVarWaitDeadlockTest, CondVarWaitDeadlock,
-                        ::testing::Range(0, 8),
-                        ::testing::PrintToStringParamName());
+INSTANTIATE_TEST_SUITE_P(CondVarWaitDeadlockTest, CondVarWaitDeadlock,
+                         ::testing::Range(0, 8),
+                         ::testing::PrintToStringParamName());
 
 // --------------------------------------------------------
 // Test for fix of bug in DequeueAllWakeable()
@@ -1032,9 +1032,9 @@
   ScopedDisableBazelTestWarnings() {
 #ifdef WIN32
     char file[MAX_PATH];
-    if (GetEnvironmentVariable(kVarName, file, sizeof(file)) < sizeof(file)) {
+    if (GetEnvironmentVariableA(kVarName, file, sizeof(file)) < sizeof(file)) {
       warnings_output_file_ = file;
-      SetEnvironmentVariable(kVarName, nullptr);
+      SetEnvironmentVariableA(kVarName, nullptr);
     }
 #else
     const char *file = getenv(kVarName);
@@ -1048,7 +1048,7 @@
   ~ScopedDisableBazelTestWarnings() {
     if (!warnings_output_file_.empty()) {
 #ifdef WIN32
-      SetEnvironmentVariable(kVarName, warnings_output_file_.c_str());
+      SetEnvironmentVariableA(kVarName, warnings_output_file_.c_str());
 #else
       setenv(kVarName, warnings_output_file_.c_str(), 0);
 #endif
@@ -1367,8 +1367,8 @@
 }
 
 // Instantiate `TimeoutTest` with `MakeTimeoutTestParamValues()`.
-INSTANTIATE_TEST_CASE_P(All, TimeoutTest,
-                        testing::ValuesIn(MakeTimeoutTestParamValues()));
+INSTANTIATE_TEST_SUITE_P(All, TimeoutTest,
+                         testing::ValuesIn(MakeTimeoutTestParamValues()));
 
 TEST_P(TimeoutTest, Await) {
   const TimeoutTestParam params = GetParam();
@@ -1548,9 +1548,9 @@
 class MutexVariableThreadCountTest : public ::testing::TestWithParam<int> {};
 
 // Instantiate the above with AllThreadCountOptions().
-INSTANTIATE_TEST_CASE_P(ThreadCounts, MutexVariableThreadCountTest,
-                        ::testing::ValuesIn(AllThreadCountValues()),
-                        ::testing::PrintToStringParamName());
+INSTANTIATE_TEST_SUITE_P(ThreadCounts, MutexVariableThreadCountTest,
+                         ::testing::ValuesIn(AllThreadCountValues()),
+                         ::testing::PrintToStringParamName());
 
 // Reduces iterations by some factor for slow platforms
 // (determined empirically).
diff --git a/absl/synchronization/notification.cc b/absl/synchronization/notification.cc
index ed8cc90..53ace00 100644
--- a/absl/synchronization/notification.cc
+++ b/absl/synchronization/notification.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -22,6 +22,7 @@
 #include "absl/time/time.h"
 
 namespace absl {
+
 void Notification::Notify() {
   MutexLock l(&this->mutex_);
 
diff --git a/absl/synchronization/notification.h b/absl/synchronization/notification.h
index 107932f..82d111a 100644
--- a/absl/synchronization/notification.h
+++ b/absl/synchronization/notification.h
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -52,6 +52,7 @@
 
 #include <atomic>
 
+#include "absl/base/macros.h"
 #include "absl/synchronization/mutex.h"
 #include "absl/time/time.h"
 
@@ -109,4 +110,5 @@
 };
 
 }  // namespace absl
+
 #endif  // ABSL_SYNCHRONIZATION_NOTIFICATION_H_
diff --git a/absl/synchronization/notification_test.cc b/absl/synchronization/notification_test.cc
index d8708d5..059d4cd 100644
--- a/absl/synchronization/notification_test.cc
+++ b/absl/synchronization/notification_test.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -72,12 +72,16 @@
   EXPECT_FALSE(notification->WaitForNotificationWithDeadline(absl::Now()));
 
   const absl::Duration delay = absl::Milliseconds(50);
+  const absl::Time start = absl::Now();
+  EXPECT_FALSE(notification->WaitForNotificationWithTimeout(delay));
+  const absl::Duration elapsed = absl::Now() - start;
+
   // Allow for a slight early return, to account for quality of implementation
   // issues on various platforms.
   const absl::Duration slop = absl::Microseconds(200);
-  absl::Time start = absl::Now();
-  EXPECT_FALSE(notification->WaitForNotificationWithTimeout(delay));
-  EXPECT_LE(start + delay, absl::Now() + slop);
+  EXPECT_LE(delay - slop, elapsed)
+      << "WaitForNotificationWithTimeout returned " << delay - elapsed
+      << " early (with " << slop << " slop), start time was " << start;
 
   ThreadSafeCounter ready_counter;
   ThreadSafeCounter done_counter;
diff --git a/absl/time/BUILD.bazel b/absl/time/BUILD.bazel
index c7c16d4..a94be65 100644
--- a/absl/time/BUILD.bazel
+++ b/absl/time/BUILD.bazel
@@ -5,7 +5,7 @@
 # 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
+#      https://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,
@@ -15,7 +15,7 @@
 #
 
 load(
-    "//absl:copts.bzl",
+    "//absl:copts/configure_copts.bzl",
     "ABSL_DEFAULT_COPTS",
     "ABSL_TEST_COPTS",
 )
@@ -27,6 +27,7 @@
 cc_library(
     name = "time",
     srcs = [
+        "civil_time.cc",
         "clock.cc",
         "duration.cc",
         "format.cc",
@@ -35,6 +36,7 @@
         "time.cc",
     ],
     hdrs = [
+        "civil_time.h",
         "clock.h",
         "time.h",
     ],
@@ -72,10 +74,10 @@
 cc_test(
     name = "time_test",
     srcs = [
+        "civil_time_test.cc",
         "clock_test.cc",
         "duration_test.cc",
         "format_test.cc",
-        "time_norm_test.cc",
         "time_test.cc",
         "time_zone_test.cc",
     ],
@@ -94,6 +96,7 @@
 cc_test(
     name = "time_benchmark",
     srcs = [
+        "civil_time_benchmark.cc",
         "clock_benchmark.cc",
         "duration_benchmark.cc",
         "format_benchmark.cc",
@@ -107,6 +110,8 @@
         ":test_util",
         ":time",
         "//absl/base",
+        "//absl/base:core_headers",
+        "//absl/hash",
         "@com_github_google_benchmark//:benchmark_main",
     ],
 )
diff --git a/absl/time/BUILD.gn b/absl/time/BUILD.gn
index 5758e9d..e3f9e1a 100644
--- a/absl/time/BUILD.gn
+++ b/absl/time/BUILD.gn
@@ -22,6 +22,7 @@
   ]
   public_configs = [ "//third_party/abseil-cpp:absl_include_config" ]
   sources = [
+    "civil_time.cc",
     "clock.cc",
     "duration.cc",
     "format.cc",
@@ -30,6 +31,7 @@
     "time.cc",
   ]
   public = [
+    "civil_time.h",
     "clock.h",
     "time.h",
   ]
diff --git a/absl/time/CMakeLists.txt b/absl/time/CMakeLists.txt
index 0627236..5909832 100644
--- a/absl/time/CMakeLists.txt
+++ b/absl/time/CMakeLists.txt
@@ -5,7 +5,7 @@
 # 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
+#      https://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,
@@ -14,83 +14,114 @@
 # limitations under the License.
 #
 
-list(APPEND TIME_PUBLIC_HEADERS
-  "clock.h"
-  "time.h"
-)
-
-
-list(APPEND TIME_INTERNAL_HEADERS
-  "internal/test_util.h"
-  "internal/cctz/include/cctz/civil_time.h"
-  "internal/cctz/include/cctz/civil_time_detail.h"
-  "internal/cctz/include/cctz/time_zone.h"
-  "internal/cctz/include/cctz/zone_info_source.h"
-)
-
-list(APPEND TIME_SRC
-  "time.cc"
+absl_cc_library(
+  NAME
+    time
+  HDRS
+    "civil_time.h"
+    "clock.h"
+    "time.h"
+  SRCS
+  "civil_time.cc"
   "clock.cc"
   "duration.cc"
   "format.cc"
+  "internal/get_current_time_chrono.inc"
+  "internal/get_current_time_posix.inc"
+  "time.cc"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::base
+    absl::core_headers
+    absl::int128
+    absl::strings
+    absl::civil_time
+    absl::time_zone
+  PUBLIC
+)
+
+absl_cc_library(
+  NAME
+    civil_time
+  HDRS
+    "internal/cctz/include/cctz/civil_time.h"
+    "internal/cctz/include/cctz/civil_time_detail.h"
+  SRCS
   "internal/cctz/src/civil_time_detail.cc"
-  "internal/cctz/src/time_zone_fixed.cc"
-  "internal/cctz/src/time_zone_fixed.h"
-  "internal/cctz/src/time_zone_format.cc"
-  "internal/cctz/src/time_zone_if.cc"
-  "internal/cctz/src/time_zone_if.h"
-  "internal/cctz/src/time_zone_impl.cc"
-  "internal/cctz/src/time_zone_impl.h"
-  "internal/cctz/src/time_zone_info.cc"
-  "internal/cctz/src/time_zone_info.h"
-  "internal/cctz/src/time_zone_libc.cc"
-  "internal/cctz/src/time_zone_libc.h"
-  "internal/cctz/src/time_zone_lookup.cc"
-  "internal/cctz/src/time_zone_posix.cc"
-  "internal/cctz/src/time_zone_posix.h"
-  "internal/cctz/src/tzfile.h"
-  "internal/cctz/src/zone_info_source.cc"
-  ${TIME_PUBLIC_HEADERS}
-  ${TIME_INTERNAL_HEADERS}
-)
-set(TIME_PUBLIC_LIBRARIES absl::base absl::stacktrace absl::int128 absl::strings)
-
-absl_library(
-  TARGET
-    absl_time
-  SOURCES
-    ${TIME_SRC}
-  PUBLIC_LIBRARIES
-    ${TIME_PUBLIC_LIBRARIES}
-  EXPORT_NAME
-    time
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
 )
 
+if(APPLE)
+  find_library(CoreFoundation CoreFoundation)
+endif()
 
-
-#
-## TESTS
-#
-
-# test time_test
-list(APPEND TIME_TEST_SRC
-  "time_test.cc"
-  "clock_test.cc"
-  "duration_test.cc"
-  "format_test.cc"
-  "time_norm_test.cc"
-  "time_test.cc"
-  "time_zone_test.cc"
-  "internal/test_util.cc"
+absl_cc_library(
+  NAME
+    time_zone
+  HDRS
+    "internal/cctz/include/cctz/time_zone.h"
+    "internal/cctz/include/cctz/zone_info_source.h"
+  SRCS
+    "internal/cctz/src/time_zone_fixed.cc"
+    "internal/cctz/src/time_zone_fixed.h"
+    "internal/cctz/src/time_zone_format.cc"
+    "internal/cctz/src/time_zone_if.cc"
+    "internal/cctz/src/time_zone_if.h"
+    "internal/cctz/src/time_zone_impl.cc"
+    "internal/cctz/src/time_zone_impl.h"
+    "internal/cctz/src/time_zone_info.cc"
+    "internal/cctz/src/time_zone_info.h"
+    "internal/cctz/src/time_zone_libc.cc"
+    "internal/cctz/src/time_zone_libc.h"
+    "internal/cctz/src/time_zone_lookup.cc"
+    "internal/cctz/src/time_zone_posix.cc"
+    "internal/cctz/src/time_zone_posix.h"
+    "internal/cctz/src/tzfile.h"
+    "internal/cctz/src/zone_info_source.cc"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    $<$<PLATFORM_ID:Darwin>:${CoreFoundation}>
 )
-set(TIME_TEST_PUBLIC_LIBRARIES absl::time)
 
-absl_test(
-  TARGET
+absl_cc_library(
+  NAME
+    test_util
+  HDRS
+    "internal/test_util.h"
+  SRCS
+    "internal/test_util.cc"
+    "internal/zoneinfo.inc"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::time
+    absl::base
+    absl::time_zone
+    gmock
+  TESTONLY
+)
+
+absl_cc_test(
+  NAME
     time_test
-  SOURCES
-    ${TIME_TEST_SRC}
-  PUBLIC_LIBRARIES
-    ${TIME_TEST_PUBLIC_LIBRARIES}
+  SRCS
+    "civil_time_test.cc"
+    "clock_test.cc"
+    "duration_test.cc"
+    "format_test.cc"
+    "time_test.cc"
+    "time_zone_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::test_util
+    absl::time
+    absl::base
+    absl::config
+    absl::core_headers
+    absl::time_zone
+    gmock_main
 )
-
diff --git a/absl/time/civil_time.cc b/absl/time/civil_time.cc
new file mode 100644
index 0000000..7527fc1
--- /dev/null
+++ b/absl/time/civil_time.cc
@@ -0,0 +1,83 @@
+// 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
+//
+//      https://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/time/civil_time.h"
+
+#include <cstdlib>
+#include <string>
+
+#include "absl/strings/str_cat.h"
+#include "absl/time/time.h"
+
+namespace absl {
+
+namespace {
+
+// Since a civil time has a larger year range than absl::Time (64-bit years vs
+// 64-bit seconds, respectively) we normalize years to roughly +/- 400 years
+// around the year 2400, which will produce an equivalent year in a range that
+// absl::Time can handle.
+inline civil_year_t NormalizeYear(civil_year_t year) {
+  return 2400 + year % 400;
+}
+
+// Formats the given CivilSecond according to the given format.
+std::string FormatYearAnd(string_view fmt, CivilSecond cs) {
+  const CivilSecond ncs(NormalizeYear(cs.year()), cs.month(), cs.day(),
+                        cs.hour(), cs.minute(), cs.second());
+  const TimeZone utc = UTCTimeZone();
+  // TODO(absl-team): Avoid conversion of fmt std::string.
+  return StrCat(cs.year(),
+                FormatTime(std::string(fmt), FromCivil(ncs, utc), utc));
+}
+
+}  // namespace
+
+std::string FormatCivilTime(CivilSecond c) {
+  return FormatYearAnd("-%m-%dT%H:%M:%S", c);
+}
+std::string FormatCivilTime(CivilMinute c) {
+  return FormatYearAnd("-%m-%dT%H:%M", c);
+}
+std::string FormatCivilTime(CivilHour c) {
+  return FormatYearAnd("-%m-%dT%H", c);
+}
+std::string FormatCivilTime(CivilDay c) { return FormatYearAnd("-%m-%d", c); }
+std::string FormatCivilTime(CivilMonth c) { return FormatYearAnd("-%m", c); }
+std::string FormatCivilTime(CivilYear c) { return FormatYearAnd("", c); }
+
+namespace time_internal {
+
+std::ostream& operator<<(std::ostream& os, CivilYear y) {
+  return os << FormatCivilTime(y);
+}
+std::ostream& operator<<(std::ostream& os, CivilMonth m) {
+  return os << FormatCivilTime(m);
+}
+std::ostream& operator<<(std::ostream& os, CivilDay d) {
+  return os << FormatCivilTime(d);
+}
+std::ostream& operator<<(std::ostream& os, CivilHour h) {
+  return os << FormatCivilTime(h);
+}
+std::ostream& operator<<(std::ostream& os, CivilMinute m) {
+  return os << FormatCivilTime(m);
+}
+std::ostream& operator<<(std::ostream& os, CivilSecond s) {
+  return os << FormatCivilTime(s);
+}
+
+}  // namespace time_internal
+
+}  // namespace absl
diff --git a/absl/time/civil_time.h b/absl/time/civil_time.h
new file mode 100644
index 0000000..2dfcbd2
--- /dev/null
+++ b/absl/time/civil_time.h
@@ -0,0 +1,485 @@
+// 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
+//
+//      https://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.
+//
+// -----------------------------------------------------------------------------
+// File: civil_time.h
+// -----------------------------------------------------------------------------
+//
+// This header file defines abstractions for computing with "civil time".
+// The term "civil time" refers to the legally recognized human-scale time
+// that is represented by the six fields `YYYY-MM-DD hh:mm:ss`. A "date"
+// is perhaps the most common example of a civil time (represented here as
+// an `absl::CivilDay`).
+//
+// Modern-day civil time follows the Gregorian Calendar and is a
+// time-zone-independent concept: a civil time of "2015-06-01 12:00:00", for
+// example, is not tied to a time zone. Put another way, a civil time does not
+// map to a unique point in time; a civil time must be mapped to an absolute
+// time *through* a time zone.
+//
+// Because a civil time is what most people think of as "time," it is common to
+// map absolute times to civil times to present to users.
+//
+// Time zones define the relationship between absolute and civil times. Given an
+// absolute or civil time and a time zone, you can compute the other time:
+//
+//   Civil Time = F(Absolute Time, Time Zone)
+//   Absolute Time = G(Civil Time, Time Zone)
+//
+// The Abseil time library allows you to construct such civil times from
+// absolute times; consult time.h for such functionality.
+//
+// This library provides six classes for constructing civil-time objects, and
+// provides several helper functions for rounding, iterating, and performing
+// arithmetic on civil-time objects, while avoiding complications like
+// daylight-saving time (DST):
+//
+//   * `absl::CivilSecond`
+//   * `absl::CivilMinute`
+//   * `absl::CivilHour`
+//   * `absl::CivilDay`
+//   * `absl::CivilMonth`
+//   * `absl::CivilYear`
+//
+// Example:
+//
+//   // Construct a civil-time object for a specific day
+//   const absl::CivilDay cd(1969, 07, 20);
+//
+//   // Construct a civil-time object for a specific second
+//   const absl::CivilSecond cd(2018, 8, 1, 12, 0, 1);
+//
+// Note: In C++14 and later, this library is usable in a constexpr context.
+//
+// Example:
+//
+//   // Valid in C++14
+//   constexpr absl::CivilDay cd(1969, 07, 20);
+
+#ifndef ABSL_TIME_CIVIL_TIME_H_
+#define ABSL_TIME_CIVIL_TIME_H_
+
+#include <string>
+
+#include "absl/strings/string_view.h"
+#include "absl/time/internal/cctz/include/cctz/civil_time.h"
+
+namespace absl {
+
+namespace time_internal {
+struct second_tag : cctz::detail::second_tag {};
+struct minute_tag : second_tag, cctz::detail::minute_tag {};
+struct hour_tag : minute_tag, cctz::detail::hour_tag {};
+struct day_tag : hour_tag, cctz::detail::day_tag {};
+struct month_tag : day_tag, cctz::detail::month_tag {};
+struct year_tag : month_tag, cctz::detail::year_tag {};
+}  // namespace time_internal
+
+// -----------------------------------------------------------------------------
+// CivilSecond, CivilMinute, CivilHour, CivilDay, CivilMonth, CivilYear
+// -----------------------------------------------------------------------------
+//
+// Each of these civil-time types is a simple value type with the same
+// interface for construction and the same six accessors for each of the civil
+// time fields (year, month, day, hour, minute, and second, aka YMDHMS). These
+// classes differ only in their alignment, which is indicated by the type name
+// and specifies the field on which arithmetic operates.
+//
+// CONSTRUCTION
+//
+// Each of the civil-time types can be constructed in two ways: by directly
+// passing to the constructor up to six integers representing the YMDHMS fields,
+// or by copying the YMDHMS fields from a differently aligned civil-time type.
+// Omitted fields are assigned their minimum valid value. Hours, minutes, and
+// seconds will be set to 0, month and day will be set to 1. Since there is no
+// minimum year, the default is 1970.
+//
+// Examples:
+//
+//   absl::CivilDay default_value;               // 1970-01-01 00:00:00
+//
+//   absl::CivilDay a(2015, 2, 3);               // 2015-02-03 00:00:00
+//   absl::CivilDay b(2015, 2, 3, 4, 5, 6);      // 2015-02-03 00:00:00
+//   absl::CivilDay c(2015);                     // 2015-01-01 00:00:00
+//
+//   absl::CivilSecond ss(2015, 2, 3, 4, 5, 6);  // 2015-02-03 04:05:06
+//   absl::CivilMinute mm(ss);                   // 2015-02-03 04:05:00
+//   absl::CivilHour hh(mm);                     // 2015-02-03 04:00:00
+//   absl::CivilDay d(hh);                       // 2015-02-03 00:00:00
+//   absl::CivilMonth m(d);                      // 2015-02-01 00:00:00
+//   absl::CivilYear y(m);                       // 2015-01-01 00:00:00
+//
+//   m = absl::CivilMonth(y);                    // 2015-01-01 00:00:00
+//   d = absl::CivilDay(m);                      // 2015-01-01 00:00:00
+//   hh = absl::CivilHour(d);                    // 2015-01-01 00:00:00
+//   mm = absl::CivilMinute(hh);                 // 2015-01-01 00:00:00
+//   ss = absl::CivilSecond(mm);                 // 2015-01-01 00:00:00
+//
+// Each civil-time class is aligned to the civil-time field indicated in the
+// class's name after normalization. Alignment is performed by setting all the
+// inferior fields to their minimum valid value (as described above). The
+// following are examples of how each of the six types would align the fields
+// representing November 22, 2015 at 12:34:56 in the afternoon. (Note: the
+// string format used here is not important; it's just a shorthand way of
+// showing the six YMDHMS fields.)
+//
+//   absl::CivilSecond   : 2015-11-22 12:34:56
+//   absl::CivilMinute   : 2015-11-22 12:34:00
+//   absl::CivilHour     : 2015-11-22 12:00:00
+//   absl::CivilDay      : 2015-11-22 00:00:00
+//   absl::CivilMonth    : 2015-11-01 00:00:00
+//   absl::CivilYear     : 2015-01-01 00:00:00
+//
+// Each civil-time type performs arithmetic on the field to which it is
+// aligned. This means that adding 1 to an absl::CivilDay increments the day
+// field (normalizing as necessary), and subtracting 7 from an absl::CivilMonth
+// operates on the month field (normalizing as necessary). All arithmetic
+// produces a valid civil time. Difference requires two similarly aligned
+// civil-time objects and returns the scalar answer in units of the objects'
+// alignment. For example, the difference between two absl::CivilHour objects
+// will give an answer in units of civil hours.
+//
+// ALIGNMENT CONVERSION
+//
+// The alignment of a civil-time object cannot change, but the object may be
+// used to construct a new object with a different alignment. This is referred
+// to as "realigning". When realigning to a type with the same or more
+// precision (e.g., absl::CivilDay -> absl::CivilSecond), the conversion may be
+// performed implicitly since no information is lost. However, if information
+// could be discarded (e.g., CivilSecond -> CivilDay), the conversion must
+// be explicit at the call site.
+//
+// Examples:
+//
+//   void UseDay(absl::CivilDay day);
+//
+//   absl::CivilSecond cs;
+//   UseDay(cs);                  // Won't compile because data may be discarded
+//   UseDay(absl::CivilDay(cs));  // OK: explicit conversion
+//
+//   absl::CivilDay cd;
+//   UseDay(cd);                  // OK: no conversion needed
+//
+//   absl::CivilMonth cm;
+//   UseDay(cm);                  // OK: implicit conversion to absl::CivilDay
+//
+// NORMALIZATION
+//
+// Normalization takes invalid values and adjusts them to produce valid values.
+// Within the civil-time library, integer arguments passed to the Civil*
+// constructors may be out-of-range, in which case they are normalized by
+// carrying overflow into a field of courser granularity to produce valid
+// civil-time objects. This normalization enables natural arithmetic on
+// constructor arguments without worrying about the field's range.
+//
+// Examples:
+//
+//   // Out-of-range; normalized to 2016-11-01
+//   absl::CivilDay d(2016, 10, 32);
+//   // Out-of-range, negative: normalized to 2016-10-30T23
+//   absl::CivilHour h1(2016, 10, 31, -1);
+//   // Normalization is cumulative: normalized to 2016-10-30T23
+//   absl::CivilHour h2(2016, 10, 32, -25);
+//
+// Note: If normalization is undesired, you can signal an error by comparing
+// the constructor arguments to the normalized values returned by the YMDHMS
+// properties.
+//
+// COMPARISON
+//
+// Comparison between civil-time objects considers all six YMDHMS fields,
+// regardless of the type's alignment. Comparison between differently aligned
+// civil-time types is allowed.
+//
+// Examples:
+//
+//   absl::CivilDay feb_3(2015, 2, 3);  // 2015-02-03 00:00:00
+//   absl::CivilDay mar_4(2015, 3, 4);  // 2015-03-04 00:00:00
+//   // feb_3 < mar_4
+//   // absl::CivilYear(feb_3) == absl::CivilYear(mar_4)
+//
+//   absl::CivilSecond feb_3_noon(2015, 2, 3, 12, 0, 0);  // 2015-02-03 12:00:00
+//   // feb_3 < feb_3_noon
+//   // feb_3 == absl::CivilDay(feb_3_noon)
+//
+//   // Iterates all the days of February 2015.
+//   for (absl::CivilDay d(2015, 2, 1); d < absl::CivilMonth(2015, 3); ++d) {
+//     // ...
+//   }
+//
+// ARITHMETIC
+//
+// Civil-time types support natural arithmetic operators such as addition,
+// subtraction, and difference. Arithmetic operates on the civil-time field
+// indicated in the type's name. Difference operators require arguments with
+// the same alignment and return the answer in units of the alignment.
+//
+// Example:
+//
+//   absl::CivilDay a(2015, 2, 3);
+//   ++a;                              // 2015-02-04 00:00:00
+//   --a;                              // 2015-02-03 00:00:00
+//   absl::CivilDay b = a + 1;         // 2015-02-04 00:00:00
+//   absl::CivilDay c = 1 + b;         // 2015-02-05 00:00:00
+//   int n = c - a;                    // n = 2 (civil days)
+//   int m = c - absl::CivilMonth(c);  // Won't compile: different types.
+//
+// ACCESSORS
+//
+// Each civil-time type has accessors for all six of the civil-time fields:
+// year, month, day, hour, minute, and second.
+//
+// civil_year_t year()
+// int          month()
+// int          day()
+// int          hour()
+// int          minute()
+// int          second()
+//
+// Recall that fields inferior to the type's aligment will be set to their
+// minimum valid value.
+//
+// Example:
+//
+//   absl::CivilDay d(2015, 6, 28);
+//   // d.year() == 2015
+//   // d.month() == 6
+//   // d.day() == 28
+//   // d.hour() == 0
+//   // d.minute() == 0
+//   // d.second() == 0
+//
+// CASE STUDY: Adding a month to January 31.
+//
+// One of the classic questions that arises when considering a civil time
+// library (or a date library or a date/time library) is this:
+//   "What is the result of adding a month to January 31?"
+// This is an interesting question because it is unclear what is meant by a
+// "month", and several different answers are possible, depending on context:
+//
+//   1. March 3 (or 2 if a leap year), if "add a month" means to add a month to
+//      the current month, and adjust the date to overflow the extra days into
+//      March. In this case the result of "February 31" would be normalized as
+//      within the civil-time library.
+//   2. February 28 (or 29 if a leap year), if "add a month" means to add a
+//      month, and adjust the date while holding the resulting month constant.
+//      In this case, the result of "February 31" would be truncated to the last
+//      day in February.
+//   3. An error. The caller may get some error, an exception, an invalid date
+//      object, or perhaps return `false`. This may make sense because there is
+//      no single unambiguously correct answer to the question.
+//
+// Practically speaking, any answer that is not what the programmer intended
+// is the wrong answer.
+//
+// The Abseil time library avoids this problem by making it impossible to
+// ask ambiguous questions. All civil-time objects are aligned to a particular
+// civil-field boundary (such as aligned to a year, month, day, hour, minute,
+// or second), and arithmetic operates on the field to which the object is
+// aligned. This means that in order to "add a month" the object must first be
+// aligned to a month boundary, which is equivalent to the first day of that
+// month.
+//
+// Of course, there are ways to compute an answer the question at hand using
+// this Abseil time library, but they require the programmer to be explicit
+// about the answer they expect. To illustrate, let's see how to compute all
+// three of the above possible answers to the question of "Jan 31 plus 1
+// month":
+//
+// Example:
+//
+//   const absl::CivilDay d(2015, 1, 31);
+//
+//   // Answer 1:
+//   // Add 1 to the month field in the constructor, and rely on normalization.
+//   const auto normalized = absl::CivilDay(d.year(), d.month() + 1, d.day());
+//   // normalized == 2015-03-03 (aka Feb 31)
+//
+//   // Answer 2:
+//   // Add 1 to month field, capping to the end of next month.
+//   const auto next_month = absl::CivilMonth(d) + 1;
+//   const auto last_day_of_next_month = absl::CivilDay(next_month + 1) - 1;
+//   const auto capped = std::min(normalized, last_day_of_next_month);
+//   // capped == 2015-02-28
+//
+//   // Answer 3:
+//   // Signal an error if the normalized answer is not in next month.
+//   if (absl::CivilMonth(normalized) != next_month) {
+//     // error, month overflow
+//   }
+//
+using CivilSecond =
+    time_internal::cctz::detail::civil_time<time_internal::second_tag>;
+using CivilMinute =
+    time_internal::cctz::detail::civil_time<time_internal::minute_tag>;
+using CivilHour =
+    time_internal::cctz::detail::civil_time<time_internal::hour_tag>;
+using CivilDay =
+    time_internal::cctz::detail::civil_time<time_internal::day_tag>;
+using CivilMonth =
+    time_internal::cctz::detail::civil_time<time_internal::month_tag>;
+using CivilYear =
+    time_internal::cctz::detail::civil_time<time_internal::year_tag>;
+
+// civil_year_t
+//
+// Type alias of a civil-time year value. This type is guaranteed to (at least)
+// support any year value supported by `time_t`.
+//
+// Example:
+//
+//   absl::CivilSecond cs = ...;
+//   absl::civil_year_t y = cs.year();
+//   cs = absl::CivilSecond(y, 1, 1, 0, 0, 0);  // CivilSecond(CivilYear(cs))
+//
+using civil_year_t = time_internal::cctz::year_t;
+
+// civil_diff_t
+//
+// Type alias of the difference between two civil-time values.
+// This type is used to indicate arguments that are not
+// normalized (such as parameters to the civil-time constructors), the results
+// of civil-time subtraction, or the operand to civil-time addition.
+//
+// Example:
+//
+//   absl::civil_diff_t n_sec = cs1 - cs2;             // cs1 == cs2 + n_sec;
+//
+using civil_diff_t = time_internal::cctz::diff_t;
+
+// Weekday::monday, Weekday::tuesday, Weekday::wednesday, Weekday::thursday,
+// Weekday::friday, Weekday::saturday, Weekday::sunday
+//
+// The Weekday enum class represents the civil-time concept of a "weekday" with
+// members for all days of the week.
+//
+//   absl::Weekday wd = absl::Weekday::thursday;
+//
+using Weekday = time_internal::cctz::weekday;
+
+// GetWeekday()
+//
+// Returns the absl::Weekday for the given absl::CivilDay.
+//
+// Example:
+//
+//   absl::CivilDay a(2015, 8, 13);
+//   absl::Weekday wd = absl::GetWeekday(a);  // wd == absl::Weekday::thursday
+//
+inline Weekday GetWeekday(CivilDay cd) {
+  return time_internal::cctz::get_weekday(cd);
+}
+
+// NextWeekday()
+// PrevWeekday()
+//
+// Returns the absl::CivilDay that strictly follows or precedes a given
+// absl::CivilDay, and that falls on the given absl::Weekday.
+//
+// Example, given the following month:
+//
+//       August 2015
+//   Su Mo Tu We Th Fr Sa
+//                      1
+//    2  3  4  5  6  7  8
+//    9 10 11 12 13 14 15
+//   16 17 18 19 20 21 22
+//   23 24 25 26 27 28 29
+//   30 31
+//
+//   absl::CivilDay a(2015, 8, 13);
+//   // absl::GetWeekday(a) == absl::Weekday::thursday
+//   absl::CivilDay b = absl::NextWeekday(a, absl::Weekday::thursday);
+//   // b = 2015-08-20
+//   absl::CivilDay c = absl::PrevWeekday(a, absl::Weekday::thursday);
+//   // c = 2015-08-06
+//
+//   absl::CivilDay d = ...
+//   // Gets the following Thursday if d is not already Thursday
+//   absl::CivilDay thurs1 = absl::PrevWeekday(d, absl::Weekday::thursday) + 7;
+//   // Gets the previous Thursday if d is not already Thursday
+//   absl::CivilDay thurs2 = absl::NextWeekday(d, absl::Weekday::thursday) - 7;
+//
+inline CivilDay NextWeekday(CivilDay cd, Weekday wd) {
+  return CivilDay(time_internal::cctz::next_weekday(cd, wd));
+}
+inline CivilDay PrevWeekday(CivilDay cd, Weekday wd) {
+  return CivilDay(time_internal::cctz::prev_weekday(cd, wd));
+}
+
+// GetYearDay()
+//
+// Returns the day-of-year for the given absl::CivilDay.
+//
+// Example:
+//
+//   absl::CivilDay a(2015, 1, 1);
+//   int yd_jan_1 = absl::GetYearDay(a);   // yd_jan_1 = 1
+//   absl::CivilDay b(2015, 12, 31);
+//   int yd_dec_31 = absl::GetYearDay(b);  // yd_dec_31 = 365
+//
+inline int GetYearDay(CivilDay cd) {
+  return time_internal::cctz::get_yearday(cd);
+}
+
+// FormatCivilTime()
+//
+// Formats the given civil-time value into a string value of the following
+// format:
+//
+//  Type        | Format
+//  ---------------------------------
+//  CivilSecond | YYYY-MM-DDTHH:MM:SS
+//  CivilMinute | YYYY-MM-DDTHH:MM
+//  CivilHour   | YYYY-MM-DDTHH
+//  CivilDay    | YYYY-MM-DD
+//  CivilMonth  | YYYY-MM
+//  CivilYear   | YYYY
+//
+// Example:
+//
+//   absl::CivilDay d = absl::CivilDay(1969, 7, 20);
+//   std::string day_string = absl::FormatCivilTime(d);  // "1969-07-20"
+//
+std::string FormatCivilTime(CivilSecond c);
+std::string FormatCivilTime(CivilMinute c);
+std::string FormatCivilTime(CivilHour c);
+std::string FormatCivilTime(CivilDay c);
+std::string FormatCivilTime(CivilMonth c);
+std::string FormatCivilTime(CivilYear c);
+
+namespace time_internal {  // For functions found via ADL on civil-time tags.
+
+// Streaming Operators
+//
+// Each civil-time type may be sent to an output stream using operator<<().
+// The result matches the string produced by `FormatCivilTime()`.
+//
+// Example:
+//
+//   absl::CivilDay d = absl::CivilDay("1969-07-20");
+//   std::cout << "Date is: " << d << "\n";
+//
+std::ostream& operator<<(std::ostream& os, CivilYear y);
+std::ostream& operator<<(std::ostream& os, CivilMonth m);
+std::ostream& operator<<(std::ostream& os, CivilDay d);
+std::ostream& operator<<(std::ostream& os, CivilHour h);
+std::ostream& operator<<(std::ostream& os, CivilMinute m);
+std::ostream& operator<<(std::ostream& os, CivilSecond s);
+
+}  // namespace time_internal
+
+}  // namespace absl
+
+#endif  // ABSL_TIME_CIVIL_TIME_H_
diff --git a/absl/time/civil_time_benchmark.cc b/absl/time/civil_time_benchmark.cc
new file mode 100644
index 0000000..4086983
--- /dev/null
+++ b/absl/time/civil_time_benchmark.cc
@@ -0,0 +1,107 @@
+// 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
+//
+//      https://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/time/civil_time.h"
+
+#include <numeric>
+#include <vector>
+
+#include "absl/hash/hash.h"
+#include "benchmark/benchmark.h"
+
+namespace {
+
+// Run on (12 X 3492 MHz CPUs); 2018-11-05T13:44:29.814239103-08:00
+// CPU: Intel Haswell with HyperThreading (6 cores) dL1:32KB dL2:256KB dL3:15MB
+// Benchmark                 Time(ns)        CPU(ns)     Iterations
+// ----------------------------------------------------------------
+// BM_Difference_Days              14.5           14.5     48531105
+// BM_Step_Days                    12.6           12.6     54876006
+// BM_Format                      587            587        1000000
+// BM_Parse                       692            692        1000000
+// BM_RoundTripFormatParse       1309           1309         532075
+// BM_CivilYearAbslHash             0.710          0.710  976400000
+// BM_CivilMonthAbslHash            1.13           1.13   619500000
+// BM_CivilDayAbslHash              1.70           1.70   426000000
+// BM_CivilHourAbslHash             2.45           2.45   287600000
+// BM_CivilMinuteAbslHash           3.21           3.21   226200000
+// BM_CivilSecondAbslHash           4.10           4.10   171800000
+
+void BM_Difference_Days(benchmark::State& state) {
+  const absl::CivilDay c(2014, 8, 22);
+  const absl::CivilDay epoch(1970, 1, 1);
+  while (state.KeepRunning()) {
+    const absl::civil_diff_t n = c - epoch;
+    benchmark::DoNotOptimize(n);
+  }
+}
+BENCHMARK(BM_Difference_Days);
+
+void BM_Step_Days(benchmark::State& state) {
+  const absl::CivilDay kStart(2014, 8, 22);
+  absl::CivilDay c = kStart;
+  while (state.KeepRunning()) {
+    benchmark::DoNotOptimize(++c);
+  }
+}
+BENCHMARK(BM_Step_Days);
+
+void BM_Format(benchmark::State& state) {
+  const absl::CivilSecond c(2014, 1, 2, 3, 4, 5);
+  while (state.KeepRunning()) {
+    const std::string s = absl::FormatCivilTime(c);
+    benchmark::DoNotOptimize(s);
+  }
+}
+BENCHMARK(BM_Format);
+
+template <typename T>
+void BM_CivilTimeAbslHash(benchmark::State& state) {
+  const int kSize = 100000;
+  std::vector<T> civil_times(kSize);
+  std::iota(civil_times.begin(), civil_times.end(), T(2018));
+
+  absl::Hash<T> absl_hasher;
+  while (state.KeepRunningBatch(kSize)) {
+    for (const T civil_time : civil_times) {
+      benchmark::DoNotOptimize(absl_hasher(civil_time));
+    }
+  }
+}
+void BM_CivilYearAbslHash(benchmark::State& state) {
+  BM_CivilTimeAbslHash<absl::CivilYear>(state);
+}
+void BM_CivilMonthAbslHash(benchmark::State& state) {
+  BM_CivilTimeAbslHash<absl::CivilMonth>(state);
+}
+void BM_CivilDayAbslHash(benchmark::State& state) {
+  BM_CivilTimeAbslHash<absl::CivilDay>(state);
+}
+void BM_CivilHourAbslHash(benchmark::State& state) {
+  BM_CivilTimeAbslHash<absl::CivilHour>(state);
+}
+void BM_CivilMinuteAbslHash(benchmark::State& state) {
+  BM_CivilTimeAbslHash<absl::CivilMinute>(state);
+}
+void BM_CivilSecondAbslHash(benchmark::State& state) {
+  BM_CivilTimeAbslHash<absl::CivilSecond>(state);
+}
+BENCHMARK(BM_CivilYearAbslHash);
+BENCHMARK(BM_CivilMonthAbslHash);
+BENCHMARK(BM_CivilDayAbslHash);
+BENCHMARK(BM_CivilHourAbslHash);
+BENCHMARK(BM_CivilMinuteAbslHash);
+BENCHMARK(BM_CivilSecondAbslHash);
+
+}  // namespace
diff --git a/absl/time/civil_time_test.cc b/absl/time/civil_time_test.cc
new file mode 100644
index 0000000..b8d5713
--- /dev/null
+++ b/absl/time/civil_time_test.cc
@@ -0,0 +1,1073 @@
+// 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
+//
+//      https://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/time/civil_time.h"
+
+#include <limits>
+#include <sstream>
+#include <type_traits>
+
+#include "absl/base/macros.h"
+#include "gtest/gtest.h"
+
+namespace {
+
+TEST(CivilTime, DefaultConstruction) {
+  absl::CivilSecond ss;
+  EXPECT_EQ("1970-01-01T00:00:00", absl::FormatCivilTime(ss));
+
+  absl::CivilMinute mm;
+  EXPECT_EQ("1970-01-01T00:00", absl::FormatCivilTime(mm));
+
+  absl::CivilHour hh;
+  EXPECT_EQ("1970-01-01T00", absl::FormatCivilTime(hh));
+
+  absl::CivilDay d;
+  EXPECT_EQ("1970-01-01", absl::FormatCivilTime(d));
+
+  absl::CivilMonth m;
+  EXPECT_EQ("1970-01", absl::FormatCivilTime(m));
+
+  absl::CivilYear y;
+  EXPECT_EQ("1970", absl::FormatCivilTime(y));
+}
+
+TEST(CivilTime, StructMember) {
+  struct S {
+    absl::CivilDay day;
+  };
+  S s = {};
+  EXPECT_EQ(absl::CivilDay{}, s.day);
+}
+
+TEST(CivilTime, FieldsConstruction) {
+  EXPECT_EQ("2015-01-02T03:04:05",
+            absl::FormatCivilTime(absl::CivilSecond(2015, 1, 2, 3, 4, 5)));
+  EXPECT_EQ("2015-01-02T03:04:00",
+            absl::FormatCivilTime(absl::CivilSecond(2015, 1, 2, 3, 4)));
+  EXPECT_EQ("2015-01-02T03:00:00",
+            absl::FormatCivilTime(absl::CivilSecond(2015, 1, 2, 3)));
+  EXPECT_EQ("2015-01-02T00:00:00",
+            absl::FormatCivilTime(absl::CivilSecond(2015, 1, 2)));
+  EXPECT_EQ("2015-01-01T00:00:00",
+            absl::FormatCivilTime(absl::CivilSecond(2015, 1)));
+  EXPECT_EQ("2015-01-01T00:00:00",
+            absl::FormatCivilTime(absl::CivilSecond(2015)));
+
+  EXPECT_EQ("2015-01-02T03:04",
+            absl::FormatCivilTime(absl::CivilMinute(2015, 1, 2, 3, 4, 5)));
+  EXPECT_EQ("2015-01-02T03:04",
+            absl::FormatCivilTime(absl::CivilMinute(2015, 1, 2, 3, 4)));
+  EXPECT_EQ("2015-01-02T03:00",
+            absl::FormatCivilTime(absl::CivilMinute(2015, 1, 2, 3)));
+  EXPECT_EQ("2015-01-02T00:00",
+            absl::FormatCivilTime(absl::CivilMinute(2015, 1, 2)));
+  EXPECT_EQ("2015-01-01T00:00",
+            absl::FormatCivilTime(absl::CivilMinute(2015, 1)));
+  EXPECT_EQ("2015-01-01T00:00",
+            absl::FormatCivilTime(absl::CivilMinute(2015)));
+
+  EXPECT_EQ("2015-01-02T03",
+            absl::FormatCivilTime(absl::CivilHour(2015, 1, 2, 3, 4, 5)));
+  EXPECT_EQ("2015-01-02T03",
+            absl::FormatCivilTime(absl::CivilHour(2015, 1, 2, 3, 4)));
+  EXPECT_EQ("2015-01-02T03",
+            absl::FormatCivilTime(absl::CivilHour(2015, 1, 2, 3)));
+  EXPECT_EQ("2015-01-02T00",
+            absl::FormatCivilTime(absl::CivilHour(2015, 1, 2)));
+  EXPECT_EQ("2015-01-01T00",
+            absl::FormatCivilTime(absl::CivilHour(2015, 1)));
+  EXPECT_EQ("2015-01-01T00",
+            absl::FormatCivilTime(absl::CivilHour(2015)));
+
+  EXPECT_EQ("2015-01-02",
+            absl::FormatCivilTime(absl::CivilDay(2015, 1, 2, 3, 4, 5)));
+  EXPECT_EQ("2015-01-02",
+            absl::FormatCivilTime(absl::CivilDay(2015, 1, 2, 3, 4)));
+  EXPECT_EQ("2015-01-02",
+            absl::FormatCivilTime(absl::CivilDay(2015, 1, 2, 3)));
+  EXPECT_EQ("2015-01-02",
+            absl::FormatCivilTime(absl::CivilDay(2015, 1, 2)));
+  EXPECT_EQ("2015-01-01",
+            absl::FormatCivilTime(absl::CivilDay(2015, 1)));
+  EXPECT_EQ("2015-01-01",
+            absl::FormatCivilTime(absl::CivilDay(2015)));
+
+  EXPECT_EQ("2015-01",
+            absl::FormatCivilTime(absl::CivilMonth(2015, 1, 2, 3, 4, 5)));
+  EXPECT_EQ("2015-01",
+            absl::FormatCivilTime(absl::CivilMonth(2015, 1, 2, 3, 4)));
+  EXPECT_EQ("2015-01",
+            absl::FormatCivilTime(absl::CivilMonth(2015, 1, 2, 3)));
+  EXPECT_EQ("2015-01",
+            absl::FormatCivilTime(absl::CivilMonth(2015, 1, 2)));
+  EXPECT_EQ("2015-01",
+            absl::FormatCivilTime(absl::CivilMonth(2015, 1)));
+  EXPECT_EQ("2015-01",
+            absl::FormatCivilTime(absl::CivilMonth(2015)));
+
+  EXPECT_EQ("2015",
+            absl::FormatCivilTime(absl::CivilYear(2015, 1, 2, 3, 4, 5)));
+  EXPECT_EQ("2015",
+            absl::FormatCivilTime(absl::CivilYear(2015, 1, 2, 3, 4)));
+  EXPECT_EQ("2015",
+            absl::FormatCivilTime(absl::CivilYear(2015, 1, 2, 3)));
+  EXPECT_EQ("2015",
+            absl::FormatCivilTime(absl::CivilYear(2015, 1, 2)));
+  EXPECT_EQ("2015",
+            absl::FormatCivilTime(absl::CivilYear(2015, 1)));
+  EXPECT_EQ("2015",
+            absl::FormatCivilTime(absl::CivilYear(2015)));
+}
+
+TEST(CivilTime, FieldsConstructionLimits) {
+  const int kIntMax = std::numeric_limits<int>::max();
+  EXPECT_EQ("2038-01-19T03:14:07",
+            absl::FormatCivilTime(absl::CivilSecond(
+                1970, 1, 1, 0, 0, kIntMax)));
+  EXPECT_EQ("6121-02-11T05:21:07",
+            absl::FormatCivilTime(absl::CivilSecond(
+                1970, 1, 1, 0, kIntMax, kIntMax)));
+  EXPECT_EQ("251104-11-20T12:21:07",
+            absl::FormatCivilTime(absl::CivilSecond(
+                1970, 1, 1, kIntMax, kIntMax, kIntMax)));
+  EXPECT_EQ("6130715-05-30T12:21:07",
+            absl::FormatCivilTime(absl::CivilSecond(
+                1970, 1, kIntMax, kIntMax, kIntMax, kIntMax)));
+  EXPECT_EQ("185087685-11-26T12:21:07",
+            absl::FormatCivilTime(absl::CivilSecond(
+                1970, kIntMax, kIntMax, kIntMax, kIntMax, kIntMax)));
+
+  const int kIntMin = std::numeric_limits<int>::min();
+  EXPECT_EQ("1901-12-13T20:45:52",
+            absl::FormatCivilTime(absl::CivilSecond(
+                1970, 1, 1, 0, 0, kIntMin)));
+  EXPECT_EQ("-2182-11-20T18:37:52",
+            absl::FormatCivilTime(absl::CivilSecond(
+                1970, 1, 1, 0, kIntMin, kIntMin)));
+  EXPECT_EQ("-247165-02-11T10:37:52",
+            absl::FormatCivilTime(absl::CivilSecond(
+                1970, 1, 1, kIntMin, kIntMin, kIntMin)));
+  EXPECT_EQ("-6126776-08-01T10:37:52",
+            absl::FormatCivilTime(absl::CivilSecond(
+                1970, 1, kIntMin, kIntMin, kIntMin, kIntMin)));
+  EXPECT_EQ("-185083747-10-31T10:37:52",
+            absl::FormatCivilTime(absl::CivilSecond(
+                1970, kIntMin, kIntMin, kIntMin, kIntMin, kIntMin)));
+}
+
+TEST(CivilTime, RangeLimits) {
+  const absl::civil_year_t kYearMax =
+      std::numeric_limits<absl::civil_year_t>::max();
+  EXPECT_EQ(absl::CivilYear(kYearMax),
+            absl::CivilYear::max());
+  EXPECT_EQ(absl::CivilMonth(kYearMax, 12),
+            absl::CivilMonth::max());
+  EXPECT_EQ(absl::CivilDay(kYearMax, 12, 31),
+            absl::CivilDay::max());
+  EXPECT_EQ(absl::CivilHour(kYearMax, 12, 31, 23),
+            absl::CivilHour::max());
+  EXPECT_EQ(absl::CivilMinute(kYearMax, 12, 31, 23, 59),
+            absl::CivilMinute::max());
+  EXPECT_EQ(absl::CivilSecond(kYearMax, 12, 31, 23, 59, 59),
+            absl::CivilSecond::max());
+
+  const absl::civil_year_t kYearMin =
+      std::numeric_limits<absl::civil_year_t>::min();
+  EXPECT_EQ(absl::CivilYear(kYearMin),
+            absl::CivilYear::min());
+  EXPECT_EQ(absl::CivilMonth(kYearMin, 1),
+            absl::CivilMonth::min());
+  EXPECT_EQ(absl::CivilDay(kYearMin, 1, 1),
+            absl::CivilDay::min());
+  EXPECT_EQ(absl::CivilHour(kYearMin, 1, 1, 0),
+            absl::CivilHour::min());
+  EXPECT_EQ(absl::CivilMinute(kYearMin, 1, 1, 0, 0),
+            absl::CivilMinute::min());
+  EXPECT_EQ(absl::CivilSecond(kYearMin, 1, 1, 0, 0, 0),
+            absl::CivilSecond::min());
+}
+
+TEST(CivilTime, ImplicitCrossAlignment) {
+  absl::CivilYear year(2015);
+  absl::CivilMonth month = year;
+  absl::CivilDay day = month;
+  absl::CivilHour hour = day;
+  absl::CivilMinute minute = hour;
+  absl::CivilSecond second = minute;
+
+  second = year;
+  EXPECT_EQ(second, year);
+  second = month;
+  EXPECT_EQ(second, month);
+  second = day;
+  EXPECT_EQ(second, day);
+  second = hour;
+  EXPECT_EQ(second, hour);
+  second = minute;
+  EXPECT_EQ(second, minute);
+
+  minute = year;
+  EXPECT_EQ(minute, year);
+  minute = month;
+  EXPECT_EQ(minute, month);
+  minute = day;
+  EXPECT_EQ(minute, day);
+  minute = hour;
+  EXPECT_EQ(minute, hour);
+
+  hour = year;
+  EXPECT_EQ(hour, year);
+  hour = month;
+  EXPECT_EQ(hour, month);
+  hour = day;
+  EXPECT_EQ(hour, day);
+
+  day = year;
+  EXPECT_EQ(day, year);
+  day = month;
+  EXPECT_EQ(day, month);
+
+  month = year;
+  EXPECT_EQ(month, year);
+
+  // Ensures unsafe conversions are not allowed.
+  EXPECT_FALSE(
+      (std::is_convertible<absl::CivilSecond, absl::CivilMinute>::value));
+  EXPECT_FALSE(
+      (std::is_convertible<absl::CivilSecond, absl::CivilHour>::value));
+  EXPECT_FALSE(
+      (std::is_convertible<absl::CivilSecond, absl::CivilDay>::value));
+  EXPECT_FALSE(
+      (std::is_convertible<absl::CivilSecond, absl::CivilMonth>::value));
+  EXPECT_FALSE(
+      (std::is_convertible<absl::CivilSecond, absl::CivilYear>::value));
+
+  EXPECT_FALSE(
+      (std::is_convertible<absl::CivilMinute, absl::CivilHour>::value));
+  EXPECT_FALSE(
+      (std::is_convertible<absl::CivilMinute, absl::CivilDay>::value));
+  EXPECT_FALSE(
+      (std::is_convertible<absl::CivilMinute, absl::CivilMonth>::value));
+  EXPECT_FALSE(
+      (std::is_convertible<absl::CivilMinute, absl::CivilYear>::value));
+
+  EXPECT_FALSE(
+      (std::is_convertible<absl::CivilHour, absl::CivilDay>::value));
+  EXPECT_FALSE(
+      (std::is_convertible<absl::CivilHour, absl::CivilMonth>::value));
+  EXPECT_FALSE(
+      (std::is_convertible<absl::CivilHour, absl::CivilYear>::value));
+
+  EXPECT_FALSE(
+      (std::is_convertible<absl::CivilDay, absl::CivilMonth>::value));
+  EXPECT_FALSE(
+      (std::is_convertible<absl::CivilDay, absl::CivilYear>::value));
+
+  EXPECT_FALSE(
+      (std::is_convertible<absl::CivilMonth, absl::CivilYear>::value));
+}
+
+TEST(CivilTime, ExplicitCrossAlignment) {
+  //
+  // Assign from smaller units -> larger units
+  //
+
+  absl::CivilSecond second(2015, 1, 2, 3, 4, 5);
+  EXPECT_EQ("2015-01-02T03:04:05", absl::FormatCivilTime(second));
+
+  absl::CivilMinute minute(second);
+  EXPECT_EQ("2015-01-02T03:04", absl::FormatCivilTime(minute));
+
+  absl::CivilHour hour(minute);
+  EXPECT_EQ("2015-01-02T03", absl::FormatCivilTime(hour));
+
+  absl::CivilDay day(hour);
+  EXPECT_EQ("2015-01-02", absl::FormatCivilTime(day));
+
+  absl::CivilMonth month(day);
+  EXPECT_EQ("2015-01", absl::FormatCivilTime(month));
+
+  absl::CivilYear year(month);
+  EXPECT_EQ("2015", absl::FormatCivilTime(year));
+
+  //
+  // Now assign from larger units -> smaller units
+  //
+
+  month = absl::CivilMonth(year);
+  EXPECT_EQ("2015-01", absl::FormatCivilTime(month));
+
+  day = absl::CivilDay(month);
+  EXPECT_EQ("2015-01-01", absl::FormatCivilTime(day));
+
+  hour = absl::CivilHour(day);
+  EXPECT_EQ("2015-01-01T00", absl::FormatCivilTime(hour));
+
+  minute = absl::CivilMinute(hour);
+  EXPECT_EQ("2015-01-01T00:00", absl::FormatCivilTime(minute));
+
+  second = absl::CivilSecond(minute);
+  EXPECT_EQ("2015-01-01T00:00:00", absl::FormatCivilTime(second));
+}
+
+// Metafunction to test whether difference is allowed between two types.
+template <typename T1, typename T2>
+struct HasDiff {
+  template <typename U1, typename U2>
+  static std::false_type test(...);
+  template <typename U1, typename U2>
+  static std::true_type test(decltype(std::declval<U1>() - std::declval<U2>()));
+  static constexpr bool value = decltype(test<T1, T2>(0))::value;
+};
+
+TEST(CivilTime, DisallowCrossAlignedDifference) {
+  // Difference is allowed between types with the same alignment.
+  static_assert(HasDiff<absl::CivilSecond, absl::CivilSecond>::value, "");
+  static_assert(HasDiff<absl::CivilMinute, absl::CivilMinute>::value, "");
+  static_assert(HasDiff<absl::CivilHour, absl::CivilHour>::value, "");
+  static_assert(HasDiff<absl::CivilDay, absl::CivilDay>::value, "");
+  static_assert(HasDiff<absl::CivilMonth, absl::CivilMonth>::value, "");
+  static_assert(HasDiff<absl::CivilYear, absl::CivilYear>::value, "");
+
+  // Difference is disallowed between types with different alignments.
+  static_assert(!HasDiff<absl::CivilSecond, absl::CivilMinute>::value, "");
+  static_assert(!HasDiff<absl::CivilSecond, absl::CivilHour>::value, "");
+  static_assert(!HasDiff<absl::CivilSecond, absl::CivilDay>::value, "");
+  static_assert(!HasDiff<absl::CivilSecond, absl::CivilMonth>::value, "");
+  static_assert(!HasDiff<absl::CivilSecond, absl::CivilYear>::value, "");
+
+  static_assert(!HasDiff<absl::CivilMinute, absl::CivilHour>::value, "");
+  static_assert(!HasDiff<absl::CivilMinute, absl::CivilDay>::value, "");
+  static_assert(!HasDiff<absl::CivilMinute, absl::CivilMonth>::value, "");
+  static_assert(!HasDiff<absl::CivilMinute, absl::CivilYear>::value, "");
+
+  static_assert(!HasDiff<absl::CivilHour, absl::CivilDay>::value, "");
+  static_assert(!HasDiff<absl::CivilHour, absl::CivilMonth>::value, "");
+  static_assert(!HasDiff<absl::CivilHour, absl::CivilYear>::value, "");
+
+  static_assert(!HasDiff<absl::CivilDay, absl::CivilMonth>::value, "");
+  static_assert(!HasDiff<absl::CivilDay, absl::CivilYear>::value, "");
+
+  static_assert(!HasDiff<absl::CivilMonth, absl::CivilYear>::value, "");
+}
+
+TEST(CivilTime, ValueSemantics) {
+  const absl::CivilHour a(2015, 1, 2, 3);
+  const absl::CivilHour b = a;
+  const absl::CivilHour c(b);
+  absl::CivilHour d;
+  d = c;
+  EXPECT_EQ("2015-01-02T03", absl::FormatCivilTime(d));
+}
+
+TEST(CivilTime, Relational) {
+  // Tests that the alignment unit is ignored in comparison.
+  const absl::CivilYear year(2014);
+  const absl::CivilMonth month(year);
+  EXPECT_EQ(year, month);
+
+#define TEST_RELATIONAL(OLDER, YOUNGER) \
+  do {                                  \
+    EXPECT_FALSE(OLDER < OLDER);        \
+    EXPECT_FALSE(OLDER > OLDER);        \
+    EXPECT_TRUE(OLDER >= OLDER);        \
+    EXPECT_TRUE(OLDER <= OLDER);        \
+    EXPECT_FALSE(YOUNGER < YOUNGER);    \
+    EXPECT_FALSE(YOUNGER > YOUNGER);    \
+    EXPECT_TRUE(YOUNGER >= YOUNGER);    \
+    EXPECT_TRUE(YOUNGER <= YOUNGER);    \
+    EXPECT_EQ(OLDER, OLDER);            \
+    EXPECT_NE(OLDER, YOUNGER);          \
+    EXPECT_LT(OLDER, YOUNGER);          \
+    EXPECT_LE(OLDER, YOUNGER);          \
+    EXPECT_GT(YOUNGER, OLDER);          \
+    EXPECT_GE(YOUNGER, OLDER);          \
+  } while (0)
+
+  // Alignment is ignored in comparison (verified above), so CivilSecond is
+  // used to test comparison in all field positions.
+  TEST_RELATIONAL(absl::CivilSecond(2014, 1, 1, 0, 0, 0),
+                  absl::CivilSecond(2015, 1, 1, 0, 0, 0));
+  TEST_RELATIONAL(absl::CivilSecond(2014, 1, 1, 0, 0, 0),
+                  absl::CivilSecond(2014, 2, 1, 0, 0, 0));
+  TEST_RELATIONAL(absl::CivilSecond(2014, 1, 1, 0, 0, 0),
+                  absl::CivilSecond(2014, 1, 2, 0, 0, 0));
+  TEST_RELATIONAL(absl::CivilSecond(2014, 1, 1, 0, 0, 0),
+                  absl::CivilSecond(2014, 1, 1, 1, 0, 0));
+  TEST_RELATIONAL(absl::CivilSecond(2014, 1, 1, 1, 0, 0),
+                  absl::CivilSecond(2014, 1, 1, 1, 1, 0));
+  TEST_RELATIONAL(absl::CivilSecond(2014, 1, 1, 1, 1, 0),
+                  absl::CivilSecond(2014, 1, 1, 1, 1, 1));
+
+  // Tests the relational operators of two different civil-time types.
+  TEST_RELATIONAL(absl::CivilDay(2014, 1, 1),
+                  absl::CivilMinute(2014, 1, 1, 1, 1));
+  TEST_RELATIONAL(absl::CivilDay(2014, 1, 1),
+                  absl::CivilMonth(2014, 2));
+
+#undef TEST_RELATIONAL
+}
+
+TEST(CivilTime, Arithmetic) {
+  absl::CivilSecond second(2015, 1, 2, 3, 4, 5);
+  EXPECT_EQ("2015-01-02T03:04:06", absl::FormatCivilTime(second += 1));
+  EXPECT_EQ("2015-01-02T03:04:07", absl::FormatCivilTime(second + 1));
+  EXPECT_EQ("2015-01-02T03:04:08", absl::FormatCivilTime(2 + second));
+  EXPECT_EQ("2015-01-02T03:04:05", absl::FormatCivilTime(second - 1));
+  EXPECT_EQ("2015-01-02T03:04:05", absl::FormatCivilTime(second -= 1));
+  EXPECT_EQ("2015-01-02T03:04:05", absl::FormatCivilTime(second++));
+  EXPECT_EQ("2015-01-02T03:04:07", absl::FormatCivilTime(++second));
+  EXPECT_EQ("2015-01-02T03:04:07", absl::FormatCivilTime(second--));
+  EXPECT_EQ("2015-01-02T03:04:05", absl::FormatCivilTime(--second));
+
+  absl::CivilMinute minute(2015, 1, 2, 3, 4);
+  EXPECT_EQ("2015-01-02T03:05", absl::FormatCivilTime(minute += 1));
+  EXPECT_EQ("2015-01-02T03:06", absl::FormatCivilTime(minute + 1));
+  EXPECT_EQ("2015-01-02T03:07", absl::FormatCivilTime(2 + minute));
+  EXPECT_EQ("2015-01-02T03:04", absl::FormatCivilTime(minute - 1));
+  EXPECT_EQ("2015-01-02T03:04", absl::FormatCivilTime(minute -= 1));
+  EXPECT_EQ("2015-01-02T03:04", absl::FormatCivilTime(minute++));
+  EXPECT_EQ("2015-01-02T03:06", absl::FormatCivilTime(++minute));
+  EXPECT_EQ("2015-01-02T03:06", absl::FormatCivilTime(minute--));
+  EXPECT_EQ("2015-01-02T03:04", absl::FormatCivilTime(--minute));
+
+  absl::CivilHour hour(2015, 1, 2, 3);
+  EXPECT_EQ("2015-01-02T04", absl::FormatCivilTime(hour += 1));
+  EXPECT_EQ("2015-01-02T05", absl::FormatCivilTime(hour + 1));
+  EXPECT_EQ("2015-01-02T06", absl::FormatCivilTime(2 + hour));
+  EXPECT_EQ("2015-01-02T03", absl::FormatCivilTime(hour - 1));
+  EXPECT_EQ("2015-01-02T03", absl::FormatCivilTime(hour -= 1));
+  EXPECT_EQ("2015-01-02T03", absl::FormatCivilTime(hour++));
+  EXPECT_EQ("2015-01-02T05", absl::FormatCivilTime(++hour));
+  EXPECT_EQ("2015-01-02T05", absl::FormatCivilTime(hour--));
+  EXPECT_EQ("2015-01-02T03", absl::FormatCivilTime(--hour));
+
+  absl::CivilDay day(2015, 1, 2);
+  EXPECT_EQ("2015-01-03", absl::FormatCivilTime(day += 1));
+  EXPECT_EQ("2015-01-04", absl::FormatCivilTime(day + 1));
+  EXPECT_EQ("2015-01-05", absl::FormatCivilTime(2 + day));
+  EXPECT_EQ("2015-01-02", absl::FormatCivilTime(day - 1));
+  EXPECT_EQ("2015-01-02", absl::FormatCivilTime(day -= 1));
+  EXPECT_EQ("2015-01-02", absl::FormatCivilTime(day++));
+  EXPECT_EQ("2015-01-04", absl::FormatCivilTime(++day));
+  EXPECT_EQ("2015-01-04", absl::FormatCivilTime(day--));
+  EXPECT_EQ("2015-01-02", absl::FormatCivilTime(--day));
+
+  absl::CivilMonth month(2015, 1);
+  EXPECT_EQ("2015-02", absl::FormatCivilTime(month += 1));
+  EXPECT_EQ("2015-03", absl::FormatCivilTime(month + 1));
+  EXPECT_EQ("2015-04", absl::FormatCivilTime(2 + month));
+  EXPECT_EQ("2015-01", absl::FormatCivilTime(month - 1));
+  EXPECT_EQ("2015-01", absl::FormatCivilTime(month -= 1));
+  EXPECT_EQ("2015-01", absl::FormatCivilTime(month++));
+  EXPECT_EQ("2015-03", absl::FormatCivilTime(++month));
+  EXPECT_EQ("2015-03", absl::FormatCivilTime(month--));
+  EXPECT_EQ("2015-01", absl::FormatCivilTime(--month));
+
+  absl::CivilYear year(2015);
+  EXPECT_EQ("2016", absl::FormatCivilTime(year += 1));
+  EXPECT_EQ("2017", absl::FormatCivilTime(year + 1));
+  EXPECT_EQ("2018", absl::FormatCivilTime(2 + year));
+  EXPECT_EQ("2015", absl::FormatCivilTime(year - 1));
+  EXPECT_EQ("2015", absl::FormatCivilTime(year -= 1));
+  EXPECT_EQ("2015", absl::FormatCivilTime(year++));
+  EXPECT_EQ("2017", absl::FormatCivilTime(++year));
+  EXPECT_EQ("2017", absl::FormatCivilTime(year--));
+  EXPECT_EQ("2015", absl::FormatCivilTime(--year));
+}
+
+TEST(CivilTime, ArithmeticLimits) {
+  const int kIntMax = std::numeric_limits<int>::max();
+  const int kIntMin = std::numeric_limits<int>::min();
+
+  absl::CivilSecond second(1970, 1, 1, 0, 0, 0);
+  second += kIntMax;
+  EXPECT_EQ("2038-01-19T03:14:07", absl::FormatCivilTime(second));
+  second -= kIntMax;
+  EXPECT_EQ("1970-01-01T00:00:00", absl::FormatCivilTime(second));
+  second += kIntMin;
+  EXPECT_EQ("1901-12-13T20:45:52", absl::FormatCivilTime(second));
+  second -= kIntMin;
+  EXPECT_EQ("1970-01-01T00:00:00", absl::FormatCivilTime(second));
+
+  absl::CivilMinute minute(1970, 1, 1, 0, 0);
+  minute += kIntMax;
+  EXPECT_EQ("6053-01-23T02:07", absl::FormatCivilTime(minute));
+  minute -= kIntMax;
+  EXPECT_EQ("1970-01-01T00:00", absl::FormatCivilTime(minute));
+  minute += kIntMin;
+  EXPECT_EQ("-2114-12-08T21:52", absl::FormatCivilTime(minute));
+  minute -= kIntMin;
+  EXPECT_EQ("1970-01-01T00:00", absl::FormatCivilTime(minute));
+
+  absl::CivilHour hour(1970, 1, 1, 0);
+  hour += kIntMax;
+  EXPECT_EQ("246953-10-09T07", absl::FormatCivilTime(hour));
+  hour -= kIntMax;
+  EXPECT_EQ("1970-01-01T00", absl::FormatCivilTime(hour));
+  hour += kIntMin;
+  EXPECT_EQ("-243014-03-24T16", absl::FormatCivilTime(hour));
+  hour -= kIntMin;
+  EXPECT_EQ("1970-01-01T00", absl::FormatCivilTime(hour));
+
+  absl::CivilDay day(1970, 1, 1);
+  day += kIntMax;
+  EXPECT_EQ("5881580-07-11", absl::FormatCivilTime(day));
+  day -= kIntMax;
+  EXPECT_EQ("1970-01-01", absl::FormatCivilTime(day));
+  day += kIntMin;
+  EXPECT_EQ("-5877641-06-23", absl::FormatCivilTime(day));
+  day -= kIntMin;
+  EXPECT_EQ("1970-01-01", absl::FormatCivilTime(day));
+
+  absl::CivilMonth month(1970, 1);
+  month += kIntMax;
+  EXPECT_EQ("178958940-08", absl::FormatCivilTime(month));
+  month -= kIntMax;
+  EXPECT_EQ("1970-01", absl::FormatCivilTime(month));
+  month += kIntMin;
+  EXPECT_EQ("-178955001-05", absl::FormatCivilTime(month));
+  month -= kIntMin;
+  EXPECT_EQ("1970-01", absl::FormatCivilTime(month));
+
+  absl::CivilYear year(0);
+  year += kIntMax;
+  EXPECT_EQ("2147483647", absl::FormatCivilTime(year));
+  year -= kIntMax;
+  EXPECT_EQ("0", absl::FormatCivilTime(year));
+  year += kIntMin;
+  EXPECT_EQ("-2147483648", absl::FormatCivilTime(year));
+  year -= kIntMin;
+  EXPECT_EQ("0", absl::FormatCivilTime(year));
+}
+
+TEST(CivilTime, Difference) {
+  absl::CivilSecond second(2015, 1, 2, 3, 4, 5);
+  EXPECT_EQ(0, second - second);
+  EXPECT_EQ(10, (second + 10) - second);
+  EXPECT_EQ(-10, (second - 10) - second);
+
+  absl::CivilMinute minute(2015, 1, 2, 3, 4);
+  EXPECT_EQ(0, minute - minute);
+  EXPECT_EQ(10, (minute + 10) - minute);
+  EXPECT_EQ(-10, (minute - 10) - minute);
+
+  absl::CivilHour hour(2015, 1, 2, 3);
+  EXPECT_EQ(0, hour - hour);
+  EXPECT_EQ(10, (hour + 10) - hour);
+  EXPECT_EQ(-10, (hour - 10) - hour);
+
+  absl::CivilDay day(2015, 1, 2);
+  EXPECT_EQ(0, day - day);
+  EXPECT_EQ(10, (day + 10) - day);
+  EXPECT_EQ(-10, (day - 10) - day);
+
+  absl::CivilMonth month(2015, 1);
+  EXPECT_EQ(0, month - month);
+  EXPECT_EQ(10, (month + 10) - month);
+  EXPECT_EQ(-10, (month - 10) - month);
+
+  absl::CivilYear year(2015);
+  EXPECT_EQ(0, year - year);
+  EXPECT_EQ(10, (year + 10) - year);
+  EXPECT_EQ(-10, (year - 10) - year);
+}
+
+TEST(CivilTime, DifferenceLimits) {
+  const absl::civil_diff_t kDiffMax =
+      std::numeric_limits<absl::civil_diff_t>::max();
+  const absl::civil_diff_t kDiffMin =
+      std::numeric_limits<absl::civil_diff_t>::min();
+
+  // Check day arithmetic at the end of the year range.
+  const absl::CivilDay max_day(kDiffMax, 12, 31);
+  EXPECT_EQ(1, max_day - (max_day - 1));
+  EXPECT_EQ(-1, (max_day - 1) - max_day);
+
+  // Check day arithmetic at the start of the year range.
+  const absl::CivilDay min_day(kDiffMin, 1, 1);
+  EXPECT_EQ(1, (min_day + 1) - min_day);
+  EXPECT_EQ(-1, min_day - (min_day + 1));
+
+  // Check the limits of the return value.
+  const absl::CivilDay d1(1970, 1, 1);
+  const absl::CivilDay d2(25252734927768524, 7, 27);
+  EXPECT_EQ(kDiffMax, d2 - d1);
+  EXPECT_EQ(kDiffMin, d1 - (d2 + 1));
+}
+
+TEST(CivilTime, Properties) {
+  absl::CivilSecond ss(2015, 2, 3, 4, 5, 6);
+  EXPECT_EQ(2015, ss.year());
+  EXPECT_EQ(2, ss.month());
+  EXPECT_EQ(3, ss.day());
+  EXPECT_EQ(4, ss.hour());
+  EXPECT_EQ(5, ss.minute());
+  EXPECT_EQ(6, ss.second());
+
+  absl::CivilMinute mm(2015, 2, 3, 4, 5, 6);
+  EXPECT_EQ(2015, mm.year());
+  EXPECT_EQ(2, mm.month());
+  EXPECT_EQ(3, mm.day());
+  EXPECT_EQ(4, mm.hour());
+  EXPECT_EQ(5, mm.minute());
+  EXPECT_EQ(0, mm.second());
+
+  absl::CivilHour hh(2015, 2, 3, 4, 5, 6);
+  EXPECT_EQ(2015, hh.year());
+  EXPECT_EQ(2, hh.month());
+  EXPECT_EQ(3, hh.day());
+  EXPECT_EQ(4, hh.hour());
+  EXPECT_EQ(0, hh.minute());
+  EXPECT_EQ(0, hh.second());
+
+  absl::CivilDay d(2015, 2, 3, 4, 5, 6);
+  EXPECT_EQ(2015, d.year());
+  EXPECT_EQ(2, d.month());
+  EXPECT_EQ(3, d.day());
+  EXPECT_EQ(0, d.hour());
+  EXPECT_EQ(0, d.minute());
+  EXPECT_EQ(0, d.second());
+
+  absl::CivilMonth m(2015, 2, 3, 4, 5, 6);
+  EXPECT_EQ(2015, m.year());
+  EXPECT_EQ(2, m.month());
+  EXPECT_EQ(1, m.day());
+  EXPECT_EQ(0, m.hour());
+  EXPECT_EQ(0, m.minute());
+  EXPECT_EQ(0, m.second());
+
+  absl::CivilYear y(2015, 2, 3, 4, 5, 6);
+  EXPECT_EQ(2015, y.year());
+  EXPECT_EQ(1, y.month());
+  EXPECT_EQ(1, y.day());
+  EXPECT_EQ(0, y.hour());
+  EXPECT_EQ(0, y.minute());
+  EXPECT_EQ(0, y.second());
+}
+
+TEST(CivilTime, Format) {
+  absl::CivilSecond ss;
+  EXPECT_EQ("1970-01-01T00:00:00", absl::FormatCivilTime(ss));
+
+  absl::CivilMinute mm;
+  EXPECT_EQ("1970-01-01T00:00", absl::FormatCivilTime(mm));
+
+  absl::CivilHour hh;
+  EXPECT_EQ("1970-01-01T00", absl::FormatCivilTime(hh));
+
+  absl::CivilDay d;
+  EXPECT_EQ("1970-01-01", absl::FormatCivilTime(d));
+
+  absl::CivilMonth m;
+  EXPECT_EQ("1970-01", absl::FormatCivilTime(m));
+
+  absl::CivilYear y;
+  EXPECT_EQ("1970", absl::FormatCivilTime(y));
+}
+
+TEST(CivilTime, FormatAndParseLenient) {
+  absl::CivilSecond ss;
+  EXPECT_EQ("1970-01-01T00:00:00", absl::FormatCivilTime(ss));
+
+  absl::CivilMinute mm;
+  EXPECT_EQ("1970-01-01T00:00", absl::FormatCivilTime(mm));
+
+  absl::CivilHour hh;
+  EXPECT_EQ("1970-01-01T00", absl::FormatCivilTime(hh));
+
+  absl::CivilDay d;
+  EXPECT_EQ("1970-01-01", absl::FormatCivilTime(d));
+
+  absl::CivilMonth m;
+  EXPECT_EQ("1970-01", absl::FormatCivilTime(m));
+
+  absl::CivilYear y;
+  EXPECT_EQ("1970", absl::FormatCivilTime(y));
+}
+
+TEST(CivilTime, OutputStream) {
+  absl::CivilSecond cs(2016, 2, 3, 4, 5, 6);
+  {
+    std::stringstream ss;
+    ss << std::left << std::setfill('.');
+    ss << std::setw(3) << 'X';
+    ss << std::setw(21) << absl::CivilYear(cs);
+    ss << std::setw(3) << 'X';
+    EXPECT_EQ("X..2016.................X..", ss.str());
+  }
+  {
+    std::stringstream ss;
+    ss << std::left << std::setfill('.');
+    ss << std::setw(3) << 'X';
+    ss << std::setw(21) << absl::CivilMonth(cs);
+    ss << std::setw(3) << 'X';
+    EXPECT_EQ("X..2016-02..............X..", ss.str());
+  }
+  {
+    std::stringstream ss;
+    ss << std::left << std::setfill('.');
+    ss << std::setw(3) << 'X';
+    ss << std::setw(21) << absl::CivilDay(cs);
+    ss << std::setw(3) << 'X';
+    EXPECT_EQ("X..2016-02-03...........X..", ss.str());
+  }
+  {
+    std::stringstream ss;
+    ss << std::left << std::setfill('.');
+    ss << std::setw(3) << 'X';
+    ss << std::setw(21) << absl::CivilHour(cs);
+    ss << std::setw(3) << 'X';
+    EXPECT_EQ("X..2016-02-03T04........X..", ss.str());
+  }
+  {
+    std::stringstream ss;
+    ss << std::left << std::setfill('.');
+    ss << std::setw(3) << 'X';
+    ss << std::setw(21) << absl::CivilMinute(cs);
+    ss << std::setw(3) << 'X';
+    EXPECT_EQ("X..2016-02-03T04:05.....X..", ss.str());
+  }
+  {
+    std::stringstream ss;
+    ss << std::left << std::setfill('.');
+    ss << std::setw(3) << 'X';
+    ss << std::setw(21) << absl::CivilSecond(cs);
+    ss << std::setw(3) << 'X';
+    EXPECT_EQ("X..2016-02-03T04:05:06..X..", ss.str());
+  }
+  {
+    std::stringstream ss;
+    ss << std::left << std::setfill('.');
+    ss << std::setw(3) << 'X';
+    ss << std::setw(21) << absl::Weekday::wednesday;
+    ss << std::setw(3) << 'X';
+    EXPECT_EQ("X..Wednesday............X..", ss.str());
+  }
+}
+
+TEST(CivilTime, Weekday) {
+  absl::CivilDay d(1970, 1, 1);
+  EXPECT_EQ(absl::Weekday::thursday, absl::GetWeekday(d)) << d;
+
+  // We used to get this wrong for years < -30.
+  d = absl::CivilDay(-31, 12, 24);
+  EXPECT_EQ(absl::Weekday::wednesday, absl::GetWeekday(d)) << d;
+}
+
+TEST(CivilTime, NextPrevWeekday) {
+  // Jan 1, 1970 was a Thursday.
+  const absl::CivilDay thursday(1970, 1, 1);
+
+  // Thursday -> Thursday
+  absl::CivilDay d = absl::NextWeekday(thursday, absl::Weekday::thursday);
+  EXPECT_EQ(7, d - thursday) << d;
+  EXPECT_EQ(d - 14, absl::PrevWeekday(thursday, absl::Weekday::thursday));
+
+  // Thursday -> Friday
+  d = absl::NextWeekday(thursday, absl::Weekday::friday);
+  EXPECT_EQ(1, d - thursday) << d;
+  EXPECT_EQ(d - 7, absl::PrevWeekday(thursday, absl::Weekday::friday));
+
+  // Thursday -> Saturday
+  d = absl::NextWeekday(thursday, absl::Weekday::saturday);
+  EXPECT_EQ(2, d - thursday) << d;
+  EXPECT_EQ(d - 7, absl::PrevWeekday(thursday, absl::Weekday::saturday));
+
+  // Thursday -> Sunday
+  d = absl::NextWeekday(thursday, absl::Weekday::sunday);
+  EXPECT_EQ(3, d - thursday) << d;
+  EXPECT_EQ(d - 7, absl::PrevWeekday(thursday, absl::Weekday::sunday));
+
+  // Thursday -> Monday
+  d = absl::NextWeekday(thursday, absl::Weekday::monday);
+  EXPECT_EQ(4, d - thursday) << d;
+  EXPECT_EQ(d - 7, absl::PrevWeekday(thursday, absl::Weekday::monday));
+
+  // Thursday -> Tuesday
+  d = absl::NextWeekday(thursday, absl::Weekday::tuesday);
+  EXPECT_EQ(5, d - thursday) << d;
+  EXPECT_EQ(d - 7, absl::PrevWeekday(thursday, absl::Weekday::tuesday));
+
+  // Thursday -> Wednesday
+  d = absl::NextWeekday(thursday, absl::Weekday::wednesday);
+  EXPECT_EQ(6, d - thursday) << d;
+  EXPECT_EQ(d - 7, absl::PrevWeekday(thursday, absl::Weekday::wednesday));
+}
+
+// NOTE: Run this with --copt=-ftrapv to detect overflow problems.
+TEST(CivilTime, DifferenceWithHugeYear) {
+  absl::CivilDay d1(9223372036854775807, 1, 1);
+  absl::CivilDay d2(9223372036854775807, 12, 31);
+  EXPECT_EQ(364, d2 - d1);
+
+  d1 = absl::CivilDay(-9223372036854775807 - 1, 1, 1);
+  d2 = absl::CivilDay(-9223372036854775807 - 1, 12, 31);
+  EXPECT_EQ(365, d2 - d1);
+
+  // Check the limits of the return value at the end of the year range.
+  d1 = absl::CivilDay(9223372036854775807, 1, 1);
+  d2 = absl::CivilDay(9198119301927009252, 6, 6);
+  EXPECT_EQ(9223372036854775807, d1 - d2);
+  d2 = d2 - 1;
+  EXPECT_EQ(-9223372036854775807 - 1, d2 - d1);
+
+  // Check the limits of the return value at the start of the year range.
+  d1 = absl::CivilDay(-9223372036854775807 - 1, 1, 1);
+  d2 = absl::CivilDay(-9198119301927009254, 7, 28);
+  EXPECT_EQ(9223372036854775807, d2 - d1);
+  d2 = d2 + 1;
+  EXPECT_EQ(-9223372036854775807 - 1, d1 - d2);
+
+  // Check the limits of the return value from either side of year 0.
+  d1 = absl::CivilDay(-12626367463883278, 9, 3);
+  d2 = absl::CivilDay(12626367463883277, 3, 28);
+  EXPECT_EQ(9223372036854775807, d2 - d1);
+  d2 = d2 + 1;
+  EXPECT_EQ(-9223372036854775807 - 1, d1 - d2);
+}
+
+// NOTE: Run this with --copt=-ftrapv to detect overflow problems.
+TEST(CivilTime, DifferenceNoIntermediateOverflow) {
+  // The difference up to the minute field would be below the minimum
+  // int64_t, but the 52 extra seconds brings us back to the minimum.
+  absl::CivilSecond s1(-292277022657, 1, 27, 8, 29 - 1, 52);
+  absl::CivilSecond s2(1970, 1, 1, 0, 0 - 1, 0);
+  EXPECT_EQ(-9223372036854775807 - 1, s1 - s2);
+
+  // The difference up to the minute field would be above the maximum
+  // int64_t, but the -53 extra seconds brings us back to the maximum.
+  s1 = absl::CivilSecond(292277026596, 12, 4, 15, 30, 7 - 7);
+  s2 = absl::CivilSecond(1970, 1, 1, 0, 0, 0 - 7);
+  EXPECT_EQ(9223372036854775807, s1 - s2);
+}
+
+TEST(CivilTime, NormalizeSimpleOverflow) {
+  absl::CivilSecond cs;
+  cs = absl::CivilSecond(2013, 11, 15, 16, 32, 59 + 1);
+  EXPECT_EQ("2013-11-15T16:33:00", absl::FormatCivilTime(cs));
+  cs = absl::CivilSecond(2013, 11, 15, 16, 59 + 1, 14);
+  EXPECT_EQ("2013-11-15T17:00:14", absl::FormatCivilTime(cs));
+  cs = absl::CivilSecond(2013, 11, 15, 23 + 1, 32, 14);
+  EXPECT_EQ("2013-11-16T00:32:14", absl::FormatCivilTime(cs));
+  cs = absl::CivilSecond(2013, 11, 30 + 1, 16, 32, 14);
+  EXPECT_EQ("2013-12-01T16:32:14", absl::FormatCivilTime(cs));
+  cs = absl::CivilSecond(2013, 12 + 1, 15, 16, 32, 14);
+  EXPECT_EQ("2014-01-15T16:32:14", absl::FormatCivilTime(cs));
+}
+
+TEST(CivilTime, NormalizeSimpleUnderflow) {
+  absl::CivilSecond cs;
+  cs = absl::CivilSecond(2013, 11, 15, 16, 32, 0 - 1);
+  EXPECT_EQ("2013-11-15T16:31:59", absl::FormatCivilTime(cs));
+  cs = absl::CivilSecond(2013, 11, 15, 16, 0 - 1, 14);
+  EXPECT_EQ("2013-11-15T15:59:14", absl::FormatCivilTime(cs));
+  cs = absl::CivilSecond(2013, 11, 15, 0 - 1, 32, 14);
+  EXPECT_EQ("2013-11-14T23:32:14", absl::FormatCivilTime(cs));
+  cs = absl::CivilSecond(2013, 11, 1 - 1, 16, 32, 14);
+  EXPECT_EQ("2013-10-31T16:32:14", absl::FormatCivilTime(cs));
+  cs = absl::CivilSecond(2013, 1 - 1, 15, 16, 32, 14);
+  EXPECT_EQ("2012-12-15T16:32:14", absl::FormatCivilTime(cs));
+}
+
+TEST(CivilTime, NormalizeMultipleOverflow) {
+  absl::CivilSecond cs(2013, 12, 31, 23, 59, 59 + 1);
+  EXPECT_EQ("2014-01-01T00:00:00", absl::FormatCivilTime(cs));
+}
+
+TEST(CivilTime, NormalizeMultipleUnderflow) {
+  absl::CivilSecond cs(2014, 1, 1, 0, 0, 0 - 1);
+  EXPECT_EQ("2013-12-31T23:59:59", absl::FormatCivilTime(cs));
+}
+
+TEST(CivilTime, NormalizeOverflowLimits) {
+  absl::CivilSecond cs;
+
+  const int kintmax = std::numeric_limits<int>::max();
+  cs = absl::CivilSecond(0, kintmax, kintmax, kintmax, kintmax, kintmax);
+  EXPECT_EQ("185085715-11-27T12:21:07", absl::FormatCivilTime(cs));
+
+  const int kintmin = std::numeric_limits<int>::min();
+  cs = absl::CivilSecond(0, kintmin, kintmin, kintmin, kintmin, kintmin);
+  EXPECT_EQ("-185085717-10-31T10:37:52", absl::FormatCivilTime(cs));
+}
+
+TEST(CivilTime, NormalizeComplexOverflow) {
+  absl::CivilSecond cs;
+  cs = absl::CivilSecond(2013, 11, 15, 16, 32, 14 + 123456789);
+  EXPECT_EQ("2017-10-14T14:05:23", absl::FormatCivilTime(cs));
+  cs = absl::CivilSecond(2013, 11, 15, 16, 32 + 1234567, 14);
+  EXPECT_EQ("2016-03-22T00:39:14", absl::FormatCivilTime(cs));
+  cs = absl::CivilSecond(2013, 11, 15, 16 + 123456, 32, 14);
+  EXPECT_EQ("2027-12-16T16:32:14", absl::FormatCivilTime(cs));
+  cs = absl::CivilSecond(2013, 11, 15 + 1234, 16, 32, 14);
+  EXPECT_EQ("2017-04-02T16:32:14", absl::FormatCivilTime(cs));
+  cs = absl::CivilSecond(2013, 11 + 123, 15, 16, 32, 14);
+  EXPECT_EQ("2024-02-15T16:32:14", absl::FormatCivilTime(cs));
+}
+
+TEST(CivilTime, NormalizeComplexUnderflow) {
+  absl::CivilSecond cs;
+  cs = absl::CivilSecond(1999, 3, 0, 0, 0, 0);  // year 400
+  EXPECT_EQ("1999-02-28T00:00:00", absl::FormatCivilTime(cs));
+  cs = absl::CivilSecond(2013, 11, 15, 16, 32, 14 - 123456789);
+  EXPECT_EQ("2009-12-17T18:59:05", absl::FormatCivilTime(cs));
+  cs = absl::CivilSecond(2013, 11, 15, 16, 32 - 1234567, 14);
+  EXPECT_EQ("2011-07-12T08:25:14", absl::FormatCivilTime(cs));
+  cs = absl::CivilSecond(2013, 11, 15, 16 - 123456, 32, 14);
+  EXPECT_EQ("1999-10-16T16:32:14", absl::FormatCivilTime(cs));
+  cs = absl::CivilSecond(2013, 11, 15 - 1234, 16, 32, 14);
+  EXPECT_EQ("2010-06-30T16:32:14", absl::FormatCivilTime(cs));
+  cs = absl::CivilSecond(2013, 11 - 123, 15, 16, 32, 14);
+  EXPECT_EQ("2003-08-15T16:32:14", absl::FormatCivilTime(cs));
+}
+
+TEST(CivilTime, NormalizeMishmash) {
+  absl::CivilSecond cs;
+  cs = absl::CivilSecond(2013, 11 - 123, 15 + 1234, 16 - 123456, 32 + 1234567,
+                         14 - 123456789);
+  EXPECT_EQ("1991-05-09T03:06:05", absl::FormatCivilTime(cs));
+  cs = absl::CivilSecond(2013, 11 + 123, 15 - 1234, 16 + 123456, 32 - 1234567,
+                         14 + 123456789);
+  EXPECT_EQ("2036-05-24T05:58:23", absl::FormatCivilTime(cs));
+
+  cs = absl::CivilSecond(2013, 11, -146097 + 1, 16, 32, 14);
+  EXPECT_EQ("1613-11-01T16:32:14", absl::FormatCivilTime(cs));
+  cs = absl::CivilSecond(2013, 11 + 400 * 12, -146097 + 1, 16, 32, 14);
+  EXPECT_EQ("2013-11-01T16:32:14", absl::FormatCivilTime(cs));
+}
+
+// Convert all the days from 1970-1-1 to 1970-1-146097 (aka 2369-12-31)
+// and check that they normalize to the expected time.  146097 days span
+// the 400-year Gregorian cycle used during normalization.
+TEST(CivilTime, NormalizeAllTheDays) {
+  absl::CivilDay expected(1970, 1, 1);
+  for (int day = 1; day <= 146097; ++day) {
+    absl::CivilSecond cs(1970, 1, day, 0, 0, 0);
+    EXPECT_EQ(expected, cs);
+    ++expected;
+  }
+}
+
+TEST(CivilTime, NormalizeWithHugeYear) {
+  absl::CivilMonth c(9223372036854775807, 1);
+  EXPECT_EQ("9223372036854775807-01", absl::FormatCivilTime(c));
+  c = c - 1;  // Causes normalization
+  EXPECT_EQ("9223372036854775806-12", absl::FormatCivilTime(c));
+
+  c = absl::CivilMonth(-9223372036854775807 - 1, 1);
+  EXPECT_EQ("-9223372036854775808-01", absl::FormatCivilTime(c));
+  c = c + 12;  // Causes normalization
+  EXPECT_EQ("-9223372036854775807-01", absl::FormatCivilTime(c));
+}
+
+TEST(CivilTime, LeapYears) {
+  const absl::CivilSecond s1(2013, 2, 28 + 1, 0, 0, 0);
+  EXPECT_EQ("2013-03-01T00:00:00", absl::FormatCivilTime(s1));
+
+  const absl::CivilSecond s2(2012, 2, 28 + 1, 0, 0, 0);
+  EXPECT_EQ("2012-02-29T00:00:00", absl::FormatCivilTime(s2));
+
+  const absl::CivilSecond s3(1900, 2, 28 + 1, 0, 0, 0);
+  EXPECT_EQ("1900-03-01T00:00:00", absl::FormatCivilTime(s3));
+
+  const struct {
+    int year;
+    int days;
+    struct {
+      int month;
+      int day;
+    } leap_day;  // The date of the day after Feb 28.
+  } kLeapYearTable[]{
+      {1900, 365, {3, 1}},
+      {1999, 365, {3, 1}},
+      {2000, 366, {2, 29}},  // leap year
+      {2001, 365, {3, 1}},
+      {2002, 365, {3, 1}},
+      {2003, 365, {3, 1}},
+      {2004, 366, {2, 29}},  // leap year
+      {2005, 365, {3, 1}},
+      {2006, 365, {3, 1}},
+      {2007, 365, {3, 1}},
+      {2008, 366, {2, 29}},  // leap year
+      {2009, 365, {3, 1}},
+      {2100, 365, {3, 1}},
+  };
+
+  for (int i = 0; i < ABSL_ARRAYSIZE(kLeapYearTable); ++i) {
+    const int y = kLeapYearTable[i].year;
+    const int m = kLeapYearTable[i].leap_day.month;
+    const int d = kLeapYearTable[i].leap_day.day;
+    const int n = kLeapYearTable[i].days;
+
+    // Tests incrementing through the leap day.
+    const absl::CivilDay feb28(y, 2, 28);
+    const absl::CivilDay next_day = feb28 + 1;
+    EXPECT_EQ(m, next_day.month());
+    EXPECT_EQ(d, next_day.day());
+
+    // Tests difference in days of leap years.
+    const absl::CivilYear year(feb28);
+    const absl::CivilYear next_year = year + 1;
+    EXPECT_EQ(n, absl::CivilDay(next_year) - absl::CivilDay(year));
+  }
+}
+
+TEST(CivilTime, FirstThursdayInMonth) {
+  const absl::CivilDay nov1(2014, 11, 1);
+  const absl::CivilDay thursday =
+      absl::PrevWeekday(nov1, absl::Weekday::thursday) + 7;
+  EXPECT_EQ("2014-11-06", absl::FormatCivilTime(thursday));
+
+  // Bonus: Date of Thanksgiving in the United States
+  // Rule: Fourth Thursday of November
+  const absl::CivilDay thanksgiving = thursday +  7 * 3;
+  EXPECT_EQ("2014-11-27", absl::FormatCivilTime(thanksgiving));
+}
+
+TEST(CivilTime, DocumentationExample) {
+  absl::CivilSecond second(2015, 6, 28, 1, 2, 3);  // 2015-06-28 01:02:03
+  absl::CivilMinute minute(second);                // 2015-06-28 01:02:00
+  absl::CivilDay day(minute);                      // 2015-06-28 00:00:00
+
+  second -= 1;                    // 2015-06-28 01:02:02
+  --second;                       // 2015-06-28 01:02:01
+  EXPECT_EQ(minute, second - 1);  // Comparison between types
+  EXPECT_LT(minute, second);
+
+  // int diff = second - minute;  // ERROR: Mixed types, won't compile
+
+  absl::CivilDay june_1(2015, 6, 1);  // Pass fields to c'tor.
+  int diff = day - june_1;            // Num days between 'day' and June 1
+  EXPECT_EQ(27, diff);
+
+  // Fields smaller than alignment are floored to their minimum value.
+  absl::CivilDay day_floor(2015, 1, 2, 9, 9, 9);
+  EXPECT_EQ(0, day_floor.hour());  // 09:09:09 is floored
+  EXPECT_EQ(absl::CivilDay(2015, 1, 2), day_floor);
+
+  // Unspecified fields default to their minium value
+  absl::CivilDay day_default(2015);  // Defaults to Jan 1
+  EXPECT_EQ(absl::CivilDay(2015, 1, 1), day_default);
+
+  // Iterates all the days of June.
+  absl::CivilMonth june(day);  // CivilDay -> CivilMonth
+  absl::CivilMonth july = june + 1;
+  for (absl::CivilDay day = june_1; day < july; ++day) {
+    // ...
+  }
+}
+
+}  // namespace
diff --git a/absl/time/clock.cc b/absl/time/clock.cc
index 74ee140..fa0ed34 100644
--- a/absl/time/clock.cc
+++ b/absl/time/clock.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -379,7 +379,7 @@
 //
 // Manually mark this 'noinline' to minimize stack frame size of the fast
 // path.  Without this, sometimes a compiler may inline this big block of code
-// into the fast past.  That causes lots of register spills and reloads that
+// into the fast path.  That causes lots of register spills and reloads that
 // are unnecessary unless the slow path is taken.
 //
 // TODO(absl-team): Remove this attribute when our compiler is smart enough
diff --git a/absl/time/clock.h b/absl/time/clock.h
index 3753d4e..bb52e4f 100644
--- a/absl/time/clock.h
+++ b/absl/time/clock.h
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
diff --git a/absl/time/clock_benchmark.cc b/absl/time/clock_benchmark.cc
index 3d3cd9d..a69fe00 100644
--- a/absl/time/clock_benchmark.cc
+++ b/absl/time/clock_benchmark.cc
@@ -3,7 +3,7 @@
 // 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
+//      https://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,
diff --git a/absl/time/clock_test.cc b/absl/time/clock_test.cc
index 707166d..4bcfc6b 100644
--- a/absl/time/clock_test.cc
+++ b/absl/time/clock_test.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
diff --git a/absl/time/duration.cc b/absl/time/duration.cc
index 2950c7c..67791fe 100644
--- a/absl/time/duration.cc
+++ b/absl/time/duration.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -78,10 +78,16 @@
 
 // Can't use std::isinfinite() because it doesn't exist on windows.
 inline bool IsFinite(double d) {
+  if (std::isnan(d)) return false;
   return d != std::numeric_limits<double>::infinity() &&
          d != -std::numeric_limits<double>::infinity();
 }
 
+inline bool IsValidDivisor(double d) {
+  if (std::isnan(d)) return false;
+  return d != 0.0;
+}
+
 // Can't use std::round() because it is only available in C++11.
 // Note that we ignore the possibility of floating-point over/underflow.
 template <typename Double>
@@ -455,7 +461,7 @@
 }
 
 Duration& Duration::operator/=(double r) {
-  if (time_internal::IsInfiniteDuration(*this) || r == 0.0) {
+  if (time_internal::IsInfiniteDuration(*this) || !IsValidDivisor(r)) {
     const bool is_neg = (std::signbit(r) != 0) != (rep_hi_ < 0);
     return *this = is_neg ? -InfiniteDuration() : InfiniteDuration();
   }
@@ -743,9 +749,9 @@
 
 }  // namespace
 
-// From Go's doc at http://golang.org/pkg/time/#Duration.String
+// From Go's doc at https://golang.org/pkg/time/#Duration.String
 //   [FormatDuration] returns a string representing the duration in the
-//   form "72h3m0.5s".  Leading zero units are omitted.  As a special
+//   form "72h3m0.5s". Leading zero units are omitted.  As a special
 //   case, durations less than one second format use a smaller unit
 //   (milli-, micro-, or nanoseconds) to ensure that the leading digit
 //   is non-zero.  The zero duration formats as 0, with no unit.
@@ -849,8 +855,8 @@
 
 }  // namespace
 
-// From Go's doc at http://golang.org/pkg/time/#ParseDuration
-//   [ParseDuration] parses a duration string.  A duration string is
+// From Go's doc at https://golang.org/pkg/time/#ParseDuration
+//   [ParseDuration] parses a duration string. A duration string is
 //   a possibly signed sequence of decimal numbers, each with optional
 //   fraction and a unit suffix, such as "300ms", "-1.5h" or "2h45m".
 //   Valid time units are "ns", "us" "ms", "s", "m", "h".
@@ -895,6 +901,7 @@
   *d = dur;
   return true;
 }
+
 bool ParseFlag(const std::string& text, Duration* dst, std::string* ) {
   return ParseDuration(text, dst);
 }
diff --git a/absl/time/duration_benchmark.cc b/absl/time/duration_benchmark.cc
index d5657bd..83a836c 100644
--- a/absl/time/duration_benchmark.cc
+++ b/absl/time/duration_benchmark.cc
@@ -3,7 +3,7 @@
 // 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
+//      https://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,
@@ -17,6 +17,7 @@
 #include <ctime>
 #include <string>
 
+#include "absl/base/attributes.h"
 #include "absl/time/time.h"
 #include "benchmark/benchmark.h"
 
diff --git a/absl/time/duration_test.cc b/absl/time/duration_test.cc
index 7ae25dc..e3cede6 100644
--- a/absl/time/duration_test.cc
+++ b/absl/time/duration_test.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -56,6 +56,17 @@
   return false;
 }
 
+TEST(Duration, ConstExpr) {
+  constexpr absl::Duration d0 = absl::ZeroDuration();
+  static_assert(d0 == absl::ZeroDuration(), "ZeroDuration()");
+  constexpr absl::Duration d1 = absl::Seconds(1);
+  static_assert(d1 == absl::Seconds(1), "Seconds(1)");
+  static_assert(d1 != absl::ZeroDuration(), "Seconds(1)");
+  constexpr absl::Duration d2 = absl::InfiniteDuration();
+  static_assert(d2 == absl::InfiniteDuration(), "InfiniteDuration()");
+  static_assert(d2 != absl::ZeroDuration(), "InfiniteDuration()");
+}
+
 TEST(Duration, ValueSemantics) {
   // If this compiles, the test passes.
   constexpr absl::Duration a;      // Default construction
@@ -792,6 +803,40 @@
   EXPECT_EQ(-dbl_inf, absl::FDivDuration(-any_dur, zero));
 }
 
+TEST(Duration, NaN) {
+  // Note that IEEE 754 does not define the behavior of a nan's sign when it is
+  // copied, so the code below allows for either + or - InfiniteDuration.
+#define TEST_NAN_HANDLING(NAME, NAN)           \
+  do {                                         \
+    const auto inf = absl::InfiniteDuration(); \
+    auto x = NAME(NAN);                        \
+    EXPECT_TRUE(x == inf || x == -inf);        \
+    auto y = NAME(42);                         \
+    y *= NAN;                                  \
+    EXPECT_TRUE(y == inf || y == -inf);        \
+    auto z = NAME(42);                         \
+    z /= NAN;                                  \
+    EXPECT_TRUE(z == inf || z == -inf);        \
+  } while (0)
+
+  const double nan = std::numeric_limits<double>::quiet_NaN();
+  TEST_NAN_HANDLING(absl::Nanoseconds, nan);
+  TEST_NAN_HANDLING(absl::Microseconds, nan);
+  TEST_NAN_HANDLING(absl::Milliseconds, nan);
+  TEST_NAN_HANDLING(absl::Seconds, nan);
+  TEST_NAN_HANDLING(absl::Minutes, nan);
+  TEST_NAN_HANDLING(absl::Hours, nan);
+
+  TEST_NAN_HANDLING(absl::Nanoseconds, -nan);
+  TEST_NAN_HANDLING(absl::Microseconds, -nan);
+  TEST_NAN_HANDLING(absl::Milliseconds, -nan);
+  TEST_NAN_HANDLING(absl::Seconds, -nan);
+  TEST_NAN_HANDLING(absl::Minutes, -nan);
+  TEST_NAN_HANDLING(absl::Hours, -nan);
+
+#undef TEST_NAN_HANDLING
+}
+
 TEST(Duration, Range) {
   const absl::Duration range = ApproxYears(100 * 1e9);
   const absl::Duration range_future = range;
@@ -1726,7 +1771,7 @@
 TEST(Duration, FormatParseRoundTrip) {
 #define TEST_PARSE_ROUNDTRIP(d)                \
   do {                                         \
-    std::string s = absl::FormatDuration(d);        \
+    std::string s = absl::FormatDuration(d);   \
     absl::Duration dur;                        \
     EXPECT_TRUE(absl::ParseDuration(s, &dur)); \
     EXPECT_EQ(d, dur);                         \
diff --git a/absl/time/format.cc b/absl/time/format.cc
index ee597e4..d6ca860 100644
--- a/absl/time/format.cc
+++ b/absl/time/format.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -67,7 +67,8 @@
 
 }  // namespace
 
-std::string FormatTime(const std::string& format, absl::Time t, absl::TimeZone tz) {
+std::string FormatTime(const std::string& format, absl::Time t,
+                       absl::TimeZone tz) {
   if (t == absl::InfiniteFuture()) return kInfiniteFutureStr;
   if (t == absl::InfinitePast()) return kInfinitePastStr;
   const auto parts = Split(t);
@@ -83,15 +84,15 @@
   return absl::FormatTime(RFC3339_full, t, absl::LocalTimeZone());
 }
 
-bool ParseTime(const std::string& format, const std::string& input, absl::Time* time,
-               std::string* err) {
+bool ParseTime(const std::string& format, const std::string& input,
+               absl::Time* time, std::string* err) {
   return absl::ParseTime(format, input, absl::UTCTimeZone(), time, err);
 }
 
 // If the input string does not contain an explicit UTC offset, interpret
 // the fields with respect to the given TimeZone.
-bool ParseTime(const std::string& format, const std::string& input, absl::TimeZone tz,
-               absl::Time* time, std::string* err) {
+bool ParseTime(const std::string& format, const std::string& input,
+               absl::TimeZone tz, absl::Time* time, std::string* err) {
   const char* data = input.c_str();
   while (std::isspace(*data)) ++data;
 
diff --git a/absl/time/format_benchmark.cc b/absl/time/format_benchmark.cc
index ee53d71..249c51d 100644
--- a/absl/time/format_benchmark.cc
+++ b/absl/time/format_benchmark.cc
@@ -3,7 +3,7 @@
 // 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
+//      https://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,
@@ -38,7 +38,8 @@
   const absl::TimeZone lax =
       absl::time_internal::LoadTimeZone("America/Los_Angeles");
   const absl::Time t =
-      absl::FromDateTime(1977, 6, 28, 9, 8, 7, lax) + absl::Nanoseconds(1);
+      absl::FromCivil(absl::CivilSecond(1977, 6, 28, 9, 8, 7), lax) +
+      absl::Nanoseconds(1);
   while (state.KeepRunning()) {
     benchmark::DoNotOptimize(absl::FormatTime(fmt, t, lax).length());
   }
@@ -50,8 +51,8 @@
   state.SetLabel(fmt);
   const absl::TimeZone lax =
       absl::time_internal::LoadTimeZone("America/Los_Angeles");
-  absl::Time t =
-      absl::FromDateTime(1977, 6, 28, 9, 8, 7, lax) + absl::Nanoseconds(1);
+  absl::Time t = absl::FromCivil(absl::CivilSecond(1977, 6, 28, 9, 8, 7), lax) +
+                 absl::Nanoseconds(1);
   const std::string when = absl::FormatTime(fmt, t, lax);
   std::string err;
   while (state.KeepRunning()) {
diff --git a/absl/time/format_test.cc b/absl/time/format_test.cc
index 7c84c33..4a1f1aa 100644
--- a/absl/time/format_test.cc
+++ b/absl/time/format_test.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -27,8 +27,8 @@
 
 // A helper that tests the given format specifier by itself, and with leading
 // and trailing characters.  For example: TestFormatSpecifier(t, "%a", "Thu").
-void TestFormatSpecifier(absl::Time t, absl::TimeZone tz, const std::string& fmt,
-                         const std::string& ans) {
+void TestFormatSpecifier(absl::Time t, absl::TimeZone tz,
+                         const std::string& fmt, const std::string& ans) {
   EXPECT_EQ(ans, absl::FormatTime(fmt, t, tz));
   EXPECT_EQ("xxx " + ans, absl::FormatTime("xxx " + fmt, t, tz));
   EXPECT_EQ(ans + " yyy", absl::FormatTime(fmt + " yyy", t, tz));
@@ -118,7 +118,7 @@
   absl::TimeZone tz = absl::UTCTimeZone();
 
   // A year of 77 should be padded to 0077.
-  absl::Time t = absl::FromDateTime(77, 6, 28, 9, 8, 7, tz);
+  absl::Time t = absl::FromCivil(absl::CivilSecond(77, 6, 28, 9, 8, 7), tz);
   EXPECT_EQ("Mon, 28 Jun 0077 09:08:07 +0000",
             absl::FormatTime(absl::RFC1123_full, t, tz));
   EXPECT_EQ("28 Jun 0077 09:08:07 +0000",
@@ -154,9 +154,9 @@
   EXPECT_TRUE(absl::ParseTime("%Y-%m-%d %H:%M:%S %z",
                               "2013-06-28 19:08:09 -0800", &t, &err))
       << err;
-  absl::Time::Breakdown bd = t.In(absl::FixedTimeZone(-8 * 60 * 60));
-  ABSL_INTERNAL_EXPECT_TIME(bd, 2013, 6, 28, 19, 8, 9, -8 * 60 * 60, false);
-  EXPECT_EQ(absl::ZeroDuration(), bd.subsecond);
+  const auto ci = absl::FixedTimeZone(-8 * 60 * 60).At(t);
+  EXPECT_EQ(absl::CivilSecond(2013, 6, 28, 19, 8, 9), ci.cs);
+  EXPECT_EQ(absl::ZeroDuration(), ci.subsecond);
 }
 
 TEST(ParseTime, NullErrorString) {
@@ -177,17 +177,17 @@
   EXPECT_TRUE(
       absl::ParseTime("%Y-%m-%d %H:%M:%S", "2013-06-28 19:08:09", tz, &t, &e))
       << e;
-  absl::Time::Breakdown bd = t.In(tz);
-  ABSL_INTERNAL_EXPECT_TIME(bd, 2013, 6, 28, 19, 8, 9, -7 * 60 * 60, true);
-  EXPECT_EQ(absl::ZeroDuration(), bd.subsecond);
+  auto ci = tz.At(t);
+  EXPECT_EQ(absl::CivilSecond(2013, 6, 28, 19, 8, 9), ci.cs);
+  EXPECT_EQ(absl::ZeroDuration(), ci.subsecond);
 
   // But the timezone is ignored when a UTC offset is present.
   EXPECT_TRUE(absl::ParseTime("%Y-%m-%d %H:%M:%S %z",
                               "2013-06-28 19:08:09 +0800", tz, &t, &e))
       << e;
-  bd = t.In(absl::FixedTimeZone(8 * 60 * 60));
-  ABSL_INTERNAL_EXPECT_TIME(bd, 2013, 6, 28, 19, 8, 9, 8 * 60 * 60, false);
-  EXPECT_EQ(absl::ZeroDuration(), bd.subsecond);
+  ci = absl::FixedTimeZone(8 * 60 * 60).At(t);
+  EXPECT_EQ(absl::CivilSecond(2013, 6, 28, 19, 8, 9), ci.cs);
+  EXPECT_EQ(absl::ZeroDuration(), ci.subsecond);
 }
 
 TEST(ParseTime, ErrorCases) {
@@ -332,15 +332,15 @@
   EXPECT_TRUE(absl::ParseTime("infinite-future %H:%M", "infinite-future 03:04",
                               &t, &err));
   EXPECT_NE(absl::InfiniteFuture(), t);
-  EXPECT_EQ(3, t.In(tz).hour);
-  EXPECT_EQ(4, t.In(tz).minute);
+  EXPECT_EQ(3, tz.At(t).cs.hour());
+  EXPECT_EQ(4, tz.At(t).cs.minute());
 
   // "infinite-past" as literal std::string
   EXPECT_TRUE(
       absl::ParseTime("infinite-past %H:%M", "infinite-past 03:04", &t, &err));
   EXPECT_NE(absl::InfinitePast(), t);
-  EXPECT_EQ(3, t.In(tz).hour);
-  EXPECT_EQ(4, t.In(tz).minute);
+  EXPECT_EQ(3, tz.At(t).cs.hour());
+  EXPECT_EQ(4, tz.At(t).cs.minute());
 
   // The input doesn't match the format.
   EXPECT_FALSE(absl::ParseTime("infinite-future %H:%M", "03:04", &t, &err));
@@ -365,16 +365,18 @@
 //
 
 TEST(FormatParse, RoundTrip) {
-  const absl::TimeZone gst =
+  const absl::TimeZone lax =
       absl::time_internal::LoadTimeZone("America/Los_Angeles");
-  const absl::Time in = absl::FromDateTime(1977, 6, 28, 9, 8, 7, gst);
+  const absl::Time in =
+      absl::FromCivil(absl::CivilSecond(1977, 6, 28, 9, 8, 7), lax);
   const absl::Duration subseconds = absl::Nanoseconds(654321);
   std::string err;
 
   // RFC3339, which renders subseconds.
   {
     absl::Time out;
-    const std::string s = absl::FormatTime(absl::RFC3339_full, in + subseconds, gst);
+    const std::string s =
+        absl::FormatTime(absl::RFC3339_full, in + subseconds, lax);
     EXPECT_TRUE(absl::ParseTime(absl::RFC3339_full, s, &out, &err))
         << s << ": " << err;
     EXPECT_EQ(in + subseconds, out);  // RFC3339_full includes %Ez
@@ -383,7 +385,7 @@
   // RFC1123, which only does whole seconds.
   {
     absl::Time out;
-    const std::string s = absl::FormatTime(absl::RFC1123_full, in, gst);
+    const std::string s = absl::FormatTime(absl::RFC1123_full, in, lax);
     EXPECT_TRUE(absl::ParseTime(absl::RFC1123_full, s, &out, &err))
         << s << ": " << err;
     EXPECT_EQ(in, out);  // RFC1123_full includes %z
@@ -393,7 +395,12 @@
   // work. On Windows, `absl::ParseTime()` falls back to std::get_time() which
   // appears to fail on "%c" (or at least on the "%c" text produced by
   // `strftime()`). This makes it fail the round-trip test.
-#ifndef _MSC_VER
+  //
+  // Under the emscripten compiler `absl::ParseTime() falls back to
+  // `strptime()`, but that ends up using a different definition for "%c"
+  // compared to `strftime()`, also causing the round-trip test to fail
+  // (see https://github.com/kripken/emscripten/pull/7491).
+#if !defined(_MSC_VER) && !defined(__EMSCRIPTEN__)
   // Even though we don't know what %c will produce, it should roundtrip,
   // but only in the 0-offset timezone.
   {
@@ -402,7 +409,7 @@
     EXPECT_TRUE(absl::ParseTime("%c", s, &out, &err)) << s << ": " << err;
     EXPECT_EQ(in, out);
   }
-#endif  // _MSC_VER
+#endif  // !_MSC_VER && !__EMSCRIPTEN__
 }
 
 TEST(FormatParse, RoundTripDistantFuture) {
diff --git a/absl/time/internal/cctz/BUILD.bazel b/absl/time/internal/cctz/BUILD.bazel
index 9f1ba21..903499b 100644
--- a/absl/time/internal/cctz/BUILD.bazel
+++ b/absl/time/internal/cctz/BUILD.bazel
@@ -4,7 +4,7 @@
 # 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
+#   https://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,
@@ -12,6 +12,8 @@
 #   See the License for the specific language governing permissions and
 #   limitations under the License.
 
+package(features = ["-parse_headers"])
+
 licenses(["notice"])  # Apache License
 
 ### libraries
@@ -85,6 +87,7 @@
         "no_test_android_arm",
         "no_test_android_arm64",
         "no_test_android_x86",
+        "no_test_wasm",
     ],
     deps = [
         ":civil_time",
@@ -96,12 +99,14 @@
 cc_test(
     name = "time_zone_lookup_test",
     size = "small",
+    timeout = "moderate",
     srcs = ["src/time_zone_lookup_test.cc"],
     data = [":zoneinfo"],
     tags = [
         "no_test_android_arm",
         "no_test_android_arm64",
         "no_test_android_x86",
+        "no_test_wasm",
     ],
     deps = [
         ":civil_time",
diff --git a/absl/time/internal/cctz/include/cctz/civil_time.h b/absl/time/internal/cctz/include/cctz/civil_time.h
index 0842fa4..f844182 100644
--- a/absl/time/internal/cctz/include/cctz/civil_time.h
+++ b/absl/time/internal/cctz/include/cctz/civil_time.h
@@ -4,7 +4,7 @@
 // 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
+//   https://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,
diff --git a/absl/time/internal/cctz/include/cctz/civil_time_detail.h b/absl/time/internal/cctz/include/cctz/civil_time_detail.h
index d7f7271..a5923f1 100644
--- a/absl/time/internal/cctz/include/cctz/civil_time_detail.h
+++ b/absl/time/internal/cctz/include/cctz/civil_time_detail.h
@@ -4,7 +4,7 @@
 // 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
+//   https://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,
@@ -326,6 +326,37 @@
 
 ////////////////////////////////////////////////////////////////////////
 
+namespace impl {
+
+template <typename H>
+H AbslHashValueImpl(second_tag, H h, fields f) {
+  return H::combine(std::move(h), f.y, f.m, f.d, f.hh, f.mm, f.ss);
+}
+template <typename H>
+H AbslHashValueImpl(minute_tag, H h, fields f) {
+  return H::combine(std::move(h), f.y, f.m, f.d, f.hh, f.mm);
+}
+template <typename H>
+H AbslHashValueImpl(hour_tag, H h, fields f) {
+  return H::combine(std::move(h), f.y, f.m, f.d, f.hh);
+}
+template <typename H>
+H AbslHashValueImpl(day_tag, H h, fields f) {
+  return H::combine(std::move(h), f.y, f.m, f.d);
+}
+template <typename H>
+H AbslHashValueImpl(month_tag, H h, fields f) {
+  return H::combine(std::move(h), f.y, f.m);
+}
+template <typename H>
+H AbslHashValueImpl(year_tag, H h, fields f) {
+  return H::combine(std::move(h), f.y);
+}
+
+}  // namespace impl
+
+////////////////////////////////////////////////////////////////////////
+
 template <typename T>
 class civil_time {
  public:
@@ -355,12 +386,12 @@
       : civil_time(ct.f_) {}
 
   // Factories for the maximum/minimum representable civil_time.
-  static CONSTEXPR_F civil_time max() {
-    const auto max_year = std::numeric_limits<std::int_least64_t>::max();
+  static CONSTEXPR_F civil_time (max)() {
+    const auto max_year = (std::numeric_limits<std::int_least64_t>::max)();
     return civil_time(max_year, 12, 31, 23, 59, 59);
   }
-  static CONSTEXPR_F civil_time min() {
-    const auto min_year = std::numeric_limits<std::int_least64_t>::min();
+  static CONSTEXPR_F civil_time (min)() {
+    const auto min_year = (std::numeric_limits<std::int_least64_t>::min)();
     return civil_time(min_year, 1, 1, 0, 0, 0);
   }
 
@@ -378,7 +409,7 @@
     return *this;
   }
   CONSTEXPR_M civil_time& operator-=(diff_t n) noexcept {
-    if (n != std::numeric_limits<diff_t>::min()) {
+    if (n != (std::numeric_limits<diff_t>::min)()) {
       f_ = step(T{}, f_, -n);
     } else {
       f_ = step(T{}, step(T{}, f_, -(n + 1)), 1);
@@ -418,8 +449,7 @@
 
   template <typename H>
   friend H AbslHashValue(H h, civil_time a) {
-    return H::combine(std::move(h), a.f_.y, a.f_.m, a.f_.d,
-                                    a.f_.hh, a.f_.mm, a.f_.ss);
+    return impl::AbslHashValueImpl(T{}, std::move(h), a.f_);
   }
 
  private:
@@ -506,9 +536,11 @@
 };
 
 CONSTEXPR_F weekday get_weekday(const civil_day& cd) noexcept {
-  CONSTEXPR_D weekday k_weekday_by_sun_off[7] = {
-      weekday::sunday,     weekday::monday,    weekday::tuesday,
-      weekday::wednesday,  weekday::thursday,  weekday::friday,
+  CONSTEXPR_D weekday k_weekday_by_mon_off[13] = {
+      weekday::monday,    weekday::tuesday,  weekday::wednesday,
+      weekday::thursday,  weekday::friday,   weekday::saturday,
+      weekday::sunday,    weekday::monday,   weekday::tuesday,
+      weekday::wednesday, weekday::thursday, weekday::friday,
       weekday::saturday,
   };
   CONSTEXPR_D int k_weekday_offsets[1 + 12] = {
@@ -517,7 +549,7 @@
   year_t wd = 2400 + (cd.year() % 400) - (cd.month() < 3);
   wd += wd / 4 - wd / 100 + wd / 400;
   wd += k_weekday_offsets[cd.month()] + cd.day();
-  return k_weekday_by_sun_off[(wd % 7 + 7) % 7];
+  return k_weekday_by_mon_off[wd % 7 + 6];
 }
 
 ////////////////////////////////////////////////////////////////////////
diff --git a/absl/time/internal/cctz/include/cctz/time_zone.h b/absl/time/internal/cctz/include/cctz/time_zone.h
index f28dad1..ef6c4ba 100644
--- a/absl/time/internal/cctz/include/cctz/time_zone.h
+++ b/absl/time/internal/cctz/include/cctz/time_zone.h
@@ -4,7 +4,7 @@
 // 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
+//   https://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,
@@ -72,7 +72,7 @@
 //
 // See also:
 // - http://www.iana.org/time-zones
-// - http://en.wikipedia.org/wiki/Zoneinfo
+// - https://en.wikipedia.org/wiki/Zoneinfo
 class time_zone {
  public:
   time_zone() : time_zone(nullptr) {}  // Equivalent to UTC
diff --git a/absl/time/internal/cctz/include/cctz/zone_info_source.h b/absl/time/internal/cctz/include/cctz/zone_info_source.h
index 20a7697..2b898d1 100644
--- a/absl/time/internal/cctz/include/cctz/zone_info_source.h
+++ b/absl/time/internal/cctz/include/cctz/zone_info_source.h
@@ -4,7 +4,7 @@
 // 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
+//   https://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,
diff --git a/absl/time/internal/cctz/src/cctz_benchmark.cc b/absl/time/internal/cctz/src/cctz_benchmark.cc
index 4498d7d..445366e 100644
--- a/absl/time/internal/cctz/src/cctz_benchmark.cc
+++ b/absl/time/internal/cctz/src/cctz_benchmark.cc
@@ -4,7 +4,7 @@
 // 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
+//   https://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,
@@ -357,6 +357,7 @@
   "Asia/Pontianak",
   "Asia/Pyongyang",
   "Asia/Qatar",
+  "Asia/Qostanay",
   "Asia/Qyzylorda",
   "Asia/Rangoon",
   "Asia/Riyadh",
diff --git a/absl/time/internal/cctz/src/civil_time_detail.cc b/absl/time/internal/cctz/src/civil_time_detail.cc
index 780d5c9..cb40b6b 100644
--- a/absl/time/internal/cctz/src/civil_time_detail.cc
+++ b/absl/time/internal/cctz/src/civil_time_detail.cc
@@ -4,7 +4,7 @@
 // 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
+//   https://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,
diff --git a/absl/time/internal/cctz/src/civil_time_test.cc b/absl/time/internal/cctz/src/civil_time_test.cc
index faffde4..e590ee3 100644
--- a/absl/time/internal/cctz/src/civil_time_test.cc
+++ b/absl/time/internal/cctz/src/civil_time_test.cc
@@ -4,7 +4,7 @@
 // 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
+//   https://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,
diff --git a/absl/time/internal/cctz/src/time_zone_fixed.cc b/absl/time/internal/cctz/src/time_zone_fixed.cc
index db9a475..81ece72 100644
--- a/absl/time/internal/cctz/src/time_zone_fixed.cc
+++ b/absl/time/internal/cctz/src/time_zone_fixed.cc
@@ -4,7 +4,7 @@
 // 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
+//   https://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,
diff --git a/absl/time/internal/cctz/src/time_zone_fixed.h b/absl/time/internal/cctz/src/time_zone_fixed.h
index 489b857..9c1f5e7 100644
--- a/absl/time/internal/cctz/src/time_zone_fixed.h
+++ b/absl/time/internal/cctz/src/time_zone_fixed.h
@@ -4,7 +4,7 @@
 // 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
+//   https://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,
diff --git a/absl/time/internal/cctz/src/time_zone_format.cc b/absl/time/internal/cctz/src/time_zone_format.cc
index a02b1e3..2585098 100644
--- a/absl/time/internal/cctz/src/time_zone_format.cc
+++ b/absl/time/internal/cctz/src/time_zone_format.cc
@@ -4,7 +4,7 @@
 // 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
+//   https://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,
@@ -13,7 +13,7 @@
 //   limitations under the License.
 
 #if !defined(HAS_STRPTIME)
-# if !defined(_MSC_VER)
+# if !defined(_MSC_VER) && !defined(__MINGW32__)
 #  define HAS_STRPTIME 1  // assume everyone has strptime() except windows
 # endif
 #endif
@@ -149,15 +149,25 @@
     offset = -offset;  // bounded by 24h so no overflow
     sign = '-';
   }
-  char sep = mode[0];
-  if (sep != '\0' && mode[1] == '*') {
-    ep = Format02d(ep, offset % 60);
+  const int seconds = offset % 60;
+  const int minutes = (offset /= 60) % 60;
+  const int hours = offset /= 60;
+  const char sep = mode[0];
+  const bool ext = (sep != '\0' && mode[1] == '*');
+  const bool ccc = (ext && mode[2] == ':');
+  if (ext && (!ccc || seconds != 0)) {
+    ep = Format02d(ep, seconds);
     *--ep = sep;
+  } else {
+    // If we're not rendering seconds, sub-minute negative offsets
+    // should get a positive sign (e.g., offset=-10s => "+00:00").
+    if (hours == 0 && minutes == 0) sign = '+';
   }
-  int minutes = offset / 60;
-  ep = Format02d(ep, minutes % 60);
-  if (sep != '\0') *--ep = sep;
-  ep = Format02d(ep, minutes / 60);
+  if (!ccc || minutes != 0 || seconds != 0) {
+    ep = Format02d(ep, minutes);
+    if (sep != '\0') *--ep = sep;
+  }
+  ep = Format02d(ep, hours);
   *--ep = sign;
   return ep;
 }
@@ -384,6 +394,44 @@
       continue;
     }
 
+    // More complex specifiers that we handle ourselves.
+    if (*cur == ':' && cur + 1 != end) {
+      if (*(cur + 1) == 'z') {
+        // Formats %:z.
+        if (cur - 1 != pending) {
+          FormatTM(&result, std::string(pending, cur - 1), tm);
+        }
+        bp = FormatOffset(ep, al.offset, ":");
+        result.append(bp, static_cast<std::size_t>(ep - bp));
+        pending = cur += 2;
+        continue;
+      }
+      if (*(cur + 1) == ':' && cur + 2 != end) {
+        if (*(cur + 2) == 'z') {
+          // Formats %::z.
+          if (cur - 1 != pending) {
+            FormatTM(&result, std::string(pending, cur - 1), tm);
+          }
+          bp = FormatOffset(ep, al.offset, ":*");
+          result.append(bp, static_cast<std::size_t>(ep - bp));
+          pending = cur += 3;
+          continue;
+        }
+        if (*(cur + 2) == ':' && cur + 3 != end) {
+          if (*(cur + 3) == 'z') {
+            // Formats %:::z.
+            if (cur - 1 != pending) {
+              FormatTM(&result, std::string(pending, cur - 1), tm);
+            }
+            bp = FormatOffset(ep, al.offset, ":*:");
+            result.append(bp, static_cast<std::size_t>(ep - bp));
+            pending = cur += 4;
+            continue;
+          }
+        }
+      }
+    }
+
     // Loop if there is no E modifier.
     if (*cur != 'E' || ++cur == end) continue;
 
@@ -668,17 +716,27 @@
                         &percent_s);
         if (data != nullptr) saw_percent_s = true;
         continue;
+      case ':':
+        if (fmt[0] == 'z' ||
+            (fmt[0] == ':' &&
+             (fmt[1] == 'z' || (fmt[1] == ':' && fmt[2] == 'z')))) {
+          data = ParseOffset(data, ":", &offset);
+          if (data != nullptr) saw_offset = true;
+          fmt += (fmt[0] == 'z') ? 1 : (fmt[1] == 'z') ? 2 : 3;
+          continue;
+        }
+        break;
       case '%':
         data = (*data == '%' ? data + 1 : nullptr);
         continue;
       case 'E':
-        if (*fmt == 'z' || (*fmt == '*' && *(fmt + 1) == 'z')) {
+        if (fmt[0] == 'z' || (fmt[0] == '*' && fmt[1] == 'z')) {
           data = ParseOffset(data, ":", &offset);
           if (data != nullptr) saw_offset = true;
-          fmt += (*fmt == 'z') ? 1 : 2;
+          fmt += (fmt[0] == 'z') ? 1 : 2;
           continue;
         }
-        if (*fmt == '*' && *(fmt + 1) == 'S') {
+        if (fmt[0] == '*' && fmt[1] == 'S') {
           data = ParseInt(data, 2, 0, 60, &tm.tm_sec);
           if (data != nullptr && *data == '.') {
             data = ParseSubSeconds(data + 1, &subseconds);
@@ -686,14 +744,14 @@
           fmt += 2;
           continue;
         }
-        if (*fmt == '*' && *(fmt + 1) == 'f') {
+        if (fmt[0] == '*' && fmt[1] == 'f') {
           if (data != nullptr && std::isdigit(*data)) {
             data = ParseSubSeconds(data, &subseconds);
           }
           fmt += 2;
           continue;
         }
-        if (*fmt == '4' && *(fmt + 1) == 'Y') {
+        if (fmt[0] == '4' && fmt[1] == 'Y') {
           const char* bp = data;
           data = ParseInt(data, 4, year_t{-999}, year_t{9999}, &year);
           if (data != nullptr) {
diff --git a/absl/time/internal/cctz/src/time_zone_format_test.cc b/absl/time/internal/cctz/src/time_zone_format_test.cc
index 6b9928e..705ccdc 100644
--- a/absl/time/internal/cctz/src/time_zone_format_test.cc
+++ b/absl/time/internal/cctz/src/time_zone_format_test.cc
@@ -4,7 +4,7 @@
 // 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
+//   https://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,
@@ -64,17 +64,6 @@
   EXPECT_EQ("xxx " + ans + " yyy", format("xxx " + fmt + " yyy", tp, tz));
 }
 
-// These tests sometimes run on platforms that have zoneinfo data so old
-// that the transition we are attempting to check does not exist, most
-// notably Android emulators.  Fortunately, AndroidZoneInfoSource supports
-// time_zone::version() so, in cases where we've learned that it matters,
-// we can make the check conditionally.
-int VersionCmp(time_zone tz, const std::string& target) {
-  std::string version = tz.version();
-  if (version.empty() && !target.empty()) return 1;  // unknown > known
-  return version.compare(target);
-}
-
 }  // namespace
 
 //
@@ -174,7 +163,9 @@
   TestFormatSpecifier(tp, tz, "%M", "00");
   TestFormatSpecifier(tp, tz, "%S", "00");
   TestFormatSpecifier(tp, tz, "%U", "00");
+#if !defined(__EMSCRIPTEN__)
   TestFormatSpecifier(tp, tz, "%w", "4");  // 4=Thursday
+#endif
   TestFormatSpecifier(tp, tz, "%W", "00");
   TestFormatSpecifier(tp, tz, "%y", "70");
   TestFormatSpecifier(tp, tz, "%Y", "1970");
@@ -436,51 +427,165 @@
 }
 
 TEST(Format, ExtendedOffset) {
-  auto tp = chrono::system_clock::from_time_t(0);
+  const auto tp = chrono::system_clock::from_time_t(0);
 
-  time_zone tz = utc_time_zone();
+  auto tz = fixed_time_zone(absl::time_internal::cctz::seconds::zero());
+  TestFormatSpecifier(tp, tz, "%z", "+0000");
+  TestFormatSpecifier(tp, tz, "%:z", "+00:00");
   TestFormatSpecifier(tp, tz, "%Ez", "+00:00");
 
-  EXPECT_TRUE(load_time_zone("America/New_York", &tz));
-  TestFormatSpecifier(tp, tz, "%Ez", "-05:00");
+  tz = fixed_time_zone(chrono::seconds(56));
+  TestFormatSpecifier(tp, tz, "%z", "+0000");
+  TestFormatSpecifier(tp, tz, "%:z", "+00:00");
+  TestFormatSpecifier(tp, tz, "%Ez", "+00:00");
 
-  EXPECT_TRUE(load_time_zone("America/Los_Angeles", &tz));
-  TestFormatSpecifier(tp, tz, "%Ez", "-08:00");
+  tz = fixed_time_zone(-chrono::seconds(56));  // NOTE: +00:00
+  TestFormatSpecifier(tp, tz, "%z", "+0000");
+  TestFormatSpecifier(tp, tz, "%:z", "+00:00");
+  TestFormatSpecifier(tp, tz, "%Ez", "+00:00");
 
-  EXPECT_TRUE(load_time_zone("Australia/Sydney", &tz));
-  TestFormatSpecifier(tp, tz, "%Ez", "+10:00");
+  tz = fixed_time_zone(chrono::minutes(34));
+  TestFormatSpecifier(tp, tz, "%z", "+0034");
+  TestFormatSpecifier(tp, tz, "%:z", "+00:34");
+  TestFormatSpecifier(tp, tz, "%Ez", "+00:34");
 
-  EXPECT_TRUE(load_time_zone("Africa/Monrovia", &tz));
-  // The true offset is -00:44:30 but %z only gives (truncated) minutes.
-  TestFormatSpecifier(tp, tz, "%z", "-0044");
-  TestFormatSpecifier(tp, tz, "%Ez", "-00:44");
+  tz = fixed_time_zone(-chrono::minutes(34));
+  TestFormatSpecifier(tp, tz, "%z", "-0034");
+  TestFormatSpecifier(tp, tz, "%:z", "-00:34");
+  TestFormatSpecifier(tp, tz, "%Ez", "-00:34");
+
+  tz = fixed_time_zone(chrono::minutes(34) + chrono::seconds(56));
+  TestFormatSpecifier(tp, tz, "%z", "+0034");
+  TestFormatSpecifier(tp, tz, "%:z", "+00:34");
+  TestFormatSpecifier(tp, tz, "%Ez", "+00:34");
+
+  tz = fixed_time_zone(-chrono::minutes(34) - chrono::seconds(56));
+  TestFormatSpecifier(tp, tz, "%z", "-0034");
+  TestFormatSpecifier(tp, tz, "%:z", "-00:34");
+  TestFormatSpecifier(tp, tz, "%Ez", "-00:34");
+
+  tz = fixed_time_zone(chrono::hours(12));
+  TestFormatSpecifier(tp, tz, "%z", "+1200");
+  TestFormatSpecifier(tp, tz, "%:z", "+12:00");
+  TestFormatSpecifier(tp, tz, "%Ez", "+12:00");
+
+  tz = fixed_time_zone(-chrono::hours(12));
+  TestFormatSpecifier(tp, tz, "%z", "-1200");
+  TestFormatSpecifier(tp, tz, "%:z", "-12:00");
+  TestFormatSpecifier(tp, tz, "%Ez", "-12:00");
+
+  tz = fixed_time_zone(chrono::hours(12) + chrono::seconds(56));
+  TestFormatSpecifier(tp, tz, "%z", "+1200");
+  TestFormatSpecifier(tp, tz, "%:z", "+12:00");
+  TestFormatSpecifier(tp, tz, "%Ez", "+12:00");
+
+  tz = fixed_time_zone(-chrono::hours(12) - chrono::seconds(56));
+  TestFormatSpecifier(tp, tz, "%z", "-1200");
+  TestFormatSpecifier(tp, tz, "%:z", "-12:00");
+  TestFormatSpecifier(tp, tz, "%Ez", "-12:00");
+
+  tz = fixed_time_zone(chrono::hours(12) + chrono::minutes(34));
+  TestFormatSpecifier(tp, tz, "%z", "+1234");
+  TestFormatSpecifier(tp, tz, "%:z", "+12:34");
+  TestFormatSpecifier(tp, tz, "%Ez", "+12:34");
+
+  tz = fixed_time_zone(-chrono::hours(12) - chrono::minutes(34));
+  TestFormatSpecifier(tp, tz, "%z", "-1234");
+  TestFormatSpecifier(tp, tz, "%:z", "-12:34");
+  TestFormatSpecifier(tp, tz, "%Ez", "-12:34");
+
+  tz = fixed_time_zone(chrono::hours(12) + chrono::minutes(34) +
+                       chrono::seconds(56));
+  TestFormatSpecifier(tp, tz, "%z", "+1234");
+  TestFormatSpecifier(tp, tz, "%:z", "+12:34");
+  TestFormatSpecifier(tp, tz, "%Ez", "+12:34");
+
+  tz = fixed_time_zone(-chrono::hours(12) - chrono::minutes(34) -
+                       chrono::seconds(56));
+  TestFormatSpecifier(tp, tz, "%z", "-1234");
+  TestFormatSpecifier(tp, tz, "%:z", "-12:34");
+  TestFormatSpecifier(tp, tz, "%Ez", "-12:34");
 }
 
 TEST(Format, ExtendedSecondOffset) {
-  const time_zone utc = utc_time_zone();
-  time_point<chrono::seconds> tp;
-  time_zone tz;
+  const auto tp = chrono::system_clock::from_time_t(0);
 
-  EXPECT_TRUE(load_time_zone("America/New_York", &tz));
-  tp = convert(civil_second(1883, 11, 18, 16, 59, 59), utc);
-  if (tz.lookup(tp).offset == -5 * 60 * 60) {
-    // It looks like the tzdata is only 32 bit (probably macOS),
-    // which bottoms out at 1901-12-13T20:45:52+00:00.
-  } else {
-    TestFormatSpecifier(tp, tz, "%E*z", "-04:56:02");
-    TestFormatSpecifier(tp, tz, "%Ez", "-04:56");
-  }
-  tp += chrono::seconds(1);
-  TestFormatSpecifier(tp, tz, "%E*z", "-05:00:00");
+  auto tz = fixed_time_zone(absl::time_internal::cctz::seconds::zero());
+  TestFormatSpecifier(tp, tz, "%E*z", "+00:00:00");
+  TestFormatSpecifier(tp, tz, "%::z", "+00:00:00");
+  TestFormatSpecifier(tp, tz, "%:::z", "+00");
 
-  EXPECT_TRUE(load_time_zone("Europe/Moscow", &tz));
-  tp = convert(civil_second(1919, 6, 30, 23, 59, 59), utc);
-  if (VersionCmp(tz, "2016g") >= 0) {
-    TestFormatSpecifier(tp, tz, "%E*z", "+04:31:19");
-    TestFormatSpecifier(tp, tz, "%Ez", "+04:31");
-  }
-  tp += chrono::seconds(1);
-  TestFormatSpecifier(tp, tz, "%E*z", "+04:00:00");
+  tz = fixed_time_zone(chrono::seconds(56));
+  TestFormatSpecifier(tp, tz, "%E*z", "+00:00:56");
+  TestFormatSpecifier(tp, tz, "%::z", "+00:00:56");
+  TestFormatSpecifier(tp, tz, "%:::z", "+00:00:56");
+
+  tz = fixed_time_zone(-chrono::seconds(56));
+  TestFormatSpecifier(tp, tz, "%E*z", "-00:00:56");
+  TestFormatSpecifier(tp, tz, "%::z", "-00:00:56");
+  TestFormatSpecifier(tp, tz, "%:::z", "-00:00:56");
+
+  tz = fixed_time_zone(chrono::minutes(34));
+  TestFormatSpecifier(tp, tz, "%E*z", "+00:34:00");
+  TestFormatSpecifier(tp, tz, "%::z", "+00:34:00");
+  TestFormatSpecifier(tp, tz, "%:::z", "+00:34");
+
+  tz = fixed_time_zone(-chrono::minutes(34));
+  TestFormatSpecifier(tp, tz, "%E*z", "-00:34:00");
+  TestFormatSpecifier(tp, tz, "%::z", "-00:34:00");
+  TestFormatSpecifier(tp, tz, "%:::z", "-00:34");
+
+  tz = fixed_time_zone(chrono::minutes(34) + chrono::seconds(56));
+  TestFormatSpecifier(tp, tz, "%E*z", "+00:34:56");
+  TestFormatSpecifier(tp, tz, "%::z", "+00:34:56");
+  TestFormatSpecifier(tp, tz, "%:::z", "+00:34:56");
+
+  tz = fixed_time_zone(-chrono::minutes(34) - chrono::seconds(56));
+  TestFormatSpecifier(tp, tz, "%E*z", "-00:34:56");
+  TestFormatSpecifier(tp, tz, "%::z", "-00:34:56");
+  TestFormatSpecifier(tp, tz, "%:::z", "-00:34:56");
+
+  tz = fixed_time_zone(chrono::hours(12));
+  TestFormatSpecifier(tp, tz, "%E*z", "+12:00:00");
+  TestFormatSpecifier(tp, tz, "%::z", "+12:00:00");
+  TestFormatSpecifier(tp, tz, "%:::z", "+12");
+
+  tz = fixed_time_zone(-chrono::hours(12));
+  TestFormatSpecifier(tp, tz, "%E*z", "-12:00:00");
+  TestFormatSpecifier(tp, tz, "%::z", "-12:00:00");
+  TestFormatSpecifier(tp, tz, "%:::z", "-12");
+
+  tz = fixed_time_zone(chrono::hours(12) + chrono::seconds(56));
+  TestFormatSpecifier(tp, tz, "%E*z", "+12:00:56");
+  TestFormatSpecifier(tp, tz, "%::z", "+12:00:56");
+  TestFormatSpecifier(tp, tz, "%:::z", "+12:00:56");
+
+  tz = fixed_time_zone(-chrono::hours(12) - chrono::seconds(56));
+  TestFormatSpecifier(tp, tz, "%E*z", "-12:00:56");
+  TestFormatSpecifier(tp, tz, "%::z", "-12:00:56");
+  TestFormatSpecifier(tp, tz, "%:::z", "-12:00:56");
+
+  tz = fixed_time_zone(chrono::hours(12) + chrono::minutes(34));
+  TestFormatSpecifier(tp, tz, "%E*z", "+12:34:00");
+  TestFormatSpecifier(tp, tz, "%::z", "+12:34:00");
+  TestFormatSpecifier(tp, tz, "%:::z", "+12:34");
+
+  tz = fixed_time_zone(-chrono::hours(12) - chrono::minutes(34));
+  TestFormatSpecifier(tp, tz, "%E*z", "-12:34:00");
+  TestFormatSpecifier(tp, tz, "%::z", "-12:34:00");
+  TestFormatSpecifier(tp, tz, "%:::z", "-12:34");
+
+  tz = fixed_time_zone(chrono::hours(12) + chrono::minutes(34) +
+                       chrono::seconds(56));
+  TestFormatSpecifier(tp, tz, "%E*z", "+12:34:56");
+  TestFormatSpecifier(tp, tz, "%::z", "+12:34:56");
+  TestFormatSpecifier(tp, tz, "%:::z", "+12:34:56");
+
+  tz = fixed_time_zone(-chrono::hours(12) - chrono::minutes(34) -
+                       chrono::seconds(56));
+  TestFormatSpecifier(tp, tz, "%E*z", "-12:34:56");
+  TestFormatSpecifier(tp, tz, "%::z", "-12:34:56");
+  TestFormatSpecifier(tp, tz, "%:::z", "-12:34:56");
 }
 
 TEST(Format, ExtendedYears) {
@@ -1160,25 +1265,6 @@
   const time_zone utc = utc_time_zone();
   time_point<absl::time_internal::cctz::seconds> tp;
 
-  // %z against +-HHMM.
-  EXPECT_TRUE(parse("%z", "+0000", utc, &tp));
-  EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp);
-  EXPECT_TRUE(parse("%z", "-1234", utc, &tp));
-  EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 34, 0), utc), tp);
-  EXPECT_TRUE(parse("%z", "+1234", utc, &tp));
-  EXPECT_EQ(convert(civil_second(1969, 12, 31, 11, 26, 0), utc), tp);
-  EXPECT_FALSE(parse("%z", "-123", utc, &tp));
-
-  // %z against +-HH.
-  EXPECT_TRUE(parse("%z", "+00", utc, &tp));
-  EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp);
-  EXPECT_TRUE(parse("%z", "-12", utc, &tp));
-  EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 0, 0), utc), tp);
-  EXPECT_TRUE(parse("%z", "+12", utc, &tp));
-  EXPECT_EQ(convert(civil_second(1969, 12, 31, 12, 0, 0), utc), tp);
-  EXPECT_FALSE(parse("%z", "-1", utc, &tp));
-
-  // %Ez against +-HH:MM.
   EXPECT_TRUE(parse("%Ez", "+00:00", utc, &tp));
   EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp);
   EXPECT_TRUE(parse("%Ez", "-12:34", utc, &tp));
@@ -1187,91 +1273,70 @@
   EXPECT_EQ(convert(civil_second(1969, 12, 31, 11, 26, 0), utc), tp);
   EXPECT_FALSE(parse("%Ez", "-12:3", utc, &tp));
 
-  // %Ez against +-HHMM.
-  EXPECT_TRUE(parse("%Ez", "+0000", utc, &tp));
-  EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp);
-  EXPECT_TRUE(parse("%Ez", "-1234", utc, &tp));
-  EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 34, 0), utc), tp);
-  EXPECT_TRUE(parse("%Ez", "+1234", utc, &tp));
-  EXPECT_EQ(convert(civil_second(1969, 12, 31, 11, 26, 0), utc), tp);
-  EXPECT_FALSE(parse("%Ez", "-123", utc, &tp));
+  for (auto fmt : {"%Ez", "%z"}) {
+    EXPECT_TRUE(parse(fmt, "+0000", utc, &tp));
+    EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp);
+    EXPECT_TRUE(parse(fmt, "-1234", utc, &tp));
+    EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 34, 0), utc), tp);
+    EXPECT_TRUE(parse(fmt, "+1234", utc, &tp));
+    EXPECT_EQ(convert(civil_second(1969, 12, 31, 11, 26, 0), utc), tp);
+    EXPECT_FALSE(parse(fmt, "-123", utc, &tp));
 
-  // %Ez against +-HH.
-  EXPECT_TRUE(parse("%Ez", "+00", utc, &tp));
-  EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp);
-  EXPECT_TRUE(parse("%Ez", "-12", utc, &tp));
-  EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 0, 0), utc), tp);
-  EXPECT_TRUE(parse("%Ez", "+12", utc, &tp));
-  EXPECT_EQ(convert(civil_second(1969, 12, 31, 12, 0, 0), utc), tp);
-  EXPECT_FALSE(parse("%Ez", "-1", utc, &tp));
+    EXPECT_TRUE(parse(fmt, "+00", utc, &tp));
+    EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp);
+    EXPECT_TRUE(parse(fmt, "-12", utc, &tp));
+    EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 0, 0), utc), tp);
+    EXPECT_TRUE(parse(fmt, "+12", utc, &tp));
+    EXPECT_EQ(convert(civil_second(1969, 12, 31, 12, 0, 0), utc), tp);
+    EXPECT_FALSE(parse(fmt, "-1", utc, &tp));
+  }
 }
 
 TEST(Parse, ExtendedSecondOffset) {
   const time_zone utc = utc_time_zone();
   time_point<absl::time_internal::cctz::seconds> tp;
 
-  // %Ez against +-HH:MM:SS.
-  EXPECT_TRUE(parse("%Ez", "+00:00:00", utc, &tp));
-  EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp);
-  EXPECT_TRUE(parse("%Ez", "-12:34:56", utc, &tp));
-  EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 34, 56), utc), tp);
-  EXPECT_TRUE(parse("%Ez", "+12:34:56", utc, &tp));
-  EXPECT_EQ(convert(civil_second(1969, 12, 31, 11, 25, 4), utc), tp);
-  EXPECT_FALSE(parse("%Ez", "-12:34:5", utc, &tp));
+  for (auto fmt : {"%Ez", "%E*z", "%:z", "%::z", "%:::z"}) {
+    EXPECT_TRUE(parse(fmt, "+00:00:00", utc, &tp));
+    EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp);
+    EXPECT_TRUE(parse(fmt, "-12:34:56", utc, &tp));
+    EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 34, 56), utc), tp);
+    EXPECT_TRUE(parse(fmt, "+12:34:56", utc, &tp));
+    EXPECT_EQ(convert(civil_second(1969, 12, 31, 11, 25, 4), utc), tp);
+    EXPECT_FALSE(parse(fmt, "-12:34:5", utc, &tp));
 
-  // %Ez against +-HHMMSS.
-  EXPECT_TRUE(parse("%Ez", "+000000", utc, &tp));
-  EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp);
-  EXPECT_TRUE(parse("%Ez", "-123456", utc, &tp));
-  EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 34, 56), utc), tp);
-  EXPECT_TRUE(parse("%Ez", "+123456", utc, &tp));
-  EXPECT_EQ(convert(civil_second(1969, 12, 31, 11, 25, 4), utc), tp);
-  EXPECT_FALSE(parse("%Ez", "-12345", utc, &tp));
+    EXPECT_TRUE(parse(fmt, "+000000", utc, &tp));
+    EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp);
+    EXPECT_TRUE(parse(fmt, "-123456", utc, &tp));
+    EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 34, 56), utc), tp);
+    EXPECT_TRUE(parse(fmt, "+123456", utc, &tp));
+    EXPECT_EQ(convert(civil_second(1969, 12, 31, 11, 25, 4), utc), tp);
+    EXPECT_FALSE(parse(fmt, "-12345", utc, &tp));
 
-  // %E*z against +-HH:MM:SS.
-  EXPECT_TRUE(parse("%E*z", "+00:00:00", utc, &tp));
-  EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp);
-  EXPECT_TRUE(parse("%E*z", "-12:34:56", utc, &tp));
-  EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 34, 56), utc), tp);
-  EXPECT_TRUE(parse("%E*z", "+12:34:56", utc, &tp));
-  EXPECT_EQ(convert(civil_second(1969, 12, 31, 11, 25, 4), utc), tp);
-  EXPECT_FALSE(parse("%E*z", "-12:34:5", utc, &tp));
+    EXPECT_TRUE(parse(fmt, "+00:00", utc, &tp));
+    EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp);
+    EXPECT_TRUE(parse(fmt, "-12:34", utc, &tp));
+    EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 34, 0), utc), tp);
+    EXPECT_TRUE(parse(fmt, "+12:34", utc, &tp));
+    EXPECT_EQ(convert(civil_second(1969, 12, 31, 11, 26, 0), utc), tp);
+    EXPECT_FALSE(parse(fmt, "-12:3", utc, &tp));
 
-  // %E*z against +-HHMMSS.
-  EXPECT_TRUE(parse("%E*z", "+000000", utc, &tp));
-  EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp);
-  EXPECT_TRUE(parse("%E*z", "-123456", utc, &tp));
-  EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 34, 56), utc), tp);
-  EXPECT_TRUE(parse("%E*z", "+123456", utc, &tp));
-  EXPECT_EQ(convert(civil_second(1969, 12, 31, 11, 25, 4), utc), tp);
-  EXPECT_FALSE(parse("%E*z", "-12345", utc, &tp));
+    EXPECT_TRUE(parse(fmt, "+0000", utc, &tp));
+    EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp);
+    EXPECT_TRUE(parse(fmt, "-1234", utc, &tp));
+    EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 34, 0), utc), tp);
+    EXPECT_TRUE(parse(fmt, "+1234", utc, &tp));
+    EXPECT_EQ(convert(civil_second(1969, 12, 31, 11, 26, 0), utc), tp);
+    EXPECT_FALSE(parse(fmt, "-123", utc, &tp));
 
-  // %E*z against +-HH:MM.
-  EXPECT_TRUE(parse("%E*z", "+00:00", utc, &tp));
-  EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp);
-  EXPECT_TRUE(parse("%E*z", "-12:34", utc, &tp));
-  EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 34, 0), utc), tp);
-  EXPECT_TRUE(parse("%E*z", "+12:34", utc, &tp));
-  EXPECT_EQ(convert(civil_second(1969, 12, 31, 11, 26, 0), utc), tp);
-  EXPECT_FALSE(parse("%E*z", "-12:3", utc, &tp));
-
-  // %E*z against +-HHMM.
-  EXPECT_TRUE(parse("%E*z", "+0000", utc, &tp));
-  EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp);
-  EXPECT_TRUE(parse("%E*z", "-1234", utc, &tp));
-  EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 34, 0), utc), tp);
-  EXPECT_TRUE(parse("%E*z", "+1234", utc, &tp));
-  EXPECT_EQ(convert(civil_second(1969, 12, 31, 11, 26, 0), utc), tp);
-  EXPECT_FALSE(parse("%E*z", "-123", utc, &tp));
-
-  // %E*z against +-HH.
-  EXPECT_TRUE(parse("%E*z", "+00", utc, &tp));
-  EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp);
-  EXPECT_TRUE(parse("%E*z", "-12", utc, &tp));
-  EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 0, 0), utc), tp);
-  EXPECT_TRUE(parse("%E*z", "+12", utc, &tp));
-  EXPECT_EQ(convert(civil_second(1969, 12, 31, 12, 0, 0), utc), tp);
-  EXPECT_FALSE(parse("%E*z", "-1", utc, &tp));
+    EXPECT_TRUE(parse(fmt, "+00", utc, &tp));
+    EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp);
+    EXPECT_TRUE(parse(fmt, "-12", utc, &tp));
+    EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 0, 0), utc), tp);
+    EXPECT_TRUE(parse(fmt, "+12", utc, &tp));
+    EXPECT_EQ(convert(civil_second(1969, 12, 31, 12, 0, 0), utc), tp);
+    EXPECT_FALSE(parse(fmt, "-1", utc, &tp));
+  }
 }
 
 TEST(Parse, ExtendedYears) {
@@ -1390,6 +1455,10 @@
 #if defined(_WIN32) || defined(_WIN64)
   // Initial investigations indicate the %c does not roundtrip on Windows.
   // TODO: Figure out what is going on here (perhaps a locale problem).
+#elif defined(__EMSCRIPTEN__)
+  // strftime() and strptime() use different defintions for "%c" under
+  // emscripten (see https://github.com/kripken/emscripten/pull/7491),
+  // causing its round-trip test to fail.
 #else
   // Even though we don't know what %c will produce, it should roundtrip,
   // but only in the 0-offset timezone.
diff --git a/absl/time/internal/cctz/src/time_zone_if.cc b/absl/time/internal/cctz/src/time_zone_if.cc
index 380834a..09aaee5 100644
--- a/absl/time/internal/cctz/src/time_zone_if.cc
+++ b/absl/time/internal/cctz/src/time_zone_if.cc
@@ -4,7 +4,7 @@
 // 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
+//   https://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,
diff --git a/absl/time/internal/cctz/src/time_zone_if.h b/absl/time/internal/cctz/src/time_zone_if.h
index e4bd386..d000b7a 100644
--- a/absl/time/internal/cctz/src/time_zone_if.h
+++ b/absl/time/internal/cctz/src/time_zone_if.h
@@ -4,7 +4,7 @@
 // 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
+//   https://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,
diff --git a/absl/time/internal/cctz/src/time_zone_impl.cc b/absl/time/internal/cctz/src/time_zone_impl.cc
index 3062ccd..3cbc674 100644
--- a/absl/time/internal/cctz/src/time_zone_impl.cc
+++ b/absl/time/internal/cctz/src/time_zone_impl.cc
@@ -4,7 +4,7 @@
 // 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
+//   https://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,
diff --git a/absl/time/internal/cctz/src/time_zone_impl.h b/absl/time/internal/cctz/src/time_zone_impl.h
index 14965ef..b73fad9 100644
--- a/absl/time/internal/cctz/src/time_zone_impl.h
+++ b/absl/time/internal/cctz/src/time_zone_impl.h
@@ -4,7 +4,7 @@
 // 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
+//   https://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,
diff --git a/absl/time/internal/cctz/src/time_zone_info.cc b/absl/time/internal/cctz/src/time_zone_info.cc
index 2cb358d..50f7de5 100644
--- a/absl/time/internal/cctz/src/time_zone_info.cc
+++ b/absl/time/internal/cctz/src/time_zone_info.cc
@@ -4,7 +4,7 @@
 // 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
+//   https://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,
@@ -25,7 +25,7 @@
 // a grain of salt.
 //
 // For more information see tzfile(5), http://www.iana.org/time-zones, or
-// http://en.wikipedia.org/wiki/Zoneinfo.
+// https://en.wikipedia.org/wiki/Zoneinfo.
 //
 // Note that we assume the proleptic Gregorian calendar and 60-second
 // minutes throughout.
@@ -921,7 +921,7 @@
     ++begin;
   }
   std::int_fast64_t unix_time = ToUnixSeconds(tp);
-  const Transition target = { unix_time };
+  const Transition target = {unix_time, 0, civil_second(), civil_second()};
   const Transition* tr = std::upper_bound(begin, end, target,
                                           Transition::ByUnixTime());
   for (; tr != end; ++tr) {  // skip no-op transitions
@@ -956,7 +956,7 @@
     }
     unix_time += 1;  // ceils
   }
-  const Transition target = { unix_time };
+  const Transition target = {unix_time, 0, civil_second(), civil_second()};
   const Transition* tr = std::lower_bound(begin, end, target,
                                           Transition::ByUnixTime());
   for (; tr != begin; --tr) {  // skip no-op transitions
diff --git a/absl/time/internal/cctz/src/time_zone_info.h b/absl/time/internal/cctz/src/time_zone_info.h
index 958e9b6..bff639f 100644
--- a/absl/time/internal/cctz/src/time_zone_info.h
+++ b/absl/time/internal/cctz/src/time_zone_info.h
@@ -4,7 +4,7 @@
 // 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
+//   https://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,
diff --git a/absl/time/internal/cctz/src/time_zone_libc.cc b/absl/time/internal/cctz/src/time_zone_libc.cc
index 074c8d0..3ab1623 100644
--- a/absl/time/internal/cctz/src/time_zone_libc.cc
+++ b/absl/time/internal/cctz/src/time_zone_libc.cc
@@ -4,7 +4,7 @@
 // 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
+//   https://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,
@@ -20,6 +20,7 @@
 
 #include <chrono>
 #include <ctime>
+#include <limits>
 #include <tuple>
 #include <utility>
 
@@ -85,6 +86,76 @@
 #endif  // !defined(__tm_gmtoff) && !defined(__tm_zone)
 #endif
 
+inline std::tm* gm_time(const std::time_t *timep, std::tm *result) {
+#if defined(_WIN32) || defined(_WIN64)
+    return gmtime_s(result, timep) ? nullptr : result;
+#else
+    return gmtime_r(timep, result);
+#endif
+}
+
+inline std::tm* local_time(const std::time_t *timep, std::tm *result) {
+#if defined(_WIN32) || defined(_WIN64)
+    return localtime_s(result, timep) ? nullptr : result;
+#else
+    return localtime_r(timep, result);
+#endif
+}
+
+// Converts a civil second and "dst" flag into a time_t and UTC offset.
+// Returns false if time_t cannot represent the requested civil second.
+// Caller must have already checked that cs.year() will fit into a tm_year.
+bool make_time(const civil_second& cs, int is_dst, std::time_t* t, int* off) {
+  std::tm tm;
+  tm.tm_year = static_cast<int>(cs.year() - year_t{1900});
+  tm.tm_mon = cs.month() - 1;
+  tm.tm_mday = cs.day();
+  tm.tm_hour = cs.hour();
+  tm.tm_min = cs.minute();
+  tm.tm_sec = cs.second();
+  tm.tm_isdst = is_dst;
+  *t = std::mktime(&tm);
+  if (*t == std::time_t{-1}) {
+    std::tm tm2;
+    const std::tm* tmp = local_time(t, &tm2);
+    if (tmp == nullptr || tmp->tm_year != tm.tm_year ||
+        tmp->tm_mon != tm.tm_mon || tmp->tm_mday != tm.tm_mday ||
+        tmp->tm_hour != tm.tm_hour || tmp->tm_min != tm.tm_min ||
+        tmp->tm_sec != tm.tm_sec) {
+      // A true error (not just one second before the epoch).
+      return false;
+    }
+  }
+  *off = get_offset_abbr(tm).first;
+  return true;
+}
+
+// Find the least time_t in [lo:hi] where local time matches offset, given:
+// (1) lo doesn't match, (2) hi does, and (3) there is only one transition.
+std::time_t find_trans(std::time_t lo, std::time_t hi, int offset) {
+  std::tm tm;
+  while (lo + 1 != hi) {
+    const std::time_t mid = lo + (hi - lo) / 2;
+    if (std::tm* tmp = local_time(&mid, &tm)) {
+      if (get_offset_abbr(*tmp).first == offset) {
+        hi = mid;
+      } else {
+        lo = mid;
+      }
+    } else {
+      // If std::tm cannot hold some result we resort to a linear search,
+      // ignoring all failed conversions.  Slow, but never really happens.
+      while (++lo != hi) {
+        if (std::tm* tmp = local_time(&lo, &tm)) {
+          if (get_offset_abbr(*tmp).first == offset) break;
+        }
+      }
+      return lo;
+    }
+  }
+  return hi;
+}
+
 }  // namespace
 
 TimeZoneLibC::TimeZoneLibC(const std::string& name)
@@ -93,59 +164,116 @@
 time_zone::absolute_lookup TimeZoneLibC::BreakTime(
     const time_point<seconds>& tp) const {
   time_zone::absolute_lookup al;
-  std::time_t t = ToUnixSeconds(tp);
-  std::tm tm;
-  if (local_) {
-#if defined(_WIN32) || defined(_WIN64)
-    localtime_s(&tm, &t);
-#else
-    localtime_r(&t, &tm);
-#endif
-    std::tie(al.offset, al.abbr) = get_offset_abbr(tm);
-  } else {
-#if defined(_WIN32) || defined(_WIN64)
-    gmtime_s(&tm, &t);
-#else
-    gmtime_r(&t, &tm);
-#endif
-    al.offset = 0;
-    al.abbr = "UTC";
+  al.offset = 0;
+  al.is_dst = false;
+  al.abbr = "-00";
+
+  const std::int_fast64_t s = ToUnixSeconds(tp);
+
+  // If std::time_t cannot hold the input we saturate the output.
+  if (s < std::numeric_limits<std::time_t>::min()) {
+    al.cs = civil_second::min();
+    return al;
   }
-  al.cs = civil_second(tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
-                       tm.tm_hour, tm.tm_min, tm.tm_sec);
-  al.is_dst = tm.tm_isdst > 0;
+  if (s > std::numeric_limits<std::time_t>::max()) {
+    al.cs = civil_second::max();
+    return al;
+  }
+
+  const std::time_t t = static_cast<std::time_t>(s);
+  std::tm tm;
+  std::tm* tmp = local_ ? local_time(&t, &tm) : gm_time(&t, &tm);
+
+  // If std::tm cannot hold the result we saturate the output.
+  if (tmp == nullptr) {
+    al.cs = (s < 0) ? civil_second::min() : civil_second::max();
+    return al;
+  }
+
+  const year_t year = tmp->tm_year + year_t{1900};
+  al.cs = civil_second(year, tmp->tm_mon + 1, tmp->tm_mday,
+                       tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
+  std::tie(al.offset, al.abbr) = get_offset_abbr(*tmp);
+  if (!local_) al.abbr = "UTC";  // as expected by cctz
+  al.is_dst = tmp->tm_isdst > 0;
   return al;
 }
 
 time_zone::civil_lookup TimeZoneLibC::MakeTime(const civil_second& cs) const {
-  time_zone::civil_lookup cl;
-  std::time_t t;
-  if (local_) {
-    // Does not handle SKIPPED/AMBIGUOUS or huge years.
-    std::tm tm;
-    tm.tm_year = static_cast<int>(cs.year() - 1900);
-    tm.tm_mon = cs.month() - 1;
-    tm.tm_mday = cs.day();
-    tm.tm_hour = cs.hour();
-    tm.tm_min = cs.minute();
-    tm.tm_sec = cs.second();
-    tm.tm_isdst = -1;
-    t = std::mktime(&tm);
-  } else {
-    t = cs - civil_second();
+  if (!local_) {
+    // If time_point<seconds> cannot hold the result we saturate.
+    static const civil_second min_tp_cs =
+        civil_second() + ToUnixSeconds(time_point<seconds>::min());
+    static const civil_second max_tp_cs =
+        civil_second() + ToUnixSeconds(time_point<seconds>::max());
+    const time_point<seconds> tp =
+        (cs < min_tp_cs)
+            ? time_point<seconds>::min()
+            : (cs > max_tp_cs) ? time_point<seconds>::max()
+                               : FromUnixSeconds(cs - civil_second());
+    return {time_zone::civil_lookup::UNIQUE, tp, tp, tp};
   }
-  cl.kind = time_zone::civil_lookup::UNIQUE;
-  cl.pre = cl.trans = cl.post = FromUnixSeconds(t);
-  return cl;
+
+  // If tm_year cannot hold the requested year we saturate the result.
+  if (cs.year() < 0) {
+    if (cs.year() < std::numeric_limits<int>::min() + year_t{1900}) {
+      const time_point<seconds> tp = time_point<seconds>::min();
+      return {time_zone::civil_lookup::UNIQUE, tp, tp, tp};
+    }
+  } else {
+    if (cs.year() - year_t{1900} > std::numeric_limits<int>::max()) {
+      const time_point<seconds> tp = time_point<seconds>::max();
+      return {time_zone::civil_lookup::UNIQUE, tp, tp, tp};
+    }
+  }
+
+  // We probe with "is_dst" values of 0 and 1 to try to distinguish unique
+  // civil seconds from skipped or repeated ones.  This is not always possible
+  // however, as the "dst" flag does not change over some offset transitions.
+  // We are also subject to the vagaries of mktime() implementations.
+  std::time_t t0, t1;
+  int offset0, offset1;
+  if (make_time(cs, 0, &t0, &offset0) && make_time(cs, 1, &t1, &offset1)) {
+    if (t0 == t1) {
+      // The civil time was singular (pre == trans == post).
+      const time_point<seconds> tp = FromUnixSeconds(t0);
+      return {time_zone::civil_lookup::UNIQUE, tp, tp, tp};
+    }
+
+    if (t0 > t1) {
+      std::swap(t0, t1);
+      std::swap(offset0, offset1);
+    }
+    const std::time_t tt = find_trans(t0, t1, offset1);
+    const time_point<seconds> trans = FromUnixSeconds(tt);
+
+    if (offset0 < offset1) {
+      // The civil time did not exist (pre >= trans > post).
+      const time_point<seconds> pre = FromUnixSeconds(t1);
+      const time_point<seconds> post = FromUnixSeconds(t0);
+      return {time_zone::civil_lookup::SKIPPED, pre, trans, post};
+    }
+
+    // The civil time was ambiguous (pre < trans <= post).
+    const time_point<seconds> pre = FromUnixSeconds(t0);
+    const time_point<seconds> post = FromUnixSeconds(t1);
+    return {time_zone::civil_lookup::REPEATED, pre, trans, post};
+  }
+
+  // make_time() failed somehow so we saturate the result.
+  const time_point<seconds> tp = (cs < civil_second())
+                                     ? time_point<seconds>::min()
+                                     : time_point<seconds>::max();
+  return {time_zone::civil_lookup::UNIQUE, tp, tp, tp};
 }
 
-bool TimeZoneLibC::NextTransition(const time_point<seconds>& tp,
-                                  time_zone::civil_transition* trans) const {
+bool TimeZoneLibC::NextTransition(const time_point<seconds>&,
+                                  time_zone::civil_transition*) const {
   return false;
 }
 
-bool TimeZoneLibC::PrevTransition(const time_point<seconds>& tp,
-                                  time_zone::civil_transition* trans) const {
+bool TimeZoneLibC::PrevTransition(const time_point<seconds>&,
+                                  time_zone::civil_transition*) const {
   return false;
 }
 
diff --git a/absl/time/internal/cctz/src/time_zone_libc.h b/absl/time/internal/cctz/src/time_zone_libc.h
index 4e40c61..0d18e9a 100644
--- a/absl/time/internal/cctz/src/time_zone_libc.h
+++ b/absl/time/internal/cctz/src/time_zone_libc.h
@@ -4,7 +4,7 @@
 // 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
+//   https://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,
diff --git a/absl/time/internal/cctz/src/time_zone_lookup.cc b/absl/time/internal/cctz/src/time_zone_lookup.cc
index f2d151e..fd04e2d 100644
--- a/absl/time/internal/cctz/src/time_zone_lookup.cc
+++ b/absl/time/internal/cctz/src/time_zone_lookup.cc
@@ -4,7 +4,7 @@
 // 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
+//   https://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,
@@ -20,6 +20,11 @@
 #include <dlfcn.h>
 #endif
 #endif
+
+#if defined(__APPLE__)
+#include <CoreFoundation/CFTimeZone.h>
+#endif
+
 #include <cstdlib>
 #include <cstring>
 #include <string>
@@ -121,6 +126,11 @@
   char* tz_env = nullptr;
 #if defined(_MSC_VER)
   _dupenv_s(&tz_env, nullptr, "TZ");
+#elif defined(__APPLE__)
+  CFTimeZoneRef system_time_zone = CFTimeZoneCopyDefault();
+  CFStringRef tz_name = CFTimeZoneGetName(system_time_zone);
+  tz_env = strdup(CFStringGetCStringPtr(tz_name, CFStringGetSystemEncoding()));
+  CFRelease(system_time_zone);
 #else
   tz_env = std::getenv("TZ");
 #endif
@@ -153,6 +163,8 @@
 #if defined(_MSC_VER)
   free(localtime_env);
   free(tz_env);
+#elif defined(__APPLE__)
+  free(tz_env);
 #endif
 
   time_zone tz;
diff --git a/absl/time/internal/cctz/src/time_zone_lookup_test.cc b/absl/time/internal/cctz/src/time_zone_lookup_test.cc
index 551292f..8068e2f 100644
--- a/absl/time/internal/cctz/src/time_zone_lookup_test.cc
+++ b/absl/time/internal/cctz/src/time_zone_lookup_test.cc
@@ -4,7 +4,7 @@
 // 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
+//   https://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,
@@ -16,7 +16,9 @@
 
 #include <chrono>
 #include <cstddef>
+#include <cstdlib>
 #include <future>
+#include <limits>
 #include <string>
 #include <thread>
 #include <vector>
@@ -335,6 +337,7 @@
   "Asia/Pontianak",
   "Asia/Pyongyang",
   "Asia/Qatar",
+  "Asia/Qostanay",
   "Asia/Qyzylorda",
   "Asia/Rangoon",
   "Asia/Riyadh",
@@ -664,6 +667,7 @@
 
 }  // namespace
 
+#if !defined(__EMSCRIPTEN__)
 TEST(TimeZones, LoadZonesConcurrently) {
   std::promise<void> ready_promise;
   std::shared_future<void> ready_future(ready_promise.get_future());
@@ -711,6 +715,7 @@
   }
   EXPECT_LE(failures.size(), max_failures) << testing::PrintToString(failures);
 }
+#endif
 
 TEST(TimeZone, NamedTimeZones) {
   const time_zone utc = utc_time_zone();
@@ -925,7 +930,7 @@
   EXPECT_EQ(tp, convert(civil_second(2009, 2, 13, 18, 30, 90), tz));   // second
 }
 
-// NOTE: Run this with --copt=-ftrapv to detect overflow problems.
+// NOTE: Run this with -ftrapv to detect overflow problems.
 TEST(MakeTime, SysSecondsLimits) {
   const char RFC3339[] =  "%Y-%m-%dT%H:%M:%S%Ez";
   const time_zone utc = utc_time_zone();
@@ -990,6 +995,106 @@
   EXPECT_EQ(time_point<absl::time_internal::cctz::seconds>::min(), tp);
   tp = convert(civil_second::min(), west);
   EXPECT_EQ(time_point<absl::time_internal::cctz::seconds>::min(), tp);
+
+  // Some similar checks for the "libc" time-zone implementation.
+  if (sizeof(std::time_t) >= 8) {
+    // Checks that "tm_year + 1900", as used by the "libc" implementation,
+    // can produce year values beyond the range on an int without overflow.
+#if defined(_WIN32) || defined(_WIN64)
+    // localtime_s() and gmtime_s() don't believe in years outside [1970:3000].
+#else
+    const time_zone utc = LoadZone("libc:UTC");
+    const year_t max_tm_year = year_t{std::numeric_limits<int>::max()} + 1900;
+    tp = convert(civil_second(max_tm_year, 12, 31, 23, 59, 59), utc);
+    EXPECT_EQ("2147485547-12-31T23:59:59+00:00", format(RFC3339, tp, utc));
+    const year_t min_tm_year = year_t{std::numeric_limits<int>::min()} + 1900;
+    tp = convert(civil_second(min_tm_year, 1, 1, 0, 0, 0), utc);
+    EXPECT_EQ("-2147481748-01-01T00:00:00+00:00", format(RFC3339, tp, utc));
+#endif
+  }
+}
+
+TEST(MakeTime, LocalTimeLibC) {
+  // Checks that cctz and libc agree on transition points in [1970:2037].
+  //
+  // We limit this test case to environments where:
+  //  1) we know how to change the time zone used by localtime()/mktime(),
+  //  2) cctz and localtime()/mktime() will use similar-enough tzdata, and
+  //  3) we have some idea about how mktime() behaves during transitions.
+#if defined(__linux__) && !defined(__ANDROID__)
+  const char* const ep = getenv("TZ");
+  std::string tz_name = (ep != nullptr) ? ep : "";
+  for (const char* const* np = kTimeZoneNames; *np != nullptr; ++np) {
+    ASSERT_EQ(0, setenv("TZ", *np, 1));  // change what "localtime" means
+    const auto zi = local_time_zone();
+    const auto lc = LoadZone("libc:localtime");
+    time_zone::civil_transition trans;
+    for (auto tp = zi.lookup(civil_second()).trans;
+         zi.next_transition(tp, &trans);
+         tp = zi.lookup(trans.to).trans) {
+      const auto fcl = zi.lookup(trans.from);
+      const auto tcl = zi.lookup(trans.to);
+      civil_second cs;  // compare cs in zi and lc
+      if (fcl.kind == time_zone::civil_lookup::UNIQUE) {
+        if (tcl.kind == time_zone::civil_lookup::UNIQUE) {
+          // Both unique; must be an is_dst or abbr change.
+          ASSERT_EQ(trans.from, trans.to);
+          const auto trans = fcl.trans;
+          const auto tal = zi.lookup(trans);
+          const auto tprev = trans - absl::time_internal::cctz::seconds(1);
+          const auto pal = zi.lookup(tprev);
+          if (pal.is_dst == tal.is_dst) {
+            ASSERT_STRNE(pal.abbr, tal.abbr);
+          }
+          continue;
+        }
+        ASSERT_EQ(time_zone::civil_lookup::REPEATED, tcl.kind);
+        cs = trans.to;
+      } else {
+        ASSERT_EQ(time_zone::civil_lookup::UNIQUE, tcl.kind);
+        ASSERT_EQ(time_zone::civil_lookup::SKIPPED, fcl.kind);
+        cs = trans.from;
+      }
+      if (cs.year() > 2037) break;  // limit test time (and to 32-bit time_t)
+      const auto cl_zi = zi.lookup(cs);
+      if (zi.lookup(cl_zi.pre).is_dst == zi.lookup(cl_zi.post).is_dst) {
+        // The "libc" implementation cannot correctly classify transitions
+        // that don't change the "tm_isdst" flag.  In Europe/Volgograd, for
+        // example, there is a SKIPPED transition from +03 to +04 with dst=F
+        // on both sides ...
+        //   1540681199 = 2018-10-28 01:59:59 +03:00:00 [dst=F off=10800]
+        //   1540681200 = 2018-10-28 03:00:00 +04:00:00 [dst=F off=14400]
+        // but std::mktime(2018-10-28 02:00:00, tm_isdst=0) fails, unlike,
+        // say, the similar Europe/Chisinau transition from +02 to +03 ...
+        //   1521935999 = 2018-03-25 01:59:59 +02:00:00 [dst=F off=7200]
+        //   1521936000 = 2018-03-25 03:00:00 +03:00:00 [dst=T off=10800]
+        // where std::mktime(2018-03-25 02:00:00, tm_isdst=0) succeeds and
+        // returns 1521936000.
+        continue;
+      }
+      if (cs == civil_second(2037, 10, 4, 2, 0, 0)) {
+        const std::string tzname = *np;
+        if (tzname == "Africa/Casablanca" || tzname == "Africa/El_Aaiun") {
+          // The "libc" implementation gets this transition wrong (at least
+          // until 2018g when it was removed), returning an offset of 3600
+          // instead of 0.  TODO: Revert this when 2018g is ubiquitous.
+          continue;
+        }
+      }
+      const auto cl_lc = lc.lookup(cs);
+      SCOPED_TRACE(testing::Message() << "For " << cs << " in " << *np);
+      EXPECT_EQ(cl_zi.kind, cl_lc.kind);
+      EXPECT_EQ(cl_zi.pre, cl_lc.pre);
+      EXPECT_EQ(cl_zi.trans, cl_lc.trans);
+      EXPECT_EQ(cl_zi.post, cl_lc.post);
+    }
+  }
+  if (ep == nullptr) {
+    ASSERT_EQ(0, unsetenv("TZ"));
+  } else {
+    ASSERT_EQ(0, setenv("TZ", tz_name.c_str(), 1));
+  }
+#endif
 }
 
 TEST(NextTransition, UTC) {
diff --git a/absl/time/internal/cctz/src/time_zone_posix.cc b/absl/time/internal/cctz/src/time_zone_posix.cc
index 75ad8bc..993901a 100644
--- a/absl/time/internal/cctz/src/time_zone_posix.cc
+++ b/absl/time/internal/cctz/src/time_zone_posix.cc
@@ -4,7 +4,7 @@
 // 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
+//   https://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,
diff --git a/absl/time/internal/cctz/src/time_zone_posix.h b/absl/time/internal/cctz/src/time_zone_posix.h
index 9ccd4a8..6a60022 100644
--- a/absl/time/internal/cctz/src/time_zone_posix.h
+++ b/absl/time/internal/cctz/src/time_zone_posix.h
@@ -4,7 +4,7 @@
 // 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
+//   https://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,
@@ -68,25 +68,35 @@
 // it would take us to another day, and perhaps week, or even month.
 struct PosixTransition {
   enum DateFormat { J, N, M };
-  struct {
-    DateFormat fmt;
-    union {
-      struct {
-        std::int_fast16_t day;  // day of non-leap year [1:365]
-      } j;
-      struct {
-        std::int_fast16_t day;  // day of year [0:365]
-      } n;
-      struct {
-        std::int_fast8_t month;    // month of year [1:12]
-        std::int_fast8_t week;     // week of month [1:5] (5==last)
-        std::int_fast8_t weekday;  // 0==Sun, ..., 6=Sat
-      } m;
+
+  struct Date {
+    struct NonLeapDay {
+      std::int_fast16_t day;  // day of non-leap year [1:365]
     };
-  } date;
-  struct {
+    struct Day {
+      std::int_fast16_t day;  // day of year [0:365]
+    };
+    struct MonthWeekWeekday {
+      std::int_fast8_t month;    // month of year [1:12]
+      std::int_fast8_t week;     // week of month [1:5] (5==last)
+      std::int_fast8_t weekday;  // 0==Sun, ..., 6=Sat
+    };
+
+    DateFormat fmt;
+
+    union {
+      NonLeapDay j;
+      Day n;
+      MonthWeekWeekday m;
+    };
+  };
+
+  struct Time {
     std::int_fast32_t offset;  // seconds before/after 00:00:00
-  } time;
+  };
+
+  Date date;
+  Time time;
 };
 
 // The entirety of a POSIX-string specified time-zone rule. The standard
diff --git a/absl/time/internal/cctz/src/tzfile.h b/absl/time/internal/cctz/src/tzfile.h
index 90cfc0c..4485ba5 100644
--- a/absl/time/internal/cctz/src/tzfile.h
+++ b/absl/time/internal/cctz/src/tzfile.h
@@ -1,3 +1,5 @@
+/* Layout and location of TZif files.  */
+
 #ifndef TZFILE_H
 
 #define TZFILE_H
diff --git a/absl/time/internal/cctz/src/zone_info_source.cc b/absl/time/internal/cctz/src/zone_info_source.cc
index bf2d2d2..1324846 100644
--- a/absl/time/internal/cctz/src/zone_info_source.cc
+++ b/absl/time/internal/cctz/src/zone_info_source.cc
@@ -4,7 +4,7 @@
 // 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
+//   https://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,
@@ -54,7 +54,7 @@
 #pragma comment( \
     linker,      \
     "/alternatename:?zone_info_source_factory@cctz_extension@time_internal@absl@@3P6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@absl@@U?$default_delete@VZoneInfoSource@cctz@time_internal@absl@@@std@@@std@@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@5@ABV?$function@$$A6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@absl@@U?$default_delete@VZoneInfoSource@cctz@time_internal@absl@@@std@@@std@@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@@Z@5@@ZA=?default_factory@cctz_extension@time_internal@absl@@3P6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@absl@@U?$default_delete@VZoneInfoSource@cctz@time_internal@absl@@@std@@@std@@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@5@ABV?$function@$$A6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@absl@@U?$default_delete@VZoneInfoSource@cctz@time_internal@absl@@@std@@@std@@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@@Z@5@@ZA")
-#elif defined(_M_IA_64) || defined(_M_AMD64)
+#elif defined(_M_IA_64) || defined(_M_AMD64) || defined(_M_ARM64)
 #pragma comment( \
     linker,      \
     "/alternatename:?zone_info_source_factory@cctz_extension@time_internal@absl@@3P6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@absl@@U?$default_delete@VZoneInfoSource@cctz@time_internal@absl@@@std@@@std@@AEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@5@AEBV?$function@$$A6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@absl@@U?$default_delete@VZoneInfoSource@cctz@time_internal@absl@@@std@@@std@@AEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@@Z@5@@ZEA=?default_factory@cctz_extension@time_internal@absl@@3P6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@absl@@U?$default_delete@VZoneInfoSource@cctz@time_internal@absl@@@std@@@std@@AEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@5@AEBV?$function@$$A6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@absl@@U?$default_delete@VZoneInfoSource@cctz@time_internal@absl@@@std@@@std@@AEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@@Z@5@@ZEA")
diff --git a/absl/time/internal/cctz/testdata/version b/absl/time/internal/cctz/testdata/version
index fe86b5c..63f5800 100644
--- a/absl/time/internal/cctz/testdata/version
+++ b/absl/time/internal/cctz/testdata/version
@@ -1 +1 @@
-2018e-2-g99dd695
+2018i
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Abidjan b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Abidjan
index 6fd1af3..65d19ec 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Abidjan
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Abidjan
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Accra b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Accra
index 8726e80..eaaa818 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Accra
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Accra
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Addis_Ababa b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Addis_Ababa
index 39631f2..6e19601 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Addis_Ababa
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Addis_Ababa
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Algiers b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Algiers
index 2a25f3a..a5867a6 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Algiers
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Algiers
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Asmara b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Asmara
index 39631f2..6e19601 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Asmara
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Asmara
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Asmera b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Asmera
index 39631f2..6e19601 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Asmera
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Asmera
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Bamako b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Bamako
index 6fd1af3..65d19ec 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Bamako
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Bamako
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Bangui b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Bangui
index b1c97cc..cbdc045 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Bangui
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Bangui
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Banjul b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Banjul
index 6fd1af3..65d19ec 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Banjul
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Banjul
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Bissau b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Bissau
index 8e32be3..82ea5aa 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Bissau
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Bissau
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Blantyre b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Blantyre
index 5b871db..31cfad7 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Blantyre
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Blantyre
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Brazzaville b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Brazzaville
index b1c97cc..cbdc045 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Brazzaville
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Brazzaville
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Bujumbura b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Bujumbura
index 5b871db..31cfad7 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Bujumbura
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Bujumbura
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Cairo b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Cairo
index ba09750..0272fa1 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Cairo
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Cairo
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Casablanca b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Casablanca
index 65de344..4c57054 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Casablanca
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Casablanca
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Ceuta b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Ceuta
index aaa657f..dd75e3e 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Ceuta
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Ceuta
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Conakry b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Conakry
index 6fd1af3..65d19ec 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Conakry
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Conakry
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Dakar b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Dakar
index 6fd1af3..65d19ec 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Dakar
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Dakar
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Dar_es_Salaam b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Dar_es_Salaam
index 39631f2..6e19601 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Dar_es_Salaam
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Dar_es_Salaam
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Djibouti b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Djibouti
index 39631f2..6e19601 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Djibouti
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Djibouti
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Douala b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Douala
index b1c97cc..cbdc045 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Douala
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Douala
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/El_Aaiun b/absl/time/internal/cctz/testdata/zoneinfo/Africa/El_Aaiun
index f5f8ffb..0ea0253 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/El_Aaiun
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/El_Aaiun
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Freetown b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Freetown
index 6fd1af3..65d19ec 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Freetown
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Freetown
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Gaborone b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Gaborone
index 5b871db..31cfad7 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Gaborone
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Gaborone
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Harare b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Harare
index 5b871db..31cfad7 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Harare
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Harare
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Johannesburg b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Johannesburg
index ddf3652..b8b9270 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Johannesburg
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Johannesburg
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Juba b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Juba
index 9fa7119..83eca03 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Juba
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Juba
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Kampala b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Kampala
index 39631f2..6e19601 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Kampala
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Kampala
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Khartoum b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Khartoum
index f2c9e30..549dae2 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Khartoum
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Khartoum
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Kigali b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Kigali
index 5b871db..31cfad7 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Kigali
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Kigali
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Kinshasa b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Kinshasa
index b1c97cc..cbdc045 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Kinshasa
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Kinshasa
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Lagos b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Lagos
index b1c97cc..cbdc045 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Lagos
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Lagos
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Libreville b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Libreville
index b1c97cc..cbdc045 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Libreville
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Libreville
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Lome b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Lome
index 6fd1af3..65d19ec 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Lome
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Lome
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Luanda b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Luanda
index b1c97cc..cbdc045 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Luanda
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Luanda
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Lubumbashi b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Lubumbashi
index 5b871db..31cfad7 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Lubumbashi
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Lubumbashi
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Lusaka b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Lusaka
index 5b871db..31cfad7 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Lusaka
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Lusaka
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Malabo b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Malabo
index b1c97cc..cbdc045 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Malabo
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Malabo
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Maputo b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Maputo
index 5b871db..31cfad7 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Maputo
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Maputo
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Maseru b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Maseru
index ddf3652..b8b9270 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Maseru
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Maseru
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Mbabane b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Mbabane
index ddf3652..b8b9270 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Mbabane
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Mbabane
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Mogadishu b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Mogadishu
index 39631f2..6e19601 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Mogadishu
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Mogadishu
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Monrovia b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Monrovia
index b434c67..2a154f4 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Monrovia
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Monrovia
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Nairobi b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Nairobi
index 39631f2..6e19601 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Nairobi
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Nairobi
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Ndjamena b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Ndjamena
index bbfe19d..8779590 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Ndjamena
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Ndjamena
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Niamey b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Niamey
index b1c97cc..cbdc045 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Niamey
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Niamey
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Nouakchott b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Nouakchott
index 6fd1af3..65d19ec 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Nouakchott
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Nouakchott
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Ouagadougou b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Ouagadougou
index 6fd1af3..65d19ec 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Ouagadougou
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Ouagadougou
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Porto-Novo b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Porto-Novo
index b1c97cc..cbdc045 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Porto-Novo
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Porto-Novo
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Sao_Tome b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Sao_Tome
index a4ece7f..59f3759 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Sao_Tome
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Sao_Tome
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Timbuktu b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Timbuktu
index 6fd1af3..65d19ec 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Timbuktu
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Timbuktu
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Tripoli b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Tripoli
index b32e220..bd88531 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Tripoli
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Tripoli
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Tunis b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Tunis
index 4bd3885..0cd8ffb 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Tunis
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Tunis
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Windhoek b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Windhoek
index f5d40ba..6766185 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Windhoek
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Windhoek
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Adak b/absl/time/internal/cctz/testdata/zoneinfo/America/Adak
index 5696e0f..4323649 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Adak
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Adak
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Anchorage b/absl/time/internal/cctz/testdata/zoneinfo/America/Anchorage
index 6c8bdf2..9bbb2fd 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Anchorage
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Anchorage
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Anguilla b/absl/time/internal/cctz/testdata/zoneinfo/America/Anguilla
index 447efbe..bdedd1b 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Anguilla
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Anguilla
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Antigua b/absl/time/internal/cctz/testdata/zoneinfo/America/Antigua
index 447efbe..bdedd1b 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Antigua
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Antigua
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Araguaina b/absl/time/internal/cctz/testdata/zoneinfo/America/Araguaina
index 8b295a9..bc9a522 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Araguaina
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Araguaina
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Buenos_Aires b/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Buenos_Aires
index e4866ce..dfebfb9 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Buenos_Aires
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Buenos_Aires
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Catamarca b/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Catamarca
index 9fe9ad6..b798105 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Catamarca
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Catamarca
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/ComodRivadavia b/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/ComodRivadavia
index 9fe9ad6..b798105 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/ComodRivadavia
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/ComodRivadavia
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Cordoba b/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Cordoba
index 8c58f8c..5df3cf6 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Cordoba
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Cordoba
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Jujuy b/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Jujuy
index a74ba04..7d2ba91 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Jujuy
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Jujuy
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/La_Rioja b/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/La_Rioja
index cb184d6..7654aeb 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/La_Rioja
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/La_Rioja
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Mendoza b/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Mendoza
index 5e8c44c..1032356 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Mendoza
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Mendoza
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Rio_Gallegos b/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Rio_Gallegos
index 966a529..3c849fc 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Rio_Gallegos
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Rio_Gallegos
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Salta b/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Salta
index b19aa22..a4b71c1 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Salta
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Salta
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/San_Juan b/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/San_Juan
index 9e5ade6..948a390 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/San_Juan
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/San_Juan
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/San_Luis b/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/San_Luis
index af8aa99..acfbbe4 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/San_Luis
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/San_Luis
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Tucuman b/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Tucuman
index bbb03a0..085fc9c 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Tucuman
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Tucuman
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Ushuaia b/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Ushuaia
index 07e4e9f..1fc3256 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Ushuaia
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Ushuaia
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Aruba b/absl/time/internal/cctz/testdata/zoneinfo/America/Aruba
index d308336..d3b318d 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Aruba
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Aruba
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Asuncion b/absl/time/internal/cctz/testdata/zoneinfo/America/Asuncion
index 3c61ddb..831bf84 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Asuncion
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Asuncion
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Atikokan b/absl/time/internal/cctz/testdata/zoneinfo/America/Atikokan
index 5708b55..629ed42 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Atikokan
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Atikokan
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Atka b/absl/time/internal/cctz/testdata/zoneinfo/America/Atka
index 5696e0f..4323649 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Atka
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Atka
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Bahia b/absl/time/internal/cctz/testdata/zoneinfo/America/Bahia
index 6008a57..143eafc 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Bahia
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Bahia
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Bahia_Banderas b/absl/time/internal/cctz/testdata/zoneinfo/America/Bahia_Banderas
index 21e2b71..cd53107 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Bahia_Banderas
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Bahia_Banderas
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Barbados b/absl/time/internal/cctz/testdata/zoneinfo/America/Barbados
index 6339936..7bb7ac4 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Barbados
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Barbados
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Belem b/absl/time/internal/cctz/testdata/zoneinfo/America/Belem
index b8e13b0..ab3c8a6 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Belem
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Belem
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Belize b/absl/time/internal/cctz/testdata/zoneinfo/America/Belize
index 7dcc4fc..fd69321 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Belize
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Belize
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Blanc-Sablon b/absl/time/internal/cctz/testdata/zoneinfo/America/Blanc-Sablon
index abcde7d..f9f13a1 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Blanc-Sablon
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Blanc-Sablon
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Boa_Vista b/absl/time/internal/cctz/testdata/zoneinfo/America/Boa_Vista
index f776904..69e17a0 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Boa_Vista
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Boa_Vista
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Bogota b/absl/time/internal/cctz/testdata/zoneinfo/America/Bogota
index d893446..b7ded8e 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Bogota
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Bogota
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Boise b/absl/time/internal/cctz/testdata/zoneinfo/America/Boise
index ada6d64..f8d54e2 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Boise
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Boise
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Buenos_Aires b/absl/time/internal/cctz/testdata/zoneinfo/America/Buenos_Aires
index e4866ce..dfebfb9 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Buenos_Aires
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Buenos_Aires
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Cambridge_Bay b/absl/time/internal/cctz/testdata/zoneinfo/America/Cambridge_Bay
index d322f01..f8db4b6 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Cambridge_Bay
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Cambridge_Bay
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Campo_Grande b/absl/time/internal/cctz/testdata/zoneinfo/America/Campo_Grande
index de52bb6..495ef45 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Campo_Grande
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Campo_Grande
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Cancun b/absl/time/internal/cctz/testdata/zoneinfo/America/Cancun
index 7e69f73..de6930c 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Cancun
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Cancun
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Caracas b/absl/time/internal/cctz/testdata/zoneinfo/America/Caracas
index c8cab1a..9abd028 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Caracas
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Caracas
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Catamarca b/absl/time/internal/cctz/testdata/zoneinfo/America/Catamarca
index 9fe9ad6..b798105 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Catamarca
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Catamarca
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Cayenne b/absl/time/internal/cctz/testdata/zoneinfo/America/Cayenne
index 6db6409..ff59657 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Cayenne
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Cayenne
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Cayman b/absl/time/internal/cctz/testdata/zoneinfo/America/Cayman
index 5c1c063..55b0834 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Cayman
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Cayman
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Chicago b/absl/time/internal/cctz/testdata/zoneinfo/America/Chicago
index 3dd8f0f..a5b1617 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Chicago
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Chicago
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Chihuahua b/absl/time/internal/cctz/testdata/zoneinfo/America/Chihuahua
index e3adbdb..b268724 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Chihuahua
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Chihuahua
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Coral_Harbour b/absl/time/internal/cctz/testdata/zoneinfo/America/Coral_Harbour
index 5708b55..629ed42 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Coral_Harbour
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Coral_Harbour
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Cordoba b/absl/time/internal/cctz/testdata/zoneinfo/America/Cordoba
index 8c58f8c..5df3cf6 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Cordoba
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Cordoba
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Costa_Rica b/absl/time/internal/cctz/testdata/zoneinfo/America/Costa_Rica
index c247133..525a67e 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Costa_Rica
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Costa_Rica
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Creston b/absl/time/internal/cctz/testdata/zoneinfo/America/Creston
index 798f627..0fba741 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Creston
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Creston
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Cuiaba b/absl/time/internal/cctz/testdata/zoneinfo/America/Cuiaba
index 145c89e..8a4ee7d 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Cuiaba
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Cuiaba
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Curacao b/absl/time/internal/cctz/testdata/zoneinfo/America/Curacao
index d308336..d3b318d 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Curacao
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Curacao
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Danmarkshavn b/absl/time/internal/cctz/testdata/zoneinfo/America/Danmarkshavn
index ad68c72..9549adc 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Danmarkshavn
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Danmarkshavn
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Dawson b/absl/time/internal/cctz/testdata/zoneinfo/America/Dawson
index 61c9688..db9cead 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Dawson
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Dawson
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Dawson_Creek b/absl/time/internal/cctz/testdata/zoneinfo/America/Dawson_Creek
index 78f9076..db9e339 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Dawson_Creek
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Dawson_Creek
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Denver b/absl/time/internal/cctz/testdata/zoneinfo/America/Denver
index 7fc6691..5fbe26b 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Denver
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Denver
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Detroit b/absl/time/internal/cctz/testdata/zoneinfo/America/Detroit
index e3ea5c3..5e02260 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Detroit
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Detroit
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Dominica b/absl/time/internal/cctz/testdata/zoneinfo/America/Dominica
index 447efbe..bdedd1b 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Dominica
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Dominica
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Edmonton b/absl/time/internal/cctz/testdata/zoneinfo/America/Edmonton
index d02fbcd..3fa0579 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Edmonton
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Edmonton
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Eirunepe b/absl/time/internal/cctz/testdata/zoneinfo/America/Eirunepe
index 41047f2..99b7d06 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Eirunepe
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Eirunepe
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/El_Salvador b/absl/time/internal/cctz/testdata/zoneinfo/America/El_Salvador
index 9b8bc7a..ac774e8 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/El_Salvador
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/El_Salvador
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Ensenada b/absl/time/internal/cctz/testdata/zoneinfo/America/Ensenada
index 29c83e7..ada6bf7 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Ensenada
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Ensenada
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Fort_Nelson b/absl/time/internal/cctz/testdata/zoneinfo/America/Fort_Nelson
index 5923cc6..5a0b7f1 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Fort_Nelson
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Fort_Nelson
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Fort_Wayne b/absl/time/internal/cctz/testdata/zoneinfo/America/Fort_Wayne
index 4a92c06..09511cc 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Fort_Wayne
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Fort_Wayne
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Fortaleza b/absl/time/internal/cctz/testdata/zoneinfo/America/Fortaleza
index 22396bb..e637170 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Fortaleza
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Fortaleza
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Glace_Bay b/absl/time/internal/cctz/testdata/zoneinfo/America/Glace_Bay
index f58522b..48412a4 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Glace_Bay
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Glace_Bay
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Godthab b/absl/time/internal/cctz/testdata/zoneinfo/America/Godthab
index ea293cc..0160308 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Godthab
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Godthab
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Goose_Bay b/absl/time/internal/cctz/testdata/zoneinfo/America/Goose_Bay
index b4b945e..a3f2990 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Goose_Bay
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Goose_Bay
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Grand_Turk b/absl/time/internal/cctz/testdata/zoneinfo/America/Grand_Turk
index 4c8ca6f..4597a62 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Grand_Turk
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Grand_Turk
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Grenada b/absl/time/internal/cctz/testdata/zoneinfo/America/Grenada
index 447efbe..bdedd1b 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Grenada
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Grenada
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Guadeloupe b/absl/time/internal/cctz/testdata/zoneinfo/America/Guadeloupe
index 447efbe..bdedd1b 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Guadeloupe
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Guadeloupe
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Guatemala b/absl/time/internal/cctz/testdata/zoneinfo/America/Guatemala
index abf943b..6118b5c 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Guatemala
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Guatemala
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Guayaquil b/absl/time/internal/cctz/testdata/zoneinfo/America/Guayaquil
index 92de38b..bf087a0 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Guayaquil
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Guayaquil
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Guyana b/absl/time/internal/cctz/testdata/zoneinfo/America/Guyana
index 7d29876..d1dd2fa 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Guyana
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Guyana
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Halifax b/absl/time/internal/cctz/testdata/zoneinfo/America/Halifax
index f86ece4..756099a 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Halifax
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Halifax
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Havana b/absl/time/internal/cctz/testdata/zoneinfo/America/Havana
index 1a58fcd..8186060 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Havana
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Havana
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Hermosillo b/absl/time/internal/cctz/testdata/zoneinfo/America/Hermosillo
index ec435c2..26c269d 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Hermosillo
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Hermosillo
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Indianapolis b/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Indianapolis
index 4a92c06..09511cc 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Indianapolis
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Indianapolis
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Knox b/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Knox
index cc785da..fcd408d 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Knox
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Knox
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Marengo b/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Marengo
index a23d7b7..1abf75e 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Marengo
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Marengo
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Petersburg b/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Petersburg
index f16cb30..0133548 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Petersburg
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Petersburg
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Tell_City b/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Tell_City
index 0250bf9..4ce95c1 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Tell_City
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Tell_City
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Vevay b/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Vevay
index e934de6..d236b7c 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Vevay
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Vevay
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Vincennes b/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Vincennes
index adbdbee..c818929 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Vincennes
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Vincennes
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Winamac b/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Winamac
index b34f7b2..630935c 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Winamac
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Winamac
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Indianapolis b/absl/time/internal/cctz/testdata/zoneinfo/America/Indianapolis
index 4a92c06..09511cc 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Indianapolis
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Indianapolis
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Inuvik b/absl/time/internal/cctz/testdata/zoneinfo/America/Inuvik
index 1388e8a..e107dc4 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Inuvik
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Inuvik
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Iqaluit b/absl/time/internal/cctz/testdata/zoneinfo/America/Iqaluit
index 0785ac5..c8138bd 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Iqaluit
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Iqaluit
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Jamaica b/absl/time/internal/cctz/testdata/zoneinfo/America/Jamaica
index 7aedd26..162306f 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Jamaica
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Jamaica
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Jujuy b/absl/time/internal/cctz/testdata/zoneinfo/America/Jujuy
index a74ba04..7d2ba91 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Jujuy
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Jujuy
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Juneau b/absl/time/internal/cctz/testdata/zoneinfo/America/Juneau
index d00668a..451f349 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Juneau
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Juneau
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Kentucky/Louisville b/absl/time/internal/cctz/testdata/zoneinfo/America/Kentucky/Louisville
index fdf2e88..f4c4cf9 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Kentucky/Louisville
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Kentucky/Louisville
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Kentucky/Monticello b/absl/time/internal/cctz/testdata/zoneinfo/America/Kentucky/Monticello
index 60991aa..438e3ea 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Kentucky/Monticello
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Kentucky/Monticello
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Knox_IN b/absl/time/internal/cctz/testdata/zoneinfo/America/Knox_IN
index cc785da..fcd408d 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Knox_IN
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Knox_IN
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Kralendijk b/absl/time/internal/cctz/testdata/zoneinfo/America/Kralendijk
index d308336..d3b318d 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Kralendijk
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Kralendijk
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/La_Paz b/absl/time/internal/cctz/testdata/zoneinfo/America/La_Paz
index bc3df52..5e5fec5 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/La_Paz
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/La_Paz
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Lima b/absl/time/internal/cctz/testdata/zoneinfo/America/Lima
index 44280a5..d9fec37 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Lima
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Lima
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Los_Angeles b/absl/time/internal/cctz/testdata/zoneinfo/America/Los_Angeles
index c0ce440..9dad4f4 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Los_Angeles
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Los_Angeles
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Louisville b/absl/time/internal/cctz/testdata/zoneinfo/America/Louisville
index fdf2e88..f4c4cf9 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Louisville
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Louisville
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Lower_Princes b/absl/time/internal/cctz/testdata/zoneinfo/America/Lower_Princes
index d308336..d3b318d 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Lower_Princes
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Lower_Princes
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Maceio b/absl/time/internal/cctz/testdata/zoneinfo/America/Maceio
index 54442dc..fec8a8b 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Maceio
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Maceio
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Managua b/absl/time/internal/cctz/testdata/zoneinfo/America/Managua
index c543ffd..69256c6 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Managua
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Managua
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Manaus b/absl/time/internal/cctz/testdata/zoneinfo/America/Manaus
index 855cb02..b10241e 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Manaus
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Manaus
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Marigot b/absl/time/internal/cctz/testdata/zoneinfo/America/Marigot
index 447efbe..bdedd1b 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Marigot
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Marigot
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Martinique b/absl/time/internal/cctz/testdata/zoneinfo/America/Martinique
index f9e2399..79716de 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Martinique
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Martinique
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Matamoros b/absl/time/internal/cctz/testdata/zoneinfo/America/Matamoros
index 5671d25..5c59984 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Matamoros
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Matamoros
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Mazatlan b/absl/time/internal/cctz/testdata/zoneinfo/America/Mazatlan
index afa94c2..43ee12d 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Mazatlan
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Mazatlan
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Mendoza b/absl/time/internal/cctz/testdata/zoneinfo/America/Mendoza
index 5e8c44c..1032356 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Mendoza
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Mendoza
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Menominee b/absl/time/internal/cctz/testdata/zoneinfo/America/Menominee
index 55d6e32..3146138 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Menominee
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Menominee
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Merida b/absl/time/internal/cctz/testdata/zoneinfo/America/Merida
index ecc1856..b46298e 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Merida
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Merida
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Metlakatla b/absl/time/internal/cctz/testdata/zoneinfo/America/Metlakatla
index c033597..85a7e16 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Metlakatla
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Metlakatla
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Mexico_City b/absl/time/internal/cctz/testdata/zoneinfo/America/Mexico_City
index f11e3d2..1434ab0 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Mexico_City
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Mexico_City
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Miquelon b/absl/time/internal/cctz/testdata/zoneinfo/America/Miquelon
index 75bbcf2..06ceaad 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Miquelon
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Miquelon
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Moncton b/absl/time/internal/cctz/testdata/zoneinfo/America/Moncton
index 51cb1ba..9df8d0f 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Moncton
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Moncton
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Monterrey b/absl/time/internal/cctz/testdata/zoneinfo/America/Monterrey
index dcac92b..7dc5057 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Monterrey
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Monterrey
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Montevideo b/absl/time/internal/cctz/testdata/zoneinfo/America/Montevideo
index f524fd2..0d1e565 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Montevideo
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Montevideo
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Montreal b/absl/time/internal/cctz/testdata/zoneinfo/America/Montreal
index 7b4682a..6752c5b 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Montreal
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Montreal
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Montserrat b/absl/time/internal/cctz/testdata/zoneinfo/America/Montserrat
index 447efbe..bdedd1b 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Montserrat
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Montserrat
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Nassau b/absl/time/internal/cctz/testdata/zoneinfo/America/Nassau
index e5d0289..5091eb5 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Nassau
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Nassau
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/New_York b/absl/time/internal/cctz/testdata/zoneinfo/America/New_York
index 7553fee..2f75480 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/New_York
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/New_York
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Nipigon b/absl/time/internal/cctz/testdata/zoneinfo/America/Nipigon
index f8a0292..f6a856e 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Nipigon
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Nipigon
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Nome b/absl/time/internal/cctz/testdata/zoneinfo/America/Nome
index c886c9b..10998df 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Nome
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Nome
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Noronha b/absl/time/internal/cctz/testdata/zoneinfo/America/Noronha
index 6d91f91..95ff8a2 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Noronha
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Noronha
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/North_Dakota/Beulah b/absl/time/internal/cctz/testdata/zoneinfo/America/North_Dakota/Beulah
index 8174c88..246345d 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/North_Dakota/Beulah
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/North_Dakota/Beulah
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/North_Dakota/Center b/absl/time/internal/cctz/testdata/zoneinfo/America/North_Dakota/Center
index 8035b24..1fa0703 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/North_Dakota/Center
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/North_Dakota/Center
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/North_Dakota/New_Salem b/absl/time/internal/cctz/testdata/zoneinfo/America/North_Dakota/New_Salem
index 5b630ee..123f2ae 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/North_Dakota/New_Salem
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/North_Dakota/New_Salem
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Ojinaga b/absl/time/internal/cctz/testdata/zoneinfo/America/Ojinaga
index 190c5c8..37d7830 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Ojinaga
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Ojinaga
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Panama b/absl/time/internal/cctz/testdata/zoneinfo/America/Panama
index 5c1c063..55b0834 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Panama
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Panama
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Pangnirtung b/absl/time/internal/cctz/testdata/zoneinfo/America/Pangnirtung
index df78b62..3e4e0db 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Pangnirtung
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Pangnirtung
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Paramaribo b/absl/time/internal/cctz/testdata/zoneinfo/America/Paramaribo
index 1b608b3..b95c784 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Paramaribo
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Paramaribo
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Phoenix b/absl/time/internal/cctz/testdata/zoneinfo/America/Phoenix
index adf2823..4d51271 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Phoenix
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Phoenix
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Port-au-Prince b/absl/time/internal/cctz/testdata/zoneinfo/America/Port-au-Prince
index 7306cae..d959010 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Port-au-Prince
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Port-au-Prince
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Port_of_Spain b/absl/time/internal/cctz/testdata/zoneinfo/America/Port_of_Spain
index 447efbe..bdedd1b 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Port_of_Spain
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Port_of_Spain
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Porto_Acre b/absl/time/internal/cctz/testdata/zoneinfo/America/Porto_Acre
index b612ac2..16b7f92 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Porto_Acre
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Porto_Acre
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Porto_Velho b/absl/time/internal/cctz/testdata/zoneinfo/America/Porto_Velho
index 2423fc1..10cb02b 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Porto_Velho
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Porto_Velho
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Puerto_Rico b/absl/time/internal/cctz/testdata/zoneinfo/America/Puerto_Rico
index d4525a6..a662a57 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Puerto_Rico
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Puerto_Rico
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Punta_Arenas b/absl/time/internal/cctz/testdata/zoneinfo/America/Punta_Arenas
index 4d84eed..a5a8af5 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Punta_Arenas
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Punta_Arenas
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Rainy_River b/absl/time/internal/cctz/testdata/zoneinfo/America/Rainy_River
index 70dcd2d..ea66099 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Rainy_River
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Rainy_River
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Rankin_Inlet b/absl/time/internal/cctz/testdata/zoneinfo/America/Rankin_Inlet
index 9f50f36..61ff6fc 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Rankin_Inlet
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Rankin_Inlet
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Recife b/absl/time/internal/cctz/testdata/zoneinfo/America/Recife
index fe55739..c6d99b3 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Recife
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Recife
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Regina b/absl/time/internal/cctz/testdata/zoneinfo/America/Regina
index 5fe8d6b..20c9c84 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Regina
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Regina
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Resolute b/absl/time/internal/cctz/testdata/zoneinfo/America/Resolute
index 884b1f6..4365a5c 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Resolute
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Resolute
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Rio_Branco b/absl/time/internal/cctz/testdata/zoneinfo/America/Rio_Branco
index b612ac2..16b7f92 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Rio_Branco
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Rio_Branco
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Rosario b/absl/time/internal/cctz/testdata/zoneinfo/America/Rosario
index 8c58f8c..5df3cf6 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Rosario
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Rosario
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Santa_Isabel b/absl/time/internal/cctz/testdata/zoneinfo/America/Santa_Isabel
index 29c83e7..ada6bf7 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Santa_Isabel
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Santa_Isabel
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Santarem b/absl/time/internal/cctz/testdata/zoneinfo/America/Santarem
index d776a43..8080efa 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Santarem
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Santarem
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Santiago b/absl/time/internal/cctz/testdata/zoneinfo/America/Santiago
index ab766a4..816a042 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Santiago
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Santiago
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Santo_Domingo b/absl/time/internal/cctz/testdata/zoneinfo/America/Santo_Domingo
index cc2cbf2..4e5eba5 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Santo_Domingo
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Santo_Domingo
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Sao_Paulo b/absl/time/internal/cctz/testdata/zoneinfo/America/Sao_Paulo
index 308a545..c417ba1 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Sao_Paulo
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Sao_Paulo
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Scoresbysund b/absl/time/internal/cctz/testdata/zoneinfo/America/Scoresbysund
index 8e1366c..e20e9e1 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Scoresbysund
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Scoresbysund
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Shiprock b/absl/time/internal/cctz/testdata/zoneinfo/America/Shiprock
index 7fc6691..5fbe26b 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Shiprock
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Shiprock
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Sitka b/absl/time/internal/cctz/testdata/zoneinfo/America/Sitka
index 662b8b6..31f7061 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Sitka
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Sitka
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/St_Barthelemy b/absl/time/internal/cctz/testdata/zoneinfo/America/St_Barthelemy
index 447efbe..bdedd1b 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/St_Barthelemy
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/St_Barthelemy
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/St_Johns b/absl/time/internal/cctz/testdata/zoneinfo/America/St_Johns
index a1d1485..65a5b0c 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/St_Johns
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/St_Johns
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/St_Kitts b/absl/time/internal/cctz/testdata/zoneinfo/America/St_Kitts
index 447efbe..bdedd1b 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/St_Kitts
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/St_Kitts
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/St_Lucia b/absl/time/internal/cctz/testdata/zoneinfo/America/St_Lucia
index 447efbe..bdedd1b 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/St_Lucia
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/St_Lucia
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/St_Thomas b/absl/time/internal/cctz/testdata/zoneinfo/America/St_Thomas
index 447efbe..bdedd1b 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/St_Thomas
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/St_Thomas
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/St_Vincent b/absl/time/internal/cctz/testdata/zoneinfo/America/St_Vincent
index 447efbe..bdedd1b 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/St_Vincent
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/St_Vincent
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Swift_Current b/absl/time/internal/cctz/testdata/zoneinfo/America/Swift_Current
index 4db1300..8e9ef25 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Swift_Current
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Swift_Current
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Tegucigalpa b/absl/time/internal/cctz/testdata/zoneinfo/America/Tegucigalpa
index 7aea8f9..477e939 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Tegucigalpa
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Tegucigalpa
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Thule b/absl/time/internal/cctz/testdata/zoneinfo/America/Thule
index deefcc8..2969ebe 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Thule
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Thule
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Thunder_Bay b/absl/time/internal/cctz/testdata/zoneinfo/America/Thunder_Bay
index aa1d486..e504c9a 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Thunder_Bay
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Thunder_Bay
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Tijuana b/absl/time/internal/cctz/testdata/zoneinfo/America/Tijuana
index 29c83e7..ada6bf7 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Tijuana
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Tijuana
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Toronto b/absl/time/internal/cctz/testdata/zoneinfo/America/Toronto
index 7b4682a..6752c5b 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Toronto
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Toronto
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Tortola b/absl/time/internal/cctz/testdata/zoneinfo/America/Tortola
index 447efbe..bdedd1b 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Tortola
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Tortola
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Vancouver b/absl/time/internal/cctz/testdata/zoneinfo/America/Vancouver
index 9b5d924..0f9f832 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Vancouver
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Vancouver
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Virgin b/absl/time/internal/cctz/testdata/zoneinfo/America/Virgin
index 447efbe..bdedd1b 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Virgin
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Virgin
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Whitehorse b/absl/time/internal/cctz/testdata/zoneinfo/America/Whitehorse
index 6b62e2d..fb3cd71 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Whitehorse
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Whitehorse
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Winnipeg b/absl/time/internal/cctz/testdata/zoneinfo/America/Winnipeg
index 2ffe3d8..3718d47 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Winnipeg
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Winnipeg
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Yakutat b/absl/time/internal/cctz/testdata/zoneinfo/America/Yakutat
index 523b0a1..da209f9 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Yakutat
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Yakutat
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Yellowknife b/absl/time/internal/cctz/testdata/zoneinfo/America/Yellowknife
index d9d6eff..e6afa39 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Yellowknife
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Yellowknife
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Casey b/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Casey
index d0bbacc..f100f47 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Casey
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Casey
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Davis b/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Davis
index 40a9926..916f2c2 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Davis
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Davis
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/DumontDUrville b/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/DumontDUrville
index 0686353..bd6563e 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/DumontDUrville
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/DumontDUrville
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Macquarie b/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Macquarie
index aea2be7..83c308a 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Macquarie
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Macquarie
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Mawson b/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Mawson
index 5197dd9..e1f0b09 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Mawson
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Mawson
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/McMurdo b/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/McMurdo
index a5f5b6d..60bcef6 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/McMurdo
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/McMurdo
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Palmer b/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Palmer
index 43a01d3..3dd85f8 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Palmer
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Palmer
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Rothera b/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Rothera
index 56913f8..7940e6e 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Rothera
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Rothera
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/South_Pole b/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/South_Pole
index a5f5b6d..60bcef6 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/South_Pole
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/South_Pole
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Syowa b/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Syowa
index 94a9d5a..4bb041a 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Syowa
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Syowa
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Troll b/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Troll
index 3757fac..5e565da 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Troll
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Troll
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Vostok b/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Vostok
index 9fa335c..5696abf 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Vostok
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Vostok
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Arctic/Longyearbyen b/absl/time/internal/cctz/testdata/zoneinfo/Arctic/Longyearbyen
index 239c017..c6842af 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Arctic/Longyearbyen
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Arctic/Longyearbyen
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Aden b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Aden
index e71bc4e..b2f9a25 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Aden
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Aden
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Almaty b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Almaty
index 49a4b4d..d93201c 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Almaty
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Almaty
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Amman b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Amman
index c3f0994..281b304 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Amman
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Amman
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Anadyr b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Anadyr
index 0e623cf..6a96601 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Anadyr
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Anadyr
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Aqtau b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Aqtau
index 5803a3d..78cbcf0 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Aqtau
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Aqtau
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Aqtobe b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Aqtobe
index 808a502..7504052 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Aqtobe
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Aqtobe
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Ashgabat b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Ashgabat
index 046c472..8d9e03c 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Ashgabat
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Ashgabat
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Ashkhabad b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Ashkhabad
index 046c472..8d9e03c 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Ashkhabad
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Ashkhabad
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Atyrau b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Atyrau
index 27072eb..317466d 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Atyrau
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Atyrau
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Baghdad b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Baghdad
index 3aacd78..97fa6c7 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Baghdad
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Baghdad
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Bahrain b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Bahrain
index a0c5f66..f514092 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Bahrain
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Bahrain
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Baku b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Baku
index a17d1ad..8a090d7 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Baku
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Baku
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Bangkok b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Bangkok
index 8db5e8a..7249640 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Bangkok
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Bangkok
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Barnaul b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Barnaul
index 60efb41..82cc49c 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Barnaul
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Barnaul
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Beirut b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Beirut
index 72f0896..efb24c2 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Beirut
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Beirut
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Bishkek b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Bishkek
index e3f81ee..f7a7d54 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Bishkek
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Bishkek
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Brunei b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Brunei
index cad16b0..8624c7a 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Brunei
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Brunei
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Calcutta b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Calcutta
index b57972d..e1cfcb8 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Calcutta
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Calcutta
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Chita b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Chita
index 95f5645..3baf752 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Chita
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Chita
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Choibalsan b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Choibalsan
index 15b358f..79b9d3c 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Choibalsan
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Choibalsan
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Chongqing b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Chongqing
index dbd132f..ce9e00a 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Chongqing
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Chongqing
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Chungking b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Chungking
index dbd132f..ce9e00a 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Chungking
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Chungking
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Colombo b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Colombo
index 28fe430..4fc96c8 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Colombo
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Colombo
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Dacca b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Dacca
index 98881f0..776f27d 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Dacca
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Dacca
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Damascus b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Damascus
index ac45764..4b610b5 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Damascus
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Damascus
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Dhaka b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Dhaka
index 98881f0..776f27d 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Dhaka
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Dhaka
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Dili b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Dili
index c94fa61..f6ce91a 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Dili
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Dili
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Dubai b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Dubai
index c12f31a..7880d5d 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Dubai
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Dubai
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Dushanbe b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Dushanbe
index 67c772b..694f6e6 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Dushanbe
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Dushanbe
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Famagusta b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Famagusta
index 021f8a2..653b146 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Famagusta
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Famagusta
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Gaza b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Gaza
index 60d0de0..cf54deb 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Gaza
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Gaza
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Harbin b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Harbin
index dbd132f..ce9e00a 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Harbin
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Harbin
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Hebron b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Hebron
index a2e1b36..09c876a 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Hebron
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Hebron
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Ho_Chi_Minh b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Ho_Chi_Minh
index 9264267..eab94fe 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Ho_Chi_Minh
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Ho_Chi_Minh
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Hong_Kong b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Hong_Kong
index dc9058e..91eaff4 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Hong_Kong
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Hong_Kong
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Hovd b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Hovd
index f367a55..8eb5f64 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Hovd
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Hovd
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Irkutsk b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Irkutsk
index 8413636..e8c53c0 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Irkutsk
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Irkutsk
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Istanbul b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Istanbul
index 9a53b3a..833d4eb 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Istanbul
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Istanbul
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Jakarta b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Jakarta
index 37b4edd..673d480 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Jakarta
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Jakarta
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Jayapura b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Jayapura
index 39ddc84..a4c0829 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Jayapura
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Jayapura
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Jerusalem b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Jerusalem
index df51199..2d14c99 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Jerusalem
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Jerusalem
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kabul b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kabul
index 80429ec..a22cf59 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kabul
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kabul
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kamchatka b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kamchatka
index fab27de..b9ed49c 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kamchatka
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kamchatka
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Karachi b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Karachi
index b7dcaab..337e1d5 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Karachi
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Karachi
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kashgar b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kashgar
index b44a1e1..0342b43 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kashgar
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kashgar
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kathmandu b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kathmandu
index 0cbd295..2f810b1 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kathmandu
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kathmandu
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Katmandu b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Katmandu
index 0cbd295..2f810b1 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Katmandu
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Katmandu
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Khandyga b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Khandyga
index 9183695..2b2f5bf 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Khandyga
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Khandyga
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kolkata b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kolkata
index b57972d..e1cfcb8 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kolkata
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kolkata
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Krasnoyarsk b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Krasnoyarsk
index faec35d..59efd24 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Krasnoyarsk
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Krasnoyarsk
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kuala_Lumpur b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kuala_Lumpur
index 5c95ebc..6d7d47b 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kuala_Lumpur
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kuala_Lumpur
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kuching b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kuching
index 62b5389..4878622 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kuching
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kuching
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kuwait b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kuwait
index e71bc4e..b2f9a25 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kuwait
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kuwait
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Macao b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Macao
index 2c20a32..d801000 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Macao
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Macao
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Macau b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Macau
index 2c20a32..d801000 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Macau
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Macau
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Magadan b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Magadan
index 2db0635..b20cc57 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Magadan
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Magadan
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Makassar b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Makassar
index 3a5dcb2..ed55442 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Makassar
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Makassar
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Manila b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Manila
index 06859a7..2c9220c 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Manila
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Manila
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Muscat b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Muscat
index c12f31a..7880d5d 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Muscat
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Muscat
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Nicosia b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Nicosia
index 3e663b2..f7f10ab 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Nicosia
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Nicosia
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Novokuznetsk b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Novokuznetsk
index ed4b248..2576a3b 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Novokuznetsk
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Novokuznetsk
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Novosibirsk b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Novosibirsk
index a5d39df..95e3c73 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Novosibirsk
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Novosibirsk
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Omsk b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Omsk
index 5e0d9b6..d805e4f 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Omsk
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Omsk
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Oral b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Oral
index b8eb58d..e36aec4 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Oral
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Oral
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Phnom_Penh b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Phnom_Penh
index 8db5e8a..7249640 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Phnom_Penh
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Phnom_Penh
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Pontianak b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Pontianak
index ec98c62..9377d03 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Pontianak
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Pontianak
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Pyongyang b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Pyongyang
index dc24926..dd54989 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Pyongyang
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Pyongyang
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Qatar b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Qatar
index a0c5f66..f514092 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Qatar
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Qatar
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Qostanay b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Qostanay
new file mode 100644
index 0000000..cb6e2d9
--- /dev/null
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Qostanay
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Qyzylorda b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Qyzylorda
index 0fc7fad..fc636b3 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Qyzylorda
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Qyzylorda
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Rangoon b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Rangoon
index 3cc2aaf..a00282d 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Rangoon
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Rangoon
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Riyadh b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Riyadh
index e71bc4e..b2f9a25 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Riyadh
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Riyadh
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Saigon b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Saigon
index 9264267..eab94fe 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Saigon
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Saigon
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Sakhalin b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Sakhalin
index 8d6b4df..9c94900 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Sakhalin
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Sakhalin
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Samarkand b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Samarkand
index 10c7af7..a5d1e97 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Samarkand
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Samarkand
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Seoul b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Seoul
index 312ec40..fa1cbd3 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Seoul
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Seoul
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Shanghai b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Shanghai
index dbd132f..ce9e00a 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Shanghai
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Shanghai
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Singapore b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Singapore
index 7858366..ebc4b0d 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Singapore
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Singapore
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Srednekolymsk b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Srednekolymsk
index 16b1cd8..f8b7bb2 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Srednekolymsk
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Srednekolymsk
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Taipei b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Taipei
index 748873b..f9cbe67 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Taipei
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Taipei
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Tashkent b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Tashkent
index 6f7dea4..e75bb36 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Tashkent
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Tashkent
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Tbilisi b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Tbilisi
index 4b2d2e2..09bb06e 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Tbilisi
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Tbilisi
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Tehran b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Tehran
index 3157f80..0ae2f65 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Tehran
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Tehran
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Tel_Aviv b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Tel_Aviv
index df51199..2d14c99 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Tel_Aviv
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Tel_Aviv
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Thimbu b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Thimbu
index a8bddb9..06d3324 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Thimbu
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Thimbu
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Thimphu b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Thimphu
index a8bddb9..06d3324 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Thimphu
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Thimphu
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Tokyo b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Tokyo
index 8ad44ba..26f4d34 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Tokyo
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Tokyo
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Tomsk b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Tomsk
index 919b003..28da9c9 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Tomsk
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Tomsk
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Ujung_Pandang b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Ujung_Pandang
index 3a5dcb2..ed55442 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Ujung_Pandang
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Ujung_Pandang
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Ulaanbaatar b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Ulaanbaatar
index 94ddfea..82fd476 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Ulaanbaatar
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Ulaanbaatar
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Ulan_Bator b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Ulan_Bator
index 94ddfea..82fd476 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Ulan_Bator
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Ulan_Bator
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Urumqi b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Urumqi
index b44a1e1..0342b43 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Urumqi
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Urumqi
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Ust-Nera b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Ust-Nera
index 7431eb9..c0c3767 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Ust-Nera
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Ust-Nera
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Vientiane b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Vientiane
index 8db5e8a..7249640 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Vientiane
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Vientiane
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Vladivostok b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Vladivostok
index 80b170b..15731ab 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Vladivostok
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Vladivostok
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Yakutsk b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Yakutsk
index 220ad3d..1f86e77 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Yakutsk
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Yakutsk
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Yangon b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Yangon
index 3cc2aaf..a00282d 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Yangon
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Yangon
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Yekaterinburg b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Yekaterinburg
index c1abb93..fff9f3b 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Yekaterinburg
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Yekaterinburg
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Yerevan b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Yerevan
index 4c4e045..409c3b1 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Yerevan
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Yerevan
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Azores b/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Azores
index 1895e1b..56593db 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Azores
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Azores
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Bermuda b/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Bermuda
index 548d979..3a5c6db 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Bermuda
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Bermuda
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Canary b/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Canary
index 544f443..f319215 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Canary
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Canary
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Cape_Verde b/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Cape_Verde
index 6bda6db..e2a49d2 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Cape_Verde
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Cape_Verde
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Faeroe b/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Faeroe
index c486518..4dab7ef 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Faeroe
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Faeroe
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Faroe b/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Faroe
index c486518..4dab7ef 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Faroe
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Faroe
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Jan_Mayen b/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Jan_Mayen
index 239c017..c6842af 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Jan_Mayen
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Jan_Mayen
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Madeira b/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Madeira
index e25f8a5..5213761 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Madeira
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Madeira
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Reykjavik b/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Reykjavik
index dc49c32..ac6bd69 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Reykjavik
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Reykjavik
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/South_Georgia b/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/South_Georgia
index 56b383b..b3311b6 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/South_Georgia
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/South_Georgia
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/St_Helena b/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/St_Helena
index 6fd1af3..65d19ec 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/St_Helena
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/St_Helena
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Stanley b/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Stanley
index 3649415..2fd42a2 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Stanley
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Stanley
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Australia/ACT b/absl/time/internal/cctz/testdata/zoneinfo/Australia/ACT
index aaed12c..4ed4467 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Australia/ACT
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Australia/ACT
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Australia/Adelaide b/absl/time/internal/cctz/testdata/zoneinfo/Australia/Adelaide
index 4f331a8..190b0e3 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Australia/Adelaide
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Australia/Adelaide
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Australia/Brisbane b/absl/time/internal/cctz/testdata/zoneinfo/Australia/Brisbane
index a327d83..26ffd9a 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Australia/Brisbane
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Australia/Brisbane
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Australia/Broken_Hill b/absl/time/internal/cctz/testdata/zoneinfo/Australia/Broken_Hill
index 768b167..874c865 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Australia/Broken_Hill
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Australia/Broken_Hill
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Australia/Canberra b/absl/time/internal/cctz/testdata/zoneinfo/Australia/Canberra
index aaed12c..4ed4467 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Australia/Canberra
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Australia/Canberra
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Australia/Currie b/absl/time/internal/cctz/testdata/zoneinfo/Australia/Currie
index a3f6f29..865801e 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Australia/Currie
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Australia/Currie
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Australia/Darwin b/absl/time/internal/cctz/testdata/zoneinfo/Australia/Darwin
index c6ae9a7..cf42d1d 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Australia/Darwin
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Australia/Darwin
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Australia/Eucla b/absl/time/internal/cctz/testdata/zoneinfo/Australia/Eucla
index 99f07a9..c49d499 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Australia/Eucla
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Australia/Eucla
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Australia/Hobart b/absl/time/internal/cctz/testdata/zoneinfo/Australia/Hobart
index 07784ce..92d1215 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Australia/Hobart
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Australia/Hobart
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Australia/LHI b/absl/time/internal/cctz/testdata/zoneinfo/Australia/LHI
index 57597b0..8c6c7dd 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Australia/LHI
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Australia/LHI
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Australia/Lindeman b/absl/time/internal/cctz/testdata/zoneinfo/Australia/Lindeman
index 71ca143..8ee1a6f 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Australia/Lindeman
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Australia/Lindeman
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Australia/Lord_Howe b/absl/time/internal/cctz/testdata/zoneinfo/Australia/Lord_Howe
index 57597b0..8c6c7dd 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Australia/Lord_Howe
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Australia/Lord_Howe
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Australia/Melbourne b/absl/time/internal/cctz/testdata/zoneinfo/Australia/Melbourne
index ec8dfe0..3f2d3d7 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Australia/Melbourne
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Australia/Melbourne
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Australia/NSW b/absl/time/internal/cctz/testdata/zoneinfo/Australia/NSW
index aaed12c..4ed4467 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Australia/NSW
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Australia/NSW
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Australia/North b/absl/time/internal/cctz/testdata/zoneinfo/Australia/North
index c6ae9a7..cf42d1d 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Australia/North
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Australia/North
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Australia/Perth b/absl/time/internal/cctz/testdata/zoneinfo/Australia/Perth
index 85c26d5..d38b67e 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Australia/Perth
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Australia/Perth
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Australia/Queensland b/absl/time/internal/cctz/testdata/zoneinfo/Australia/Queensland
index a327d83..26ffd9a 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Australia/Queensland
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Australia/Queensland
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Australia/South b/absl/time/internal/cctz/testdata/zoneinfo/Australia/South
index 4f331a8..190b0e3 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Australia/South
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Australia/South
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Australia/Sydney b/absl/time/internal/cctz/testdata/zoneinfo/Australia/Sydney
index aaed12c..4ed4467 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Australia/Sydney
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Australia/Sydney
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Australia/Tasmania b/absl/time/internal/cctz/testdata/zoneinfo/Australia/Tasmania
index 07784ce..92d1215 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Australia/Tasmania
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Australia/Tasmania
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Australia/Victoria b/absl/time/internal/cctz/testdata/zoneinfo/Australia/Victoria
index ec8dfe0..3f2d3d7 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Australia/Victoria
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Australia/Victoria
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Australia/West b/absl/time/internal/cctz/testdata/zoneinfo/Australia/West
index 85c26d5..d38b67e 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Australia/West
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Australia/West
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Australia/Yancowinna b/absl/time/internal/cctz/testdata/zoneinfo/Australia/Yancowinna
index 768b167..874c865 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Australia/Yancowinna
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Australia/Yancowinna
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Brazil/Acre b/absl/time/internal/cctz/testdata/zoneinfo/Brazil/Acre
index b612ac2..16b7f92 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Brazil/Acre
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Brazil/Acre
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Brazil/DeNoronha b/absl/time/internal/cctz/testdata/zoneinfo/Brazil/DeNoronha
index 6d91f91..95ff8a2 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Brazil/DeNoronha
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Brazil/DeNoronha
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Brazil/East b/absl/time/internal/cctz/testdata/zoneinfo/Brazil/East
index 308a545..c417ba1 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Brazil/East
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Brazil/East
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Brazil/West b/absl/time/internal/cctz/testdata/zoneinfo/Brazil/West
index 855cb02..b10241e 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Brazil/West
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Brazil/West
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/CET b/absl/time/internal/cctz/testdata/zoneinfo/CET
index 4c4f8ef..d585656 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/CET
+++ b/absl/time/internal/cctz/testdata/zoneinfo/CET
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/CST6CDT b/absl/time/internal/cctz/testdata/zoneinfo/CST6CDT
index 5c8a1d9..41c4136 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/CST6CDT
+++ b/absl/time/internal/cctz/testdata/zoneinfo/CST6CDT
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Canada/Atlantic b/absl/time/internal/cctz/testdata/zoneinfo/Canada/Atlantic
index f86ece4..756099a 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Canada/Atlantic
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Canada/Atlantic
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Canada/Central b/absl/time/internal/cctz/testdata/zoneinfo/Canada/Central
index 2ffe3d8..3718d47 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Canada/Central
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Canada/Central
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Canada/Eastern b/absl/time/internal/cctz/testdata/zoneinfo/Canada/Eastern
index 7b4682a..6752c5b 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Canada/Eastern
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Canada/Eastern
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Canada/Mountain b/absl/time/internal/cctz/testdata/zoneinfo/Canada/Mountain
index d02fbcd..3fa0579 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Canada/Mountain
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Canada/Mountain
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Canada/Newfoundland b/absl/time/internal/cctz/testdata/zoneinfo/Canada/Newfoundland
index a1d1485..65a5b0c 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Canada/Newfoundland
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Canada/Newfoundland
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Canada/Pacific b/absl/time/internal/cctz/testdata/zoneinfo/Canada/Pacific
index 9b5d924..0f9f832 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Canada/Pacific
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Canada/Pacific
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Canada/Saskatchewan b/absl/time/internal/cctz/testdata/zoneinfo/Canada/Saskatchewan
index 5fe8d6b..20c9c84 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Canada/Saskatchewan
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Canada/Saskatchewan
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Canada/Yukon b/absl/time/internal/cctz/testdata/zoneinfo/Canada/Yukon
index 6b62e2d..fb3cd71 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Canada/Yukon
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Canada/Yukon
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Chile/Continental b/absl/time/internal/cctz/testdata/zoneinfo/Chile/Continental
index ab766a4..816a042 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Chile/Continental
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Chile/Continental
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Chile/EasterIsland b/absl/time/internal/cctz/testdata/zoneinfo/Chile/EasterIsland
index 060bef8..cae3744 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Chile/EasterIsland
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Chile/EasterIsland
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Cuba b/absl/time/internal/cctz/testdata/zoneinfo/Cuba
index 1a58fcd..8186060 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Cuba
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Cuba
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/EET b/absl/time/internal/cctz/testdata/zoneinfo/EET
index beb273a..d2f54c9 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/EET
+++ b/absl/time/internal/cctz/testdata/zoneinfo/EET
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/EST b/absl/time/internal/cctz/testdata/zoneinfo/EST
index ae34663..074a4fc 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/EST
+++ b/absl/time/internal/cctz/testdata/zoneinfo/EST
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/EST5EDT b/absl/time/internal/cctz/testdata/zoneinfo/EST5EDT
index 54541fc..087b641 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/EST5EDT
+++ b/absl/time/internal/cctz/testdata/zoneinfo/EST5EDT
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Egypt b/absl/time/internal/cctz/testdata/zoneinfo/Egypt
index ba09750..0272fa1 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Egypt
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Egypt
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Eire b/absl/time/internal/cctz/testdata/zoneinfo/Eire
index 655daf3..5c5a7a3 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Eire
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Eire
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT
index c05e45f..2ee1429 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+0 b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+0
index c05e45f..2ee1429 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+0
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+0
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+1 b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+1
index 082986e..087d1f9 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+1
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+1
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+10 b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+10
index 23276cd..6437c68 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+10
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+10
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+11 b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+11
index 28c579d..72a912e 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+11
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+11
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+12 b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+12
index c740603..6938a1a 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+12
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+12
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+2 b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+2
index 721cde2..a315577 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+2
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+2
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+3 b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+3
index ae06bcb..ee77619 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+3
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+3
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+4 b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+4
index 5a7f878..1ea7da2 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+4
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+4
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+5 b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+5
index 18cbf1f..dda1a9e 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+5
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+5
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+6 b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+6
index 1aa4be8..f4a0385 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+6
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+6
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+7 b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+7
index cd8ed49..2d2ccd0 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+7
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+7
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+8 b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+8
index e0ba6b8..826c770 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+8
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+8
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+9 b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+9
index eee1bcb..b125ad2 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+9
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+9
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-0 b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-0
index c05e45f..2ee1429 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-0
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-0
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-1 b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-1
index 4ff8701..dde682d 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-1
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-1
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-10 b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-10
index e12e461..352ec08 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-10
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-10
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-11 b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-11
index 37f2739..dfa27fe 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-11
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-11
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-12 b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-12
index 09297f1..eef949d 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-12
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-12
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-13 b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-13
index 97ae1e1..f9363b2 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-13
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-13
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-14 b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-14
index 58d6d1b..35add05 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-14
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-14
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-2 b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-2
index f0dc706..315cae4 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-2
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-2
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-3 b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-3
index a0790fe..7489a15 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-3
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-3
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-4 b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-4
index a75a173..560243e 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-4
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-4
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-5 b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-5
index 85ebf22..b2bbe97 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-5
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-5
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-6 b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-6
index 95def1f..b979dbb 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-6
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-6
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-7 b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-7
index c6a776e..365ab1f 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-7
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-7
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-8 b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-8
index f74a16f..742082f 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-8
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-8
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-9 b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-9
index 9b647c0..abc0b27 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-9
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-9
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT0 b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT0
index c05e45f..2ee1429 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT0
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT0
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Etc/Greenwich b/absl/time/internal/cctz/testdata/zoneinfo/Etc/Greenwich
index c05e45f..2ee1429 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Etc/Greenwich
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Etc/Greenwich
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Etc/UCT b/absl/time/internal/cctz/testdata/zoneinfo/Etc/UCT
index 40147b9..a88c4b6 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Etc/UCT
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Etc/UCT
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Etc/UTC b/absl/time/internal/cctz/testdata/zoneinfo/Etc/UTC
index c3b97f1..5583f5b 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Etc/UTC
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Etc/UTC
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Etc/Universal b/absl/time/internal/cctz/testdata/zoneinfo/Etc/Universal
index c3b97f1..5583f5b 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Etc/Universal
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Etc/Universal
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Etc/Zulu b/absl/time/internal/cctz/testdata/zoneinfo/Etc/Zulu
index c3b97f1..5583f5b 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Etc/Zulu
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Etc/Zulu
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Amsterdam b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Amsterdam
index 6dae5e4..ed064ed 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Amsterdam
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Amsterdam
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Andorra b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Andorra
index b06de7a..5962550 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Andorra
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Andorra
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Astrakhan b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Astrakhan
index 90d7c2a..5e069ea 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Astrakhan
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Astrakhan
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Athens b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Athens
index 0001602..9f3a067 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Athens
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Athens
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Belfast b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Belfast
index 4527515..a340326 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Belfast
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Belfast
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Belgrade b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Belgrade
index 79c25d7..32a5722 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Belgrade
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Belgrade
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Berlin b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Berlin
index b4f2a2a..7ddd510 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Berlin
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Berlin
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Bratislava b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Bratislava
index ba82f31..85036de 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Bratislava
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Bratislava
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Brussels b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Brussels
index d8f19a6..d0d0a08 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Brussels
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Brussels
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Bucharest b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Bucharest
index e0eac4c..4eb7ed0 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Bucharest
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Bucharest
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Budapest b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Budapest
index 3ddf6a5..dfdc6d2 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Budapest
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Budapest
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Busingen b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Busingen
index 9c2b600..ad6cf59 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Busingen
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Busingen
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Chisinau b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Chisinau
index 2109b52..5bc1bfe 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Chisinau
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Chisinau
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Copenhagen b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Copenhagen
index be87cf1..cb2ec06 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Copenhagen
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Copenhagen
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Dublin b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Dublin
index 655daf3..5c5a7a3 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Dublin
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Dublin
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Gibraltar b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Gibraltar
index a7105fa..117aadb 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Gibraltar
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Gibraltar
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Guernsey b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Guernsey
index 4527515..a340326 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Guernsey
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Guernsey
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Helsinki b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Helsinki
index 29b3c81..b4f8f9c 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Helsinki
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Helsinki
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Isle_of_Man b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Isle_of_Man
index 4527515..a340326 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Isle_of_Man
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Isle_of_Man
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Istanbul b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Istanbul
index 9a53b3a..833d4eb 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Istanbul
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Istanbul
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Jersey b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Jersey
index 4527515..a340326 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Jersey
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Jersey
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Kaliningrad b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Kaliningrad
index 37280d0..982d82a 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Kaliningrad
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Kaliningrad
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Kiev b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Kiev
index b3e20a7..9337c9e 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Kiev
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Kiev
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Kirov b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Kirov
index 40b558f..a3b5320 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Kirov
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Kirov
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Lisbon b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Lisbon
index a856530..355817b 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Lisbon
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Lisbon
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Ljubljana b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Ljubljana
index 79c25d7..32a5722 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Ljubljana
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Ljubljana
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/London b/absl/time/internal/cctz/testdata/zoneinfo/Europe/London
index 4527515..a340326 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/London
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/London
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Luxembourg b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Luxembourg
index 6fae86c..6c194a5 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Luxembourg
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Luxembourg
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Madrid b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Madrid
index 9b51a73..ccc9d85 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Madrid
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Madrid
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Malta b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Malta
index c1208e2..bf2452d 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Malta
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Malta
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Mariehamn b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Mariehamn
index 29b3c81..b4f8f9c 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Mariehamn
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Mariehamn
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Minsk b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Minsk
index 60041a4..801aead 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Minsk
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Minsk
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Monaco b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Monaco
index 0b40f1e..686ae88 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Monaco
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Monaco
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Moscow b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Moscow
index 906bd05..ddb3f4e 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Moscow
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Moscow
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Nicosia b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Nicosia
index 3e663b2..f7f10ab 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Nicosia
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Nicosia
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Oslo b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Oslo
index 239c017..c6842af 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Oslo
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Oslo
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Paris b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Paris
index cf6e2e2..ca85435 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Paris
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Paris
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Podgorica b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Podgorica
index 79c25d7..32a5722 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Podgorica
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Podgorica
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Prague b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Prague
index ba82f31..85036de 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Prague
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Prague
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Riga b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Riga
index b729ee8..8495c50 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Riga
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Riga
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Rome b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Rome
index bdd3449..78a131b 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Rome
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Rome
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Samara b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Samara
index 0539acf..97d5dd9 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Samara
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Samara
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/San_Marino b/absl/time/internal/cctz/testdata/zoneinfo/Europe/San_Marino
index bdd3449..78a131b 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/San_Marino
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/San_Marino
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Sarajevo b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Sarajevo
index 79c25d7..32a5722 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Sarajevo
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Sarajevo
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Saratov b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Saratov
index e8cd6b1..8fd5f6d 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Saratov
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Saratov
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Simferopol b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Simferopol
index f3b42b0..e82dbbc 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Simferopol
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Simferopol
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Skopje b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Skopje
index 79c25d7..32a5722 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Skopje
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Skopje
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Sofia b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Sofia
index 763e074..dcfdd08 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Sofia
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Sofia
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Stockholm b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Stockholm
index 43c7f2e..f3e0c7f 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Stockholm
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Stockholm
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Tallinn b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Tallinn
index 18f903f..3a744cc 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Tallinn
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Tallinn
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Tirane b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Tirane
index 52c16a4..0b86017 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Tirane
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Tirane
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Tiraspol b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Tiraspol
index 2109b52..5bc1bfe 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Tiraspol
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Tiraspol
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Ulyanovsk b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Ulyanovsk
index c280f43..7b61bdc 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Ulyanovsk
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Ulyanovsk
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Uzhgorod b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Uzhgorod
index 8ddba90..677f088 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Uzhgorod
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Uzhgorod
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Vaduz b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Vaduz
index 9c2b600..ad6cf59 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Vaduz
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Vaduz
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Vatican b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Vatican
index bdd3449..78a131b 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Vatican
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Vatican
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Vienna b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Vienna
index 9c0fac5..9e2d0c9 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Vienna
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Vienna
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Vilnius b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Vilnius
index da380af..46ce484 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Vilnius
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Vilnius
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Volgograd b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Volgograd
index f4cb64f..8f170dd 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Volgograd
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Volgograd
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Warsaw b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Warsaw
index 5cbba41..d6bb156 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Warsaw
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Warsaw
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Zagreb b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Zagreb
index 79c25d7..32a5722 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Zagreb
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Zagreb
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Zaporozhye b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Zaporozhye
index 6f14850..e42edfc 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Zaporozhye
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Zaporozhye
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Zurich b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Zurich
index 9c2b600..ad6cf59 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Zurich
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Zurich
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Factory b/absl/time/internal/cctz/testdata/zoneinfo/Factory
index afeeb88..95bc3a3 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Factory
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Factory
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/GB b/absl/time/internal/cctz/testdata/zoneinfo/GB
index 4527515..a340326 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/GB
+++ b/absl/time/internal/cctz/testdata/zoneinfo/GB
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/GB-Eire b/absl/time/internal/cctz/testdata/zoneinfo/GB-Eire
index 4527515..a340326 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/GB-Eire
+++ b/absl/time/internal/cctz/testdata/zoneinfo/GB-Eire
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/GMT b/absl/time/internal/cctz/testdata/zoneinfo/GMT
index c05e45f..2ee1429 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/GMT
+++ b/absl/time/internal/cctz/testdata/zoneinfo/GMT
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/GMT+0 b/absl/time/internal/cctz/testdata/zoneinfo/GMT+0
index c05e45f..2ee1429 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/GMT+0
+++ b/absl/time/internal/cctz/testdata/zoneinfo/GMT+0
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/GMT-0 b/absl/time/internal/cctz/testdata/zoneinfo/GMT-0
index c05e45f..2ee1429 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/GMT-0
+++ b/absl/time/internal/cctz/testdata/zoneinfo/GMT-0
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/GMT0 b/absl/time/internal/cctz/testdata/zoneinfo/GMT0
index c05e45f..2ee1429 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/GMT0
+++ b/absl/time/internal/cctz/testdata/zoneinfo/GMT0
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Greenwich b/absl/time/internal/cctz/testdata/zoneinfo/Greenwich
index c05e45f..2ee1429 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Greenwich
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Greenwich
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/HST b/absl/time/internal/cctz/testdata/zoneinfo/HST
index 03e4db0..616c31b 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/HST
+++ b/absl/time/internal/cctz/testdata/zoneinfo/HST
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Hongkong b/absl/time/internal/cctz/testdata/zoneinfo/Hongkong
index dc9058e..91eaff4 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Hongkong
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Hongkong
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Iceland b/absl/time/internal/cctz/testdata/zoneinfo/Iceland
index dc49c32..ac6bd69 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Iceland
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Iceland
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Indian/Antananarivo b/absl/time/internal/cctz/testdata/zoneinfo/Indian/Antananarivo
index 39631f2..6e19601 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Indian/Antananarivo
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Indian/Antananarivo
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Indian/Chagos b/absl/time/internal/cctz/testdata/zoneinfo/Indian/Chagos
index 0e5e719..f609611 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Indian/Chagos
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Indian/Chagos
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Indian/Christmas b/absl/time/internal/cctz/testdata/zoneinfo/Indian/Christmas
index 066c1e9..6babdee 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Indian/Christmas
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Indian/Christmas
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Indian/Cocos b/absl/time/internal/cctz/testdata/zoneinfo/Indian/Cocos
index 34a2457..58f8051 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Indian/Cocos
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Indian/Cocos
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Indian/Comoro b/absl/time/internal/cctz/testdata/zoneinfo/Indian/Comoro
index 39631f2..6e19601 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Indian/Comoro
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Indian/Comoro
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Indian/Kerguelen b/absl/time/internal/cctz/testdata/zoneinfo/Indian/Kerguelen
index e7d4d3d..2cb6f3e 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Indian/Kerguelen
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Indian/Kerguelen
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Indian/Mahe b/absl/time/internal/cctz/testdata/zoneinfo/Indian/Mahe
index db8ac68..49e23e5 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Indian/Mahe
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Indian/Mahe
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Indian/Maldives b/absl/time/internal/cctz/testdata/zoneinfo/Indian/Maldives
index 3f1a76e..ffa3365 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Indian/Maldives
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Indian/Maldives
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Indian/Mauritius b/absl/time/internal/cctz/testdata/zoneinfo/Indian/Mauritius
index fd8d911..b23e2ce 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Indian/Mauritius
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Indian/Mauritius
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Indian/Mayotte b/absl/time/internal/cctz/testdata/zoneinfo/Indian/Mayotte
index 39631f2..6e19601 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Indian/Mayotte
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Indian/Mayotte
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Indian/Reunion b/absl/time/internal/cctz/testdata/zoneinfo/Indian/Reunion
index d5f9aa4..11c6002 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Indian/Reunion
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Indian/Reunion
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Iran b/absl/time/internal/cctz/testdata/zoneinfo/Iran
index 3157f80..0ae2f65 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Iran
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Iran
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Israel b/absl/time/internal/cctz/testdata/zoneinfo/Israel
index df51199..2d14c99 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Israel
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Israel
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Jamaica b/absl/time/internal/cctz/testdata/zoneinfo/Jamaica
index 7aedd26..162306f 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Jamaica
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Jamaica
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Japan b/absl/time/internal/cctz/testdata/zoneinfo/Japan
index 8ad44ba..26f4d34 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Japan
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Japan
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Kwajalein b/absl/time/internal/cctz/testdata/zoneinfo/Kwajalein
index 1a27122..d641357 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Kwajalein
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Kwajalein
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Libya b/absl/time/internal/cctz/testdata/zoneinfo/Libya
index b32e220..bd88531 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Libya
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Libya
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/MET b/absl/time/internal/cctz/testdata/zoneinfo/MET
index 71963d5..388dd74 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/MET
+++ b/absl/time/internal/cctz/testdata/zoneinfo/MET
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/MST b/absl/time/internal/cctz/testdata/zoneinfo/MST
index a1bee7c..da3e926 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/MST
+++ b/absl/time/internal/cctz/testdata/zoneinfo/MST
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/MST7MDT b/absl/time/internal/cctz/testdata/zoneinfo/MST7MDT
index 726a7e5..ddca8d1 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/MST7MDT
+++ b/absl/time/internal/cctz/testdata/zoneinfo/MST7MDT
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Mexico/BajaNorte b/absl/time/internal/cctz/testdata/zoneinfo/Mexico/BajaNorte
index 29c83e7..ada6bf7 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Mexico/BajaNorte
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Mexico/BajaNorte
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Mexico/BajaSur b/absl/time/internal/cctz/testdata/zoneinfo/Mexico/BajaSur
index afa94c2..43ee12d 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Mexico/BajaSur
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Mexico/BajaSur
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Mexico/General b/absl/time/internal/cctz/testdata/zoneinfo/Mexico/General
index f11e3d2..1434ab0 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Mexico/General
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Mexico/General
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/NZ b/absl/time/internal/cctz/testdata/zoneinfo/NZ
index a5f5b6d..60bcef6 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/NZ
+++ b/absl/time/internal/cctz/testdata/zoneinfo/NZ
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/NZ-CHAT b/absl/time/internal/cctz/testdata/zoneinfo/NZ-CHAT
index 957c80b..abe09cb 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/NZ-CHAT
+++ b/absl/time/internal/cctz/testdata/zoneinfo/NZ-CHAT
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Navajo b/absl/time/internal/cctz/testdata/zoneinfo/Navajo
index 7fc6691..5fbe26b 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Navajo
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Navajo
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/PRC b/absl/time/internal/cctz/testdata/zoneinfo/PRC
index dbd132f..ce9e00a 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/PRC
+++ b/absl/time/internal/cctz/testdata/zoneinfo/PRC
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/PST8PDT b/absl/time/internal/cctz/testdata/zoneinfo/PST8PDT
index 6242ac0..d773e28 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/PST8PDT
+++ b/absl/time/internal/cctz/testdata/zoneinfo/PST8PDT
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Apia b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Apia
index 4091a85..fd03ff7 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Apia
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Apia
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Auckland b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Auckland
index a5f5b6d..60bcef6 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Auckland
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Auckland
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Bougainville b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Bougainville
index dc5a7d7..6a6c2da 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Bougainville
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Bougainville
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Chatham b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Chatham
index 957c80b..abe09cb 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Chatham
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Chatham
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Chuuk b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Chuuk
index 289b795..8004d65 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Chuuk
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Chuuk
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Easter b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Easter
index 060bef8..cae3744 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Easter
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Easter
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Efate b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Efate
index 5cee55d..d650a05 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Efate
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Efate
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Enderbury b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Enderbury
index a3f30e5..8087350 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Enderbury
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Enderbury
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Fakaofo b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Fakaofo
index 6e4b8af..4fa169f 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Fakaofo
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Fakaofo
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Fiji b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Fiji
index 912db18..61a6695 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Fiji
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Fiji
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Funafuti b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Funafuti
index 3289094..e6a1544 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Funafuti
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Funafuti
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Galapagos b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Galapagos
index 76b2b3a..859b76d 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Galapagos
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Galapagos
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Gambier b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Gambier
index 625016d..4e9e36c 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Gambier
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Gambier
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Guadalcanal b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Guadalcanal
index 0c24095..908ccc1 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Guadalcanal
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Guadalcanal
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Guam b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Guam
index 4286e6b..e224247 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Guam
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Guam
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Honolulu b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Honolulu
index bd85577..c7cd060 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Honolulu
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Honolulu
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Johnston b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Johnston
index bd85577..c7cd060 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Johnston
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Johnston
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Kiritimati b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Kiritimati
index 762275d..cf5b3bd 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Kiritimati
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Kiritimati
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Kosrae b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Kosrae
index f8222e6..11583b1 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Kosrae
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Kosrae
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Kwajalein b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Kwajalein
index 1a27122..d641357 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Kwajalein
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Kwajalein
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Majuro b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Majuro
index b3a8c18..65990cb 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Majuro
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Majuro
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Marquesas b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Marquesas
index 10c5c9b..5fad0e1 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Marquesas
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Marquesas
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Midway b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Midway
index 3e38e97..72707b5 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Midway
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Midway
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Nauru b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Nauru
index 6092119..86d3b7d 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Nauru
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Nauru
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Niue b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Niue
index df6110d..1d58fe3 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Niue
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Niue
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Norfolk b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Norfolk
index d0b9607..f630a65 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Norfolk
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Norfolk
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Noumea b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Noumea
index d9c68f8..99f6bca 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Noumea
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Noumea
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Pago_Pago b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Pago_Pago
index 3e38e97..72707b5 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Pago_Pago
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Pago_Pago
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Palau b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Palau
index e1bbea5..05633b8 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Palau
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Palau
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Pitcairn b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Pitcairn
index 54783cf..9092e48 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Pitcairn
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Pitcairn
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Pohnpei b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Pohnpei
index 9743bc3..090429c 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Pohnpei
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Pohnpei
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Ponape b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Ponape
index 9743bc3..090429c 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Ponape
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Ponape
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Port_Moresby b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Port_Moresby
index 3fa1f7f..f6fd51c 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Port_Moresby
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Port_Moresby
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Rarotonga b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Rarotonga
index ace1ce4..9708b87 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Rarotonga
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Rarotonga
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Saipan b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Saipan
index 4286e6b..e224247 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Saipan
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Saipan
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Samoa b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Samoa
index 3e38e97..72707b5 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Samoa
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Samoa
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Tahiti b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Tahiti
index 7867d8b..37e4e88 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Tahiti
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Tahiti
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Tarawa b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Tarawa
index 3340413..e23c0cd 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Tarawa
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Tarawa
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Tongatapu b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Tongatapu
index b3a5a89..35c9e2c 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Tongatapu
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Tongatapu
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Truk b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Truk
index 289b795..8004d65 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Truk
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Truk
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Wake b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Wake
index 2dc630c..837ce1f 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Wake
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Wake
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Wallis b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Wallis
index b4f0f9b..8be9ac4 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Wallis
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Wallis
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Yap b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Yap
index 289b795..8004d65 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Yap
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Yap
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Poland b/absl/time/internal/cctz/testdata/zoneinfo/Poland
index 5cbba41..d6bb156 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Poland
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Poland
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Portugal b/absl/time/internal/cctz/testdata/zoneinfo/Portugal
index a856530..355817b 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Portugal
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Portugal
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/ROC b/absl/time/internal/cctz/testdata/zoneinfo/ROC
index 748873b..f9cbe67 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/ROC
+++ b/absl/time/internal/cctz/testdata/zoneinfo/ROC
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/ROK b/absl/time/internal/cctz/testdata/zoneinfo/ROK
index 312ec40..fa1cbd3 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/ROK
+++ b/absl/time/internal/cctz/testdata/zoneinfo/ROK
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Singapore b/absl/time/internal/cctz/testdata/zoneinfo/Singapore
index 7858366..ebc4b0d 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Singapore
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Singapore
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Turkey b/absl/time/internal/cctz/testdata/zoneinfo/Turkey
index 9a53b3a..833d4eb 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Turkey
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Turkey
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/UCT b/absl/time/internal/cctz/testdata/zoneinfo/UCT
index 40147b9..a88c4b6 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/UCT
+++ b/absl/time/internal/cctz/testdata/zoneinfo/UCT
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/US/Alaska b/absl/time/internal/cctz/testdata/zoneinfo/US/Alaska
index 6c8bdf2..9bbb2fd 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/US/Alaska
+++ b/absl/time/internal/cctz/testdata/zoneinfo/US/Alaska
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/US/Aleutian b/absl/time/internal/cctz/testdata/zoneinfo/US/Aleutian
index 5696e0f..4323649 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/US/Aleutian
+++ b/absl/time/internal/cctz/testdata/zoneinfo/US/Aleutian
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/US/Arizona b/absl/time/internal/cctz/testdata/zoneinfo/US/Arizona
index adf2823..4d51271 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/US/Arizona
+++ b/absl/time/internal/cctz/testdata/zoneinfo/US/Arizona
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/US/Central b/absl/time/internal/cctz/testdata/zoneinfo/US/Central
index 3dd8f0f..a5b1617 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/US/Central
+++ b/absl/time/internal/cctz/testdata/zoneinfo/US/Central
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/US/East-Indiana b/absl/time/internal/cctz/testdata/zoneinfo/US/East-Indiana
index 4a92c06..09511cc 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/US/East-Indiana
+++ b/absl/time/internal/cctz/testdata/zoneinfo/US/East-Indiana
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/US/Eastern b/absl/time/internal/cctz/testdata/zoneinfo/US/Eastern
index 7553fee..2f75480 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/US/Eastern
+++ b/absl/time/internal/cctz/testdata/zoneinfo/US/Eastern
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/US/Hawaii b/absl/time/internal/cctz/testdata/zoneinfo/US/Hawaii
index bd85577..c7cd060 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/US/Hawaii
+++ b/absl/time/internal/cctz/testdata/zoneinfo/US/Hawaii
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/US/Indiana-Starke b/absl/time/internal/cctz/testdata/zoneinfo/US/Indiana-Starke
index cc785da..fcd408d 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/US/Indiana-Starke
+++ b/absl/time/internal/cctz/testdata/zoneinfo/US/Indiana-Starke
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/US/Michigan b/absl/time/internal/cctz/testdata/zoneinfo/US/Michigan
index e3ea5c3..5e02260 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/US/Michigan
+++ b/absl/time/internal/cctz/testdata/zoneinfo/US/Michigan
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/US/Mountain b/absl/time/internal/cctz/testdata/zoneinfo/US/Mountain
index 7fc6691..5fbe26b 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/US/Mountain
+++ b/absl/time/internal/cctz/testdata/zoneinfo/US/Mountain
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/US/Pacific b/absl/time/internal/cctz/testdata/zoneinfo/US/Pacific
index c0ce440..9dad4f4 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/US/Pacific
+++ b/absl/time/internal/cctz/testdata/zoneinfo/US/Pacific
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/US/Samoa b/absl/time/internal/cctz/testdata/zoneinfo/US/Samoa
index 3e38e97..72707b5 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/US/Samoa
+++ b/absl/time/internal/cctz/testdata/zoneinfo/US/Samoa
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/UTC b/absl/time/internal/cctz/testdata/zoneinfo/UTC
index c3b97f1..5583f5b 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/UTC
+++ b/absl/time/internal/cctz/testdata/zoneinfo/UTC
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Universal b/absl/time/internal/cctz/testdata/zoneinfo/Universal
index c3b97f1..5583f5b 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Universal
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Universal
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/W-SU b/absl/time/internal/cctz/testdata/zoneinfo/W-SU
index 906bd05..ddb3f4e 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/W-SU
+++ b/absl/time/internal/cctz/testdata/zoneinfo/W-SU
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/WET b/absl/time/internal/cctz/testdata/zoneinfo/WET
index 444a193..9b03a17 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/WET
+++ b/absl/time/internal/cctz/testdata/zoneinfo/WET
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Zulu b/absl/time/internal/cctz/testdata/zoneinfo/Zulu
index c3b97f1..5583f5b 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Zulu
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Zulu
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/iso3166.tab b/absl/time/internal/cctz/testdata/zoneinfo/iso3166.tab
index c2e0f8e..4e4a5c3 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/iso3166.tab
+++ b/absl/time/internal/cctz/testdata/zoneinfo/iso3166.tab
@@ -10,7 +10,7 @@
 #
 # 1.  ISO 3166-1 alpha-2 country code, current as of
 #     ISO 3166-1 N905 (2016-11-15).  See: Updates on ISO 3166-1
-#     http://isotc.iso.org/livelink/livelink/Open/16944257
+#     https://isotc.iso.org/livelink/livelink/Open/16944257
 # 2.  The usual English name for the coded region,
 #     chosen so that alphabetic sorting of subsets produces helpful lists.
 #     This is not the same as the English name in the ISO 3166 tables.
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/zone1970.tab b/absl/time/internal/cctz/testdata/zoneinfo/zone1970.tab
index 2d90ed7..9a8e424 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/zone1970.tab
+++ b/absl/time/internal/cctz/testdata/zoneinfo/zone1970.tab
@@ -1,35 +1,35 @@
-# tz zone descriptions
+# tzdb timezone descriptions
 #
 # This file is in the public domain.
 #
-# From Paul Eggert (2017-10-01):
-# This file contains a table where each row stands for a zone where
-# civil time stamps have agreed since 1970.  Columns are separated by
+# From Paul Eggert (2018-06-27):
+# This file contains a table where each row stands for a timezone where
+# civil timestamps have agreed since 1970.  Columns are separated by
 # a single tab.  Lines beginning with '#' are comments.  All text uses
 # UTF-8 encoding.  The columns of the table are as follows:
 #
-# 1.  The countries that overlap the zone, as a comma-separated list
+# 1.  The countries that overlap the timezone, as a comma-separated list
 #     of ISO 3166 2-character country codes.  See the file 'iso3166.tab'.
-# 2.  Latitude and longitude of the zone's principal location
+# 2.  Latitude and longitude of the timezone's principal location
 #     in ISO 6709 sign-degrees-minutes-seconds format,
 #     either ±DDMM±DDDMM or ±DDMMSS±DDDMMSS,
 #     first latitude (+ is north), then longitude (+ is east).
-# 3.  Zone name used in value of TZ environment variable.
-#     Please see the theory.html file for how zone names are chosen.
-#     If multiple zones overlap a country, each has a row in the
+# 3.  Timezone name used in value of TZ environment variable.
+#     Please see the theory.html file for how these names are chosen.
+#     If multiple timezones overlap a country, each has a row in the
 #     table, with each column 1 containing the country code.
-# 4.  Comments; present if and only if a country has multiple zones.
+# 4.  Comments; present if and only if a country has multiple timezones.
 #
-# If a zone covers multiple countries, the most-populous city is used,
+# If a timezone covers multiple countries, the most-populous city is used,
 # and that country is listed first in column 1; any other countries
 # are listed alphabetically by country code.  The table is sorted
 # first by country code, then (if possible) by an order within the
 # country that (1) makes some geographical sense, and (2) puts the
-# most populous zones first, where that does not contradict (1).
+# most populous timezones first, where that does not contradict (1).
 #
-# This table is intended as an aid for users, to help them select time
-# zone data entries appropriate for their practical needs.  It is not
-# intended to take or endorse any position on legal or territorial claims.
+# This table is intended as an aid for users, to help them select timezones
+# appropriate for their practical needs.  It is not intended to take or
+# endorse any position on legal or territorial claims.
 #
 #country-
 #codes	coordinates	TZ	comments
@@ -211,6 +211,7 @@
 KR	+3733+12658	Asia/Seoul
 KZ	+4315+07657	Asia/Almaty	Kazakhstan (most areas)
 KZ	+4448+06528	Asia/Qyzylorda	Qyzylorda/Kyzylorda/Kzyl-Orda
+KZ	+5312+06337	Asia/Qostanay	Qostanay/Kostanay/Kustanay
 KZ	+5017+05710	Asia/Aqtobe	Aqtöbe/Aktobe
 KZ	+4431+05016	Asia/Aqtau	Mangghystaū/Mankistau
 KZ	+4707+05156	Asia/Atyrau	Atyraū/Atirau/Gur'yev
@@ -231,7 +232,7 @@
 MN	+4755+10653	Asia/Ulaanbaatar	Mongolia (most areas)
 MN	+4801+09139	Asia/Hovd	Bayan-Ölgii, Govi-Altai, Hovd, Uvs, Zavkhan
 MN	+4804+11430	Asia/Choibalsan	Dornod, Sükhbaatar
-MO	+2214+11335	Asia/Macau
+MO	+221150+1133230	Asia/Macau
 MQ	+1436-06105	America/Martinique
 MT	+3554+01431	Europe/Malta
 MU	-2010+05730	Indian/Mauritius
@@ -289,9 +290,9 @@
 RU	+5443+02030	Europe/Kaliningrad	MSK-01 - Kaliningrad
 RU	+554521+0373704	Europe/Moscow	MSK+00 - Moscow area
 RU	+4457+03406	Europe/Simferopol	MSK+00 - Crimea
-RU	+4844+04425	Europe/Volgograd	MSK+00 - Volgograd
 RU	+5836+04939	Europe/Kirov	MSK+00 - Kirov
 RU	+4621+04803	Europe/Astrakhan	MSK+01 - Astrakhan
+RU	+4844+04425	Europe/Volgograd	MSK+01 - Volgograd
 RU	+5134+04602	Europe/Saratov	MSK+01 - Saratov
 RU	+5420+04824	Europe/Ulyanovsk	MSK+01 - Ulyanovsk
 RU	+5312+05009	Europe/Samara	MSK+01 - Samara, Udmurtia
diff --git a/absl/time/internal/get_current_time_chrono.inc b/absl/time/internal/get_current_time_chrono.inc
index cf884a1..5180230 100644
--- a/absl/time/internal/get_current_time_chrono.inc
+++ b/absl/time/internal/get_current_time_chrono.inc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
diff --git a/absl/time/internal/test_util.cc b/absl/time/internal/test_util.cc
index bbbef7d..59166a7 100644
--- a/absl/time/internal/test_util.cc
+++ b/absl/time/internal/test_util.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -26,12 +26,6 @@
 namespace absl {
 namespace time_internal {
 
-#if GTEST_USES_SIMPLE_RE
-extern const char kZoneAbbrRE[] = ".*";  // just punt
-#else
-extern const char kZoneAbbrRE[] = "[A-Za-z]{3,4}|[-+][0-9]{2}([0-9]{2})?";
-#endif
-
 TimeZone LoadTimeZone(const std::string& name) {
   TimeZone tz;
   ABSL_RAW_CHECK(LoadTimeZone(name, &tz), name.c_str());
diff --git a/absl/time/internal/test_util.h b/absl/time/internal/test_util.h
index 8fd5fb9..d7319ea 100644
--- a/absl/time/internal/test_util.h
+++ b/absl/time/internal/test_util.h
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -17,35 +17,11 @@
 
 #include <string>
 
-#include "gmock/gmock.h"
-#include "gtest/gtest.h"
 #include "absl/time/time.h"
 
-// This helper is a macro so that failed expectations show up with the
-// correct line numbers.
-//
-// This is for internal testing of the Base Time library itself. This is not
-// part of a public API.
-#define ABSL_INTERNAL_EXPECT_TIME(bd, y, m, d, h, min, s, off, isdst)     \
-  do {                                                                    \
-    EXPECT_EQ(y, bd.year);                                                \
-    EXPECT_EQ(m, bd.month);                                               \
-    EXPECT_EQ(d, bd.day);                                                 \
-    EXPECT_EQ(h, bd.hour);                                                \
-    EXPECT_EQ(min, bd.minute);                                            \
-    EXPECT_EQ(s, bd.second);                                              \
-    EXPECT_EQ(off, bd.offset);                                            \
-    EXPECT_EQ(isdst, bd.is_dst);                                          \
-    EXPECT_THAT(bd.zone_abbr,                                             \
-                testing::MatchesRegex(absl::time_internal::kZoneAbbrRE)); \
-  } while (0)
-
 namespace absl {
 namespace time_internal {
 
-// A regular expression that matches all zone abbreviations (%Z).
-extern const char kZoneAbbrRE[];
-
 // Loads the named timezone, but dies on any failure.
 absl::TimeZone LoadTimeZone(const std::string& name);
 
diff --git a/absl/time/time.cc b/absl/time/time.cc
index 71fd8ee..977a951 100644
--- a/absl/time/time.cc
+++ b/absl/time/time.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -22,13 +22,14 @@
 // NOTE: To keep type verbosity to a minimum, the following variable naming
 // conventions are used throughout this file.
 //
-// cz: A cctz::time_zone
 // tz: An absl::TimeZone
+// ci: An absl::TimeZone::CivilInfo
+// ti: An absl::TimeZone::TimeInfo
+// cd: An absl::CivilDay or a cctz::civil_day
+// cs: An absl::CivilSecond or a cctz::civil_second
+// bd: An absl::Time::Breakdown
 // cl: A cctz::time_zone::civil_lookup
 // al: A cctz::time_zone::absolute_lookup
-// cd: A cctz::civil_day
-// cs: A cctz::civil_second
-// bd: An absl::Time::Breakdown
 
 #include "absl/time/time.h"
 
@@ -40,6 +41,7 @@
 #include "absl/time/internal/cctz/include/cctz/time_zone.h"
 
 namespace cctz = absl::time_internal::cctz;
+
 namespace absl {
 
 namespace {
@@ -75,7 +77,7 @@
   return bd;
 }
 
-inline Time::Breakdown InfinitePastBreakdown() {
+inline absl::Time::Breakdown InfinitePastBreakdown() {
   Time::Breakdown bd;
   bd.year = std::numeric_limits<int64_t>::min();
   bd.month = 1;
@@ -92,6 +94,26 @@
   return bd;
 }
 
+inline absl::TimeZone::CivilInfo InfiniteFutureCivilInfo() {
+  TimeZone::CivilInfo ci;
+  ci.cs = CivilSecond::max();
+  ci.subsecond = InfiniteDuration();
+  ci.offset = 0;
+  ci.is_dst = false;
+  ci.zone_abbr = "-00";
+  return ci;
+}
+
+inline absl::TimeZone::CivilInfo InfinitePastCivilInfo() {
+  TimeZone::CivilInfo ci;
+  ci.cs = CivilSecond::min();
+  ci.subsecond = -InfiniteDuration();
+  ci.offset = 0;
+  ci.is_dst = false;
+  ci.zone_abbr = "-00";
+  return ci;
+}
+
 inline absl::TimeConversion InfiniteFutureTimeConversion() {
   absl::TimeConversion tc;
   tc.pre = tc.trans = tc.post = absl::InfiniteFuture();
@@ -134,19 +156,6 @@
   return time_internal::FromUnixDuration(time_internal::MakeDuration(hi));
 }
 
-inline absl::TimeConversion::Kind MapKind(
-    const cctz::time_zone::civil_lookup::civil_kind& kind) {
-  switch (kind) {
-    case cctz::time_zone::civil_lookup::UNIQUE:
-      return absl::TimeConversion::UNIQUE;
-    case cctz::time_zone::civil_lookup::SKIPPED:
-      return absl::TimeConversion::SKIPPED;
-    case cctz::time_zone::civil_lookup::REPEATED:
-      return absl::TimeConversion::REPEATED;
-  }
-  return absl::TimeConversion::UNIQUE;
-}
-
 // Returns Mon=1..Sun=7.
 inline int MapWeekday(const cctz::weekday& wd) {
   switch (wd) {
@@ -168,11 +177,29 @@
   return 1;
 }
 
+bool FindTransition(const cctz::time_zone& tz,
+                    bool (cctz::time_zone::*find_transition)(
+                        const cctz::time_point<cctz::seconds>& tp,
+                        cctz::time_zone::civil_transition* trans) const,
+                    Time t, TimeZone::CivilTransition* trans) {
+  // Transitions are second-aligned, so we can discard any fractional part.
+  const auto tp = unix_epoch() + cctz::seconds(ToUnixSeconds(t));
+  cctz::time_zone::civil_transition tr;
+  if (!(tz.*find_transition)(tp, &tr)) return false;
+  trans->from = CivilSecond(tr.from);
+  trans->to = CivilSecond(tr.to);
+  return true;
+}
+
 }  // namespace
 
+//
+// Time
+//
+
 absl::Time::Breakdown Time::In(absl::TimeZone tz) const {
-  if (*this == absl::InfiniteFuture()) return absl::InfiniteFutureBreakdown();
-  if (*this == absl::InfinitePast()) return absl::InfinitePastBreakdown();
+  if (*this == absl::InfiniteFuture()) return InfiniteFutureBreakdown();
+  if (*this == absl::InfinitePast()) return InfinitePastBreakdown();
 
   const auto tp = unix_epoch() + cctz::seconds(time_internal::GetRepHi(rep_));
   const auto al = cctz::time_zone(tz).lookup(tp);
@@ -187,92 +214,18 @@
   bd.minute = cs.minute();
   bd.second = cs.second();
   bd.subsecond = time_internal::MakeDuration(0, time_internal::GetRepLo(rep_));
-  bd.weekday = MapWeekday(get_weekday(cd));
-  bd.yearday = get_yearday(cd);
+  bd.weekday = MapWeekday(cctz::get_weekday(cd));
+  bd.yearday = cctz::get_yearday(cd);
   bd.offset = al.offset;
   bd.is_dst = al.is_dst;
   bd.zone_abbr = al.abbr;
   return bd;
 }
 
-absl::Time FromTM(const struct tm& tm, absl::TimeZone tz) {
-  const auto cz = cctz::time_zone(tz);
-  const auto cs =
-      cctz::civil_second(tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
-                         tm.tm_hour, tm.tm_min, tm.tm_sec);
-  const auto cl = cz.lookup(cs);
-  const auto tp = tm.tm_isdst == 0 ? cl.post : cl.pre;
-  return MakeTimeWithOverflow(tp, cs, cz);
-}
-
-struct tm ToTM(absl::Time t, absl::TimeZone tz) {
-  const absl::Time::Breakdown bd = t.In(tz);
-  struct tm tm;
-  std::memset(&tm, 0, sizeof(tm));
-  tm.tm_sec = bd.second;
-  tm.tm_min = bd.minute;
-  tm.tm_hour = bd.hour;
-  tm.tm_mday = bd.day;
-  tm.tm_mon = bd.month - 1;
-
-  // Saturates tm.tm_year in cases of over/underflow, accounting for the fact
-  // that tm.tm_year is years since 1900.
-  if (bd.year < std::numeric_limits<int>::min() + 1900) {
-    tm.tm_year = std::numeric_limits<int>::min();
-  } else if (bd.year > std::numeric_limits<int>::max()) {
-    tm.tm_year = std::numeric_limits<int>::max() - 1900;
-  } else {
-    tm.tm_year = static_cast<int>(bd.year - 1900);
-  }
-
-  tm.tm_wday = bd.weekday % 7;
-  tm.tm_yday = bd.yearday - 1;
-  tm.tm_isdst = bd.is_dst ? 1 : 0;
-
-  return tm;
-}
-
 //
-// Factory functions.
+// Conversions from/to other time types.
 //
 
-absl::TimeConversion ConvertDateTime(int64_t year, int mon, int day, int hour,
-                                     int min, int sec, TimeZone tz) {
-  // Avoids years that are too extreme for civil_second to normalize.
-  if (year > 300000000000) return InfiniteFutureTimeConversion();
-  if (year < -300000000000) return InfinitePastTimeConversion();
-  const auto cz = cctz::time_zone(tz);
-  const auto cs = cctz::civil_second(year, mon, day, hour, min, sec);
-  absl::TimeConversion tc;
-  tc.normalized = year != cs.year() || mon != cs.month() || day != cs.day() ||
-                  hour != cs.hour() || min != cs.minute() || sec != cs.second();
-  const auto cl = cz.lookup(cs);
-  // Converts the civil_lookup struct to a TimeConversion.
-  tc.pre = MakeTimeWithOverflow(cl.pre, cs, cz, &tc.normalized);
-  tc.trans = MakeTimeWithOverflow(cl.trans, cs, cz, &tc.normalized);
-  tc.post = MakeTimeWithOverflow(cl.post, cs, cz, &tc.normalized);
-  tc.kind = MapKind(cl.kind);
-  return tc;
-}
-
-absl::Time FromDateTime(int64_t year, int mon, int day, int hour, int min,
-                        int sec, TimeZone tz) {
-  if (year > 300000000000) return InfiniteFuture();
-  if (year < -300000000000) return InfinitePast();
-  const auto cz = cctz::time_zone(tz);
-  const auto cs = cctz::civil_second(year, mon, day, hour, min, sec);
-  const auto cl = cz.lookup(cs);
-  return MakeTimeWithOverflow(cl.pre, cs, cz);
-}
-
-absl::Time TimeFromTimespec(timespec ts) {
-  return time_internal::FromUnixDuration(absl::DurationFromTimespec(ts));
-}
-
-absl::Time TimeFromTimeval(timeval tv) {
-  return time_internal::FromUnixDuration(absl::DurationFromTimeval(tv));
-}
-
 absl::Time FromUDate(double udate) {
   return time_internal::FromUnixDuration(absl::Milliseconds(udate));
 }
@@ -281,10 +234,6 @@
   return absl::UniversalEpoch() + 100 * absl::Nanoseconds(universal);
 }
 
-//
-// Conversion to other time types.
-//
-
 int64_t ToUnixNanos(Time t) {
   if (time_internal::GetRepHi(time_internal::ToUnixDuration(t)) >= 0 &&
       time_internal::GetRepHi(time_internal::ToUnixDuration(t)) >> 33 == 0) {
@@ -321,6 +270,23 @@
 
 time_t ToTimeT(Time t) { return absl::ToTimespec(t).tv_sec; }
 
+double ToUDate(Time t) {
+  return absl::FDivDuration(time_internal::ToUnixDuration(t),
+                            absl::Milliseconds(1));
+}
+
+int64_t ToUniversal(absl::Time t) {
+  return absl::FloorToUnit(t - absl::UniversalEpoch(), absl::Nanoseconds(100));
+}
+
+absl::Time TimeFromTimespec(timespec ts) {
+  return time_internal::FromUnixDuration(absl::DurationFromTimespec(ts));
+}
+
+absl::Time TimeFromTimeval(timeval tv) {
+  return time_internal::FromUnixDuration(absl::DurationFromTimeval(tv));
+}
+
 timespec ToTimespec(Time t) {
   timespec ts;
   absl::Duration d = time_internal::ToUnixDuration(t);
@@ -359,15 +325,6 @@
   return tv;
 }
 
-double ToUDate(Time t) {
-  return absl::FDivDuration(time_internal::ToUnixDuration(t),
-                            absl::Milliseconds(1));
-}
-
-int64_t ToUniversal(absl::Time t) {
-  return absl::FloorToUnit(t - absl::UniversalEpoch(), absl::Nanoseconds(100));
-}
-
 Time FromChrono(const std::chrono::system_clock::time_point& tp) {
   return time_internal::FromUnixDuration(time_internal::FromChrono(
       tp - std::chrono::system_clock::from_time_t(0)));
@@ -381,4 +338,149 @@
          time_internal::ToChronoDuration<D>(d);
 }
 
+//
+// TimeZone
+//
+
+absl::TimeZone::CivilInfo TimeZone::At(Time t) const {
+  if (t == absl::InfiniteFuture()) return InfiniteFutureCivilInfo();
+  if (t == absl::InfinitePast()) return InfinitePastCivilInfo();
+
+  const auto ud = time_internal::ToUnixDuration(t);
+  const auto tp = unix_epoch() + cctz::seconds(time_internal::GetRepHi(ud));
+  const auto al = cz_.lookup(tp);
+
+  TimeZone::CivilInfo ci;
+  ci.cs = CivilSecond(al.cs);
+  ci.subsecond = time_internal::MakeDuration(0, time_internal::GetRepLo(ud));
+  ci.offset = al.offset;
+  ci.is_dst = al.is_dst;
+  ci.zone_abbr = al.abbr;
+  return ci;
+}
+
+absl::TimeZone::TimeInfo TimeZone::At(CivilSecond ct) const {
+  const cctz::civil_second cs(ct);
+  const auto cl = cz_.lookup(cs);
+
+  TimeZone::TimeInfo ti;
+  switch (cl.kind) {
+    case cctz::time_zone::civil_lookup::UNIQUE:
+      ti.kind = TimeZone::TimeInfo::UNIQUE;
+      break;
+    case cctz::time_zone::civil_lookup::SKIPPED:
+      ti.kind = TimeZone::TimeInfo::SKIPPED;
+      break;
+    case cctz::time_zone::civil_lookup::REPEATED:
+      ti.kind = TimeZone::TimeInfo::REPEATED;
+      break;
+  }
+  ti.pre = MakeTimeWithOverflow(cl.pre, cs, cz_);
+  ti.trans = MakeTimeWithOverflow(cl.trans, cs, cz_);
+  ti.post = MakeTimeWithOverflow(cl.post, cs, cz_);
+  return ti;
+}
+
+bool TimeZone::NextTransition(Time t, CivilTransition* trans) const {
+  return FindTransition(cz_, &cctz::time_zone::next_transition, t, trans);
+}
+
+bool TimeZone::PrevTransition(Time t, CivilTransition* trans) const {
+  return FindTransition(cz_, &cctz::time_zone::prev_transition, t, trans);
+}
+
+//
+// Conversions involving time zones.
+//
+
+absl::TimeConversion ConvertDateTime(int64_t year, int mon, int day, int hour,
+                                     int min, int sec, TimeZone tz) {
+  // Avoids years that are too extreme for CivilSecond to normalize.
+  if (year > 300000000000) return InfiniteFutureTimeConversion();
+  if (year < -300000000000) return InfinitePastTimeConversion();
+
+  const CivilSecond cs(year, mon, day, hour, min, sec);
+  const auto ti = tz.At(cs);
+
+  TimeConversion tc;
+  tc.pre = ti.pre;
+  tc.trans = ti.trans;
+  tc.post = ti.post;
+  switch (ti.kind) {
+    case TimeZone::TimeInfo::UNIQUE:
+      tc.kind = TimeConversion::UNIQUE;
+      break;
+    case TimeZone::TimeInfo::SKIPPED:
+      tc.kind = TimeConversion::SKIPPED;
+      break;
+    case TimeZone::TimeInfo::REPEATED:
+      tc.kind = TimeConversion::REPEATED;
+      break;
+  }
+  tc.normalized = false;
+  if (year != cs.year() || mon != cs.month() || day != cs.day() ||
+      hour != cs.hour() || min != cs.minute() || sec != cs.second()) {
+    tc.normalized = true;
+  }
+  return tc;
+}
+
+absl::Time FromTM(const struct tm& tm, absl::TimeZone tz) {
+  const CivilSecond cs(tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
+                       tm.tm_hour, tm.tm_min, tm.tm_sec);
+  const auto ti = tz.At(cs);
+  return tm.tm_isdst == 0 ? ti.post : ti.pre;
+}
+
+struct tm ToTM(absl::Time t, absl::TimeZone tz) {
+  struct tm tm = {};
+
+  const auto ci = tz.At(t);
+  const auto& cs = ci.cs;
+  tm.tm_sec = cs.second();
+  tm.tm_min = cs.minute();
+  tm.tm_hour = cs.hour();
+  tm.tm_mday = cs.day();
+  tm.tm_mon = cs.month() - 1;
+
+  // Saturates tm.tm_year in cases of over/underflow, accounting for the fact
+  // that tm.tm_year is years since 1900.
+  if (cs.year() < std::numeric_limits<int>::min() + 1900) {
+    tm.tm_year = std::numeric_limits<int>::min();
+  } else if (cs.year() > std::numeric_limits<int>::max()) {
+    tm.tm_year = std::numeric_limits<int>::max() - 1900;
+  } else {
+    tm.tm_year = static_cast<int>(cs.year() - 1900);
+  }
+
+  const CivilDay cd(cs);
+  switch (GetWeekday(cd)) {
+    case Weekday::sunday:
+      tm.tm_wday = 0;
+      break;
+    case Weekday::monday:
+      tm.tm_wday = 1;
+      break;
+    case Weekday::tuesday:
+      tm.tm_wday = 2;
+      break;
+    case Weekday::wednesday:
+      tm.tm_wday = 3;
+      break;
+    case Weekday::thursday:
+      tm.tm_wday = 4;
+      break;
+    case Weekday::friday:
+      tm.tm_wday = 5;
+      break;
+    case Weekday::saturday:
+      tm.tm_wday = 6;
+      break;
+  }
+  tm.tm_yday = GetYearDay(cd) - 1;
+  tm.tm_isdst = ci.is_dst ? 1 : 0;
+
+  return tm;
+}
+
 }  // namespace absl
diff --git a/absl/time/time.h b/absl/time/time.h
index 50bf971..594396c 100644
--- a/absl/time/time.h
+++ b/absl/time/time.h
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -25,18 +25,29 @@
 //  * `absl::TimeZone` defines geopolitical time zone regions (as collected
 //     within the IANA Time Zone database (https://www.iana.org/time-zones)).
 //
+// Note: Absolute times are distinct from civil times, which refer to the
+// human-scale time commonly represented by `YYYY-MM-DD hh:mm:ss`. The mapping
+// between absolute and civil times can be specified by use of time zones
+// (`absl::TimeZone` within this API). That is:
+//
+//   Civil Time = F(Absolute Time, Time Zone)
+//   Absolute Time = G(Civil Time, Time Zone)
+//
+// See civil_time.h for abstractions related to constructing and manipulating
+// civil time.
 //
 // Example:
 //
 //   absl::TimeZone nyc;
-//
 //   // LoadTimeZone() may fail so it's always better to check for success.
 //   if (!absl::LoadTimeZone("America/New_York", &nyc)) {
 //      // handle error case
 //   }
 //
 //   // My flight leaves NYC on Jan 2, 2017 at 03:04:05
-//   absl::Time takeoff = absl::FromDateTime(2017, 1, 2, 3, 4, 5, nyc);
+//   absl::CivilSecond cs(2017, 1, 2, 3, 4, 5);
+//   absl::Time takeoff = absl::FromCivil(cs, nyc);
+//
 //   absl::Duration flight_duration = absl::Hours(21) + absl::Minutes(35);
 //   absl::Time landing = takeoff + flight_duration;
 //
@@ -47,7 +58,7 @@
 //   std::string s = absl::FormatTime(
 //       "My flight will land in Sydney on %Y-%m-%d at %H:%M:%S",
 //       landing, syd);
-//
+
 #ifndef ABSL_TIME_TIME_H_
 #define ABSL_TIME_TIME_H_
 
@@ -57,6 +68,7 @@
 #include <winsock2.h>
 #endif
 #include <chrono>  // NOLINT(build/c++11)
+#include <cmath>
 #include <cstdint>
 #include <ctime>
 #include <ostream>
@@ -64,8 +76,8 @@
 #include <type_traits>
 #include <utility>
 
-#include "absl/base/port.h"  // Needed for string vs std::string
 #include "absl/strings/string_view.h"
+#include "absl/time/civil_time.h"
 #include "absl/time/internal/cctz/include/cctz/time_zone.h"
 
 namespace absl {
@@ -140,6 +152,16 @@
   // Value semantics.
   constexpr Duration() : rep_hi_(0), rep_lo_(0) {}  // zero-length duration
 
+  // Copyable.
+#if !defined(__clang__) && defined(_MSC_VER) && _MSC_VER < 1910
+  // Explicitly defining the constexpr copy constructor avoids an MSVC bug.
+  constexpr Duration(const Duration& d)
+      : rep_hi_(d.rep_hi_), rep_lo_(d.rep_lo_) {}
+#else
+  constexpr Duration(const Duration& d) = default;
+#endif
+  Duration& operator=(const Duration& d) = default;
+
   // Compound assignment operators.
   Duration& operator+=(Duration d);
   Duration& operator-=(Duration d);
@@ -348,11 +370,11 @@
 // Factory functions for constructing `Duration` values from an integral number
 // of the unit indicated by the factory function's name.
 //
-// Note: no "Days()" factory function exists because "a day" is ambiguous. Civil
-// days are not always 24 hours long, and a 24-hour duration often does not
-// correspond with a civil day. If a 24-hour duration is needed, use
-// `absl::Hours(24)`.
-//
+// Note: no "Days()" factory function exists because "a day" is ambiguous.
+// Civil days are not always 24 hours long, and a 24-hour duration often does
+// not correspond with a civil day. If a 24-hour duration is needed, use
+// `absl::Hours(24)`. (If you actually want a civil day, use absl::CivilDay
+// from civil_time.h.)
 //
 // Example:
 //
@@ -371,6 +393,7 @@
 // factories, which should be preferred.
 //
 // Example:
+//
 //   auto a = absl::Seconds(1.5);        // OK
 //   auto b = absl::Milliseconds(1500);  // BETTER
 template <typename T, time_internal::EnableIfFloat<T> = 0>
@@ -387,11 +410,13 @@
 }
 template <typename T, time_internal::EnableIfFloat<T> = 0>
 Duration Seconds(T n) {
-  if (n >= 0) {
-    if (n >= std::numeric_limits<int64_t>::max()) return InfiniteDuration();
+  if (n >= 0) {  // Note: `NaN >= 0` is false.
+    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();
+    if (std::isnan(n))
+      return std::signbit(n) ? -InfiniteDuration() : InfiniteDuration();
+    if (n <= (std::numeric_limits<int64_t>::min)()) return -InfiniteDuration();
     return -time_internal::MakePosDoubleDuration(-n);
   }
 }
@@ -543,10 +568,9 @@
 // The `absl::Time` class represents an instant in time as a count of clock
 // ticks of some granularity (resolution) from some starting point (epoch).
 //
-//
 // `absl::Time` uses a resolution that is high enough to avoid loss in
 // precision, and a range that is wide enough to avoid overflow, when
-// converting between tick counts in most Google time scales (i.e., precision
+// converting between tick counts in most Google time scales (i.e., resolution
 // of at least one nanosecond, and range +/-100 billion years).  Conversions
 // between the time scales are performed by truncating (towards negative
 // infinity) to the nearest representable point.
@@ -556,7 +580,6 @@
 //   absl::Time t1 = ...;
 //   absl::Time t2 = t1 + absl::Minutes(2);
 //   absl::Duration d = t2 - t1;  // == absl::Minutes(2)
-//   absl::Time::Breakdown bd = t1.In(absl::LocalTimeZone());
 //
 class Time {
  public:
@@ -571,7 +594,11 @@
   //   absl::Time t = absl::Now();
   //   absl::Time t = absl::TimeFromTimeval(tv);
   //   absl::Time t = absl::InfinitePast();
-  constexpr Time() {}
+  constexpr Time() = default;
+
+  // Copyable.
+  constexpr Time(const Time& t) = default;
+  Time& operator=(const Time& t) = default;
 
   // Assignment operators.
   Time& operator+=(Duration d) {
@@ -590,7 +617,10 @@
   // intended to represent an instant in time. So, rather than passing
   // a `Time::Breakdown` to a function, pass an `absl::Time` and an
   // `absl::TimeZone`.
-  struct Breakdown {
+  //
+  // Deprecated. Use `absl::TimeZone::CivilInfo`.
+  struct
+      Breakdown {
     int64_t year;          // year (e.g., 2013)
     int month;           // month of year [1:12]
     int day;             // day of month [1:31]
@@ -614,6 +644,8 @@
   // Time::In()
   //
   // Returns the breakdown of this instant in the given TimeZone.
+  //
+  // Deprecated. Use `absl::TimeZone::At(Time)`.
   Breakdown In(TimeZone tz) const;
 
   template <typename H>
@@ -668,7 +700,7 @@
 // Returns an `absl::Time` that is infinitely far in the future.
 constexpr Time InfiniteFuture() {
   return Time(
-      time_internal::MakeDuration(std::numeric_limits<int64_t>::max(), ~0U));
+      time_internal::MakeDuration((std::numeric_limits<int64_t>::max)(), ~0U));
 }
 
 // InfinitePast()
@@ -676,129 +708,9 @@
 // Returns an `absl::Time` that is infinitely far in the past.
 constexpr Time InfinitePast() {
   return Time(
-      time_internal::MakeDuration(std::numeric_limits<int64_t>::min(), ~0U));
+      time_internal::MakeDuration((std::numeric_limits<int64_t>::min)(), ~0U));
 }
 
-// TimeConversion
-//
-// An `absl::TimeConversion` represents the conversion of year, month, day,
-// hour, minute, and second values (i.e., a civil time), in a particular
-// `absl::TimeZone`, to a time instant (an absolute time), as returned by
-// `absl::ConvertDateTime()`. (Subseconds must be handled separately.)
-//
-// It is possible, though, for a caller to try to convert values that
-// do not represent an actual or unique instant in time (due to a shift
-// in UTC offset in the `absl::TimeZone`, which results in a discontinuity in
-// the civil-time components). For example, a daylight-saving-time
-// transition skips or repeats civil times---in the United States, March
-// 13, 2011 02:15 never occurred, while November 6, 2011 01:15 occurred
-// twice---so requests for such times are not well-defined.
-//
-// To account for these possibilities, `absl::TimeConversion` is richer
-// than just a single `absl::Time`. When the civil time is skipped or
-// repeated, `absl::ConvertDateTime()` returns times calculated using the
-// pre-transition and post-transition UTC offsets, plus the transition
-// time itself.
-//
-// Examples:
-//
-//   absl::TimeZone lax;
-//   if (!absl::LoadTimeZone("America/Los_Angeles", &lax)) {
-//     // handle error case
-//   }
-//
-//   // A unique civil time
-//   absl::TimeConversion jan01 =
-//       absl::ConvertDateTime(2011, 1, 1, 0, 0, 0, lax);
-//   // jan01.kind == TimeConversion::UNIQUE
-//   // jan01.pre    is 2011/01/01 00:00:00 -0800
-//   // jan01.trans  is 2011/01/01 00:00:00 -0800
-//   // jan01.post   is 2011/01/01 00:00:00 -0800
-//
-//   // A Spring DST transition, when there is a gap in civil time
-//   absl::TimeConversion mar13 =
-//       absl::ConvertDateTime(2011, 3, 13, 2, 15, 0, lax);
-//   // mar13.kind == TimeConversion::SKIPPED
-//   // mar13.pre   is 2011/03/13 03:15:00 -0700
-//   // mar13.trans is 2011/03/13 03:00:00 -0700
-//   // mar13.post  is 2011/03/13 01:15:00 -0800
-//
-//   // A Fall DST transition, when civil times are repeated
-//   absl::TimeConversion nov06 =
-//       absl::ConvertDateTime(2011, 11, 6, 1, 15, 0, lax);
-//   // nov06.kind == TimeConversion::REPEATED
-//   // nov06.pre   is 2011/11/06 01:15:00 -0700
-//   // nov06.trans is 2011/11/06 01:00:00 -0800
-//   // nov06.post  is 2011/11/06 01:15:00 -0800
-//
-// The input month, day, hour, minute, and second values can also be
-// outside of their valid ranges, in which case they will be "normalized"
-// during the conversion.
-//
-// Example:
-//
-//   // "October 32" normalizes to "November 1".
-//   absl::TimeZone tz = absl::LocalTimeZone();
-//   absl::TimeConversion tc =
-//       absl::ConvertDateTime(2013, 10, 32, 8, 30, 0, tz);
-//   // tc.kind == TimeConversion::UNIQUE && tc.normalized == true
-//   // tc.pre.In(tz).month == 11 && tc.pre.In(tz).day == 1
-struct TimeConversion {
-  Time pre;    // time calculated using the pre-transition offset
-  Time trans;  // when the civil-time discontinuity occurred
-  Time post;   // time calculated using the post-transition offset
-
-  enum Kind {
-    UNIQUE,    // the civil time was singular (pre == trans == post)
-    SKIPPED,   // the civil time did not exist
-    REPEATED,  // the civil time was ambiguous
-  };
-  Kind kind;
-
-  bool normalized;  // input values were outside their valid ranges
-};
-
-// ConvertDateTime()
-//
-// The full generality of a civil time to absl::Time conversion.
-TimeConversion ConvertDateTime(int64_t year, int mon, int day, int hour,
-                               int min, int sec, TimeZone tz);
-
-// FromDateTime()
-//
-// A convenience wrapper for `absl::ConvertDateTime()` that simply returns the
-// "pre" `absl::Time`.  That is, the unique result, or the instant that
-// is correct using the pre-transition offset (as if the transition
-// never happened). This is typically the answer that humans expected when
-// faced with non-unique times, such as near daylight-saving time transitions.
-//
-// Example:
-//
-//   absl::TimeZone seattle;
-//   if (!absl::LoadTimeZone("America/Los_Angeles", &seattle)) {
-//     // handle error case
-//   }
-//   absl::Time t =  absl::FromDateTime(2017, 9, 26, 9, 30, 0, seattle);
-Time FromDateTime(int64_t year, int mon, int day, int hour, int min, int sec,
-                  TimeZone tz);
-
-// FromTM()
-//
-// Converts the `tm_year`, `tm_mon`, `tm_mday`, `tm_hour`, `tm_min`, and
-// `tm_sec` fields to an `absl::Time` using the given time zone. See ctime(3)
-// for a description of the expected values of the tm fields. IFF the indicated
-// time instant is not unique (see `absl::ConvertDateTime()` above), the
-// `tm_isdst` field is consulted to select the desired instant (`tm_isdst` > 0
-// means DST, `tm_isdst` == 0 means no DST, `tm_isdst` < 0 means use the default
-// like `absl::FromDateTime()`).
-Time FromTM(const struct tm& tm, TimeZone tz);
-
-// ToTM()
-//
-// Converts the given `absl::Time` to a struct tm using the given time zone.
-// See ctime(3) for a description of the values of the tm fields.
-struct tm ToTM(Time t, TimeZone tz);
-
 // FromUnixNanos()
 // FromUnixMicros()
 // FromUnixMillis()
@@ -883,140 +795,6 @@
 //   // tp == std::chrono::system_clock::from_time_t(123);
 std::chrono::system_clock::time_point ToChronoTime(Time);
 
-// RFC3339_full
-// RFC3339_sec
-//
-// FormatTime()/ParseTime() format specifiers for RFC3339 date/time strings,
-// with trailing zeros trimmed or with fractional seconds omitted altogether.
-//
-// Note that RFC3339_sec[] matches an ISO 8601 extended format for date and
-// time with UTC offset.  Also note the use of "%Y": RFC3339 mandates that
-// years have exactly four digits, but we allow them to take their natural
-// width.
-extern const char RFC3339_full[];  // %Y-%m-%dT%H:%M:%E*S%Ez
-extern const char RFC3339_sec[];   // %Y-%m-%dT%H:%M:%S%Ez
-
-// RFC1123_full
-// RFC1123_no_wday
-//
-// FormatTime()/ParseTime() format specifiers for RFC1123 date/time strings.
-extern const char RFC1123_full[];     // %a, %d %b %E4Y %H:%M:%S %z
-extern const char RFC1123_no_wday[];  // %d %b %E4Y %H:%M:%S %z
-
-// FormatTime()
-//
-// Formats the given `absl::Time` in the `absl::TimeZone` according to the
-// provided format string. Uses strftime()-like formatting options, with
-// the following extensions:
-//
-//   - %Ez  - RFC3339-compatible numeric UTC offset (+hh:mm or -hh:mm)
-//   - %E*z - Full-resolution numeric UTC offset (+hh:mm:ss or -hh:mm:ss)
-//   - %E#S - Seconds with # digits of fractional precision
-//   - %E*S - Seconds with full fractional precision (a literal '*')
-//   - %E#f - Fractional seconds with # digits of precision
-//   - %E*f - Fractional seconds with full precision (a literal '*')
-//   - %E4Y - Four-character years (-999 ... -001, 0000, 0001 ... 9999)
-//
-// Note that %E0S behaves like %S, and %E0f produces no characters.  In
-// contrast %E*f always produces at least one digit, which may be '0'.
-//
-// Note that %Y produces as many characters as it takes to fully render the
-// year.  A year outside of [-999:9999] when formatted with %E4Y will produce
-// more than four characters, just like %Y.
-//
-// We recommend that format strings include the UTC offset (%z, %Ez, or %E*z)
-// so that the result uniquely identifies a time instant.
-//
-// Example:
-//
-//   absl::TimeZone lax;
-//   if (!absl::LoadTimeZone("America/Los_Angeles", &lax)) {
-//     // handle error case
-//   }
-//   absl::Time t = absl::FromDateTime(2013, 1, 2, 3, 4, 5, lax);
-//
-//   string f = absl::FormatTime("%H:%M:%S", t, lax);  // "03:04:05"
-//   f = absl::FormatTime("%H:%M:%E3S", t, lax);  // "03:04:05.000"
-//
-// Note: If the given `absl::Time` is `absl::InfiniteFuture()`, the returned
-// string will be exactly "infinite-future". If the given `absl::Time` is
-// `absl::InfinitePast()`, the returned string will be exactly "infinite-past".
-// In both cases the given format string and `absl::TimeZone` are ignored.
-//
-std::string FormatTime(const std::string& format, Time t, TimeZone tz);
-
-// Convenience functions that format the given time using the RFC3339_full
-// format.  The first overload uses the provided TimeZone, while the second
-// uses LocalTimeZone().
-std::string FormatTime(Time t, TimeZone tz);
-std::string FormatTime(Time t);
-
-// Output stream operator.
-inline std::ostream& operator<<(std::ostream& os, Time t) {
-  return os << FormatTime(t);
-}
-
-// ParseTime()
-//
-// Parses an input string according to the provided format string and
-// returns the corresponding `absl::Time`. Uses strftime()-like formatting
-// options, with the same extensions as FormatTime(), but with the
-// exceptions that %E#S is interpreted as %E*S, and %E#f as %E*f.  %Ez
-// and %E*z also accept the same inputs.
-//
-// %Y consumes as many numeric characters as it can, so the matching data
-// should always be terminated with a non-numeric.  %E4Y always consumes
-// exactly four characters, including any sign.
-//
-// Unspecified fields are taken from the default date and time of ...
-//
-//   "1970-01-01 00:00:00.0 +0000"
-//
-// For example, parsing a string of "15:45" (%H:%M) will return an absl::Time
-// that represents "1970-01-01 15:45:00.0 +0000".
-//
-// Note that since ParseTime() returns time instants, it makes the most sense
-// to parse fully-specified date/time strings that include a UTC offset (%z,
-// %Ez, or %E*z).
-//
-// Note also that `absl::ParseTime()` only heeds the fields year, month, day,
-// hour, minute, (fractional) second, and UTC offset.  Other fields, like
-// weekday (%a or %A), while parsed for syntactic validity, are ignored
-// in the conversion.
-//
-// Date and time fields that are out-of-range will be treated as errors
-// rather than normalizing them like `absl::FromDateTime()` does.  For example,
-// it is an error to parse the date "Oct 32, 2013" because 32 is out of range.
-//
-// A leap second of ":60" is normalized to ":00" of the following minute
-// with fractional seconds discarded.  The following table shows how the
-// given seconds and subseconds will be parsed:
-//
-//   "59.x" -> 59.x  // exact
-//   "60.x" -> 00.0  // normalized
-//   "00.x" -> 00.x  // exact
-//
-// Errors are indicated by returning false and assigning an error message
-// to the "err" out param if it is non-null.
-//
-// Note: If the input string is exactly "infinite-future", the returned
-// `absl::Time` will be `absl::InfiniteFuture()` and `true` will be returned.
-// If the input string is "infinite-past", the returned `absl::Time` will be
-// `absl::InfinitePast()` and `true` will be returned.
-//
-bool ParseTime(const std::string& format, const std::string& input, Time* time,
-               std::string* err);
-
-// Like ParseTime() above, but if the format string does not contain a UTC
-// offset specification (%z/%Ez/%E*z) then the input is interpreted in the
-// given TimeZone.  This means that the input, by itself, does not identify a
-// unique instant.  Being time-zone dependent, it also admits the possibility
-// of ambiguity or non-existence, in which case the "pre" time (as defined
-// for ConvertDateTime()) is returned.  For these reasons we recommend that
-// all date/time strings include a UTC offset so they're context independent.
-bool ParseTime(const std::string& format, const std::string& input, TimeZone tz,
-               Time* time, std::string* err);
-
 // Support for flag values of type Time. Time flags must be specified in a
 // format that matches absl::RFC3339_full. For example:
 //
@@ -1056,12 +834,14 @@
 //
 // See also:
 // - https://github.com/google/cctz
-// - http://www.iana.org/time-zones
-// - http://en.wikipedia.org/wiki/Zoneinfo
+// - https://www.iana.org/time-zones
+// - https://en.wikipedia.org/wiki/Zoneinfo
 class TimeZone {
  public:
   explicit TimeZone(time_internal::cctz::time_zone tz) : cz_(tz) {}
   TimeZone() = default;  // UTC, but prefer UTCTimeZone() to be explicit.
+
+  // Copyable.
   TimeZone(const TimeZone&) = default;
   TimeZone& operator=(const TimeZone&) = default;
 
@@ -1069,6 +849,136 @@
 
   std::string name() const { return cz_.name(); }
 
+  // TimeZone::CivilInfo
+  //
+  // Information about the civil time corresponding to an absolute time.
+  // This struct is not intended to represent an instant in time. So, rather
+  // than passing a `TimeZone::CivilInfo` to a function, pass an `absl::Time`
+  // and an `absl::TimeZone`.
+  struct CivilInfo {
+    CivilSecond cs;
+    Duration subsecond;
+
+    // Note: The following fields exist for backward compatibility
+    // with older APIs.  Accessing these fields directly is a sign of
+    // imprudent logic in the calling code.  Modern time-related code
+    // should only access this data indirectly by way of FormatTime().
+    // These fields are undefined for InfiniteFuture() and InfinitePast().
+    int offset;             // seconds east of UTC
+    bool is_dst;            // is offset non-standard?
+    const char* zone_abbr;  // time-zone abbreviation (e.g., "PST")
+  };
+
+  // TimeZone::At(Time)
+  //
+  // Returns the civil time for this TimeZone at a certain `absl::Time`.
+  // If the input time is infinite, the output civil second will be set to
+  // CivilSecond::max() or min(), and the subsecond will be infinite.
+  //
+  // Example:
+  //
+  //   const auto epoch = lax.At(absl::UnixEpoch());
+  //   // epoch.cs == 1969-12-31 16:00:00
+  //   // epoch.subsecond == absl::ZeroDuration()
+  //   // epoch.offset == -28800
+  //   // epoch.is_dst == false
+  //   // epoch.abbr == "PST"
+  CivilInfo At(Time t) const;
+
+  // TimeZone::TimeInfo
+  //
+  // Information about the absolute times corresponding to a civil time.
+  // (Subseconds must be handled separately.)
+  //
+  // It is possible for a caller to pass a civil-time value that does
+  // not represent an actual or unique instant in time (due to a shift
+  // in UTC offset in the TimeZone, which results in a discontinuity in
+  // the civil-time components). For example, a daylight-saving-time
+  // transition skips or repeats civil times---in the United States,
+  // March 13, 2011 02:15 never occurred, while November 6, 2011 01:15
+  // occurred twice---so requests for such times are not well-defined.
+  // To account for these possibilities, `absl::TimeZone::TimeInfo` is
+  // richer than just a single `absl::Time`.
+  struct TimeInfo {
+    enum CivilKind {
+      UNIQUE,    // the civil time was singular (pre == trans == post)
+      SKIPPED,   // the civil time did not exist (pre >= trans > post)
+      REPEATED,  // the civil time was ambiguous (pre < trans <= post)
+    } kind;
+    Time pre;    // time calculated using the pre-transition offset
+    Time trans;  // when the civil-time discontinuity occurred
+    Time post;   // time calculated using the post-transition offset
+  };
+
+  // TimeZone::At(CivilSecond)
+  //
+  // Returns an `absl::TimeInfo` containing the absolute time(s) for this
+  // TimeZone at an `absl::CivilSecond`. When the civil time is skipped or
+  // repeated, returns times calculated using the pre-transition and post-
+  // transition UTC offsets, plus the transition time itself.
+  //
+  // Examples:
+  //
+  //   // A unique civil time
+  //   const auto jan01 = lax.At(absl::CivilSecond(2011, 1, 1, 0, 0, 0));
+  //   // jan01.kind == TimeZone::TimeInfo::UNIQUE
+  //   // jan01.pre    is 2011-01-01 00:00:00 -0800
+  //   // jan01.trans  is 2011-01-01 00:00:00 -0800
+  //   // jan01.post   is 2011-01-01 00:00:00 -0800
+  //
+  //   // A Spring DST transition, when there is a gap in civil time
+  //   const auto mar13 = lax.At(absl::CivilSecond(2011, 3, 13, 2, 15, 0));
+  //   // mar13.kind == TimeZone::TimeInfo::SKIPPED
+  //   // mar13.pre   is 2011-03-13 03:15:00 -0700
+  //   // mar13.trans is 2011-03-13 03:00:00 -0700
+  //   // mar13.post  is 2011-03-13 01:15:00 -0800
+  //
+  //   // A Fall DST transition, when civil times are repeated
+  //   const auto nov06 = lax.At(absl::CivilSecond(2011, 11, 6, 1, 15, 0));
+  //   // nov06.kind == TimeZone::TimeInfo::REPEATED
+  //   // nov06.pre   is 2011-11-06 01:15:00 -0700
+  //   // nov06.trans is 2011-11-06 01:00:00 -0800
+  //   // nov06.post  is 2011-11-06 01:15:00 -0800
+  TimeInfo At(CivilSecond ct) const;
+
+  // TimeZone::NextTransition()
+  // TimeZone::PrevTransition()
+  //
+  // Finds the time of the next/previous offset change in this time zone.
+  //
+  // By definition, `NextTransition(t, &trans)` returns false when `t` is
+  // `InfiniteFuture()`, and `PrevTransition(t, &trans)` returns false
+  // when `t` is `InfinitePast()`. If the zone has no transitions, the
+  // result will also be false no matter what the argument.
+  //
+  // Otherwise, when `t` is `InfinitePast()`, `NextTransition(t, &trans)`
+  // returns true and sets `trans` to the first recorded transition. Chains
+  // of calls to `NextTransition()/PrevTransition()` will eventually return
+  // false, but it is unspecified exactly when `NextTransition(t, &trans)`
+  // jumps to false, or what time is set by `PrevTransition(t, &trans)` for
+  // a very distant `t`.
+  //
+  // Note: Enumeration of time-zone transitions is for informational purposes
+  // only. Modern time-related code should not care about when offset changes
+  // occur.
+  //
+  // Example:
+  //   absl::TimeZone nyc;
+  //   if (!absl::LoadTimeZone("America/New_York", &nyc)) { ... }
+  //   const auto now = absl::Now();
+  //   auto t = absl::InfinitePast();
+  //   absl::TimeZone::CivilTransition trans;
+  //   while (t <= now && nyc.NextTransition(t, &trans)) {
+  //     // transition: trans.from -> trans.to
+  //     t = nyc.At(trans.to).trans;
+  //   }
+  struct CivilTransition {
+    CivilSecond from;  // the civil time we jump from
+    CivilSecond to;    // the civil time we jump to
+  };
+  bool NextTransition(Time t, CivilTransition* trans) const;
+  bool PrevTransition(Time t, CivilTransition* trans) const;
+
   template <typename H>
   friend H AbslHashValue(H h, TimeZone tz) {
     return H::combine(std::move(h), tz.cz_);
@@ -1127,6 +1037,270 @@
   return TimeZone(time_internal::cctz::local_time_zone());
 }
 
+// ToCivilSecond()
+// ToCivilMinute()
+// ToCivilHour()
+// ToCivilDay()
+// ToCivilMonth()
+// ToCivilYear()
+//
+// Helpers for TimeZone::At(Time) to return particularly aligned civil times.
+//
+// Example:
+//
+//   absl::Time t = ...;
+//   absl::TimeZone tz = ...;
+//   const auto cd = absl::ToCivilDay(t, tz);
+inline CivilSecond ToCivilSecond(Time t, TimeZone tz) {
+  return tz.At(t).cs;  // already a CivilSecond
+}
+inline CivilMinute ToCivilMinute(Time t, TimeZone tz) {
+  return CivilMinute(tz.At(t).cs);
+}
+inline CivilHour ToCivilHour(Time t, TimeZone tz) {
+  return CivilHour(tz.At(t).cs);
+}
+inline CivilDay ToCivilDay(Time t, TimeZone tz) {
+  return CivilDay(tz.At(t).cs);
+}
+inline CivilMonth ToCivilMonth(Time t, TimeZone tz) {
+  return CivilMonth(tz.At(t).cs);
+}
+inline CivilYear ToCivilYear(Time t, TimeZone tz) {
+  return CivilYear(tz.At(t).cs);
+}
+
+// FromCivil()
+//
+// Helper for TimeZone::At(CivilSecond) that provides "order-preserving
+// semantics." If the civil time maps to a unique time, that time is
+// returned. If the civil time is repeated in the given time zone, the
+// time using the pre-transition offset is returned. Otherwise, the
+// civil time is skipped in the given time zone, and the transition time
+// is returned. This means that for any two civil times, ct1 and ct2,
+// (ct1 < ct2) => (FromCivil(ct1) <= FromCivil(ct2)), the equal case
+// being when two non-existent civil times map to the same transition time.
+//
+// Note: Accepts civil times of any alignment.
+inline Time FromCivil(CivilSecond ct, TimeZone tz) {
+  const auto ti = tz.At(ct);
+  if (ti.kind == TimeZone::TimeInfo::SKIPPED) return ti.trans;
+  return ti.pre;
+}
+
+// TimeConversion
+//
+// An `absl::TimeConversion` represents the conversion of year, month, day,
+// hour, minute, and second values (i.e., a civil time), in a particular
+// `absl::TimeZone`, to a time instant (an absolute time), as returned by
+// `absl::ConvertDateTime()`. Lecacy version of `absl::TimeZone::TimeInfo`.
+//
+// Deprecated. Use `absl::TimeZone::TimeInfo`.
+struct
+    TimeConversion {
+  Time pre;    // time calculated using the pre-transition offset
+  Time trans;  // when the civil-time discontinuity occurred
+  Time post;   // time calculated using the post-transition offset
+
+  enum Kind {
+    UNIQUE,    // the civil time was singular (pre == trans == post)
+    SKIPPED,   // the civil time did not exist
+    REPEATED,  // the civil time was ambiguous
+  };
+  Kind kind;
+
+  bool normalized;  // input values were outside their valid ranges
+};
+
+// ConvertDateTime()
+//
+// Legacy version of `absl::TimeZone::At(absl::CivilSecond)` that takes
+// the civil time as six, separate values (YMDHMS).
+//
+// The input month, day, hour, minute, and second values can be outside
+// of their valid ranges, in which case they will be "normalized" during
+// the conversion.
+//
+// Example:
+//
+//   // "October 32" normalizes to "November 1".
+//   absl::TimeConversion tc =
+//       absl::ConvertDateTime(2013, 10, 32, 8, 30, 0, lax);
+//   // tc.kind == TimeConversion::UNIQUE && tc.normalized == true
+//   // absl::ToCivilDay(tc.pre, tz).month() == 11
+//   // absl::ToCivilDay(tc.pre, tz).day() == 1
+//
+// Deprecated. Use `absl::TimeZone::At(CivilSecond)`.
+TimeConversion ConvertDateTime(int64_t year, int mon, int day, int hour,
+                               int min, int sec, TimeZone tz);
+
+// FromDateTime()
+//
+// A convenience wrapper for `absl::ConvertDateTime()` that simply returns
+// the "pre" `absl::Time`.  That is, the unique result, or the instant that
+// is correct using the pre-transition offset (as if the transition never
+// happened).
+//
+// Example:
+//
+//   absl::Time t = absl::FromDateTime(2017, 9, 26, 9, 30, 0, lax);
+//   // t = 2017-09-26 09:30:00 -0700
+//
+// Deprecated. Use `absl::FromCivil(CivilSecond, TimeZone)`. Note that the
+// behavior of `FromCivil()` differs from `FromDateTime()` for skipped civil
+// times. If you care about that see `absl::TimeZone::At(absl::CivilSecond)`.
+inline Time FromDateTime(int64_t year, int mon, int day, int hour,
+                         int min, int sec, TimeZone tz) {
+  return ConvertDateTime(year, mon, day, hour, min, sec, tz).pre;
+}
+
+// FromTM()
+//
+// Converts the `tm_year`, `tm_mon`, `tm_mday`, `tm_hour`, `tm_min`, and
+// `tm_sec` fields to an `absl::Time` using the given time zone. See ctime(3)
+// for a description of the expected values of the tm fields. If the indicated
+// time instant is not unique (see `absl::TimeZone::At(absl::CivilSecond)`
+// above), the `tm_isdst` field is consulted to select the desired instant
+// (`tm_isdst` > 0 means DST, `tm_isdst` == 0 means no DST, `tm_isdst` < 0
+// means use the post-transition offset).
+Time FromTM(const struct tm& tm, TimeZone tz);
+
+// ToTM()
+//
+// Converts the given `absl::Time` to a struct tm using the given time zone.
+// See ctime(3) for a description of the values of the tm fields.
+struct tm ToTM(Time t, TimeZone tz);
+
+// RFC3339_full
+// RFC3339_sec
+//
+// FormatTime()/ParseTime() format specifiers for RFC3339 date/time strings,
+// with trailing zeros trimmed or with fractional seconds omitted altogether.
+//
+// Note that RFC3339_sec[] matches an ISO 8601 extended format for date and
+// time with UTC offset.  Also note the use of "%Y": RFC3339 mandates that
+// years have exactly four digits, but we allow them to take their natural
+// width.
+extern const char RFC3339_full[];  // %Y-%m-%dT%H:%M:%E*S%Ez
+extern const char RFC3339_sec[];   // %Y-%m-%dT%H:%M:%S%Ez
+
+// RFC1123_full
+// RFC1123_no_wday
+//
+// FormatTime()/ParseTime() format specifiers for RFC1123 date/time strings.
+extern const char RFC1123_full[];     // %a, %d %b %E4Y %H:%M:%S %z
+extern const char RFC1123_no_wday[];  // %d %b %E4Y %H:%M:%S %z
+
+// FormatTime()
+//
+// Formats the given `absl::Time` in the `absl::TimeZone` according to the
+// provided format string. Uses strftime()-like formatting options, with
+// the following extensions:
+//
+//   - %Ez  - RFC3339-compatible numeric UTC offset (+hh:mm or -hh:mm)
+//   - %E*z - Full-resolution numeric UTC offset (+hh:mm:ss or -hh:mm:ss)
+//   - %E#S - Seconds with # digits of fractional precision
+//   - %E*S - Seconds with full fractional precision (a literal '*')
+//   - %E#f - Fractional seconds with # digits of precision
+//   - %E*f - Fractional seconds with full precision (a literal '*')
+//   - %E4Y - Four-character years (-999 ... -001, 0000, 0001 ... 9999)
+//
+// Note that %E0S behaves like %S, and %E0f produces no characters.  In
+// contrast %E*f always produces at least one digit, which may be '0'.
+//
+// Note that %Y produces as many characters as it takes to fully render the
+// year.  A year outside of [-999:9999] when formatted with %E4Y will produce
+// more than four characters, just like %Y.
+//
+// We recommend that format strings include the UTC offset (%z, %Ez, or %E*z)
+// so that the result uniquely identifies a time instant.
+//
+// Example:
+//
+//   absl::CivilSecond cs(2013, 1, 2, 3, 4, 5);
+//   absl::Time t = absl::FromCivil(cs, lax);
+//   std::string f = absl::FormatTime("%H:%M:%S", t, lax);  // "03:04:05"
+//   f = absl::FormatTime("%H:%M:%E3S", t, lax);  // "03:04:05.000"
+//
+// Note: If the given `absl::Time` is `absl::InfiniteFuture()`, the returned
+// string will be exactly "infinite-future". If the given `absl::Time` is
+// `absl::InfinitePast()`, the returned string will be exactly "infinite-past".
+// In both cases the given format string and `absl::TimeZone` are ignored.
+//
+std::string FormatTime(const std::string& format, Time t, TimeZone tz);
+
+// Convenience functions that format the given time using the RFC3339_full
+// format.  The first overload uses the provided TimeZone, while the second
+// uses LocalTimeZone().
+std::string FormatTime(Time t, TimeZone tz);
+std::string FormatTime(Time t);
+
+// Output stream operator.
+inline std::ostream& operator<<(std::ostream& os, Time t) {
+  return os << FormatTime(t);
+}
+
+// ParseTime()
+//
+// Parses an input string according to the provided format string and
+// returns the corresponding `absl::Time`. Uses strftime()-like formatting
+// options, with the same extensions as FormatTime(), but with the
+// exceptions that %E#S is interpreted as %E*S, and %E#f as %E*f.  %Ez
+// and %E*z also accept the same inputs.
+//
+// %Y consumes as many numeric characters as it can, so the matching data
+// should always be terminated with a non-numeric.  %E4Y always consumes
+// exactly four characters, including any sign.
+//
+// Unspecified fields are taken from the default date and time of ...
+//
+//   "1970-01-01 00:00:00.0 +0000"
+//
+// For example, parsing a string of "15:45" (%H:%M) will return an absl::Time
+// that represents "1970-01-01 15:45:00.0 +0000".
+//
+// Note that since ParseTime() returns time instants, it makes the most sense
+// to parse fully-specified date/time strings that include a UTC offset (%z,
+// %Ez, or %E*z).
+//
+// Note also that `absl::ParseTime()` only heeds the fields year, month, day,
+// hour, minute, (fractional) second, and UTC offset.  Other fields, like
+// weekday (%a or %A), while parsed for syntactic validity, are ignored
+// in the conversion.
+//
+// Date and time fields that are out-of-range will be treated as errors
+// rather than normalizing them like `absl::CivilSecond` does.  For example,
+// it is an error to parse the date "Oct 32, 2013" because 32 is out of range.
+//
+// A leap second of ":60" is normalized to ":00" of the following minute
+// with fractional seconds discarded.  The following table shows how the
+// given seconds and subseconds will be parsed:
+//
+//   "59.x" -> 59.x  // exact
+//   "60.x" -> 00.0  // normalized
+//   "00.x" -> 00.x  // exact
+//
+// Errors are indicated by returning false and assigning an error message
+// to the "err" out param if it is non-null.
+//
+// Note: If the input string is exactly "infinite-future", the returned
+// `absl::Time` will be `absl::InfiniteFuture()` and `true` will be returned.
+// If the input string is "infinite-past", the returned `absl::Time` will be
+// `absl::InfinitePast()` and `true` will be returned.
+//
+bool ParseTime(const std::string& format, const std::string& input, Time* time,
+               std::string* err);
+
+// Like ParseTime() above, but if the format string does not contain a UTC
+// offset specification (%z/%Ez/%E*z) then the input is interpreted in the
+// given TimeZone.  This means that the input, by itself, does not identify a
+// unique instant.  Being time-zone dependent, it also admits the possibility
+// of ambiguity or non-existence, in which case the "pre" time (as defined
+// by TimeZone::TimeInfo) is returned.  For these reasons we recommend that
+// all date/time strings include a UTC offset so they're context independent.
+bool ParseTime(const std::string& format, const std::string& input, TimeZone tz,
+               Time* time, std::string* err);
+
 // ============================================================================
 // Implementation Details Follow
 // ============================================================================
@@ -1164,17 +1338,20 @@
   return (ticks < 0) ? MakeDuration(sec - 1, ticks + kTicksPerSecond)
                      : MakeDuration(sec, ticks);
 }
+
 // Provide access to the Duration representation.
 constexpr int64_t GetRepHi(Duration d) { return d.rep_hi_; }
 constexpr uint32_t GetRepLo(Duration d) { return d.rep_lo_; }
+
+// Returns true iff d is positive or negative infinity.
 constexpr bool IsInfiniteDuration(Duration d) { return GetRepLo(d) == ~0U; }
 
 // Returns an infinite Duration with the opposite sign.
 // REQUIRES: IsInfiniteDuration(d)
 constexpr Duration OppositeInfinity(Duration d) {
   return GetRepHi(d) < 0
-             ? MakeDuration(std::numeric_limits<int64_t>::max(), ~0U)
-             : MakeDuration(std::numeric_limits<int64_t>::min(), ~0U);
+             ? MakeDuration((std::numeric_limits<int64_t>::max)(), ~0U)
+             : MakeDuration((std::numeric_limits<int64_t>::min)(), ~0U);
 }
 
 // Returns (-n)-1 (equivalently -(n+1)) without avoidable overflow.
@@ -1199,14 +1376,14 @@
       v / N, v % N * kTicksPerNanosecond * 1000 * 1000 * 1000 / N);
 }
 constexpr Duration FromInt64(int64_t v, std::ratio<60>) {
-  return (v <= std::numeric_limits<int64_t>::max() / 60 &&
-          v >= std::numeric_limits<int64_t>::min() / 60)
+  return (v <= (std::numeric_limits<int64_t>::max)() / 60 &&
+          v >= (std::numeric_limits<int64_t>::min)() / 60)
              ? MakeDuration(v * 60)
              : v > 0 ? InfiniteDuration() : -InfiniteDuration();
 }
 constexpr Duration FromInt64(int64_t v, std::ratio<3600>) {
-  return (v <= std::numeric_limits<int64_t>::max() / 3600 &&
-          v >= std::numeric_limits<int64_t>::min() / 3600)
+  return (v <= (std::numeric_limits<int64_t>::max)() / 3600 &&
+          v >= (std::numeric_limits<int64_t>::min)() / 3600)
              ? MakeDuration(v * 3600)
              : v > 0 ? InfiniteDuration() : -InfiniteDuration();
 }
@@ -1263,14 +1440,15 @@
   using Period = typename T::period;
   static_assert(IsValidRep64<Rep>(0), "duration::rep is invalid");
   if (time_internal::IsInfiniteDuration(d))
-    return d < ZeroDuration() ? T::min() : T::max();
+    return d < ZeroDuration() ? (T::min)() : (T::max)();
   const auto v = ToInt64(d, Period{});
-  if (v > std::numeric_limits<Rep>::max()) return T::max();
-  if (v < std::numeric_limits<Rep>::min()) return T::min();
+  if (v > (std::numeric_limits<Rep>::max)()) return (T::max)();
+  if (v < (std::numeric_limits<Rep>::min)()) return (T::min)();
   return T{v};
 }
 
 }  // namespace time_internal
+
 constexpr Duration Nanoseconds(int64_t n) {
   return time_internal::FromInt64(n, std::nano{});
 }
@@ -1293,7 +1471,8 @@
 constexpr bool operator<(Duration lhs, Duration rhs) {
   return time_internal::GetRepHi(lhs) != time_internal::GetRepHi(rhs)
              ? time_internal::GetRepHi(lhs) < time_internal::GetRepHi(rhs)
-             : time_internal::GetRepHi(lhs) == std::numeric_limits<int64_t>::min()
+             : time_internal::GetRepHi(lhs) ==
+                       (std::numeric_limits<int64_t>::min)()
                    ? time_internal::GetRepLo(lhs) + 1 <
                          time_internal::GetRepLo(rhs) + 1
                    : time_internal::GetRepLo(lhs) <
@@ -1318,7 +1497,8 @@
   // a second's worth of ticks and avoid overflow (as negating int64_t-min + 1
   // is safe).
   return time_internal::GetRepLo(d) == 0
-             ? time_internal::GetRepHi(d) == std::numeric_limits<int64_t>::min()
+             ? time_internal::GetRepHi(d) ==
+                       (std::numeric_limits<int64_t>::min)()
                    ? InfiniteDuration()
                    : time_internal::MakeDuration(-time_internal::GetRepHi(d))
              : time_internal::IsInfiniteDuration(d)
@@ -1331,7 +1511,8 @@
 }
 
 constexpr Duration InfiniteDuration() {
-  return time_internal::MakeDuration(std::numeric_limits<int64_t>::max(), ~0U);
+  return time_internal::MakeDuration((std::numeric_limits<int64_t>::max)(),
+                                     ~0U);
 }
 
 constexpr Duration FromChrono(const std::chrono::nanoseconds& d) {
diff --git a/absl/time/time_benchmark.cc b/absl/time/time_benchmark.cc
index e100994..99e6279 100644
--- a/absl/time/time_benchmark.cc
+++ b/absl/time/time_benchmark.cc
@@ -3,7 +3,7 @@
 // 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
+//      https://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,
@@ -169,32 +169,32 @@
 BENCHMARK(BM_Time_ToUnixSeconds);
 
 //
-// FromDateTime
+// FromCivil
 //
-// In each "FromDateTime" benchmark we switch between two YMDhms
-// values separated by at least one transition in order to defeat any
-// internal caching of previous results (e.g., see time_local_hint_).
+// In each "FromCivil" benchmark we switch between two YMDhms values
+// separated by at least one transition in order to defeat any internal
+// caching of previous results (e.g., see time_local_hint_).
 //
 // The "UTC" variants use UTC instead of the Google/local time zone.
 // The "Day0" variants require normalization of the day of month.
 //
 
-void BM_Time_FromDateTime_Absl(benchmark::State& state) {
+void BM_Time_FromCivil_Absl(benchmark::State& state) {
   const absl::TimeZone tz =
       absl::time_internal::LoadTimeZone("America/Los_Angeles");
   int i = 0;
   while (state.KeepRunning()) {
     if ((i & 1) == 0) {
-      absl::FromDateTime(2014, 12, 18, 20, 16, 18, tz);
+      absl::FromCivil(absl::CivilSecond(2014, 12, 18, 20, 16, 18), tz);
     } else {
-      absl::FromDateTime(2013, 11, 15, 18, 30, 27, tz);
+      absl::FromCivil(absl::CivilSecond(2013, 11, 15, 18, 30, 27), tz);
     }
     ++i;
   }
 }
-BENCHMARK(BM_Time_FromDateTime_Absl);
+BENCHMARK(BM_Time_FromCivil_Absl);
 
-void BM_Time_FromDateTime_Libc(benchmark::State& state) {
+void BM_Time_FromCivil_Libc(benchmark::State& state) {
   // No timezone support, so just use localtime.
   int i = 0;
   while (state.KeepRunning()) {
@@ -219,32 +219,32 @@
     ++i;
   }
 }
-BENCHMARK(BM_Time_FromDateTime_Libc);
+BENCHMARK(BM_Time_FromCivil_Libc);
 
-void BM_Time_FromDateTimeUTC_Absl(benchmark::State& state) {
+void BM_Time_FromCivilUTC_Absl(benchmark::State& state) {
   const absl::TimeZone tz = absl::UTCTimeZone();
   while (state.KeepRunning()) {
-    FromDateTime(2014, 12, 18, 20, 16, 18, tz);
+    absl::FromCivil(absl::CivilSecond(2014, 12, 18, 20, 16, 18), tz);
   }
 }
-BENCHMARK(BM_Time_FromDateTimeUTC_Absl);
+BENCHMARK(BM_Time_FromCivilUTC_Absl);
 
-void BM_Time_FromDateTimeDay0_Absl(benchmark::State& state) {
+void BM_Time_FromCivilDay0_Absl(benchmark::State& state) {
   const absl::TimeZone tz =
       absl::time_internal::LoadTimeZone("America/Los_Angeles");
   int i = 0;
   while (state.KeepRunning()) {
     if ((i & 1) == 0) {
-      absl::FromDateTime(2014, 12, 0, 20, 16, 18, tz);
+      absl::FromCivil(absl::CivilSecond(2014, 12, 0, 20, 16, 18), tz);
     } else {
-      absl::FromDateTime(2013, 11, 0, 18, 30, 27, tz);
+      absl::FromCivil(absl::CivilSecond(2013, 11, 0, 18, 30, 27), tz);
     }
     ++i;
   }
 }
-BENCHMARK(BM_Time_FromDateTimeDay0_Absl);
+BENCHMARK(BM_Time_FromCivilDay0_Absl);
 
-void BM_Time_FromDateTimeDay0_Libc(benchmark::State& state) {
+void BM_Time_FromCivilDay0_Libc(benchmark::State& state) {
   // No timezone support, so just use localtime.
   int i = 0;
   while (state.KeepRunning()) {
@@ -269,7 +269,7 @@
     ++i;
   }
 }
-BENCHMARK(BM_Time_FromDateTimeDay0_Libc);
+BENCHMARK(BM_Time_FromCivilDay0_Libc);
 
 //
 // To/FromTimespec
diff --git a/absl/time/time_norm_test.cc b/absl/time/time_norm_test.cc
deleted file mode 100644
index 4436242..0000000
--- a/absl/time/time_norm_test.cc
+++ /dev/null
@@ -1,306 +0,0 @@
-// Copyright 2017 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.
-
-// This file contains tests for FromDateTime() normalization, which is
-// time-zone independent so we just use UTC throughout.
-
-#include <cstdint>
-#include <limits>
-
-#include "gmock/gmock.h"
-#include "gtest/gtest.h"
-#include "absl/time/internal/test_util.h"
-#include "absl/time/time.h"
-
-namespace {
-
-TEST(TimeNormCase, SimpleOverflow) {
-  const absl::TimeZone utc = absl::UTCTimeZone();
-
-  absl::TimeConversion tc =
-      absl::ConvertDateTime(2013, 11, 15, 16, 32, 59 + 1, utc);
-  EXPECT_TRUE(tc.normalized);
-  EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
-  absl::Time::Breakdown bd = tc.pre.In(utc);
-  ABSL_INTERNAL_EXPECT_TIME(bd, 2013, 11, 15, 16, 33, 0, 0, false);
-
-  tc = absl::ConvertDateTime(2013, 11, 15, 16, 59 + 1, 14, utc);
-  EXPECT_TRUE(tc.normalized);
-  EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
-  bd = tc.pre.In(utc);
-  ABSL_INTERNAL_EXPECT_TIME(bd, 2013, 11, 15, 17, 0, 14, 0, false);
-
-  tc = absl::ConvertDateTime(2013, 11, 15, 23 + 1, 32, 14, utc);
-  EXPECT_TRUE(tc.normalized);
-  EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
-  bd = tc.pre.In(utc);
-  ABSL_INTERNAL_EXPECT_TIME(bd, 2013, 11, 16, 0, 32, 14, 0, false);
-
-  tc = absl::ConvertDateTime(2013, 11, 30 + 1, 16, 32, 14, utc);
-  EXPECT_TRUE(tc.normalized);
-  EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
-  bd = tc.pre.In(utc);
-  ABSL_INTERNAL_EXPECT_TIME(bd, 2013, 12, 1, 16, 32, 14, 0, false);
-
-  tc = absl::ConvertDateTime(2013, 12 + 1, 15, 16, 32, 14, utc);
-  EXPECT_TRUE(tc.normalized);
-  EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
-  bd = tc.pre.In(utc);
-  ABSL_INTERNAL_EXPECT_TIME(bd, 2014, 1, 15, 16, 32, 14, 0, false);
-}
-
-TEST(TimeNormCase, SimpleUnderflow) {
-  const absl::TimeZone utc = absl::UTCTimeZone();
-
-  absl::TimeConversion tc = ConvertDateTime(2013, 11, 15, 16, 32, 0 - 1, utc);
-  EXPECT_TRUE(tc.normalized);
-  EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
-  absl::Time::Breakdown bd = tc.pre.In(utc);
-  ABSL_INTERNAL_EXPECT_TIME(bd, 2013, 11, 15, 16, 31, 59, 0, false);
-
-  tc = ConvertDateTime(2013, 11, 15, 16, 0 - 1, 14, utc);
-  EXPECT_TRUE(tc.normalized);
-  EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
-  bd = tc.pre.In(utc);
-  ABSL_INTERNAL_EXPECT_TIME(bd, 2013, 11, 15, 15, 59, 14, 0, false);
-
-  tc = ConvertDateTime(2013, 11, 15, 0 - 1, 32, 14, utc);
-  EXPECT_TRUE(tc.normalized);
-  EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
-  bd = tc.pre.In(utc);
-  ABSL_INTERNAL_EXPECT_TIME(bd, 2013, 11, 14, 23, 32, 14, 0, false);
-
-  tc = ConvertDateTime(2013, 11, 1 - 1, 16, 32, 14, utc);
-  EXPECT_TRUE(tc.normalized);
-  EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
-  bd = tc.pre.In(utc);
-  ABSL_INTERNAL_EXPECT_TIME(bd, 2013, 10, 31, 16, 32, 14, 0, false);
-
-  tc = ConvertDateTime(2013, 1 - 1, 15, 16, 32, 14, utc);
-  EXPECT_TRUE(tc.normalized);
-  EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
-  bd = tc.pre.In(utc);
-  ABSL_INTERNAL_EXPECT_TIME(bd, 2012, 12, 15, 16, 32, 14, 0, false);
-}
-
-TEST(TimeNormCase, MultipleOverflow) {
-  const absl::TimeZone utc = absl::UTCTimeZone();
-  absl::TimeConversion tc = ConvertDateTime(2013, 12, 31, 23, 59, 59 + 1, utc);
-  EXPECT_TRUE(tc.normalized);
-  EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
-  absl::Time::Breakdown bd = tc.pre.In(utc);
-  ABSL_INTERNAL_EXPECT_TIME(bd, 2014, 1, 1, 0, 0, 0, 0, false);
-}
-
-TEST(TimeNormCase, MultipleUnderflow) {
-  const absl::TimeZone utc = absl::UTCTimeZone();
-  absl::TimeConversion tc = absl::ConvertDateTime(2014, 1, 1, 0, 0, 0 - 1, utc);
-  EXPECT_TRUE(tc.normalized);
-  EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
-  absl::Time::Breakdown bd = tc.pre.In(utc);
-  ABSL_INTERNAL_EXPECT_TIME(bd, 2013, 12, 31, 23, 59, 59, 0, false);
-}
-
-TEST(TimeNormCase, OverflowLimits) {
-  const absl::TimeZone utc = absl::UTCTimeZone();
-  absl::TimeConversion tc;
-  absl::Time::Breakdown bd;
-
-  const int kintmax = std::numeric_limits<int>::max();
-  tc = absl::ConvertDateTime(0, kintmax, kintmax, kintmax, kintmax, kintmax,
-                             utc);
-  EXPECT_TRUE(tc.normalized);
-  EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
-  bd = tc.pre.In(utc);
-  ABSL_INTERNAL_EXPECT_TIME(bd, 185085715, 11, 27, 12, 21, 7, 0, false);
-
-  const int kintmin = std::numeric_limits<int>::min();
-  tc = absl::ConvertDateTime(0, kintmin, kintmin, kintmin, kintmin, kintmin,
-                             utc);
-  EXPECT_TRUE(tc.normalized);
-  EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
-  bd = tc.pre.In(utc);
-  ABSL_INTERNAL_EXPECT_TIME(bd, -185085717, 10, 31, 10, 37, 52, 0, false);
-
-  const int64_t max_year = std::numeric_limits<int64_t>::max();
-  tc = absl::ConvertDateTime(max_year, 12, 31, 23, 59, 59, utc);
-  EXPECT_TRUE(tc.normalized);
-  EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
-  EXPECT_EQ(absl::InfiniteFuture(), tc.pre);
-
-  const int64_t min_year = std::numeric_limits<int64_t>::min();
-  tc = absl::ConvertDateTime(min_year, 1, 1, 0, 0, 0, utc);
-  EXPECT_TRUE(tc.normalized);
-  EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
-  EXPECT_EQ(absl::InfinitePast(), tc.pre);
-}
-
-TEST(TimeNormCase, ComplexOverflow) {
-  const absl::TimeZone utc = absl::UTCTimeZone();
-
-  absl::TimeConversion tc =
-      ConvertDateTime(2013, 11, 15, 16, 32, 14 + 123456789, utc);
-  EXPECT_TRUE(tc.normalized);
-  EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
-  absl::Time::Breakdown bd = tc.pre.In(utc);
-  ABSL_INTERNAL_EXPECT_TIME(bd, 2017, 10, 14, 14, 5, 23, 0, false);
-
-  tc = absl::ConvertDateTime(2013, 11, 15, 16, 32 + 1234567, 14, utc);
-  EXPECT_TRUE(tc.normalized);
-  EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
-  bd = tc.pre.In(utc);
-  ABSL_INTERNAL_EXPECT_TIME(bd, 2016, 3, 22, 0, 39, 14, 0, false);
-
-  tc = absl::ConvertDateTime(2013, 11, 15, 16 + 123456, 32, 14, utc);
-  EXPECT_TRUE(tc.normalized);
-  EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
-  bd = tc.pre.In(utc);
-  ABSL_INTERNAL_EXPECT_TIME(bd, 2027, 12, 16, 16, 32, 14, 0, false);
-
-  tc = absl::ConvertDateTime(2013, 11, 15 + 1234, 16, 32, 14, utc);
-  EXPECT_TRUE(tc.normalized);
-  EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
-  bd = tc.pre.In(utc);
-  ABSL_INTERNAL_EXPECT_TIME(bd, 2017, 4, 2, 16, 32, 14, 0, false);
-
-  tc = absl::ConvertDateTime(2013, 11 + 123, 15, 16, 32, 14, utc);
-  EXPECT_TRUE(tc.normalized);
-  EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
-  bd = tc.pre.In(utc);
-  ABSL_INTERNAL_EXPECT_TIME(bd, 2024, 2, 15, 16, 32, 14, 0, false);
-}
-
-TEST(TimeNormCase, ComplexUnderflow) {
-  const absl::TimeZone utc = absl::UTCTimeZone();
-
-  absl::TimeConversion tc =
-      absl::ConvertDateTime(1999, 3, 0, 0, 0, 0, utc);  // year 400
-  EXPECT_TRUE(tc.normalized);
-  EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
-  absl::Time::Breakdown bd = tc.pre.In(utc);
-  ABSL_INTERNAL_EXPECT_TIME(bd, 1999, 2, 28, 0, 0, 0, 0, false);
-
-  tc = absl::ConvertDateTime(2013, 11, 15, 16, 32, 14 - 123456789, utc);
-  EXPECT_TRUE(tc.normalized);
-  EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
-  bd = tc.pre.In(utc);
-  ABSL_INTERNAL_EXPECT_TIME(bd, 2009, 12, 17, 18, 59, 5, 0, false);
-
-  tc = absl::ConvertDateTime(2013, 11, 15, 16, 32 - 1234567, 14, utc);
-  EXPECT_TRUE(tc.normalized);
-  EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
-  bd = tc.pre.In(utc);
-  ABSL_INTERNAL_EXPECT_TIME(bd, 2011, 7, 12, 8, 25, 14, 0, false);
-
-  tc = absl::ConvertDateTime(2013, 11, 15, 16 - 123456, 32, 14, utc);
-  EXPECT_TRUE(tc.normalized);
-  EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
-  bd = tc.pre.In(utc);
-  ABSL_INTERNAL_EXPECT_TIME(bd, 1999, 10, 16, 16, 32, 14, 0, false);
-
-  tc = absl::ConvertDateTime(2013, 11, 15 - 1234, 16, 32, 14, utc);
-  EXPECT_TRUE(tc.normalized);
-  EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
-  bd = tc.pre.In(utc);
-  ABSL_INTERNAL_EXPECT_TIME(bd, 2010, 6, 30, 16, 32, 14, 0, false);
-
-  tc = absl::ConvertDateTime(2013, 11 - 123, 15, 16, 32, 14, utc);
-  EXPECT_TRUE(tc.normalized);
-  EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
-  bd = tc.pre.In(utc);
-  ABSL_INTERNAL_EXPECT_TIME(bd, 2003, 8, 15, 16, 32, 14, 0, false);
-}
-
-TEST(TimeNormCase, Mishmash) {
-  const absl::TimeZone utc = absl::UTCTimeZone();
-
-  absl::TimeConversion tc =
-      absl::ConvertDateTime(2013, 11 - 123, 15 + 1234, 16 - 123456,
-                            32 + 1234567, 14 - 123456789, utc);
-  EXPECT_TRUE(tc.normalized);
-  EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
-  absl::Time::Breakdown bd = tc.pre.In(utc);
-  ABSL_INTERNAL_EXPECT_TIME(bd, 1991, 5, 9, 3, 6, 5, 0, false);
-
-  tc = absl::ConvertDateTime(2013, 11 + 123, 15 - 1234, 16 + 123456,
-                             32 - 1234567, 14 + 123456789, utc);
-  EXPECT_TRUE(tc.normalized);
-  EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
-  bd = tc.pre.In(utc);
-  ABSL_INTERNAL_EXPECT_TIME(bd, 2036, 5, 24, 5, 58, 23, 0, false);
-
-  // Here is a normalization case we got wrong for a while.  Because the
-  // day is converted to "1" within a 400-year (146097-day) period, we
-  // didn't need to roll the month and so we didn't mark it as normalized.
-  tc = absl::ConvertDateTime(2013, 11, -146097 + 1, 16, 32, 14, utc);
-  EXPECT_TRUE(tc.normalized);
-  EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
-  bd = tc.pre.In(utc);
-  ABSL_INTERNAL_EXPECT_TIME(bd, 1613, 11, 1, 16, 32, 14, 0, false);
-
-  // Even though the month overflow compensates for the day underflow,
-  // this should still be marked as normalized.
-  tc = absl::ConvertDateTime(2013, 11 + 400 * 12, -146097 + 1, 16, 32, 14, utc);
-  EXPECT_TRUE(tc.normalized);
-  EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
-  bd = tc.pre.In(utc);
-  ABSL_INTERNAL_EXPECT_TIME(bd, 2013, 11, 1, 16, 32, 14, 0, false);
-}
-
-TEST(TimeNormCase, LeapYears) {
-  const absl::TimeZone utc = absl::UTCTimeZone();
-
-  absl::TimeConversion tc =
-      absl::ConvertDateTime(2013, 2, 28 + 1, 0, 0, 0, utc);
-  EXPECT_TRUE(tc.normalized);
-  EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
-  absl::Time::Breakdown bd = tc.pre.In(utc);
-  ABSL_INTERNAL_EXPECT_TIME(bd, 2013, 3, 1, 0, 0, 0, 0, false);
-
-  tc = absl::ConvertDateTime(2012, 2, 28 + 1, 0, 0, 0, utc);
-  EXPECT_FALSE(tc.normalized);
-  EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
-  bd = tc.pre.In(utc);
-  ABSL_INTERNAL_EXPECT_TIME(bd, 2012, 2, 29, 0, 0, 0, 0, false);
-
-  tc = absl::ConvertDateTime(2000, 2, 28 + 1, 0, 0, 0, utc);
-  EXPECT_FALSE(tc.normalized);
-  EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
-  bd = tc.pre.In(utc);
-  ABSL_INTERNAL_EXPECT_TIME(bd, 2000, 2, 29, 0, 0, 0, 0, false);
-
-  tc = absl::ConvertDateTime(1900, 2, 28 + 1, 0, 0, 0, utc);
-  EXPECT_TRUE(tc.normalized);
-  EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
-  bd = tc.pre.In(utc);
-  ABSL_INTERNAL_EXPECT_TIME(bd, 1900, 3, 1, 0, 0, 0, 0, false);
-}
-
-// Convert all the days from 1970-1-1 to 1970-1-146097 (aka 2369-12-31)
-// and check that they normalize to the expected time.  146097 days span
-// the 400-year Gregorian cycle used during normalization.
-TEST(TimeNormCase, AllTheDays) {
-  const absl::TimeZone utc = absl::UTCTimeZone();
-  absl::Time exp_time = absl::UnixEpoch();
-
-  for (int day = 1; day <= 146097; ++day) {
-    absl::TimeConversion tc = absl::ConvertDateTime(1970, 1, day, 0, 0, 0, utc);
-    EXPECT_EQ(day > 31, tc.normalized);
-    EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
-    EXPECT_EQ(exp_time, tc.pre);
-    exp_time += absl::Hours(24);
-  }
-}
-
-}  // namespace
diff --git a/absl/time/time_test.cc b/absl/time/time_test.cc
index 4f8f58a..74148d5 100644
--- a/absl/time/time_test.cc
+++ b/absl/time/time_test.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -28,6 +28,27 @@
 
 namespace {
 
+#if GTEST_USES_SIMPLE_RE
+const char kZoneAbbrRE[] = ".*";  // just punt
+#else
+const char kZoneAbbrRE[] = "[A-Za-z]{3,4}|[-+][0-9]{2}([0-9]{2})?";
+#endif
+
+// This helper is a macro so that failed expectations show up with the
+// correct line numbers.
+#define EXPECT_CIVIL_INFO(ci, y, m, d, h, min, s, off, isdst)      \
+  do {                                                             \
+    EXPECT_EQ(y, ci.cs.year());                                    \
+    EXPECT_EQ(m, ci.cs.month());                                   \
+    EXPECT_EQ(d, ci.cs.day());                                     \
+    EXPECT_EQ(h, ci.cs.hour());                                    \
+    EXPECT_EQ(min, ci.cs.minute());                                \
+    EXPECT_EQ(s, ci.cs.second());                                  \
+    EXPECT_EQ(off, ci.offset);                                     \
+    EXPECT_EQ(isdst, ci.is_dst);                                   \
+    EXPECT_THAT(ci.zone_abbr, testing::MatchesRegex(kZoneAbbrRE)); \
+  } while (0)
+
 // A gMock matcher to match timespec values. Use this matcher like:
 // timespec ts1, ts2;
 // EXPECT_THAT(ts1, TimespecMatcher(ts2));
@@ -84,10 +105,10 @@
 }
 
 TEST(Time, UnixEpoch) {
-  absl::Time::Breakdown bd = absl::UnixEpoch().In(absl::UTCTimeZone());
-  ABSL_INTERNAL_EXPECT_TIME(bd, 1970, 1, 1, 0, 0, 0, 0, false);
-  EXPECT_EQ(absl::ZeroDuration(), bd.subsecond);
-  EXPECT_EQ(4, bd.weekday);  // Thursday
+  const auto ci = absl::UTCTimeZone().At(absl::UnixEpoch());
+  EXPECT_EQ(absl::CivilSecond(1970, 1, 1, 0, 0, 0), ci.cs);
+  EXPECT_EQ(absl::ZeroDuration(), ci.subsecond);
+  EXPECT_EQ(absl::Weekday::thursday, absl::GetWeekday(absl::CivilDay(ci.cs)));
 }
 
 TEST(Time, Breakdown) {
@@ -95,26 +116,26 @@
   absl::Time t = absl::UnixEpoch();
 
   // The Unix epoch as seen in NYC.
-  absl::Time::Breakdown bd = t.In(tz);
-  ABSL_INTERNAL_EXPECT_TIME(bd, 1969, 12, 31, 19, 0, 0, -18000, false);
-  EXPECT_EQ(absl::ZeroDuration(), bd.subsecond);
-  EXPECT_EQ(3, bd.weekday);  // Wednesday
+  auto ci = tz.At(t);
+  EXPECT_CIVIL_INFO(ci, 1969, 12, 31, 19, 0, 0, -18000, false);
+  EXPECT_EQ(absl::ZeroDuration(), ci.subsecond);
+  EXPECT_EQ(absl::Weekday::wednesday, absl::GetWeekday(absl::CivilDay(ci.cs)));
 
   // Just before the epoch.
   t -= absl::Nanoseconds(1);
-  bd = t.In(tz);
-  ABSL_INTERNAL_EXPECT_TIME(bd, 1969, 12, 31, 18, 59, 59, -18000, false);
-  EXPECT_EQ(absl::Nanoseconds(999999999), bd.subsecond);
-  EXPECT_EQ(3, bd.weekday);  // Wednesday
+  ci = tz.At(t);
+  EXPECT_CIVIL_INFO(ci, 1969, 12, 31, 18, 59, 59, -18000, false);
+  EXPECT_EQ(absl::Nanoseconds(999999999), ci.subsecond);
+  EXPECT_EQ(absl::Weekday::wednesday, absl::GetWeekday(absl::CivilDay(ci.cs)));
 
   // Some time later.
   t += absl::Hours(24) * 2735;
   t += absl::Hours(18) + absl::Minutes(30) + absl::Seconds(15) +
        absl::Nanoseconds(9);
-  bd = t.In(tz);
-  ABSL_INTERNAL_EXPECT_TIME(bd, 1977, 6, 28, 14, 30, 15, -14400, true);
-  EXPECT_EQ(8, bd.subsecond / absl::Nanoseconds(1));
-  EXPECT_EQ(2, bd.weekday);  // Tuesday
+  ci = tz.At(t);
+  EXPECT_CIVIL_INFO(ci, 1977, 6, 28, 14, 30, 15, -14400, true);
+  EXPECT_EQ(8, ci.subsecond / absl::Nanoseconds(1));
+  EXPECT_EQ(absl::Weekday::tuesday, absl::GetWeekday(absl::CivilDay(ci.cs)));
 }
 
 TEST(Time, AdditiveOperators) {
@@ -550,67 +571,63 @@
             absl::ToChronoTime(absl::UnixEpoch() - tick));
 }
 
-TEST(Time, ConvertDateTime) {
-  const absl::TimeZone utc = absl::UTCTimeZone();
-  const absl::TimeZone goog =
-      absl::time_internal::LoadTimeZone("America/Los_Angeles");
+TEST(Time, TimeZoneAt) {
   const absl::TimeZone nyc =
       absl::time_internal::LoadTimeZone("America/New_York");
   const std::string fmt = "%a, %e %b %Y %H:%M:%S %z (%Z)";
 
-  // A simple case of normalization.
-  absl::TimeConversion oct32 = ConvertDateTime(2013, 10, 32, 8, 30, 0, goog);
-  EXPECT_TRUE(oct32.normalized);
-  EXPECT_EQ(absl::TimeConversion::UNIQUE, oct32.kind);
-  absl::TimeConversion nov01 = ConvertDateTime(2013, 11, 1, 8, 30, 0, goog);
-  EXPECT_FALSE(nov01.normalized);
-  EXPECT_EQ(absl::TimeConversion::UNIQUE, nov01.kind);
-  EXPECT_EQ(oct32.pre, nov01.pre);
-  EXPECT_EQ("Fri,  1 Nov 2013 08:30:00 -0700 (PDT)",
-            absl::FormatTime(fmt, nov01.pre, goog));
+  // A non-transition where the civil time is unique.
+  absl::CivilSecond nov01(2013, 11, 1, 8, 30, 0);
+  const auto nov01_ci = nyc.At(nov01);
+  EXPECT_EQ(absl::TimeZone::TimeInfo::UNIQUE, nov01_ci.kind);
+  EXPECT_EQ("Fri,  1 Nov 2013 08:30:00 -0400 (EDT)",
+            absl::FormatTime(fmt, nov01_ci.pre, nyc));
+  EXPECT_EQ(nov01_ci.pre, nov01_ci.trans);
+  EXPECT_EQ(nov01_ci.pre, nov01_ci.post);
+  EXPECT_EQ(nov01_ci.pre, absl::FromCivil(nov01, nyc));
 
   // A Spring DST transition, when there is a gap in civil time
   // and we prefer the later of the possible interpretations of a
   // non-existent time.
-  absl::TimeConversion mar13 = ConvertDateTime(2011, 3, 13, 2, 15, 0, nyc);
-  EXPECT_FALSE(mar13.normalized);
-  EXPECT_EQ(absl::TimeConversion::SKIPPED, mar13.kind);
+  absl::CivilSecond mar13(2011, 3, 13, 2, 15, 0);
+  const auto mar_ci = nyc.At(mar13);
+  EXPECT_EQ(absl::TimeZone::TimeInfo::SKIPPED, mar_ci.kind);
   EXPECT_EQ("Sun, 13 Mar 2011 03:15:00 -0400 (EDT)",
-            absl::FormatTime(fmt, mar13.pre, nyc));
+            absl::FormatTime(fmt, mar_ci.pre, nyc));
   EXPECT_EQ("Sun, 13 Mar 2011 03:00:00 -0400 (EDT)",
-            absl::FormatTime(fmt, mar13.trans, nyc));
+            absl::FormatTime(fmt, mar_ci.trans, nyc));
   EXPECT_EQ("Sun, 13 Mar 2011 01:15:00 -0500 (EST)",
-            absl::FormatTime(fmt, mar13.post, nyc));
-  EXPECT_EQ(mar13.pre, absl::FromDateTime(2011, 3, 13, 2, 15, 0, nyc));
+            absl::FormatTime(fmt, mar_ci.post, nyc));
+  EXPECT_EQ(mar_ci.trans, absl::FromCivil(mar13, nyc));
 
   // A Fall DST transition, when civil times are repeated and
   // we prefer the earlier of the possible interpretations of an
   // ambiguous time.
-  absl::TimeConversion nov06 = ConvertDateTime(2011, 11, 6, 1, 15, 0, nyc);
-  EXPECT_FALSE(nov06.normalized);
-  EXPECT_EQ(absl::TimeConversion::REPEATED, nov06.kind);
+  absl::CivilSecond nov06(2011, 11, 6, 1, 15, 0);
+  const auto nov06_ci = nyc.At(nov06);
+  EXPECT_EQ(absl::TimeZone::TimeInfo::REPEATED, nov06_ci.kind);
   EXPECT_EQ("Sun,  6 Nov 2011 01:15:00 -0400 (EDT)",
-            absl::FormatTime(fmt, nov06.pre, nyc));
+            absl::FormatTime(fmt, nov06_ci.pre, nyc));
   EXPECT_EQ("Sun,  6 Nov 2011 01:00:00 -0500 (EST)",
-            absl::FormatTime(fmt, nov06.trans, nyc));
+            absl::FormatTime(fmt, nov06_ci.trans, nyc));
   EXPECT_EQ("Sun,  6 Nov 2011 01:15:00 -0500 (EST)",
-            absl::FormatTime(fmt, nov06.post, nyc));
-  EXPECT_EQ(nov06.pre, absl::FromDateTime(2011, 11, 6, 1, 15, 0, nyc));
+            absl::FormatTime(fmt, nov06_ci.post, nyc));
+  EXPECT_EQ(nov06_ci.pre, absl::FromCivil(nov06, nyc));
 
   // Check that (time_t) -1 is handled correctly.
-  absl::TimeConversion minus1 = ConvertDateTime(1969, 12, 31, 18, 59, 59, nyc);
-  EXPECT_FALSE(minus1.normalized);
-  EXPECT_EQ(absl::TimeConversion::UNIQUE, minus1.kind);
-  EXPECT_EQ(-1, absl::ToTimeT(minus1.pre));
+  absl::CivilSecond minus1(1969, 12, 31, 18, 59, 59);
+  const auto minus1_cl = nyc.At(minus1);
+  EXPECT_EQ(absl::TimeZone::TimeInfo::UNIQUE, minus1_cl.kind);
+  EXPECT_EQ(-1, absl::ToTimeT(minus1_cl.pre));
   EXPECT_EQ("Wed, 31 Dec 1969 18:59:59 -0500 (EST)",
-            absl::FormatTime(fmt, minus1.pre, nyc));
+            absl::FormatTime(fmt, minus1_cl.pre, nyc));
   EXPECT_EQ("Wed, 31 Dec 1969 23:59:59 +0000 (UTC)",
-            absl::FormatTime(fmt, minus1.pre, utc));
+            absl::FormatTime(fmt, minus1_cl.pre, absl::UTCTimeZone()));
 }
 
-// FromDateTime(year, mon, day, hour, min, sec, UTCTimeZone()) has
-// a specialized fastpath implementation which we exercise here.
-TEST(Time, FromDateTimeUTC) {
+// FromCivil(CivilSecond(year, mon, day, hour, min, sec), UTCTimeZone())
+// has a specialized fastpath implementation, which we exercise here.
+TEST(Time, FromCivilUTC) {
   const absl::TimeZone utc = absl::UTCTimeZone();
   const std::string fmt = "%a, %e %b %Y %H:%M:%S %z (%Z)";
   const int kMax = std::numeric_limits<int>::max();
@@ -618,65 +635,36 @@
   absl::Time t;
 
   // 292091940881 is the last positive year to use the fastpath.
-  t = absl::FromDateTime(292091940881, kMax, kMax, kMax, kMax, kMax, utc);
+  t = absl::FromCivil(
+      absl::CivilSecond(292091940881, kMax, kMax, kMax, kMax, kMax), utc);
   EXPECT_EQ("Fri, 25 Nov 292277026596 12:21:07 +0000 (UTC)",
             absl::FormatTime(fmt, t, utc));
-  t = absl::FromDateTime(292091940882, kMax, kMax, kMax, kMax, kMax, utc);
-  EXPECT_EQ("infinite-future", absl::FormatTime(fmt, t, utc));  // no overflow
-  t = absl::FromDateTime(
-      std::numeric_limits<int64_t>::max(), kMax, kMax, kMax, kMax, kMax, utc);
+  t = absl::FromCivil(
+      absl::CivilSecond(292091940882, kMax, kMax, kMax, kMax, kMax), utc);
   EXPECT_EQ("infinite-future", absl::FormatTime(fmt, t, utc));  // no overflow
 
   // -292091936940 is the last negative year to use the fastpath.
-  t = absl::FromDateTime(-292091936940, kMin, kMin, kMin, kMin, kMin, utc);
+  t = absl::FromCivil(
+      absl::CivilSecond(-292091936940, kMin, kMin, kMin, kMin, kMin), utc);
   EXPECT_EQ("Fri,  1 Nov -292277022657 10:37:52 +0000 (UTC)",
             absl::FormatTime(fmt, t, utc));
-  t = absl::FromDateTime(-292091936941, kMin, kMin, kMin, kMin, kMin, utc);
+  t = absl::FromCivil(
+      absl::CivilSecond(-292091936941, kMin, kMin, kMin, kMin, kMin), utc);
   EXPECT_EQ("infinite-past", absl::FormatTime(fmt, t, utc));  // no underflow
-  t = absl::FromDateTime(
-      std::numeric_limits<int64_t>::min(), kMin, kMin, kMin, kMin, kMin, utc);
-  EXPECT_EQ("infinite-past", absl::FormatTime(fmt, t, utc));  // no overflow
 
   // Check that we're counting leap years correctly.
-  t = absl::FromDateTime(1900, 2, 28, 23, 59, 59, utc);
+  t = absl::FromCivil(absl::CivilSecond(1900, 2, 28, 23, 59, 59), utc);
   EXPECT_EQ("Wed, 28 Feb 1900 23:59:59 +0000 (UTC)",
             absl::FormatTime(fmt, t, utc));
-  t = absl::FromDateTime(1900, 3, 1, 0, 0, 0, utc);
+  t = absl::FromCivil(absl::CivilSecond(1900, 3, 1, 0, 0, 0), utc);
   EXPECT_EQ("Thu,  1 Mar 1900 00:00:00 +0000 (UTC)",
             absl::FormatTime(fmt, t, utc));
-  t = absl::FromDateTime(2000, 2, 29, 23, 59, 59, utc);
+  t = absl::FromCivil(absl::CivilSecond(2000, 2, 29, 23, 59, 59), utc);
   EXPECT_EQ("Tue, 29 Feb 2000 23:59:59 +0000 (UTC)",
             absl::FormatTime(fmt, t, utc));
-  t = absl::FromDateTime(2000, 3, 1, 0, 0, 0, utc);
+  t = absl::FromCivil(absl::CivilSecond(2000, 3, 1, 0, 0, 0), utc);
   EXPECT_EQ("Wed,  1 Mar 2000 00:00:00 +0000 (UTC)",
             absl::FormatTime(fmt, t, utc));
-
-  // Check normalization.
-  const std::string ymdhms = "%Y-%m-%d %H:%M:%S";
-  t = absl::FromDateTime(2015, 1, 1, 0, 0, 60, utc);
-  EXPECT_EQ("2015-01-01 00:01:00", absl::FormatTime(ymdhms, t, utc));
-  t = absl::FromDateTime(2015, 1, 1, 0, 60, 0, utc);
-  EXPECT_EQ("2015-01-01 01:00:00", absl::FormatTime(ymdhms, t, utc));
-  t = absl::FromDateTime(2015, 1, 1, 24, 0, 0, utc);
-  EXPECT_EQ("2015-01-02 00:00:00", absl::FormatTime(ymdhms, t, utc));
-  t = absl::FromDateTime(2015, 1, 32, 0, 0, 0, utc);
-  EXPECT_EQ("2015-02-01 00:00:00", absl::FormatTime(ymdhms, t, utc));
-  t = absl::FromDateTime(2015, 13, 1, 0, 0, 0, utc);
-  EXPECT_EQ("2016-01-01 00:00:00", absl::FormatTime(ymdhms, t, utc));
-  t = absl::FromDateTime(2015, 13, 32, 60, 60, 60, utc);
-  EXPECT_EQ("2016-02-03 13:01:00", absl::FormatTime(ymdhms, t, utc));
-  t = absl::FromDateTime(2015, 1, 1, 0, 0, -1, utc);
-  EXPECT_EQ("2014-12-31 23:59:59", absl::FormatTime(ymdhms, t, utc));
-  t = absl::FromDateTime(2015, 1, 1, 0, -1, 0, utc);
-  EXPECT_EQ("2014-12-31 23:59:00", absl::FormatTime(ymdhms, t, utc));
-  t = absl::FromDateTime(2015, 1, 1, -1, 0, 0, utc);
-  EXPECT_EQ("2014-12-31 23:00:00", absl::FormatTime(ymdhms, t, utc));
-  t = absl::FromDateTime(2015, 1, -1, 0, 0, 0, utc);
-  EXPECT_EQ("2014-12-30 00:00:00", absl::FormatTime(ymdhms, t, utc));
-  t = absl::FromDateTime(2015, -1, 1, 0, 0, 0, utc);
-  EXPECT_EQ("2014-11-01 00:00:00", absl::FormatTime(ymdhms, t, utc));
-  t = absl::FromDateTime(2015, -1, -1, -1, -1, -1, utc);
-  EXPECT_EQ("2014-10-29 22:58:59", absl::FormatTime(ymdhms, t, utc));
 }
 
 TEST(Time, ToTM) {
@@ -684,8 +672,10 @@
 
   // Compares the results of ToTM() to gmtime_r() for lots of times over the
   // course of a few days.
-  const absl::Time start = absl::FromDateTime(2014, 1, 2, 3, 4, 5, utc);
-  const absl::Time end = absl::FromDateTime(2014, 1, 5, 3, 4, 5, utc);
+  const absl::Time start =
+      absl::FromCivil(absl::CivilSecond(2014, 1, 2, 3, 4, 5), utc);
+  const absl::Time end =
+      absl::FromCivil(absl::CivilSecond(2014, 1, 5, 3, 4, 5), utc);
   for (absl::Time t = start; t < end; t += absl::Seconds(30)) {
     const struct tm tm_bt = ToTM(t, utc);
     const time_t tt = absl::ToTimeT(t);
@@ -711,12 +701,12 @@
   // Checks that the tm_isdst field is correct when in standard time.
   const absl::TimeZone nyc =
       absl::time_internal::LoadTimeZone("America/New_York");
-  absl::Time t = absl::FromDateTime(2014, 3, 1, 0, 0, 0, nyc);
+  absl::Time t = absl::FromCivil(absl::CivilSecond(2014, 3, 1, 0, 0, 0), nyc);
   struct tm tm = ToTM(t, nyc);
   EXPECT_FALSE(tm.tm_isdst);
 
   // Checks that the tm_isdst field is correct when in daylight time.
-  t = absl::FromDateTime(2014, 4, 1, 0, 0, 0, nyc);
+  t = absl::FromCivil(absl::CivilSecond(2014, 4, 1, 0, 0, 0), nyc);
   tm = ToTM(t, nyc);
   EXPECT_TRUE(tm.tm_isdst);
 
@@ -808,8 +798,8 @@
       absl::time_internal::LoadTimeZone("America/New_York");
 
   // Test round-tripping across a skipped transition
-  absl::Time start = absl::FromDateTime(2014, 3, 9, 0, 0, 0, nyc);
-  absl::Time end = absl::FromDateTime(2014, 3, 9, 4, 0, 0, nyc);
+  absl::Time start = absl::FromCivil(absl::CivilHour(2014, 3, 9, 0), nyc);
+  absl::Time end = absl::FromCivil(absl::CivilHour(2014, 3, 9, 4), nyc);
   for (absl::Time t = start; t < end; t += absl::Minutes(1)) {
     struct tm tm = ToTM(t, nyc);
     absl::Time rt = FromTM(tm, nyc);
@@ -817,8 +807,8 @@
   }
 
   // Test round-tripping across an ambiguous transition
-  start = absl::FromDateTime(2014, 11, 2, 0, 0, 0, nyc);
-  end = absl::FromDateTime(2014, 11, 2, 4, 0, 0, nyc);
+  start = absl::FromCivil(absl::CivilHour(2014, 11, 2, 0), nyc);
+  end = absl::FromCivil(absl::CivilHour(2014, 11, 2, 4), nyc);
   for (absl::Time t = start; t < end; t += absl::Minutes(1)) {
     struct tm tm = ToTM(t, nyc);
     absl::Time rt = FromTM(tm, nyc);
@@ -826,8 +816,8 @@
   }
 
   // Test round-tripping of unique instants crossing a day boundary
-  start = absl::FromDateTime(2014, 6, 27, 22, 0, 0, nyc);
-  end = absl::FromDateTime(2014, 6, 28, 4, 0, 0, nyc);
+  start = absl::FromCivil(absl::CivilHour(2014, 6, 27, 22), nyc);
+  end = absl::FromCivil(absl::CivilHour(2014, 6, 28, 4), nyc);
   for (absl::Time t = start; t < end; t += absl::Minutes(1)) {
     struct tm tm = ToTM(t, nyc);
     absl::Time rt = FromTM(tm, nyc);
@@ -980,27 +970,27 @@
   EXPECT_EQ(min_timespec_sec, ts.tv_sec);
   EXPECT_EQ(0, ts.tv_nsec);
 
-  // Checks how Time::In() saturates on infinities.
-  absl::Time::Breakdown bd = absl::InfiniteFuture().In(utc);
-  ABSL_INTERNAL_EXPECT_TIME(bd, std::numeric_limits<int64_t>::max(), 12, 31, 23,
+  // Checks how TimeZone::At() saturates on infinities.
+  auto ci = utc.At(absl::InfiniteFuture());
+  EXPECT_CIVIL_INFO(ci, std::numeric_limits<int64_t>::max(), 12, 31, 23,
                             59, 59, 0, false);
-  EXPECT_EQ(absl::InfiniteDuration(), bd.subsecond);
-  EXPECT_EQ(4, bd.weekday);  // Thursday
-  EXPECT_EQ(365, bd.yearday);
-  EXPECT_STREQ("-00", bd.zone_abbr);  // artifact of absl::Time::In()
-  bd = absl::InfinitePast().In(utc);
-  ABSL_INTERNAL_EXPECT_TIME(bd, std::numeric_limits<int64_t>::min(), 1, 1, 0, 0,
+  EXPECT_EQ(absl::InfiniteDuration(), ci.subsecond);
+  EXPECT_EQ(absl::Weekday::thursday, absl::GetWeekday(absl::CivilDay(ci.cs)));
+  EXPECT_EQ(365, absl::GetYearDay(absl::CivilDay(ci.cs)));
+  EXPECT_STREQ("-00", ci.zone_abbr);  // artifact of TimeZone::At()
+  ci = utc.At(absl::InfinitePast());
+  EXPECT_CIVIL_INFO(ci, std::numeric_limits<int64_t>::min(), 1, 1, 0, 0,
                             0, 0, false);
-  EXPECT_EQ(-absl::InfiniteDuration(), bd.subsecond);
-  EXPECT_EQ(7, bd.weekday);  // Sunday
-  EXPECT_EQ(1, bd.yearday);
-  EXPECT_STREQ("-00", bd.zone_abbr);  // artifact of absl::Time::In()
+  EXPECT_EQ(-absl::InfiniteDuration(), ci.subsecond);
+  EXPECT_EQ(absl::Weekday::sunday, absl::GetWeekday(absl::CivilDay(ci.cs)));
+  EXPECT_EQ(1, absl::GetYearDay(absl::CivilDay(ci.cs)));
+  EXPECT_STREQ("-00", ci.zone_abbr);  // artifact of TimeZone::At()
 
   // Approach the maximal Time value from below.
-  t = absl::FromDateTime(292277026596, 12, 4, 15, 30, 6, utc);
+  t = absl::FromCivil(absl::CivilSecond(292277026596, 12, 4, 15, 30, 6), utc);
   EXPECT_EQ("292277026596-12-04T15:30:06+00:00",
             absl::FormatTime(absl::RFC3339_full, t, utc));
-  t = absl::FromDateTime(292277026596, 12, 4, 15, 30, 7, utc);
+  t = absl::FromCivil(absl::CivilSecond(292277026596, 12, 4, 15, 30, 7), utc);
   EXPECT_EQ("292277026596-12-04T15:30:07+00:00",
             absl::FormatTime(absl::RFC3339_full, t, utc));
   EXPECT_EQ(
@@ -1008,21 +998,21 @@
 
   // Checks that we can also get the maximal Time value for a far-east zone.
   const absl::TimeZone plus14 = absl::FixedTimeZone(14 * 60 * 60);
-  t = absl::FromDateTime(292277026596, 12, 5, 5, 30, 7, plus14);
+  t = absl::FromCivil(absl::CivilSecond(292277026596, 12, 5, 5, 30, 7), plus14);
   EXPECT_EQ("292277026596-12-05T05:30:07+14:00",
             absl::FormatTime(absl::RFC3339_full, t, plus14));
   EXPECT_EQ(
       absl::UnixEpoch() + absl::Seconds(std::numeric_limits<int64_t>::max()), t);
 
   // One second later should push us to infinity.
-  t = absl::FromDateTime(292277026596, 12, 4, 15, 30, 8, utc);
+  t = absl::FromCivil(absl::CivilSecond(292277026596, 12, 4, 15, 30, 8), utc);
   EXPECT_EQ("infinite-future", absl::FormatTime(absl::RFC3339_full, t, utc));
 
   // Approach the minimal Time value from above.
-  t = absl::FromDateTime(-292277022657, 1, 27, 8, 29, 53, utc);
+  t = absl::FromCivil(absl::CivilSecond(-292277022657, 1, 27, 8, 29, 53), utc);
   EXPECT_EQ("-292277022657-01-27T08:29:53+00:00",
             absl::FormatTime(absl::RFC3339_full, t, utc));
-  t = absl::FromDateTime(-292277022657, 1, 27, 8, 29, 52, utc);
+  t = absl::FromCivil(absl::CivilSecond(-292277022657, 1, 27, 8, 29, 52), utc);
   EXPECT_EQ("-292277022657-01-27T08:29:52+00:00",
             absl::FormatTime(absl::RFC3339_full, t, utc));
   EXPECT_EQ(
@@ -1030,14 +1020,15 @@
 
   // Checks that we can also get the minimal Time value for a far-west zone.
   const absl::TimeZone minus12 = absl::FixedTimeZone(-12 * 60 * 60);
-  t = absl::FromDateTime(-292277022657, 1, 26, 20, 29, 52, minus12);
+  t = absl::FromCivil(absl::CivilSecond(-292277022657, 1, 26, 20, 29, 52),
+                      minus12);
   EXPECT_EQ("-292277022657-01-26T20:29:52-12:00",
             absl::FormatTime(absl::RFC3339_full, t, minus12));
   EXPECT_EQ(
       absl::UnixEpoch() + absl::Seconds(std::numeric_limits<int64_t>::min()), t);
 
   // One second before should push us to -infinity.
-  t = absl::FromDateTime(-292277022657, 1, 27, 8, 29, 51, utc);
+  t = absl::FromCivil(absl::CivilSecond(-292277022657, 1, 27, 8, 29, 51), utc);
   EXPECT_EQ("infinite-past", absl::FormatTime(absl::RFC3339_full, t, utc));
 }
 
@@ -1051,38 +1042,160 @@
       absl::time_internal::LoadTimeZone("America/New_York");
   const absl::Time max =
       absl::FromUnixSeconds(std::numeric_limits<int64_t>::max());
-  absl::Time::Breakdown bd;
+  absl::TimeZone::CivilInfo ci;
   absl::Time t;
 
   // The maximal time converted in each zone.
-  bd = max.In(syd);
-  ABSL_INTERNAL_EXPECT_TIME(bd, 292277026596, 12, 5, 2, 30, 7, 39600, true);
-  t = absl::FromDateTime(292277026596, 12, 5, 2, 30, 7, syd);
+  ci = syd.At(max);
+  EXPECT_CIVIL_INFO(ci, 292277026596, 12, 5, 2, 30, 7, 39600, true);
+  t = absl::FromCivil(absl::CivilSecond(292277026596, 12, 5, 2, 30, 7), syd);
   EXPECT_EQ(max, t);
-  bd = max.In(nyc);
-  ABSL_INTERNAL_EXPECT_TIME(bd, 292277026596, 12, 4, 10, 30, 7, -18000, false);
-  t = absl::FromDateTime(292277026596, 12, 4, 10, 30, 7, nyc);
+  ci = nyc.At(max);
+  EXPECT_CIVIL_INFO(ci, 292277026596, 12, 4, 10, 30, 7, -18000, false);
+  t = absl::FromCivil(absl::CivilSecond(292277026596, 12, 4, 10, 30, 7), nyc);
   EXPECT_EQ(max, t);
 
   // One second later should push us to infinity.
-  t = absl::FromDateTime(292277026596, 12, 5, 2, 30, 8, syd);
+  t = absl::FromCivil(absl::CivilSecond(292277026596, 12, 5, 2, 30, 8), syd);
   EXPECT_EQ(absl::InfiniteFuture(), t);
-  t = absl::FromDateTime(292277026596, 12, 4, 10, 30, 8, nyc);
+  t = absl::FromCivil(absl::CivilSecond(292277026596, 12, 4, 10, 30, 8), nyc);
   EXPECT_EQ(absl::InfiniteFuture(), t);
 
   // And we should stick there.
-  t = absl::FromDateTime(292277026596, 12, 5, 2, 30, 9, syd);
+  t = absl::FromCivil(absl::CivilSecond(292277026596, 12, 5, 2, 30, 9), syd);
   EXPECT_EQ(absl::InfiniteFuture(), t);
-  t = absl::FromDateTime(292277026596, 12, 4, 10, 30, 9, nyc);
+  t = absl::FromCivil(absl::CivilSecond(292277026596, 12, 4, 10, 30, 9), nyc);
   EXPECT_EQ(absl::InfiniteFuture(), t);
 
   // All the way up to a saturated date/time, without overflow.
-  t = absl::FromDateTime(
-      std::numeric_limits<int64_t>::max(), 12, 31, 23, 59, 59, syd);
+  t = absl::FromCivil(absl::CivilSecond::max(), syd);
   EXPECT_EQ(absl::InfiniteFuture(), t);
-  t = absl::FromDateTime(
-      std::numeric_limits<int64_t>::max(), 12, 31, 23, 59, 59, nyc);
+  t = absl::FromCivil(absl::CivilSecond::max(), nyc);
   EXPECT_EQ(absl::InfiniteFuture(), t);
 }
 
+TEST(Time, FromCivilAlignment) {
+  const absl::TimeZone utc = absl::UTCTimeZone();
+  const absl::CivilSecond cs(2015, 2, 3, 4, 5, 6);
+  absl::Time t = absl::FromCivil(cs, utc);
+  EXPECT_EQ("2015-02-03T04:05:06+00:00", absl::FormatTime(t, utc));
+  t = absl::FromCivil(absl::CivilMinute(cs), utc);
+  EXPECT_EQ("2015-02-03T04:05:00+00:00", absl::FormatTime(t, utc));
+  t = absl::FromCivil(absl::CivilHour(cs), utc);
+  EXPECT_EQ("2015-02-03T04:00:00+00:00", absl::FormatTime(t, utc));
+  t = absl::FromCivil(absl::CivilDay(cs), utc);
+  EXPECT_EQ("2015-02-03T00:00:00+00:00", absl::FormatTime(t, utc));
+  t = absl::FromCivil(absl::CivilMonth(cs), utc);
+  EXPECT_EQ("2015-02-01T00:00:00+00:00", absl::FormatTime(t, utc));
+  t = absl::FromCivil(absl::CivilYear(cs), utc);
+  EXPECT_EQ("2015-01-01T00:00:00+00:00", absl::FormatTime(t, utc));
+}
+
+TEST(Time, LegacyDateTime) {
+  const absl::TimeZone utc = absl::UTCTimeZone();
+  const std::string ymdhms = "%Y-%m-%d %H:%M:%S";
+  const int kMax = std::numeric_limits<int>::max();
+  const int kMin = std::numeric_limits<int>::min();
+  absl::Time t;
+
+  t = absl::FromDateTime(std::numeric_limits<absl::civil_year_t>::max(),
+                         kMax, kMax, kMax, kMax, kMax, utc);
+  EXPECT_EQ("infinite-future",
+            absl::FormatTime(ymdhms, t, utc));  // no overflow
+  t = absl::FromDateTime(std::numeric_limits<absl::civil_year_t>::min(),
+                         kMin, kMin, kMin, kMin, kMin, utc);
+  EXPECT_EQ("infinite-past",
+            absl::FormatTime(ymdhms, t, utc));  // no overflow
+
+  // Check normalization.
+  EXPECT_TRUE(absl::ConvertDateTime(2013, 10, 32, 8, 30, 0, utc).normalized);
+  t = absl::FromDateTime(2015, 1, 1, 0, 0, 60, utc);
+  EXPECT_EQ("2015-01-01 00:01:00", absl::FormatTime(ymdhms, t, utc));
+  t = absl::FromDateTime(2015, 1, 1, 0, 60, 0, utc);
+  EXPECT_EQ("2015-01-01 01:00:00", absl::FormatTime(ymdhms, t, utc));
+  t = absl::FromDateTime(2015, 1, 1, 24, 0, 0, utc);
+  EXPECT_EQ("2015-01-02 00:00:00", absl::FormatTime(ymdhms, t, utc));
+  t = absl::FromDateTime(2015, 1, 32, 0, 0, 0, utc);
+  EXPECT_EQ("2015-02-01 00:00:00", absl::FormatTime(ymdhms, t, utc));
+  t = absl::FromDateTime(2015, 13, 1, 0, 0, 0, utc);
+  EXPECT_EQ("2016-01-01 00:00:00", absl::FormatTime(ymdhms, t, utc));
+  t = absl::FromDateTime(2015, 13, 32, 60, 60, 60, utc);
+  EXPECT_EQ("2016-02-03 13:01:00", absl::FormatTime(ymdhms, t, utc));
+  t = absl::FromDateTime(2015, 1, 1, 0, 0, -1, utc);
+  EXPECT_EQ("2014-12-31 23:59:59", absl::FormatTime(ymdhms, t, utc));
+  t = absl::FromDateTime(2015, 1, 1, 0, -1, 0, utc);
+  EXPECT_EQ("2014-12-31 23:59:00", absl::FormatTime(ymdhms, t, utc));
+  t = absl::FromDateTime(2015, 1, 1, -1, 0, 0, utc);
+  EXPECT_EQ("2014-12-31 23:00:00", absl::FormatTime(ymdhms, t, utc));
+  t = absl::FromDateTime(2015, 1, -1, 0, 0, 0, utc);
+  EXPECT_EQ("2014-12-30 00:00:00", absl::FormatTime(ymdhms, t, utc));
+  t = absl::FromDateTime(2015, -1, 1, 0, 0, 0, utc);
+  EXPECT_EQ("2014-11-01 00:00:00", absl::FormatTime(ymdhms, t, utc));
+  t = absl::FromDateTime(2015, -1, -1, -1, -1, -1, utc);
+  EXPECT_EQ("2014-10-29 22:58:59", absl::FormatTime(ymdhms, t, utc));
+}
+
+TEST(Time, NextTransitionUTC) {
+  const auto tz = absl::UTCTimeZone();
+  absl::TimeZone::CivilTransition trans;
+
+  auto t = absl::InfinitePast();
+  EXPECT_FALSE(tz.NextTransition(t, &trans));
+
+  t = absl::InfiniteFuture();
+  EXPECT_FALSE(tz.NextTransition(t, &trans));
+}
+
+TEST(Time, PrevTransitionUTC) {
+  const auto tz = absl::UTCTimeZone();
+  absl::TimeZone::CivilTransition trans;
+
+  auto t = absl::InfiniteFuture();
+  EXPECT_FALSE(tz.PrevTransition(t, &trans));
+
+  t = absl::InfinitePast();
+  EXPECT_FALSE(tz.PrevTransition(t, &trans));
+}
+
+TEST(Time, NextTransitionNYC) {
+  const auto tz = absl::time_internal::LoadTimeZone("America/New_York");
+  absl::TimeZone::CivilTransition trans;
+
+  auto t = absl::FromCivil(absl::CivilSecond(2018, 6, 30, 0, 0, 0), tz);
+  EXPECT_TRUE(tz.NextTransition(t, &trans));
+  EXPECT_EQ(absl::CivilSecond(2018, 11, 4, 2, 0, 0), trans.from);
+  EXPECT_EQ(absl::CivilSecond(2018, 11, 4, 1, 0, 0), trans.to);
+
+  t = absl::InfiniteFuture();
+  EXPECT_FALSE(tz.NextTransition(t, &trans));
+
+  t = absl::InfinitePast();
+  EXPECT_TRUE(tz.NextTransition(t, &trans));
+  if (trans.from == absl::CivilSecond(1918, 03, 31, 2, 0, 0)) {
+    // It looks like the tzdata is only 32 bit (probably macOS),
+    // which bottoms out at 1901-12-13T20:45:52+00:00.
+    EXPECT_EQ(absl::CivilSecond(1918, 3, 31, 3, 0, 0), trans.to);
+  } else {
+    EXPECT_EQ(absl::CivilSecond(1883, 11, 18, 12, 3, 58), trans.from);
+    EXPECT_EQ(absl::CivilSecond(1883, 11, 18, 12, 0, 0), trans.to);
+  }
+}
+
+TEST(Time, PrevTransitionNYC) {
+  const auto tz = absl::time_internal::LoadTimeZone("America/New_York");
+  absl::TimeZone::CivilTransition trans;
+
+  auto t = absl::FromCivil(absl::CivilSecond(2018, 6, 30, 0, 0, 0), tz);
+  EXPECT_TRUE(tz.PrevTransition(t, &trans));
+  EXPECT_EQ(absl::CivilSecond(2018, 3, 11, 2, 0, 0), trans.from);
+  EXPECT_EQ(absl::CivilSecond(2018, 3, 11, 3, 0, 0), trans.to);
+
+  t = absl::InfinitePast();
+  EXPECT_FALSE(tz.PrevTransition(t, &trans));
+
+  t = absl::InfiniteFuture();
+  EXPECT_TRUE(tz.PrevTransition(t, &trans));
+  // We have a transition but we don't know which one.
+}
+
 }  // namespace
diff --git a/absl/time/time_zone_test.cc b/absl/time/time_zone_test.cc
index 43d9190..8f1e74a 100644
--- a/absl/time/time_zone_test.cc
+++ b/absl/time/time_zone_test.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
diff --git a/absl/types/BUILD.bazel b/absl/types/BUILD.bazel
index 32f690c..7da0003 100644
--- a/absl/types/BUILD.bazel
+++ b/absl/types/BUILD.bazel
@@ -5,7 +5,7 @@
 # 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
+#      https://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,
@@ -15,7 +15,7 @@
 #
 
 load(
-    "//absl:copts.bzl",
+    "//absl:copts/configure_copts.bzl",
     "ABSL_DEFAULT_COPTS",
     "ABSL_TEST_COPTS",
     "ABSL_EXCEPTIONS_FLAG",
@@ -168,6 +168,7 @@
     deps = [
         ":bad_optional_access",
         "//absl/base:config",
+        "//absl/base:core_headers",
         "//absl/memory",
         "//absl/meta:type_traits",
         "//absl/utility",
@@ -286,6 +287,7 @@
     linkopts = ABSL_EXCEPTIONS_FLAG_LINKOPTS,
     deps = [
         ":variant",
+        "//absl/base:config",
         "//absl/base:exception_safety_testing",
         "//absl/memory",
         "@com_google_googletest//:gtest_main",
diff --git a/absl/types/CMakeLists.txt b/absl/types/CMakeLists.txt
index 2f2e3a7..8afde46 100644
--- a/absl/types/CMakeLists.txt
+++ b/absl/types/CMakeLists.txt
@@ -5,7 +5,7 @@
 # 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
+#      https://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,
@@ -13,216 +13,306 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 #
-
-list(APPEND TYPES_PUBLIC_HEADERS
-  "any.h"
-  "bad_any_cast.h"
-  "bad_optional_access.h"
-  "optional.h"
-  "span.h"
-  "variant.h"
-)
-
-
-# any library
-absl_header_library(
-  TARGET
-    absl_any
-  PUBLIC_LIBRARIES
-    absl::bad_any_cast
-    absl::base
-    absl::meta
-    absl::utility
-  PRIVATE_COMPILE_FLAGS
-    ${ABSL_EXCEPTIONS_FLAG}
-  EXPORT_NAME
+absl_cc_library(
+  NAME
     any
-)
-
-# span library
-absl_header_library(
-  TARGET
-    absl_span
-  PUBLIC_LIBRARIES
+  HDRS
+    "any.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::bad_any_cast
+    absl::config
+    absl::core_headers
+    absl::type_traits
     absl::utility
-  EXPORT_NAME
-    span
+  PUBLIC
 )
 
-
-# bad_any_cast library
-list(APPEND BAD_ANY_CAST_SRC
-  "bad_any_cast.cc"
-  ${TYPES_PUBLIC_HEADERS}
-)
-
-absl_library(
-  TARGET
-    absl_bad_any_cast
-  SOURCES
-    ${BAD_ANY_CAST_SRC}
-  PUBLIC_LIBRARIES
-  EXPORT_NAME
+absl_cc_library(
+  NAME
     bad_any_cast
+  HDRS
+   "bad_any_cast.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::bad_any_cast_impl
+    absl::config
+  PUBLIC
 )
 
-
-# optional library
-list(APPEND OPTIONAL_SRC
-  "optional.cc"
-)
-
-absl_library(
-  TARGET
-    absl_optional
-  SOURCES
-    ${OPTIONAL_SRC}
-  PUBLIC_LIBRARIES
-    absl::bad_optional_access
+absl_cc_library(
+  NAME
+    bad_any_cast_impl
+  SRCS
+   "bad_any_cast.h"
+   "bad_any_cast.cc"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+    ${ABSL_EXCEPTIONS_FLAG}
+  LINKOPTS
+    ${ABSL_EXCEPTIONS_FLAG_LINKOPTS}
+  DEPS
     absl::base
-    absl::memory
-    absl::meta
-    absl::utility
-  EXPORT_NAME
-    optional
+    absl::config
 )
 
-
-set(BAD_OPTIONAL_ACCESS_SRC "bad_optional_access.cc")
-set(BAD_OPTIONAL_ACCESS_LIBRARIES absl::base)
-
-absl_library(
-  TARGET
-    absl_bad_optional_access
-  SOURCES
-    ${BAD_OPTIONAL_ACCESS_SRC}
-  PUBLIC_LIBRARIES
-    ${BAD_OPTIONAL_ACCESS_PUBLIC_LIBRARIES}
-  EXPORT_NAME
-    bad_optional_access
-)
-
-# variant library
-absl_library(
-  TARGET
-    absl_variant
-  SOURCES
-    "bad_variant_access.h" "bad_variant_access.cc" "variant.h" "internal/variant.h"
-  PUBLIC_LIBRARIES
-    absl::base absl::meta absl::utility
-  PRIVATE_COMPILE_FLAGS
-    ${ABSL_EXCEPTIONS_FLAG}
-  EXPORT_NAME
-    variant
-)
-
-#
-## TESTS
-#
-
-
-# test any_test
-set(ANY_TEST_SRC "any_test.cc")
-set(ANY_TEST_PUBLIC_LIBRARIES absl::base absl::throw_delegate absl::any absl::bad_any_cast test_instance_tracker_lib)
-
-absl_test(
-  TARGET
+absl_cc_test(
+  NAME
     any_test
-  SOURCES
-    ${ANY_TEST_SRC}
-  PUBLIC_LIBRARIES
-    ${ANY_TEST_PUBLIC_LIBRARIES}
-  PRIVATE_COMPILE_FLAGS
+  SRCS
+    "any_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
     ${ABSL_EXCEPTIONS_FLAG}
+  LINKOPTS
+    ${ABSL_EXCEPTIONS_FLAG_LINKOPTS}
+  DEPS
+    absl::any
+    absl::base
+    absl::config
+    absl::exception_testing
+    absl::test_instance_tracker
+    gmock_main
 )
 
-
-# test any_test_noexceptions
-absl_test(
-  TARGET
+absl_cc_test(
+  NAME
     any_test_noexceptions
-  SOURCES
-    ${ANY_TEST_SRC}
-  PUBLIC_LIBRARIES
-    ${ANY_TEST_PUBLIC_LIBRARIES}
+  SRCS
+    "any_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::any
+    absl::base
+    absl::config
+    absl::exception_testing
+    absl::test_instance_tracker
+    gmock_main
 )
 
-# test any_exception_safety_test
-set(ANY_EXCEPTION_SAFETY_TEST_SRC "any_exception_safety_test.cc")
-set(ANY_EXCEPTION_SAFETY_TEST_PUBLIC_LIBRARIES
-  absl::any
-  absl::base
-  absl_base_internal_exception_safety_testing
-)
-
-absl_test(
-  TARGET
+absl_cc_test(
+  NAME
     any_exception_safety_test
-  SOURCES
-    ${ANY_EXCEPTION_SAFETY_TEST_SRC}
-  PUBLIC_LIBRARIES
-    ${ANY_EXCEPTION_SAFETY_TEST_PUBLIC_LIBRARIES}
-  PRIVATE_COMPILE_FLAGS
+  SRCS
+    "any_exception_safety_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
     ${ABSL_EXCEPTIONS_FLAG}
+  LINKOPTS
+    ${ABSL_EXCEPTIONS_FLAG_LINKOPTS}
+  DEPS
+    absl::any
+    absl::exception_safety_testing
+    gmock_main
 )
 
+absl_cc_library(
+  NAME
+    span
+  HDRS
+    "span.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::algorithm
+    absl::core_headers
+    absl::throw_delegate
+    absl::type_traits
+  PUBLIC
+)
 
-# test span_test
-set(SPAN_TEST_SRC "span_test.cc")
-set(SPAN_TEST_PUBLIC_LIBRARIES absl::base absl::strings absl::throw_delegate absl::span test_instance_tracker_lib)
-
-absl_test(
-  TARGET
+absl_cc_test(
+  NAME
     span_test
-  SOURCES
-    ${SPAN_TEST_SRC}
-  PUBLIC_LIBRARIES
-    ${SPAN_TEST_PUBLIC_LIBRARIES}
-  PRIVATE_COMPILE_FLAGS
+  SRCS
+    "span_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
     ${ABSL_EXCEPTIONS_FLAG}
+  LINKOPTS
+    ${ABSL_EXCEPTIONS_FLAG_LINKOPTS}
+  DEPS
+    absl::span
+    absl::base
+    absl::config
+    absl::core_headers
+    absl::exception_testing
+    absl::fixed_array
+    absl::inlined_vector
+    absl::hash_testing
+    absl::strings
+    gmock_main
 )
 
-
-# test span_test_noexceptions
-absl_test(
-  TARGET
+absl_cc_test(
+  NAME
     span_test_noexceptions
-  SOURCES
-    ${SPAN_TEST_SRC}
-  PUBLIC_LIBRARIES
-    ${SPAN_TEST_PUBLIC_LIBRARIES}
+  SRCS
+    "span_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::span
+    absl::base
+    absl::config
+    absl::core_headers
+    absl::exception_testing
+    absl::fixed_array
+    absl::inlined_vector
+    absl::hash_testing
+    absl::strings
+    gmock_main
 )
 
-
-
-# test optional_test
-set(OPTIONAL_TEST_SRC "optional_test.cc")
-set(OPTIONAL_TEST_PUBLIC_LIBRARIES absl::base absl::throw_delegate absl::optional absl_bad_optional_access)
-
-absl_test(
-  TARGET
-    optional_test
-  SOURCES
-    ${OPTIONAL_TEST_SRC}
-  PUBLIC_LIBRARIES
-    ${OPTIONAL_TEST_PUBLIC_LIBRARIES}
+absl_cc_library(
+  NAME
+    optional
+  HDRS
+    "optional.h"
+  SRCS
+    "optional.cc"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::bad_optional_access
+    absl::config
+    absl::core_headers
+    absl::memory
+    absl::type_traits
+    absl::utility
+  PUBLIC
 )
 
-
-# test optional_exception_safety_test
-set(OPTIONAL_EXCEPTION_SAFETY_TEST_SRC "optional_exception_safety_test.cc")
-set(OPTIONAL_EXCEPTION_SAFETY_TEST_PUBLIC_LIBRARIES
-  absl::optional
-  absl_base_internal_exception_safety_testing
-)
-
-absl_test(
-  TARGET
-    optional_exception_safety_test
-  SOURCES
-    ${OPTIONAL_EXCEPTION_SAFETY_TEST_SRC}
-  PUBLIC_LIBRARIES
-    ${OPTIONAL_EXCEPTION_SAFETY_TEST_PUBLIC_LIBRARIES}
-  PRIVATE_COMPILE_FLAGS
+absl_cc_library(
+  NAME
+    bad_optional_access
+  HDRS
+    "bad_optional_access.h"
+  SRCS
+    "bad_optional_access.cc"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
     ${ABSL_EXCEPTIONS_FLAG}
+  LINKOPTS
+    ${ABSL_EXCEPTIONS_FLAG_LINKOPTS}
+  DEPS
+    absl::base
+    absl::config
+  PUBLIC
 )
+
+absl_cc_library(
+  NAME
+    bad_variant_access
+  HDRS
+    "bad_variant_access.h"
+  SRCS
+    "bad_variant_access.cc"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+    ${ABSL_EXCEPTIONS_FLAG}
+  LINKOPTS
+    ${ABSL_EXCEPTIONS_FLAG_LINKOPTS}
+  DEPS
+    absl::base
+    absl::config
+  PUBLIC
+)
+
+absl_cc_test(
+  NAME
+    optional_test
+  SRCS
+    "optional_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+    ${ABSL_EXCEPTIONS_FLAG}
+  LINKOPTS
+    ${ABSL_EXCEPTIONS_FLAG_LINKOPTS}
+  DEPS
+    absl::optional
+    absl::base
+    absl::config
+    absl::type_traits
+    absl::strings
+    gmock_main
+)
+
+absl_cc_test(
+  NAME
+    optional_exception_safety_test
+  SRCS
+    "optional_exception_safety_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+    ${ABSL_EXCEPTIONS_FLAG}
+  LINKOPTS
+    ${ABSL_EXCEPTIONS_FLAG_LINKOPTS}
+  DEPS
+    absl::optional
+    absl::exception_safety_testing
+    gmock_main
+)
+
+absl_cc_library(
+  NAME
+    variant
+  HDRS
+    "variant.h"
+  SRCS
+    "internal/variant.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::bad_variant_access
+    absl::base_internal
+    absl::config
+    absl::core_headers
+    absl::type_traits
+    absl::utility
+  PUBLIC
+)
+
+absl_cc_test(
+  NAME
+    variant_test
+  SRCS
+    "variant_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+    ${ABSL_EXCEPTIONS_FLAG}
+  LINKOPTS
+    ${ABSL_EXCEPTIONS_FLAG_LINKOPTS}
+  DEPS
+    absl::variant
+    absl::config
+    absl::core_headers
+    absl::memory
+    absl::type_traits
+    absl::strings
+    gmock_main
+)
+
+# TODO(cohenjon,zhangxy) Figure out why this test is failing on gcc 4.8
+if(CMAKE_COMPILER_IS_GNUCC AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 4.9)
+absl_cc_test(
+  NAME
+    variant_exception_safety_test
+  SRCS
+    "variant_exception_safety_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+    ${ABSL_EXCEPTIONS_FLAG}
+  LINKOPTS
+    ${ABSL_EXCEPTIONS_FLAG_LINKOPTS}
+  DEPS
+    absl::variant
+    absl::config
+    absl::exception_safety_testing
+    absl::memory
+    gmock_main
+)
+endif()
diff --git a/absl/types/any.h b/absl/types/any.h
index a973c6d..f3a3281 100644
--- a/absl/types/any.h
+++ b/absl/types/any.h
@@ -5,7 +5,7 @@
 // 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
+//      https://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,
@@ -58,7 +58,7 @@
 
 #ifdef ABSL_HAVE_STD_ANY
 
-#include <any>
+#include <any>  // IWYU pragma: export
 
 namespace absl {
 using std::any;
diff --git a/absl/types/any_exception_safety_test.cc b/absl/types/any_exception_safety_test.cc
index f9dd8c4..5d7d8a5 100644
--- a/absl/types/any_exception_safety_test.cc
+++ b/absl/types/any_exception_safety_test.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -135,6 +135,7 @@
   EXPECT_TRUE(strong_empty_any_tester.Test(assign_val));
   EXPECT_TRUE(strong_empty_any_tester.Test(move));
 }
+
 // libstdc++ std::any fails this test
 #if !defined(ABSL_HAVE_STD_ANY)
 TEST(AnyExceptionSafety, Emplace) {
diff --git a/absl/types/any_test.cc b/absl/types/any_test.cc
index 115e78d..a6351bf 100644
--- a/absl/types/any_test.cc
+++ b/absl/types/any_test.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
diff --git a/absl/types/bad_any_cast.cc b/absl/types/bad_any_cast.cc
index 2e2fd29..505919a 100644
--- a/absl/types/bad_any_cast.cc
+++ b/absl/types/bad_any_cast.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
diff --git a/absl/types/bad_any_cast.h b/absl/types/bad_any_cast.h
index 6039013..8d020ed 100644
--- a/absl/types/bad_any_cast.h
+++ b/absl/types/bad_any_cast.h
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
diff --git a/absl/types/bad_optional_access.cc b/absl/types/bad_optional_access.cc
index 5587077..a791c7c 100644
--- a/absl/types/bad_optional_access.cc
+++ b/absl/types/bad_optional_access.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
diff --git a/absl/types/bad_optional_access.h b/absl/types/bad_optional_access.h
index c6c2746..add5c45 100644
--- a/absl/types/bad_optional_access.h
+++ b/absl/types/bad_optional_access.h
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
diff --git a/absl/types/bad_variant_access.cc b/absl/types/bad_variant_access.cc
index d27d775..a4325c8 100644
--- a/absl/types/bad_variant_access.cc
+++ b/absl/types/bad_variant_access.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
diff --git a/absl/types/bad_variant_access.h b/absl/types/bad_variant_access.h
index e7355a5..637db43 100644
--- a/absl/types/bad_variant_access.h
+++ b/absl/types/bad_variant_access.h
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
diff --git a/absl/types/internal/variant.h b/absl/types/internal/variant.h
index eff4fef..5ca66e2 100644
--- a/absl/types/internal/variant.h
+++ b/absl/types/internal/variant.h
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -1234,23 +1234,29 @@
 // Base that is dependent on whether or not the move-assign can be trivial.
 template <class... T>
 using VariantMoveAssignBase = absl::conditional_t<
-    absl::disjunction<absl::conjunction<absl::is_move_assignable<Union<T...>>,
-                                        std::is_move_constructible<Union<T...>>,
-                                        std::is_destructible<Union<T...>>>,
-                      absl::negation<absl::conjunction<
-                          std::is_move_constructible<T>...,
-                          absl::is_move_assignable<T>...>>>::value,
+    absl::disjunction<
+        absl::conjunction<absl::is_move_assignable<Union<T...>>,
+                          std::is_move_constructible<Union<T...>>,
+                          std::is_destructible<Union<T...>>>,
+        absl::negation<absl::conjunction<std::is_move_constructible<T>...,
+                                         // Note: We're not qualifying this with
+                                         // absl:: because it doesn't compile
+                                         // under MSVC.
+                                         is_move_assignable<T>...>>>::value,
     VariantCopyBase<T...>, VariantMoveAssignBaseNontrivial<T...>>;
 
 // Base that is dependent on whether or not the copy-assign can be trivial.
 template <class... T>
 using VariantCopyAssignBase = absl::conditional_t<
-    absl::disjunction<absl::conjunction<absl::is_copy_assignable<Union<T...>>,
-                                        std::is_copy_constructible<Union<T...>>,
-                                        std::is_destructible<Union<T...>>>,
-                      absl::negation<absl::conjunction<
-                          std::is_copy_constructible<T>...,
-                          absl::is_copy_assignable<T>...>>>::value,
+    absl::disjunction<
+        absl::conjunction<absl::is_copy_assignable<Union<T...>>,
+                          std::is_copy_constructible<Union<T...>>,
+                          std::is_destructible<Union<T...>>>,
+        absl::negation<absl::conjunction<std::is_copy_constructible<T>...,
+                                         // Note: We're not qualifying this with
+                                         // absl:: because it doesn't compile
+                                         // under MSVC.
+                                         is_copy_assignable<T>...>>>::value,
     VariantMoveAssignBase<T...>, VariantCopyAssignBaseNontrivial<T...>>;
 
 template <class... T>
@@ -1542,8 +1548,8 @@
   variant<Types...>* w;
   template <std::size_t I>
   void operator()(SizeT<I>) const {
-    using std::swap;
-    swap(VariantCoreAccess::Access<I>(*v), VariantCoreAccess::Access<I>(*w));
+    type_traits_internal::Swap(VariantCoreAccess::Access<I>(*v),
+                               VariantCoreAccess::Access<I>(*w));
   }
 
   void operator()(SizeT<variant_npos>) const {}
@@ -1598,11 +1604,12 @@
 template <typename Variant, typename... Ts>
 struct VariantHashBase<Variant,
                        absl::enable_if_t<absl::conjunction<
-                           type_traits_internal::IsHashEnabled<Ts>...>::value>,
+                           type_traits_internal::IsHashable<Ts>...>::value>,
                        Ts...> {
   using argument_type = Variant;
   using result_type = size_t;
   size_t operator()(const Variant& var) const {
+    type_traits_internal::AssertHashEnabled<Ts...>();
     if (var.valueless_by_exception()) {
       return 239799884;
     }
diff --git a/absl/types/optional.cc b/absl/types/optional.cc
index ef27290..44ff829 100644
--- a/absl/types/optional.cc
+++ b/absl/types/optional.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
diff --git a/absl/types/optional.h b/absl/types/optional.h
index 1421001..f0ae9a1 100644
--- a/absl/types/optional.h
+++ b/absl/types/optional.h
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -36,11 +36,12 @@
 #define ABSL_TYPES_OPTIONAL_H_
 
 #include "absl/base/config.h"
+#include "absl/memory/memory.h"
 #include "absl/utility/utility.h"
 
 #ifdef ABSL_HAVE_STD_OPTIONAL
 
-#include <optional>
+#include <optional>  // IWYU pragma: export
 
 namespace absl {
 using std::bad_optional_access;
@@ -60,7 +61,6 @@
 #include <utility>
 
 #include "absl/base/attributes.h"
-#include "absl/memory/memory.h"
 #include "absl/meta/type_traits.h"
 #include "absl/types/bad_optional_access.h"
 
@@ -114,10 +114,6 @@
 //      need the inline variable support in C++17 for external linkage.
 //    * Throws `absl::bad_optional_access` instead of
 //      `std::bad_optional_access`.
-//    * `optional::swap()` and `absl::swap()` relies on
-//      `std::is_(nothrow_)swappable()`, which has been introduced in C++17.
-//      As a workaround, we assume `is_swappable()` is always `true`
-//      and `is_nothrow_swappable()` is the same as `std::is_trivial()`.
 //    * `make_optional()` cannot be declared `constexpr` due to the absence of
 //      guaranteed copy elision.
 //    * The move constructor's `noexcept` specification is stronger, i.e. if the
@@ -163,7 +159,7 @@
 // This class stores the data in optional<T>.
 // It is specialized based on whether T is trivially destructible.
 // This is the specialization for non trivially destructible type.
-template <typename T, bool = std::is_trivially_destructible<T>::value>
+template <typename T, bool unused = std::is_trivially_destructible<T>::value>
 class optional_data_dtor_base {
   struct dummy_type {
     static_assert(sizeof(T) % sizeof(empty_struct) == 0, "");
@@ -261,10 +257,10 @@
 // have trivial move but nontrivial copy.
 // Also, we should be checking is_trivially_copyable here, which is not
 // supported now, so we use is_trivially_* traits instead.
-template <typename T, bool = absl::is_trivially_copy_constructible<T>::value&&
-                          absl::is_trivially_copy_assignable<
-                              typename std::remove_cv<T>::type>::value&&
-                              std::is_trivially_destructible<T>::value>
+template <typename T,
+          bool unused = absl::is_trivially_copy_constructible<T>::value&&
+              absl::is_trivially_copy_assignable<typename std::remove_cv<
+                  T>::type>::value&& std::is_trivially_destructible<T>::value>
 class optional_data;
 
 // Trivially copyable types
@@ -295,7 +291,7 @@
 
   optional_data() = default;
 
-  optional_data(const optional_data& rhs) {
+  optional_data(const optional_data& rhs) : optional_data_base<T>() {
     if (rhs.engaged_) {
       this->construct(rhs.data_);
     }
@@ -303,7 +299,8 @@
 
   optional_data(optional_data&& rhs) noexcept(
       absl::default_allocator_is_nothrow::value ||
-      std::is_nothrow_move_constructible<T>::value) {
+      std::is_nothrow_move_constructible<T>::value)
+      : optional_data_base<T>() {
     if (rhs.engaged_) {
       this->construct(std::move(rhs.data_));
     }
@@ -403,23 +400,24 @@
 };
 
 template <typename T>
-constexpr copy_traits get_ctor_copy_traits() {
-  return std::is_copy_constructible<T>::value
-             ? copy_traits::copyable
-             : std::is_move_constructible<T>::value ? copy_traits::movable
-                                                    : copy_traits::non_movable;
-}
+struct ctor_copy_traits {
+  static constexpr copy_traits traits =
+      std::is_copy_constructible<T>::value
+          ? copy_traits::copyable
+          : std::is_move_constructible<T>::value ? copy_traits::movable
+                                                 : copy_traits::non_movable;
+};
 
 template <typename T>
-constexpr copy_traits get_assign_copy_traits() {
-  return absl::is_copy_assignable<T>::value &&
-                 std::is_copy_constructible<T>::value
-             ? copy_traits::copyable
-             : absl::is_move_assignable<T>::value &&
-                       std::is_move_constructible<T>::value
-                   ? copy_traits::movable
-                   : copy_traits::non_movable;
-}
+struct assign_copy_traits {
+  static constexpr copy_traits traits =
+      absl::is_copy_assignable<T>::value && std::is_copy_constructible<T>::value
+          ? copy_traits::copyable
+          : absl::is_move_assignable<T>::value &&
+                    std::is_move_constructible<T>::value
+                ? copy_traits::movable
+                : copy_traits::non_movable;
+};
 
 // Whether T is constructible or convertible from optional<U>.
 template <typename T, typename U>
@@ -467,6 +465,7 @@
   using argument_type = absl::optional<T>;
   using result_type = size_t;
   size_t operator()(const absl::optional<T>& opt) const {
+    absl::type_traits_internal::AssertHashEnabled<absl::remove_const_t<T>>();
     if (opt) {
       return std::hash<absl::remove_const_t<T> >()(*opt);
     } else {
@@ -484,9 +483,9 @@
 template <typename T>
 class optional : private optional_internal::optional_data<T>,
                  private optional_internal::optional_ctor_base<
-                     optional_internal::get_ctor_copy_traits<T>()>,
+                     optional_internal::ctor_copy_traits<T>::traits>,
                  private optional_internal::optional_assign_base<
-                     optional_internal::get_assign_copy_traits<T>()> {
+                     optional_internal::assign_copy_traits<T>::traits> {
   using data_base = optional_internal::optional_data<T>;
 
  public:
@@ -511,10 +510,11 @@
   // the arguments `std::forward<Args>(args)...`  within the `optional`.
   // (The `in_place_t` is a tag used to indicate that the contained object
   // should be constructed in-place.)
-  //
-  // TODO(absl-team): Add std::is_constructible<T, Args&&...> SFINAE.
-  template <typename... Args>
-  constexpr explicit optional(in_place_t, Args&&... args)
+  template <typename InPlaceT, typename... Args,
+            absl::enable_if_t<absl::conjunction<
+                std::is_same<InPlaceT, in_place_t>,
+                std::is_constructible<T, Args&&...> >::value>* = nullptr>
+  constexpr explicit optional(InPlaceT, Args&&... args)
       : data_base(in_place_t(), absl::forward<Args>(args)...) {}
 
   // Constructs a non-empty `optional` direct-initialized value of type `T` from
@@ -750,11 +750,10 @@
   // Swap, standard semantics
   void swap(optional& rhs) noexcept(
       std::is_nothrow_move_constructible<T>::value&&
-          std::is_trivial<T>::value) {
+          type_traits_internal::IsNothrowSwappable<T>::value) {
     if (*this) {
       if (rhs) {
-        using std::swap;
-        swap(**this, *rhs);
+        type_traits_internal::Swap(**this, *rhs);
       } else {
         rhs.construct(std::move(**this));
         this->destruct();
@@ -906,12 +905,10 @@
 //
 // Performs a swap between two `absl::optional` objects, using standard
 // semantics.
-//
-// NOTE: we assume `is_swappable()` is always `true`. A compile error will
-// result if this is not the case.
-template <typename T,
-          typename std::enable_if<std::is_move_constructible<T>::value,
-                                  bool>::type = false>
+template <typename T, typename std::enable_if<
+                          std::is_move_constructible<T>::value &&
+                              type_traits_internal::IsSwappable<T>::value,
+                          bool>::type = false>
 void swap(optional<T>& a, optional<T>& b) noexcept(noexcept(a.swap(b))) {
   a.swap(b);
 }
diff --git a/absl/types/optional_exception_safety_test.cc b/absl/types/optional_exception_safety_test.cc
index d117ee5..aaf8ebc 100644
--- a/absl/types/optional_exception_safety_test.cc
+++ b/absl/types/optional_exception_safety_test.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
diff --git a/absl/types/optional_test.cc b/absl/types/optional_test.cc
index d90db9f..0665488 100644
--- a/absl/types/optional_test.cc
+++ b/absl/types/optional_test.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -157,6 +157,16 @@
   NonMovable& operator=(NonMovable&&) = delete;
 };
 
+struct NoDefault {
+  NoDefault() = delete;
+  NoDefault(const NoDefault&) {}
+  NoDefault& operator=(const NoDefault&) { return *this; }
+};
+
+struct ConvertsFromInPlaceT {
+  ConvertsFromInPlaceT(absl::in_place_t) {}  // NOLINT
+};
+
 TEST(optionalTest, DefaultConstructor) {
   absl::optional<int> empty;
   EXPECT_FALSE(empty);
@@ -337,16 +347,18 @@
   static_assert((*opt2).x == ConstexprType::kCtorInitializerList, "");
 #endif
 
-  // TODO(absl-team): uncomment these when std::is_constructible<T, Args&&...>
-  // SFINAE is added to optional::optional(absl::in_place_t, Args&&...).
-  // struct I {
-  //   I(absl::in_place_t);
-  // };
+  EXPECT_FALSE((std::is_constructible<absl::optional<ConvertsFromInPlaceT>,
+                                      absl::in_place_t>::value));
+  EXPECT_FALSE((std::is_constructible<absl::optional<ConvertsFromInPlaceT>,
+                                      const absl::in_place_t&>::value));
+  EXPECT_TRUE(
+      (std::is_constructible<absl::optional<ConvertsFromInPlaceT>,
+                             absl::in_place_t, absl::in_place_t>::value));
 
-  // EXPECT_FALSE((std::is_constructible<absl::optional<I>,
-  // absl::in_place_t>::value));
-  // EXPECT_FALSE((std::is_constructible<absl::optional<I>, const
-  // absl::in_place_t&>::value));
+  EXPECT_FALSE((std::is_constructible<absl::optional<NoDefault>,
+                                      absl::in_place_t>::value));
+  EXPECT_FALSE((std::is_constructible<absl::optional<NoDefault>,
+                                      absl::in_place_t&&>::value));
 }
 
 // template<U=T> optional(U&&);
@@ -1042,9 +1054,9 @@
   // test exception throw on value()
   absl::optional<int> empty;
 #ifdef ABSL_HAVE_EXCEPTIONS
-  EXPECT_THROW(empty.value(), absl::bad_optional_access);
+  EXPECT_THROW((void)empty.value(), absl::bad_optional_access);
 #else
-  EXPECT_DEATH(empty.value(), "Bad optional access");
+  EXPECT_DEATH((void)empty.value(), "Bad optional access");
 #endif
 
   // test constexpr value()
@@ -1476,8 +1488,8 @@
 
 TEST(optionalTest, ValueType) {
   EXPECT_TRUE((std::is_same<absl::optional<int>::value_type, int>::value));
-  EXPECT_TRUE(
-      (std::is_same<absl::optional<std::string>::value_type, std::string>::value));
+  EXPECT_TRUE((std::is_same<absl::optional<std::string>::value_type,
+                            std::string>::value));
   EXPECT_FALSE(
       (std::is_same<absl::optional<int>::value_type, absl::nullopt_t>::value));
 }
@@ -1504,18 +1516,19 @@
 
   static_assert(is_hash_enabled_for<absl::optional<int>>::value, "");
   static_assert(is_hash_enabled_for<absl::optional<Hashable>>::value, "");
+  static_assert(
+      absl::type_traits_internal::IsHashable<absl::optional<int>>::value, "");
+  static_assert(
+      absl::type_traits_internal::IsHashable<absl::optional<Hashable>>::value,
+      "");
+  absl::type_traits_internal::AssertHashEnabled<absl::optional<int>>();
+  absl::type_traits_internal::AssertHashEnabled<absl::optional<Hashable>>();
 
-#if defined(_MSC_VER) || (defined(_LIBCPP_VERSION) && \
-                          _LIBCPP_VERSION < 4000 && _LIBCPP_STD_VER > 11)
-  // For MSVC and libc++ (< 4.0 and c++14), std::hash primary template has a
-  // static_assert to catch any user-defined type that doesn't provide a hash
-  // specialization. So instantiating std::hash<absl::optional<T>> will result
-  // in a hard error which is not SFINAE friendly.
-#define ABSL_STD_HASH_NOT_SFINAE_FRIENDLY 1
-#endif
-
-#ifndef ABSL_STD_HASH_NOT_SFINAE_FRIENDLY
+#if ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_
   static_assert(!is_hash_enabled_for<absl::optional<NonHashable>>::value, "");
+  static_assert(!absl::type_traits_internal::IsHashable<
+                    absl::optional<NonHashable>>::value,
+                "");
 #endif
 
   // libstdc++ std::optional is missing remove_const_t, i.e. it's using
@@ -1623,4 +1636,29 @@
   EXPECT_TRUE(absl::is_copy_assignable<absl::optional<AnyLike>>::value);
 }
 
+#if !defined(ABSL_HAVE_STD_OPTIONAL) && !defined(_LIBCPP_VERSION)
+struct NestedClassBug {
+  struct Inner {
+    bool dummy = false;
+  };
+  absl::optional<Inner> value;
+};
+
+TEST(optionalTest, InPlaceTSFINAEBug) {
+  NestedClassBug b;
+  ((void)b);
+  using Inner = NestedClassBug::Inner;
+
+  EXPECT_TRUE((std::is_default_constructible<Inner>::value));
+  EXPECT_TRUE((std::is_constructible<Inner>::value));
+  EXPECT_TRUE(
+      (std::is_constructible<absl::optional<Inner>, absl::in_place_t>::value));
+
+  absl::optional<Inner> o(absl::in_place);
+  EXPECT_TRUE(o.has_value());
+  o.emplace();
+  EXPECT_TRUE(o.has_value());
+}
+#endif  // !defined(ABSL_HAVE_STD_OPTIONAL) && !defined(_LIBCPP_VERSION)
+
 }  // namespace
diff --git a/absl/types/span.h b/absl/types/span.h
index 911af0c..d7f48d9 100644
--- a/absl/types/span.h
+++ b/absl/types/span.h
@@ -5,7 +5,7 @@
 // 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
+//      https://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,
@@ -87,7 +87,7 @@
   return c.data();
 }
 
-// Before C++17, string::data returns a const char* in all cases.
+// Before C++17, std::string::data returns a const char* in all cases.
 inline char* GetDataImpl(std::string& s,  // NOLINT(runtime/references)
                          int) noexcept {
   return &s[0];
@@ -485,6 +485,40 @@
                : (base_internal::ThrowStdOutOfRange("pos > size()"), Span());
   }
 
+  // Span::first()
+  //
+  // Returns a `Span` containing first `len` elements. Parameter `len` is of
+  // type `size_type` and thus non-negative. `len` value must be <= size().
+  //
+  // Examples:
+  //
+  //   std::vector<int> vec = {10, 11, 12, 13};
+  //   absl::MakeSpan(vec).first(1);  // {10}
+  //   absl::MakeSpan(vec).first(3);  // {10, 11, 12}
+  //   absl::MakeSpan(vec).first(5);  // throws std::out_of_range
+  constexpr Span first(size_type len) const {
+    return (len <= size())
+               ? Span(data(), len)
+               : (base_internal::ThrowStdOutOfRange("len > size()"), Span());
+  }
+
+  // Span::last()
+  //
+  // Returns a `Span` containing last `len` elements. Parameter `len` is of
+  // type `size_type` and thus non-negative. `len` value must be <= size().
+  //
+  // Examples:
+  //
+  //   std::vector<int> vec = {10, 11, 12, 13};
+  //   absl::MakeSpan(vec).last(1);  // {13}
+  //   absl::MakeSpan(vec).last(3);  // {11, 12, 13}
+  //   absl::MakeSpan(vec).last(5);  // throws std::out_of_range
+  constexpr Span last(size_type len) const {
+    return (len <= size())
+               ? Span(size() - len + data(), len)
+               : (base_internal::ThrowStdOutOfRange("len > size()"), Span());
+  }
+
   // Support for absl::Hash.
   template <typename H>
   friend H AbslHashValue(H h, Span v) {
diff --git a/absl/types/span_test.cc b/absl/types/span_test.cc
index bd739ff..9269f91 100644
--- a/absl/types/span_test.cc
+++ b/absl/types/span_test.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -139,8 +139,10 @@
   EXPECT_THAT(s_const_abc, SpanIs(abc));
 
   EXPECT_FALSE((std::is_constructible<absl::Span<int>, std::string>::value));
-  EXPECT_FALSE((std::is_constructible<absl::Span<const int>, std::string>::value));
-  EXPECT_TRUE((std::is_convertible<std::string, absl::Span<const char>>::value));
+  EXPECT_FALSE(
+      (std::is_constructible<absl::Span<const int>, std::string>::value));
+  EXPECT_TRUE(
+      (std::is_convertible<std::string, absl::Span<const char>>::value));
 }
 
 TEST(IntSpan, FromConstPointer) {
@@ -293,6 +295,38 @@
 #endif
 }
 
+TEST(IntSpan, First) {
+  std::vector<int> empty;
+  EXPECT_THAT(absl::MakeSpan(empty).first(0), SpanIs(empty));
+
+  auto ramp = MakeRamp(10);
+  EXPECT_THAT(absl::MakeSpan(ramp).first(0), SpanIs(ramp.data(), 0));
+  EXPECT_THAT(absl::MakeSpan(ramp).first(10), SpanIs(ramp));
+  EXPECT_THAT(absl::MakeSpan(ramp).first(3), SpanIs(ramp.data(), 3));
+
+#ifdef ABSL_HAVE_EXCEPTIONS
+  EXPECT_THROW(absl::MakeSpan(ramp).first(11), std::out_of_range);
+#else
+  EXPECT_DEATH_IF_SUPPORTED(absl::MakeSpan(ramp).first(11), "");
+#endif
+}
+
+TEST(IntSpan, Last) {
+  std::vector<int> empty;
+  EXPECT_THAT(absl::MakeSpan(empty).last(0), SpanIs(empty));
+
+  auto ramp = MakeRamp(10);
+  EXPECT_THAT(absl::MakeSpan(ramp).last(0), SpanIs(ramp.data() + 10, 0));
+  EXPECT_THAT(absl::MakeSpan(ramp).last(10), SpanIs(ramp));
+  EXPECT_THAT(absl::MakeSpan(ramp).last(3), SpanIs(ramp.data() + 7, 3));
+
+#ifdef ABSL_HAVE_EXCEPTIONS
+  EXPECT_THROW(absl::MakeSpan(ramp).last(11), std::out_of_range);
+#else
+  EXPECT_DEATH_IF_SUPPORTED(absl::MakeSpan(ramp).last(11), "");
+#endif
+}
+
 TEST(IntSpan, MakeSpanPtrLength) {
   std::vector<int> empty;
   auto s_empty = absl::MakeSpan(empty.data(), empty.size());
@@ -767,6 +801,8 @@
   ABSL_TEST_CONSTEXPR(span.begin());
   ABSL_TEST_CONSTEXPR(span.cbegin());
   ABSL_TEST_CONSTEXPR(span.subspan(0, 0));
+  ABSL_TEST_CONSTEXPR(span.first(1));
+  ABSL_TEST_CONSTEXPR(span.last(1));
   ABSL_TEST_CONSTEXPR(span[0]);
 }
 
@@ -779,4 +815,19 @@
   EXPECT_LE(sizeof(absl::Span<BigStruct>), 2 * sizeof(void*));
 }
 
+TEST(Span, Hash) {
+  int array[] = {1, 2, 3, 4};
+  int array2[] = {1, 2, 3};
+  using T = absl::Span<const int>;
+  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(
+      {// Empties
+       T(), T(nullptr, 0), T(array, 0), T(array2, 0),
+       // Different array with same value
+       T(array, 3), T(array2), T({1, 2, 3}),
+       // Same array, but different length
+       T(array, 1), T(array, 2),
+       // Same length, but different array
+       T(array + 1, 2), T(array + 2, 2)}));
+}
+
 }  // namespace
diff --git a/absl/types/variant.h b/absl/types/variant.h
index 2f78722..ebd52d2 100644
--- a/absl/types/variant.h
+++ b/absl/types/variant.h
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -47,7 +47,7 @@
 
 #ifdef ABSL_HAVE_STD_VARIANT
 
-#include <variant>
+#include <variant>  // IWYU pragma: export
 
 namespace absl {
 using std::bad_variant_access;
@@ -82,7 +82,7 @@
 // absl::variant
 // -----------------------------------------------------------------------------
 //
-// An 'absl::variant` type is a form of type-safe union. An `absl::variant` --
+// An `absl::variant` type is a form of type-safe union. An `absl::variant` --
 // except in exceptional cases -- always holds a value of one of its alternative
 // types.
 //
@@ -129,14 +129,19 @@
 // type (in which case, they will be swapped) or to two different types (in
 // which case the values will need to be moved).
 //
-template <typename... Ts>
+template <
+    typename... Ts,
+    absl::enable_if_t<
+        absl::conjunction<std::is_move_constructible<Ts>...,
+                          type_traits_internal::IsSwappable<Ts>...>::value,
+        int> = 0>
 void swap(variant<Ts...>& v, variant<Ts...>& w) noexcept(noexcept(v.swap(w))) {
   v.swap(w);
 }
 
 // variant_size
 //
-// Returns the number of alterative types available for a given `absl::variant`
+// Returns the number of alternative types available for a given `absl::variant`
 // type as a compile-time constant expression. As this is a class template, it
 // is not generally useful for accessing the number of alternative types of
 // any given `absl::variant` instance.
@@ -399,9 +404,9 @@
 // Calls a provided functor on a given set of variants. `absl::visit()` is
 // commonly used to conditionally inspect the state of a given variant (or set
 // of variants).
-// Requires: The expression in the Effects: element shall be a valid expression
-// of the same type and value category, for all combinations of alternative
-// types of all variants. Otherwise, the program is ill-formed.
+//
+// The functor must return the same type when called with any of the variants'
+// alternatives.
 //
 // Example:
 //
@@ -414,6 +419,7 @@
 //   };
 //
 //   // Declare our variant, and call `absl::visit()` on it.
+//   // Note that `GetVariant()` returns void in either case.
 //   absl::variant<int, std::string> foo = std::string("foo");
 //   GetVariant visitor;
 //   absl::visit(visitor, foo);  // Prints `The variant's value is: foo'
@@ -453,7 +459,7 @@
                                   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
+  // Intentionally not qualifying `negation` with `absl::` to work around a bug
   // in MSVC 2015 with inline namespace and variadic template.
   static_assert(absl::conjunction<negation<std::is_array<T0> >,
                                   negation<std::is_array<Tn> >...>::value,
@@ -561,7 +567,7 @@
 
   // Assignment Operators
 
-  // Copy assignement operator
+  // Copy assignment operator
   variant& operator=(const variant& other) = default;
 
   // Move assignment operator
@@ -687,12 +693,12 @@
   //
   // Swaps the values of two variant objects.
   //
-  // TODO(calabrese)
-  //   `variant::swap()` and `swap()` rely on `std::is_(nothrow)_swappable()`
-  //   which is introduced in C++17. So we assume `is_swappable()` is always
-  //   true and `is_nothrow_swappable()` is same as `std::is_trivial()`.
   void swap(variant& rhs) noexcept(
-      absl::conjunction<std::is_trivial<T0>, std::is_trivial<Tn>...>::value) {
+      absl::conjunction<
+          std::is_nothrow_move_constructible<T0>,
+          std::is_nothrow_move_constructible<Tn>...,
+          type_traits_internal::IsNothrowSwappable<T0>,
+          type_traits_internal::IsNothrowSwappable<Tn>...>::value) {
     return variant_internal::VisitIndices<sizeof...(Tn) + 1>::Run(
         variant_internal::Swap<T0, Tn...>{this, &rhs}, rhs.index());
   }
diff --git a/absl/types/variant_benchmark.cc b/absl/types/variant_benchmark.cc
index 99658ac..a5f5216 100644
--- a/absl/types/variant_benchmark.cc
+++ b/absl/types/variant_benchmark.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
diff --git a/absl/types/variant_exception_safety_test.cc b/absl/types/variant_exception_safety_test.cc
index 58436f0..76beb59 100644
--- a/absl/types/variant_exception_safety_test.cc
+++ b/absl/types/variant_exception_safety_test.cc
@@ -4,13 +4,14 @@
 // 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
+//      https://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/types/variant.h"
 
 #include <iostream>
@@ -20,9 +21,13 @@
 
 #include "gmock/gmock.h"
 #include "gtest/gtest.h"
+#include "absl/base/config.h"
 #include "absl/base/internal/exception_safety_testing.h"
 #include "absl/memory/memory.h"
 
+// See comment in absl/base/config.h
+#if !defined(ABSL_INTERNAL_MSVC_2017_DBG_MODE)
+
 namespace absl {
 namespace {
 
@@ -311,6 +316,12 @@
     EXPECT_FALSE(tester.WithContracts(strong_guarantee).Test());
   }
   {
+    // libstdc++ introduced a regression between 2018-09-25 and 2019-01-06.
+    // The fix is targeted for gcc-9.
+    // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87431#c7
+    // https://gcc.gnu.org/viewcvs/gcc?view=revision&revision=267614
+#if !(defined(ABSL_HAVE_STD_VARIANT) && \
+      defined(_GLIBCXX_RELEASE) && _GLIBCXX_RELEASE == 8)
     // - otherwise (index() != j), equivalent to
     // emplace<j>(get<j>(std::move(rhs)))
     // - If an exception is thrown during the call to Tj's move construction
@@ -326,6 +337,8 @@
                       auto copy = rhs;
                       *lhs = std::move(copy);
                     }));
+#endif  // !(defined(ABSL_HAVE_STD_VARIANT) &&
+        //   defined(_GLIBCXX_RELEASE) && _GLIBCXX_RELEASE == 8)
   }
 }
 
@@ -506,3 +519,5 @@
 
 }  // namespace
 }  // namespace absl
+
+#endif  // !defined(ABSL_INTERNAL_MSVC_2017_DBG_MODE)
diff --git a/absl/types/variant_test.cc b/absl/types/variant_test.cc
index bfb8bd7..ab40ed2 100644
--- a/absl/types/variant_test.cc
+++ b/absl/types/variant_test.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -52,7 +52,7 @@
 #endif  // ABSL_HAVE_EXCEPTIONS
 
 #define ABSL_VARIANT_TEST_EXPECT_BAD_VARIANT_ACCESS(...)                 \
-  ABSL_VARIANT_TEST_EXPECT_FAIL((__VA_ARGS__), absl::bad_variant_access, \
+  ABSL_VARIANT_TEST_EXPECT_FAIL((void)(__VA_ARGS__), absl::bad_variant_access, \
                                 "Bad variant access")
 
 struct Hashable {};
@@ -257,7 +257,7 @@
 // each type.
 template <typename T>
 class VariantTypesTest : public ::testing::Test {};
-TYPED_TEST_CASE(VariantTypesTest, VariantTypes);
+TYPED_TEST_SUITE(VariantTypesTest, VariantTypes);
 
 ////////////////////
 // [variant.ctor] //
@@ -484,7 +484,8 @@
 }
 
 TEST(VariantTest, InPlaceTypeInitializerList) {
-  using Var = variant<int, std::string, NonCopyable, MoveOnlyWithListConstructor>;
+  using Var =
+      variant<int, std::string, NonCopyable, MoveOnlyWithListConstructor>;
 
   Var v1(in_place_type_t<MoveOnlyWithListConstructor>(), {1, 2, 3, 4, 5}, 6);
   ASSERT_TRUE(absl::holds_alternative<MoveOnlyWithListConstructor>(v1));
@@ -519,7 +520,8 @@
 }
 
 TEST(VariantTest, InPlaceIndexInitializerList) {
-  using Var = variant<int, std::string, NonCopyable, MoveOnlyWithListConstructor>;
+  using Var =
+      variant<int, std::string, NonCopyable, MoveOnlyWithListConstructor>;
 
   Var v1(in_place_index_t<3>(), {1, 2, 3, 4, 5}, 6);
   ASSERT_TRUE(absl::holds_alternative<MoveOnlyWithListConstructor>(v1));
@@ -560,8 +562,14 @@
 
 #ifdef ABSL_HAVE_EXCEPTIONS
 
+// See comment in absl/base/config.h
+#if defined(ABSL_INTERNAL_MSVC_2017_DBG_MODE)
+TEST(VariantTest, DISABLED_TestDtorValuelessByException)
+#else
 // Test destruction when in the valueless_by_exception state.
-TEST(VariantTest, TestDtorValuelessByException) {
+TEST(VariantTest, TestDtorValuelessByException)
+#endif
+{
   int counter = 0;
   IncrementInDtor counter_adjuster(&counter);
 
@@ -826,7 +834,8 @@
 }
 
 TEST(VariantTest, TestEmplaceInitializerList) {
-  using Var = variant<int, std::string, NonCopyable, MoveOnlyWithListConstructor>;
+  using Var =
+      variant<int, std::string, NonCopyable, MoveOnlyWithListConstructor>;
 
   Var v1(absl::in_place_index_t<0>{}, 555);
   MoveOnlyWithListConstructor& emplace_result =
@@ -863,7 +872,8 @@
 }
 
 TEST(VariantTest, TestEmplaceIndexInitializerList) {
-  using Var = variant<int, std::string, NonCopyable, MoveOnlyWithListConstructor>;
+  using Var =
+      variant<int, std::string, NonCopyable, MoveOnlyWithListConstructor>;
 
   Var v1(absl::in_place_index_t<0>{}, 555);
   MoveOnlyWithListConstructor& emplace_result =
@@ -1301,7 +1311,8 @@
         absl::get<std::string>(std::move(v)));
 
     const Var& const_v = v;
-    ABSL_VARIANT_TEST_EXPECT_BAD_VARIANT_ACCESS(absl::get<std::string>(const_v));
+    ABSL_VARIANT_TEST_EXPECT_BAD_VARIANT_ACCESS(
+        absl::get<std::string>(const_v));
     ABSL_VARIANT_TEST_EXPECT_BAD_VARIANT_ACCESS(
         absl::get<std::string>(std::move(const_v)));  // NOLINT
   }
@@ -1358,7 +1369,8 @@
       EXPECT_EQ(*elem, 0);
       {
         auto* bad_elem = absl::get_if<1>(&const_v);
-        EXPECT_TRUE((std::is_same<decltype(bad_elem), const std::string*>::value));
+        EXPECT_TRUE(
+            (std::is_same<decltype(bad_elem), const std::string*>::value));
         EXPECT_EQ(bad_elem, nullptr);
       }
       {
@@ -1467,7 +1479,8 @@
       }
       {
         auto* bad_elem = absl::get_if<1>(&const_v);
-        EXPECT_TRUE((std::is_same<decltype(bad_elem), const std::string*>::value));
+        EXPECT_TRUE(
+            (std::is_same<decltype(bad_elem), const std::string*>::value));
         EXPECT_EQ(bad_elem, nullptr);
       }
       {
@@ -1520,7 +1533,8 @@
       }
       {
         auto* bad_elem = absl::get_if<1>(&const_v);
-        EXPECT_TRUE((std::is_same<decltype(bad_elem), const std::string*>::value));
+        EXPECT_TRUE(
+            (std::is_same<decltype(bad_elem), const std::string*>::value));
         EXPECT_EQ(bad_elem, nullptr);
       }
       {
@@ -1723,9 +1737,13 @@
     bool operator()(std::string&&) const { return true; }  // NOLINT
 
     int operator()(const std::string&, const std::string&) const { return 0; }
-    int operator()(const std::string&, std::string&&) const { return 1; }  // NOLINT
-    int operator()(std::string&&, const std::string&) const { return 2; }  // NOLINT
-    int operator()(std::string&&, std::string&&) const { return 3; }       // NOLINT
+    int operator()(const std::string&, std::string&&) const {
+      return 1;
+    }  // NOLINT
+    int operator()(std::string&&, const std::string&) const {
+      return 2;
+    }                                                                 // NOLINT
+    int operator()(std::string&&, std::string&&) const { return 3; }  // NOLINT
   };
   EXPECT_FALSE(absl::visit(Visitor{}, v));
   EXPECT_TRUE(absl::visit(Visitor{}, absl::move(v)));
@@ -1801,9 +1819,9 @@
   EXPECT_THAT(absl::visit(Visitor(), A(std::string("BBBBB")),
                           B(std::unique_ptr<int>(new int(7)))),
               ::testing::Pair(5, 7));
-  EXPECT_THAT(
-      absl::visit(Visitor(), A(std::string("BBBBB")), B(absl::string_view("ABC"))),
-      ::testing::Pair(5, 3));
+  EXPECT_THAT(absl::visit(Visitor(), A(std::string("BBBBB")),
+                          B(absl::string_view("ABC"))),
+              ::testing::Pair(5, 3));
 }
 
 TEST(VariantTest, VisitNoArgs) {
@@ -1972,29 +1990,17 @@
 }
 
 TEST(VariantTest, Hash) {
-  static_assert(type_traits_internal::IsHashEnabled<variant<int>>::value, "");
-  static_assert(type_traits_internal::IsHashEnabled<variant<Hashable>>::value,
+  static_assert(type_traits_internal::IsHashable<variant<int>>::value, "");
+  static_assert(type_traits_internal::IsHashable<variant<Hashable>>::value, "");
+  static_assert(type_traits_internal::IsHashable<variant<int, Hashable>>::value,
+                "");
+
+#if ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_
+  static_assert(!type_traits_internal::IsHashable<variant<NonHashable>>::value,
                 "");
   static_assert(
-      type_traits_internal::IsHashEnabled<variant<int, Hashable>>::value, "");
-
-#if defined(_MSC_VER) ||                                   \
-    (defined(_LIBCPP_VERSION) && _LIBCPP_VERSION < 4000 && \
-     _LIBCPP_STD_VER > 11) ||                              \
-    defined(__APPLE__)
-  // For MSVC and libc++ (< 4.0 and c++14), std::hash primary template has a
-  // static_assert to catch any user-defined type T that doesn't provide a hash
-  // specialization. So instantiating std::hash<variant<T>> will result
-  // in a hard error which is not SFINAE friendly.
-#define ABSL_STD_HASH_NOT_SFINAE_FRIENDLY 1
-#endif
-
-#ifndef ABSL_STD_HASH_NOT_SFINAE_FRIENDLY
-  static_assert(
-      !type_traits_internal::IsHashEnabled<variant<NonHashable>>::value, "");
-  static_assert(!type_traits_internal::IsHashEnabled<
-                    variant<Hashable, NonHashable>>::value,
-                "");
+      !type_traits_internal::IsHashable<variant<Hashable, NonHashable>>::value,
+      "");
 #endif
 
 // MSVC std::hash<std::variant> does not use the index, thus produce the same
@@ -2018,11 +2024,10 @@
     EXPECT_GT(hashcodes.size(), 90);
 
     // test const-qualified
+    static_assert(type_traits_internal::IsHashable<variant<const int>>::value,
+                  "");
     static_assert(
-        type_traits_internal::IsHashEnabled<variant<const int>>::value, "");
-    static_assert(
-        type_traits_internal::IsHashEnabled<variant<const Hashable>>::value,
-        "");
+        type_traits_internal::IsHashable<variant<const Hashable>>::value, "");
     std::hash<absl::variant<const int>> c_hash;
     for (int i = 0; i < 100; ++i) {
       EXPECT_EQ(hash(i), c_hash(i));
@@ -2171,7 +2176,8 @@
 
   // We still need the explicit cast for std::string, because C++ won't apply
   // two user-defined implicit conversions in a row.
-  EXPECT_TRUE(absl::holds_alternative<std::string>(PassThrough(std::string("foo"))));
+  EXPECT_TRUE(
+      absl::holds_alternative<std::string>(PassThrough(std::string("foo"))));
 }
 
 struct Convertible2;
@@ -2195,7 +2201,8 @@
 
 TEST(VariantTest, TestRvalueConversion) {
   variant<double, std::string> var(
-      ConvertVariantTo<variant<double, std::string>>(variant<std::string, int>(0)));
+      ConvertVariantTo<variant<double, std::string>>(
+          variant<std::string, int>(0)));
   ASSERT_TRUE(absl::holds_alternative<double>(var));
   EXPECT_EQ(0.0, absl::get<double>(var));
 
@@ -2287,7 +2294,8 @@
 TEST(VariantTest, TestMoveConversion) {
   using Variant =
       variant<std::unique_ptr<const int>, std::unique_ptr<const std::string>>;
-  using OtherVariant = variant<std::unique_ptr<int>, std::unique_ptr<std::string>>;
+  using OtherVariant =
+      variant<std::unique_ptr<int>, std::unique_ptr<std::string>>;
 
   Variant var(
       ConvertVariantTo<Variant>(OtherVariant{absl::make_unique<int>(0)}));
@@ -2295,8 +2303,8 @@
   ASSERT_NE(absl::get<std::unique_ptr<const int>>(var), nullptr);
   EXPECT_EQ(0, *absl::get<std::unique_ptr<const int>>(var));
 
-  var =
-      ConvertVariantTo<Variant>(OtherVariant(absl::make_unique<std::string>("foo")));
+  var = ConvertVariantTo<Variant>(
+      OtherVariant(absl::make_unique<std::string>("foo")));
   ASSERT_TRUE(absl::holds_alternative<std::unique_ptr<const std::string>>(var));
   EXPECT_EQ("foo", *absl::get<std::unique_ptr<const std::string>>(var));
 }
@@ -2307,7 +2315,8 @@
   // whether moving or copying has occurred.
   using Variant =
       variant<std::shared_ptr<const int>, std::shared_ptr<const std::string>>;
-  using OtherVariant = variant<std::shared_ptr<int>, std::shared_ptr<std::string>>;
+  using OtherVariant =
+      variant<std::shared_ptr<int>, std::shared_ptr<std::string>>;
 
   Variant v1(std::make_shared<const int>(0));
 
@@ -2336,7 +2345,8 @@
 
 TEST(VariantTest, TestRvalueConversionViaConvertVariantTo) {
   variant<double, std::string> var(
-      ConvertVariantTo<variant<double, std::string>>(variant<std::string, int>(3)));
+      ConvertVariantTo<variant<double, std::string>>(
+          variant<std::string, int>(3)));
   EXPECT_THAT(absl::get_if<double>(&var), Pointee(3.0));
 
   var = ConvertVariantTo<variant<double, std::string>>(
@@ -2378,7 +2388,8 @@
 
   variant<const char*, float> source2 = "foo";
   destination = ConvertVariantTo<variant<double, std::string>>(source2);
-  EXPECT_THAT(absl::get_if<std::string>(&destination), Pointee(std::string("foo")));
+  EXPECT_THAT(absl::get_if<std::string>(&destination),
+              Pointee(std::string("foo")));
 
   variant<int, float> source3(42);
   variant<double> singleton(ConvertVariantTo<variant<double>>(source3));
@@ -2415,15 +2426,16 @@
 TEST(VariantTest, TestMoveConversionViaConvertVariantTo) {
   using Variant =
       variant<std::unique_ptr<const int>, std::unique_ptr<const std::string>>;
-  using OtherVariant = variant<std::unique_ptr<int>, std::unique_ptr<std::string>>;
+  using OtherVariant =
+      variant<std::unique_ptr<int>, std::unique_ptr<std::string>>;
 
   Variant var(
       ConvertVariantTo<Variant>(OtherVariant{absl::make_unique<int>(3)}));
   EXPECT_THAT(absl::get_if<std::unique_ptr<const int>>(&var),
               Pointee(Pointee(3)));
 
-  var =
-      ConvertVariantTo<Variant>(OtherVariant(absl::make_unique<std::string>("foo")));
+  var = ConvertVariantTo<Variant>(
+      OtherVariant(absl::make_unique<std::string>("foo")));
   EXPECT_THAT(absl::get_if<std::unique_ptr<const std::string>>(&var),
               Pointee(Pointee(std::string("foo"))));
 }
diff --git a/absl/utility/BUILD.bazel b/absl/utility/BUILD.bazel
index c01b49b..5185ccd 100644
--- a/absl/utility/BUILD.bazel
+++ b/absl/utility/BUILD.bazel
@@ -1,5 +1,5 @@
 load(
-    "//absl:copts.bzl",
+    "//absl:copts/configure_copts.bzl",
     "ABSL_DEFAULT_COPTS",
     "ABSL_TEST_COPTS",
 )
diff --git a/absl/utility/CMakeLists.txt b/absl/utility/CMakeLists.txt
index dc3a631..e1edd19 100644
--- a/absl/utility/CMakeLists.txt
+++ b/absl/utility/CMakeLists.txt
@@ -5,7 +5,7 @@
 # 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
+#      https://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,
@@ -14,39 +14,31 @@
 # limitations under the License.
 #
 
-
-list(APPEND UTILITY_PUBLIC_HEADERS
-  "utility.h"
-)
-
-absl_header_library(
-  TARGET
-    absl_utility
-  PUBLIC_LIBRARIES
-    absl::base
-  EXPORT_NAME
+absl_cc_library(
+  NAME
     utility
+  HDRS
+    "utility.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::base_internal
+    absl::config
+    absl::type_traits
+  PUBLIC
 )
 
-
-#
-## TESTS
-#
-
-# test utility_test
-set(UTILITY_TEST_SRC "utility_test.cc")
-set(UTILITY_TEST_PUBLIC_LIBRARIES
-  absl::base
-  absl::memory
-  absl::strings
-  absl::utility
-)
-
-absl_test(
-  TARGET
+absl_cc_test(
+  NAME
     utility_test
-  SOURCES
-    ${UTILITY_TEST_SRC}
-  PUBLIC_LIBRARIES
-    ${UTILITY_TEST_PUBLIC_LIBRARIES}
+  SRCS
+    "utility_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::utility
+    absl::core_headers
+    absl::memory
+    absl::strings
+    gmock_main
 )
diff --git a/absl/utility/utility.h b/absl/utility/utility.h
index aef4baa..853c1fb 100644
--- a/absl/utility/utility.h
+++ b/absl/utility/utility.h
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -32,10 +32,9 @@
 //
 // References:
 //
-//  http://en.cppreference.com/w/cpp/utility/integer_sequence
-//  http://en.cppreference.com/w/cpp/utility/apply
+//  https://en.cppreference.com/w/cpp/utility/integer_sequence
+//  https://en.cppreference.com/w/cpp/utility/apply
 //  http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3658.html
-//
 
 #ifndef ABSL_UTILITY_UTILITY_H_
 #define ABSL_UTILITY_UTILITY_H_
@@ -234,25 +233,33 @@
 //
 // Example:
 //
-//   class Foo{void Bar(int);};
-//   void user_function(int, string);
-//   void user_function(std::unique_ptr<Foo>);
+//   class Foo {
+//    public:
+//     void Bar(int);
+//   };
+//   void user_function1(int, std::string);
+//   void user_function2(std::unique_ptr<Foo>);
+//   auto user_lambda = [](int, int) {};
 //
 //   int main()
 //   {
-//       std::tuple<int, string> tuple1(42, "bar");
-//       // Invokes the user function overload on int, string.
-//       absl::apply(&user_function, tuple1);
+//       std::tuple<int, std::string> tuple1(42, "bar");
+//       // Invokes the first user function on int, std::string.
+//       absl::apply(&user_function1, tuple1);
 //
-//       auto foo = absl::make_unique<Foo>();
-//       std::tuple<Foo*, int> tuple2(foo.get(), 42);
-//       // Invokes the method Bar on foo with one argument 42.
-//       absl::apply(&Foo::Bar, foo.get(), 42);
-//
-//       std::tuple<std::unique_ptr<Foo>> tuple3(absl::make_unique<Foo>());
+//       std::tuple<std::unique_ptr<Foo>> tuple2(absl::make_unique<Foo>());
 //       // Invokes the user function that takes ownership of the unique
 //       // pointer.
-//       absl::apply(&user_function, std::move(tuple));
+//       absl::apply(&user_function2, std::move(tuple2));
+//
+//       auto foo = absl::make_unique<Foo>();
+//       std::tuple<Foo*, int> tuple3(foo.get(), 42);
+//       // Invokes the method Bar on foo with one argument, 42.
+//       absl::apply(&Foo::Bar, tuple3);
+//
+//       std::tuple<int, int> tuple4(8, 9);
+//       // Invokes a lambda.
+//       absl::apply(user_lambda, tuple4);
 //   }
 template <typename Functor, typename Tuple>
 auto apply(Functor&& functor, Tuple&& t)
diff --git a/absl/utility/utility_test.cc b/absl/utility/utility_test.cc
index 3c447b2..5a4972b 100644
--- a/absl/utility/utility_test.cc
+++ b/absl/utility/utility_test.cc
@@ -4,7 +4,7 @@
 // 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
+//      https://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,
@@ -135,7 +135,7 @@
 
 template <typename Tup, size_t... Is>
 std::vector<std::string> TupStringVecImpl(const Tup& tup,
-                                     absl::index_sequence<Is...>) {
+                                          absl::index_sequence<Is...>) {
   return {Fmt(std::get<Is>(tup))...};
 }
 
diff --git a/api/array_view.h b/api/array_view.h
index efc642d..bf91484 100644
--- a/api/array_view.h
+++ b/api/array_view.h
@@ -231,6 +231,12 @@
                               HasDataAndSize<U, T>::value>::type* = nullptr>
   ArrayView(U& u)  // NOLINT
       : ArrayView(u.data(), u.size()) {}
+  template <
+      typename U,
+      typename std::enable_if<Size == impl::kArrayViewVarSize &&
+                              HasDataAndSize<U, T>::value>::type* = nullptr>
+  ArrayView(const U& u)  // NOLINT(runtime/explicit)
+      : ArrayView(u.data(), u.size()) {}
 
   // Indexing and iteration. These allow mutation even if the ArrayView is
   // const, because the ArrayView doesn't own the array. (To prevent mutation,
diff --git a/api/array_view_unittest.cc b/api/array_view_unittest.cc
index 694ed0b..62b51c0 100644
--- a/api/array_view_unittest.cc
+++ b/api/array_view_unittest.cc
@@ -28,16 +28,21 @@
 using ::testing::IsEmpty;
 
 template <typename T>
-void Call(ArrayView<T>) {}
+size_t Call(ArrayView<T> av) {
+  return av.size();
+}
+
+template <typename T, size_t N>
+void CallFixed(ArrayView<T, N> av) {}
 
 }  // namespace
 
 TEST(ArrayViewTest, TestConstructFromPtrAndArray) {
   char arr[] = "Arrr!";
   const char carr[] = "Carrr!";
-  Call<const char>(arr);
-  Call<const char>(carr);
-  Call<char>(arr);
+  EXPECT_EQ(6u, Call<const char>(arr));
+  EXPECT_EQ(7u, Call<const char>(carr));
+  EXPECT_EQ(6u, Call<char>(arr));
   // Call<char>(carr);  // Compile error, because can't drop const.
   // Call<int>(arr);  // Compile error, because incompatible types.
   ArrayView<int*> x;
@@ -182,6 +187,8 @@
 }
 
 TEST(ArrayViewTest, TestStdArray) {
+  EXPECT_EQ(4u, Call<const int>(std::array<int, 4>{1, 2, 3, 4}));
+  CallFixed<const int, 3>(std::array<int, 3>{2, 3, 4});
   constexpr size_t size = 5;
   std::array<float, size> arr{};
   // Fixed size view.
@@ -214,11 +221,12 @@
 }
 
 TEST(ArrayViewTest, TestStdVector) {
+  EXPECT_EQ(3u, Call<const int>(std::vector<int>{4, 5, 6}));
   std::vector<int> v;
   v.push_back(3);
   v.push_back(11);
-  Call<const int>(v);
-  Call<int>(v);
+  EXPECT_EQ(2u, Call<const int>(v));
+  EXPECT_EQ(2u, Call<int>(v));
   // Call<unsigned int>(v);  // Compile error, because incompatible types.
   ArrayView<int> x = v;
   EXPECT_EQ(2u, x.size());
@@ -229,7 +237,7 @@
   EXPECT_EQ(v.data(), y.data());
   // ArrayView<double> d = v;  // Compile error, because incompatible types.
   const std::vector<int> cv;
-  Call<const int>(cv);
+  EXPECT_EQ(0u, Call<const int>(cv));
   // Call<int>(cv);  // Compile error, because can't drop const.
   ArrayView<const int> z = cv;
   EXPECT_EQ(0u, z.size());
@@ -239,8 +247,8 @@
 
 TEST(ArrayViewTest, TestRtcBuffer) {
   rtc::Buffer b = "so buffer";
-  Call<const uint8_t>(b);
-  Call<uint8_t>(b);
+  EXPECT_EQ(10u, Call<const uint8_t>(b));
+  EXPECT_EQ(10u, Call<uint8_t>(b));
   // Call<int8_t>(b);  // Compile error, because incompatible types.
   ArrayView<uint8_t> x = b;
   EXPECT_EQ(10u, x.size());
@@ -251,7 +259,7 @@
   EXPECT_EQ(b.data(), y.data());
   // ArrayView<char> d = b;  // Compile error, because incompatible types.
   const rtc::Buffer cb = "very const";
-  Call<const uint8_t>(cb);
+  EXPECT_EQ(11u, Call<const uint8_t>(cb));
   // Call<uint8_t>(cb);  // Compile error, because can't drop const.
   ArrayView<const uint8_t> z = cb;
   EXPECT_EQ(11u, z.size());
diff --git a/api/async_resolver_factory.h b/api/async_resolver_factory.h
new file mode 100644
index 0000000..93d3f79
--- /dev/null
+++ b/api/async_resolver_factory.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_ASYNC_RESOLVER_FACTORY_H_
+#define API_ASYNC_RESOLVER_FACTORY_H_
+
+#include "rtc_base/async_resolver_interface.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_ASYNC_RESOLVER_FACTORY_H_
diff --git a/api/audio/audio_frame.cc b/api/audio/audio_frame.cc
index 75d30b0..1e706b9 100644
--- a/api/audio/audio_frame.cc
+++ b/api/audio/audio_frame.cc
@@ -13,7 +13,7 @@
 #include <string.h>
 
 #include "rtc_base/checks.h"
-#include "rtc_base/timeutils.h"
+#include "rtc_base/time_utils.h"
 
 namespace webrtc {
 
diff --git a/api/audio/audio_frame.h b/api/audio/audio_frame.h
index dd6ac02..8f1dc62 100644
--- a/api/audio/audio_frame.h
+++ b/api/audio/audio_frame.h
@@ -14,7 +14,7 @@
 #include <stddef.h>
 #include <stdint.h>
 
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
diff --git a/api/audio/audio_mixer.h b/api/audio/audio_mixer.h
index 14eefc1..b290cfa 100644
--- a/api/audio/audio_mixer.h
+++ b/api/audio/audio_mixer.h
@@ -14,7 +14,7 @@
 #include <memory>
 
 #include "api/audio/audio_frame.h"
-#include "rtc_base/refcount.h"
+#include "rtc_base/ref_count.h"
 
 namespace webrtc {
 
diff --git a/api/audio/echo_canceller3_config.cc b/api/audio/echo_canceller3_config.cc
index 3eb2a8d..a560c9e 100644
--- a/api/audio/echo_canceller3_config.cc
+++ b/api/audio/echo_canceller3_config.cc
@@ -87,19 +87,11 @@
     c->delay.down_sampling_factor = 4;
     res = false;
   }
-  if (c->delay.delay_headroom_blocks <= 1 &&
-      c->delay.hysteresis_limit_1_blocks == 1) {
-    c->delay.hysteresis_limit_1_blocks = 0;
-    res = false;
-  }
+
   res = res & Limit(&c->delay.default_delay, 0, 5000);
   res = res & Limit(&c->delay.num_filters, 0, 5000);
-  res = res & Limit(&c->delay.api_call_jitter_blocks, 1, 5000);
-  res = res & Limit(&c->delay.min_echo_path_delay_blocks, 0, 5000);
-  res = res & Limit(&c->delay.delay_headroom_blocks, 0, 5000);
-  res = res & Limit(&c->delay.hysteresis_limit_1_blocks, 0, 5000);
-  res = res & Limit(&c->delay.hysteresis_limit_2_blocks, 0, 5000);
-  res = res & Limit(&c->delay.skew_hysteresis_blocks, 0, 5000);
+  res = res & Limit(&c->delay.delay_headroom_samples, 0, 5000);
+  res = res & Limit(&c->delay.hysteresis_limit_blocks, 0, 5000);
   res = res & Limit(&c->delay.fixed_capture_delay_samples, 0, 5000);
   res = res & Limit(&c->delay.delay_estimate_smoothing, 0.f, 1.f);
   res = res & Limit(&c->delay.delay_candidate_detection_threshold, 0.f, 1.f);
@@ -150,9 +142,7 @@
   }
   res = res & Limit(&c->erle.num_sections, 1, c->filter.main.length_blocks);
 
-  res = res & Limit(&c->ep_strength.lf, 0.f, 1000000.f);
-  res = res & Limit(&c->ep_strength.mf, 0.f, 1000000.f);
-  res = res & Limit(&c->ep_strength.hf, 0.f, 1000000.f);
+  res = res & Limit(&c->ep_strength.default_gain, 0.f, 1000000.f);
   res = res & Limit(&c->ep_strength.default_len, -1.f, 1.f);
 
   res =
@@ -174,15 +164,6 @@
   res = res & Limit(&c->render_levels.poor_excitation_render_limit_ds8, 0.f,
                     32768.f * 32768.f);
 
-  res =
-      res & Limit(&c->echo_removal_control.gain_rampup.initial_gain, 0.f, 1.f);
-  res = res & Limit(&c->echo_removal_control.gain_rampup.first_non_zero_gain,
-                    0.f, 1.f);
-  res = res & Limit(&c->echo_removal_control.gain_rampup.non_zero_gain_blocks,
-                    0, 100000);
-  res = res &
-        Limit(&c->echo_removal_control.gain_rampup.full_gain_blocks, 0, 100000);
-
   res = res & Limit(&c->echo_model.noise_floor_hold, 0, 1000);
   res = res & Limit(&c->echo_model.min_noise_floor_power, 0, 2000000.f);
   res = res & Limit(&c->echo_model.stationary_gate_slope, 0, 1000000.f);
@@ -244,12 +225,6 @@
 
   res = res & Limit(&c->suppressor.floor_first_increase, 0.f, 1000000.f);
 
-  if (c->delay.delay_headroom_blocks >
-      c->filter.main_initial.length_blocks - 1) {
-    c->delay.delay_headroom_blocks = c->filter.main_initial.length_blocks - 1;
-    res = false;
-  }
-
   return res;
 }
 }  // namespace webrtc
diff --git a/api/audio/echo_canceller3_config.h b/api/audio/echo_canceller3_config.h
index ffe17f2..7dcc7dd 100644
--- a/api/audio/echo_canceller3_config.h
+++ b/api/audio/echo_canceller3_config.h
@@ -27,7 +27,6 @@
   EchoCanceller3Config(const EchoCanceller3Config& e);
 
   struct Buffering {
-    bool use_new_render_buffering = true;
     size_t excess_render_detection_interval_blocks = 250;
     size_t max_allowed_excess_render_blocks = 8;
   } buffering;
@@ -38,12 +37,8 @@
     size_t default_delay = 5;
     size_t down_sampling_factor = 4;
     size_t num_filters = 5;
-    size_t api_call_jitter_blocks = 26;
-    size_t min_echo_path_delay_blocks = 0;
-    size_t delay_headroom_blocks = 2;
-    size_t hysteresis_limit_1_blocks = 1;
-    size_t hysteresis_limit_2_blocks = 1;
-    size_t skew_hysteresis_blocks = 3;
+    size_t delay_headroom_samples = 32;
+    size_t hysteresis_limit_blocks = 1;
     size_t fixed_capture_delay_samples = 0;
     float delay_estimate_smoothing = 0.7f;
     float delay_candidate_detection_threshold = 0.2f;
@@ -91,9 +86,7 @@
   } erle;
 
   struct EpStrength {
-    float lf = 1.f;
-    float mf = 1.f;
-    float hf = 1.f;
+    float default_gain = 1.f;
     float default_len = 0.83f;
     bool reverb_based_on_render = true;
     bool echo_can_saturate = true;
@@ -118,12 +111,6 @@
   } render_levels;
 
   struct EchoRemovalControl {
-    struct GainRampup {
-      float initial_gain = 0.0f;
-      float first_non_zero_gain = 0.001f;
-      int non_zero_gain_blocks = 187;
-      int full_gain_blocks = 312;
-    } gain_rampup;
     bool has_clock_drift = false;
     bool linear_and_stable_echo_path = false;
   } echo_removal_control;
diff --git a/api/audio/echo_canceller3_config_json.cc b/api/audio/echo_canceller3_config_json.cc
index 01a831c..4c8c8ab 100644
--- a/api/audio/echo_canceller3_config_json.cc
+++ b/api/audio/echo_canceller3_config_json.cc
@@ -9,9 +9,11 @@
  */
 #include "api/audio/echo_canceller3_config_json.h"
 
+#include <stddef.h>
 #include <string>
 #include <vector>
 
+#include "rtc_base/checks.h"
 #include "rtc_base/logging.h"
 #include "rtc_base/strings/json.h"
 #include "rtc_base/strings/string_builder.h"
@@ -136,8 +138,6 @@
 
   Json::Value section;
   if (rtc::GetValueFromJsonObject(root, "buffering", &section)) {
-    ReadParam(section, "use_new_render_buffering",
-              &cfg.buffering.use_new_render_buffering);
     ReadParam(section, "excess_render_detection_interval_blocks",
               &cfg.buffering.excess_render_detection_interval_blocks);
     ReadParam(section, "max_allowed_excess_render_blocks",
@@ -148,18 +148,10 @@
     ReadParam(section, "default_delay", &cfg.delay.default_delay);
     ReadParam(section, "down_sampling_factor", &cfg.delay.down_sampling_factor);
     ReadParam(section, "num_filters", &cfg.delay.num_filters);
-    ReadParam(section, "api_call_jitter_blocks",
-              &cfg.delay.api_call_jitter_blocks);
-    ReadParam(section, "min_echo_path_delay_blocks",
-              &cfg.delay.min_echo_path_delay_blocks);
-    ReadParam(section, "delay_headroom_blocks",
-              &cfg.delay.delay_headroom_blocks);
-    ReadParam(section, "hysteresis_limit_1_blocks",
-              &cfg.delay.hysteresis_limit_1_blocks);
-    ReadParam(section, "hysteresis_limit_2_blocks",
-              &cfg.delay.hysteresis_limit_2_blocks);
-    ReadParam(section, "skew_hysteresis_blocks",
-              &cfg.delay.skew_hysteresis_blocks);
+    ReadParam(section, "delay_headroom_samples",
+              &cfg.delay.delay_headroom_samples);
+    ReadParam(section, "hysteresis_limit_blocks",
+              &cfg.delay.hysteresis_limit_blocks);
     ReadParam(section, "fixed_capture_delay_samples",
               &cfg.delay.fixed_capture_delay_samples);
     ReadParam(section, "delay_estimate_smoothing",
@@ -201,9 +193,7 @@
   }
 
   if (rtc::GetValueFromJsonObject(aec3_root, "ep_strength", &section)) {
-    ReadParam(section, "lf", &cfg.ep_strength.lf);
-    ReadParam(section, "mf", &cfg.ep_strength.mf);
-    ReadParam(section, "hf", &cfg.ep_strength.hf);
+    ReadParam(section, "default_gain", &cfg.ep_strength.default_gain);
     ReadParam(section, "default_len", &cfg.ep_strength.default_len);
     ReadParam(section, "reverb_based_on_render",
               &cfg.ep_strength.reverb_based_on_render);
@@ -241,17 +231,6 @@
 
   if (rtc::GetValueFromJsonObject(aec3_root, "echo_removal_control",
                                   &section)) {
-    Json::Value subsection;
-    if (rtc::GetValueFromJsonObject(section, "gain_rampup", &subsection)) {
-      ReadParam(subsection, "initial_gain",
-                &cfg.echo_removal_control.gain_rampup.initial_gain);
-      ReadParam(subsection, "first_non_zero_gain",
-                &cfg.echo_removal_control.gain_rampup.first_non_zero_gain);
-      ReadParam(subsection, "non_zero_gain_blocks",
-                &cfg.echo_removal_control.gain_rampup.non_zero_gain_blocks);
-      ReadParam(subsection, "full_gain_blocks",
-                &cfg.echo_removal_control.gain_rampup.full_gain_blocks);
-    }
     ReadParam(section, "has_clock_drift",
               &cfg.echo_removal_control.has_clock_drift);
     ReadParam(section, "linear_and_stable_echo_path",
@@ -352,17 +331,9 @@
   ost << "\"down_sampling_factor\": " << config.delay.down_sampling_factor
       << ",";
   ost << "\"num_filters\": " << config.delay.num_filters << ",";
-  ost << "\"api_call_jitter_blocks\": " << config.delay.api_call_jitter_blocks
+  ost << "\"delay_headroom_samples\": " << config.delay.delay_headroom_samples
       << ",";
-  ost << "\"min_echo_path_delay_blocks\": "
-      << config.delay.min_echo_path_delay_blocks << ",";
-  ost << "\"delay_headroom_blocks\": " << config.delay.delay_headroom_blocks
-      << ",";
-  ost << "\"hysteresis_limit_1_blocks\": "
-      << config.delay.hysteresis_limit_1_blocks << ",";
-  ost << "\"hysteresis_limit_2_blocks\": "
-      << config.delay.hysteresis_limit_2_blocks << ",";
-  ost << "\"skew_hysteresis_blocks\": " << config.delay.skew_hysteresis_blocks
+  ost << "\"hysteresis_limit_blocks\": " << config.delay.hysteresis_limit_blocks
       << ",";
   ost << "\"fixed_capture_delay_samples\": "
       << config.delay.fixed_capture_delay_samples << ",";
@@ -431,9 +402,7 @@
   ost << "},";
 
   ost << "\"ep_strength\": {";
-  ost << "\"lf\": " << config.ep_strength.lf << ",";
-  ost << "\"mf\": " << config.ep_strength.mf << ",";
-  ost << "\"hf\": " << config.ep_strength.hf << ",";
+  ost << "\"default_gain\": " << config.ep_strength.default_gain << ",";
   ost << "\"default_len\": " << config.ep_strength.default_len << ",";
   ost << "\"reverb_based_on_render\": "
       << (config.ep_strength.reverb_based_on_render ? "true" : "false") << ",";
@@ -474,16 +443,6 @@
   ost << "},";
 
   ost << "\"echo_removal_control\": {";
-  ost << "\"gain_rampup\": {";
-  ost << "\"initial_gain\": "
-      << config.echo_removal_control.gain_rampup.initial_gain << ",";
-  ost << "\"first_non_zero_gain\": "
-      << config.echo_removal_control.gain_rampup.first_non_zero_gain << ",";
-  ost << "\"non_zero_gain_blocks\": "
-      << config.echo_removal_control.gain_rampup.non_zero_gain_blocks << ",";
-  ost << "\"full_gain_blocks\": "
-      << config.echo_removal_control.gain_rampup.full_gain_blocks;
-  ost << "},";
   ost << "\"has_clock_drift\": "
       << (config.echo_removal_control.has_clock_drift ? "true" : "false")
       << ",";
diff --git a/api/audio_options.cc b/api/audio_options.cc
index e33214b..16c0430 100644
--- a/api/audio_options.cc
+++ b/api/audio_options.cc
@@ -10,6 +10,7 @@
 
 #include "api/audio_options.h"
 
+#include "api/array_view.h"
 #include "rtc_base/strings/string_builder.h"
 
 namespace cricket {
@@ -51,6 +52,8 @@
           change.audio_jitter_buffer_fast_accelerate);
   SetFrom(&audio_jitter_buffer_min_delay_ms,
           change.audio_jitter_buffer_min_delay_ms);
+  SetFrom(&audio_jitter_buffer_enable_rtx_handling,
+          change.audio_jitter_buffer_enable_rtx_handling);
   SetFrom(&typing_detection, change.typing_detection);
   SetFrom(&experimental_agc, change.experimental_agc);
   SetFrom(&extended_filter_aec, change.extended_filter_aec);
@@ -80,6 +83,8 @@
              o.audio_jitter_buffer_fast_accelerate &&
          audio_jitter_buffer_min_delay_ms ==
              o.audio_jitter_buffer_min_delay_ms &&
+         audio_jitter_buffer_enable_rtx_handling ==
+             o.audio_jitter_buffer_enable_rtx_handling &&
          typing_detection == o.typing_detection &&
          experimental_agc == o.experimental_agc &&
          extended_filter_aec == o.extended_filter_aec &&
@@ -113,6 +118,8 @@
                 audio_jitter_buffer_fast_accelerate);
   ToStringIfSet(&result, "audio_jitter_buffer_min_delay_ms",
                 audio_jitter_buffer_min_delay_ms);
+  ToStringIfSet(&result, "audio_jitter_buffer_enable_rtx_handling",
+                audio_jitter_buffer_enable_rtx_handling);
   ToStringIfSet(&result, "typing", typing_detection);
   ToStringIfSet(&result, "experimental_agc", experimental_agc);
   ToStringIfSet(&result, "extended_filter_aec", extended_filter_aec);
diff --git a/api/audio_options.h b/api/audio_options.h
index c2d1f44..478bff6 100644
--- a/api/audio_options.h
+++ b/api/audio_options.h
@@ -56,6 +56,8 @@
   absl::optional<bool> audio_jitter_buffer_fast_accelerate;
   // Audio receiver jitter buffer (NetEq) minimum target delay in milliseconds.
   absl::optional<int> audio_jitter_buffer_min_delay_ms;
+  // Audio receiver jitter buffer (NetEq) should handle retransmitted packets.
+  absl::optional<bool> audio_jitter_buffer_enable_rtx_handling;
   // Audio processing to detect typing.
   absl::optional<bool> typing_detection;
   absl::optional<bool> experimental_agc;
diff --git a/api/candidate.cc b/api/candidate.cc
index 275b173..c857f89 100644
--- a/api/candidate.cc
+++ b/api/candidate.cc
@@ -11,7 +11,7 @@
 #include "api/candidate.h"
 
 #include "rtc_base/helpers.h"
-#include "rtc_base/ipaddress.h"
+#include "rtc_base/ip_address.h"
 #include "rtc_base/strings/string_builder.h"
 
 namespace cricket {
@@ -125,4 +125,19 @@
   return !(*this == o);
 }
 
+Candidate Candidate::ToSanitizedCopy(bool use_hostname_address,
+                                     bool filter_related_address) const {
+  Candidate copy(*this);
+  if (use_hostname_address) {
+    rtc::SocketAddress hostname_only_addr(address().hostname(),
+                                          address().port());
+    copy.set_address(hostname_only_addr);
+  }
+  if (filter_related_address) {
+    copy.set_related_address(
+        rtc::EmptySocketAddressWithFamily(copy.address().family()));
+  }
+  return copy;
+}
+
 }  // namespace cricket
diff --git a/api/candidate.h b/api/candidate.h
index 4c650d9..7452055 100644
--- a/api/candidate.h
+++ b/api/candidate.h
@@ -19,7 +19,7 @@
 
 #include "rtc_base/checks.h"
 #include "rtc_base/network_constants.h"
-#include "rtc_base/socketaddress.h"
+#include "rtc_base/socket_address.h"
 #include "rtc_base/system/rtc_export.h"
 
 namespace cricket {
@@ -166,6 +166,16 @@
   bool operator==(const Candidate& o) const;
   bool operator!=(const Candidate& o) const;
 
+  // Returns a sanitized copy configured by the given booleans. If
+  // |use_host_address| is true, the returned copy has its IP removed from
+  // |address()|, which leads |address()| to be a hostname address. If
+  // |filter_related_address|, the returned copy has its related address reset
+  // to the wildcard address (i.e. 0.0.0.0 for IPv4 and :: for IPv6). Note that
+  // setting both booleans to false returns an identical copy to the original
+  // candidate.
+  Candidate ToSanitizedCopy(bool use_hostname_address,
+                            bool filter_related_address) const;
+
  private:
   std::string ToStringInternal(bool sensitive) const;
 
diff --git a/api/create_peerconnection_factory.cc b/api/create_peerconnection_factory.cc
index 1a6d086..0d15e8c 100644
--- a/api/create_peerconnection_factory.cc
+++ b/api/create_peerconnection_factory.cc
@@ -13,104 +13,26 @@
 #include <memory>
 #include <utility>
 
-#include "api/call/callfactoryinterface.h"
-#include "api/peerconnectioninterface.h"
+#include "api/audio/audio_mixer.h"
+#include "api/audio_codecs/audio_decoder_factory.h"
+#include "api/audio_codecs/audio_encoder_factory.h"
+#include "api/call/call_factory_interface.h"
+#include "api/fec_controller.h"
+#include "api/peer_connection_interface.h"
+#include "api/scoped_refptr.h"
+#include "api/transport/network_control.h"
 #include "api/video_codecs/video_decoder_factory.h"
 #include "api/video_codecs/video_encoder_factory.h"
 #include "logging/rtc_event_log/rtc_event_log_factory.h"
 #include "logging/rtc_event_log/rtc_event_log_factory_interface.h"
-#include "media/engine/webrtcmediaengine.h"
+#include "media/base/media_engine.h"
+#include "media/engine/webrtc_media_engine.h"
 #include "modules/audio_device/include/audio_device.h"
 #include "modules/audio_processing/include/audio_processing.h"
-#include "rtc_base/bind.h"
-#include "rtc_base/scoped_ref_ptr.h"
 #include "rtc_base/thread.h"
 
 namespace webrtc {
 
-#if defined(USE_BUILTIN_SW_CODECS)
-rtc::scoped_refptr<PeerConnectionFactoryInterface> CreatePeerConnectionFactory(
-    rtc::scoped_refptr<AudioEncoderFactory> audio_encoder_factory,
-    rtc::scoped_refptr<AudioDecoderFactory> audio_decoder_factory) {
-  return CreatePeerConnectionFactoryWithAudioMixer(
-      nullptr /*network_thread*/, nullptr /*worker_thread*/,
-      nullptr /*signaling_thread*/, nullptr /*default_adm*/,
-      audio_encoder_factory, audio_decoder_factory,
-      nullptr /*video_encoder_factory*/, nullptr /*video_decoder_factory*/,
-      nullptr /*audio_mixer*/);
-}
-
-// Note: all the other CreatePeerConnectionFactory variants just end up calling
-// this, ultimately.
-rtc::scoped_refptr<PeerConnectionFactoryInterface> CreatePeerConnectionFactory(
-    rtc::Thread* network_thread,
-    rtc::Thread* worker_thread,
-    rtc::Thread* signaling_thread,
-    AudioDeviceModule* default_adm,
-    rtc::scoped_refptr<AudioEncoderFactory> audio_encoder_factory,
-    rtc::scoped_refptr<AudioDecoderFactory> audio_decoder_factory,
-    cricket::WebRtcVideoEncoderFactory* video_encoder_factory,
-    cricket::WebRtcVideoDecoderFactory* video_decoder_factory,
-    rtc::scoped_refptr<AudioMixer> audio_mixer,
-    rtc::scoped_refptr<AudioProcessing> audio_processing) {
-  rtc::scoped_refptr<AudioProcessing> audio_processing_use = audio_processing;
-  if (!audio_processing_use) {
-    audio_processing_use = AudioProcessingBuilder().Create();
-  }
-
-  std::unique_ptr<cricket::MediaEngineInterface> media_engine(
-      cricket::WebRtcMediaEngineFactory::Create(
-          default_adm, audio_encoder_factory, audio_decoder_factory,
-          video_encoder_factory, video_decoder_factory, audio_mixer,
-          audio_processing_use));
-
-  std::unique_ptr<CallFactoryInterface> call_factory = CreateCallFactory();
-
-  std::unique_ptr<RtcEventLogFactoryInterface> event_log_factory =
-      CreateRtcEventLogFactory();
-
-  return CreateModularPeerConnectionFactory(
-      network_thread, worker_thread, signaling_thread, std::move(media_engine),
-      std::move(call_factory), std::move(event_log_factory));
-}
-
-rtc::scoped_refptr<PeerConnectionFactoryInterface> CreatePeerConnectionFactory(
-    rtc::Thread* network_thread,
-    rtc::Thread* worker_thread,
-    rtc::Thread* signaling_thread,
-    AudioDeviceModule* default_adm,
-    rtc::scoped_refptr<AudioEncoderFactory> audio_encoder_factory,
-    rtc::scoped_refptr<AudioDecoderFactory> audio_decoder_factory,
-    cricket::WebRtcVideoEncoderFactory* video_encoder_factory,
-    cricket::WebRtcVideoDecoderFactory* video_decoder_factory,
-    rtc::scoped_refptr<AudioMixer> audio_mixer,
-    rtc::scoped_refptr<AudioProcessing> audio_processing,
-    std::unique_ptr<FecControllerFactoryInterface> fec_controller_factory,
-    std::unique_ptr<NetworkControllerFactoryInterface>
-        network_controller_factory) {
-  rtc::scoped_refptr<AudioProcessing> audio_processing_use = audio_processing;
-  if (!audio_processing_use) {
-    audio_processing_use = AudioProcessingBuilder().Create();
-  }
-
-  std::unique_ptr<cricket::MediaEngineInterface> media_engine(
-      cricket::WebRtcMediaEngineFactory::Create(
-          default_adm, audio_encoder_factory, audio_decoder_factory,
-          video_encoder_factory, video_decoder_factory, audio_mixer,
-          audio_processing_use));
-
-  std::unique_ptr<CallFactoryInterface> call_factory = CreateCallFactory();
-
-  std::unique_ptr<RtcEventLogFactoryInterface> event_log_factory =
-      CreateRtcEventLogFactory();
-
-  return CreateModularPeerConnectionFactory(
-      network_thread, worker_thread, signaling_thread, std::move(media_engine),
-      std::move(call_factory), std::move(event_log_factory),
-      std::move(fec_controller_factory), std::move(network_controller_factory));
-}
-#endif
-
 rtc::scoped_refptr<PeerConnectionFactoryInterface> CreatePeerConnectionFactory(
     rtc::Thread* network_thread,
     rtc::Thread* worker_thread,
@@ -145,38 +67,4 @@
   return CreateModularPeerConnectionFactory(std::move(dependencies));
 }
 
-#if defined(USE_BUILTIN_SW_CODECS)
-rtc::scoped_refptr<PeerConnectionFactoryInterface>
-CreatePeerConnectionFactoryWithAudioMixer(
-    rtc::Thread* network_thread,
-    rtc::Thread* worker_thread,
-    rtc::Thread* signaling_thread,
-    AudioDeviceModule* default_adm,
-    rtc::scoped_refptr<AudioEncoderFactory> audio_encoder_factory,
-    rtc::scoped_refptr<AudioDecoderFactory> audio_decoder_factory,
-    cricket::WebRtcVideoEncoderFactory* video_encoder_factory,
-    cricket::WebRtcVideoDecoderFactory* video_decoder_factory,
-    rtc::scoped_refptr<AudioMixer> audio_mixer) {
-  return CreatePeerConnectionFactory(
-      network_thread, worker_thread, signaling_thread, default_adm,
-      audio_encoder_factory, audio_decoder_factory, video_encoder_factory,
-      video_decoder_factory, audio_mixer, nullptr);
-}
-
-rtc::scoped_refptr<PeerConnectionFactoryInterface> CreatePeerConnectionFactory(
-    rtc::Thread* network_thread,
-    rtc::Thread* worker_thread,
-    rtc::Thread* signaling_thread,
-    AudioDeviceModule* default_adm,
-    rtc::scoped_refptr<AudioEncoderFactory> audio_encoder_factory,
-    rtc::scoped_refptr<AudioDecoderFactory> audio_decoder_factory,
-    cricket::WebRtcVideoEncoderFactory* video_encoder_factory,
-    cricket::WebRtcVideoDecoderFactory* video_decoder_factory) {
-  return CreatePeerConnectionFactoryWithAudioMixer(
-      network_thread, worker_thread, signaling_thread, default_adm,
-      audio_encoder_factory, audio_decoder_factory, video_encoder_factory,
-      video_decoder_factory, nullptr);
-}
-#endif
-
 }  // namespace webrtc
diff --git a/api/create_peerconnection_factory.h b/api/create_peerconnection_factory.h
index baa50c7..40f1276 100644
--- a/api/create_peerconnection_factory.h
+++ b/api/create_peerconnection_factory.h
@@ -17,9 +17,10 @@
 #include "api/audio_codecs/audio_decoder_factory.h"
 #include "api/audio_codecs/audio_encoder_factory.h"
 #include "api/fec_controller.h"
-#include "api/peerconnectioninterface.h"
+#include "api/peer_connection_interface.h"
+#include "api/scoped_refptr.h"
 #include "api/transport/network_control.h"
-#include "rtc_base/scoped_ref_ptr.h"
+#include "rtc_base/deprecation.h"
 
 namespace rtc {
 // TODO(bugs.webrtc.org/9987): Move rtc::Thread to api/ or expose a better
@@ -28,104 +29,14 @@
 class Thread;
 }  // namespace rtc
 
-namespace cricket {
-class WebRtcVideoDecoderFactory;
-class WebRtcVideoEncoderFactory;
-}  // namespace cricket
-
 namespace webrtc {
 
 class AudioDeviceModule;
 class AudioProcessing;
 
-#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"
-// for the PeerConnectionFactory it creates.
-//
-// As such, if the current thread is not already running an rtc::Thread message
-// loop, an application using this method must eventually either call
-// rtc::Thread::Current()->Run(), or call
-// rtc::Thread::Current()->ProcessMessages() within the application's own
-// message loop.
-RTC_EXPORT rtc::scoped_refptr<PeerConnectionFactoryInterface>
-CreatePeerConnectionFactory(
-    rtc::scoped_refptr<AudioEncoderFactory> audio_encoder_factory,
-    rtc::scoped_refptr<AudioDecoderFactory> audio_decoder_factory);
-
-// Create a new instance of PeerConnectionFactoryInterface.
-//
-// |network_thread|, |worker_thread| and |signaling_thread| are
-// the only mandatory parameters.
-//
-// If non-null, a reference is added to |default_adm|, and ownership of
-// |video_encoder_factory| and |video_decoder_factory| is transferred to the
-// returned factory.
-// TODO(deadbeef): Use rtc::scoped_refptr<> and std::unique_ptr<> to make this
-// ownership transfer and ref counting more obvious.
-RTC_EXPORT rtc::scoped_refptr<PeerConnectionFactoryInterface>
-CreatePeerConnectionFactory(
-    rtc::Thread* network_thread,
-    rtc::Thread* worker_thread,
-    rtc::Thread* signaling_thread,
-    AudioDeviceModule* default_adm,
-    rtc::scoped_refptr<AudioEncoderFactory> audio_encoder_factory,
-    rtc::scoped_refptr<AudioDecoderFactory> audio_decoder_factory,
-    cricket::WebRtcVideoEncoderFactory* video_encoder_factory,
-    cricket::WebRtcVideoDecoderFactory* video_decoder_factory);
-
-// Create a new instance of PeerConnectionFactoryInterface with optional
-// external audio mixed and audio processing modules.
-//
-// If |audio_mixer| is null, an internal audio mixer will be created and used.
-// If |audio_processing| is null, an internal audio processing module will be
-// created and used.
-RTC_EXPORT rtc::scoped_refptr<PeerConnectionFactoryInterface>
-CreatePeerConnectionFactory(
-    rtc::Thread* network_thread,
-    rtc::Thread* worker_thread,
-    rtc::Thread* signaling_thread,
-    AudioDeviceModule* default_adm,
-    rtc::scoped_refptr<AudioEncoderFactory> audio_encoder_factory,
-    rtc::scoped_refptr<AudioDecoderFactory> audio_decoder_factory,
-    cricket::WebRtcVideoEncoderFactory* video_encoder_factory,
-    cricket::WebRtcVideoDecoderFactory* video_decoder_factory,
-    rtc::scoped_refptr<AudioMixer> audio_mixer,
-    rtc::scoped_refptr<AudioProcessing> audio_processing);
-
-// Create a new instance of PeerConnectionFactoryInterface with optional
-// external audio mixer, audio processing, and fec controller modules.
-//
-// If |audio_mixer| is null, an internal audio mixer will be created and used.
-// If |audio_processing| is null, an internal audio processing module will be
-// created and used.
-// If |fec_controller_factory| is null, an internal fec controller module will
-// be created and used.
-// If |network_controller_factory| is provided, it will be used if enabled via
-// field trial.
-RTC_EXPORT rtc::scoped_refptr<PeerConnectionFactoryInterface>
-CreatePeerConnectionFactory(
-    rtc::Thread* network_thread,
-    rtc::Thread* worker_thread,
-    rtc::Thread* signaling_thread,
-    AudioDeviceModule* default_adm,
-    rtc::scoped_refptr<AudioEncoderFactory> audio_encoder_factory,
-    rtc::scoped_refptr<AudioDecoderFactory> audio_decoder_factory,
-    cricket::WebRtcVideoEncoderFactory* video_encoder_factory,
-    cricket::WebRtcVideoDecoderFactory* video_decoder_factory,
-    rtc::scoped_refptr<AudioMixer> audio_mixer,
-    rtc::scoped_refptr<AudioProcessing> audio_processing,
-    std::unique_ptr<FecControllerFactoryInterface> fec_controller_factory,
-    std::unique_ptr<NetworkControllerFactoryInterface>
-        network_controller_factory = nullptr);
-#endif  // defined(USE_BUILTIN_SW_CODECS)
-
 // Create a new instance of PeerConnectionFactoryInterface with optional video
 // codec factories. These video factories represents all video codecs, i.e. no
 // extra internal video codecs will be added.
-// When building WebRTC with rtc_use_builtin_sw_codecs = false, this is the
-// only available CreatePeerConnectionFactory overload.
 RTC_EXPORT rtc::scoped_refptr<PeerConnectionFactoryInterface>
 CreatePeerConnectionFactory(
     rtc::Thread* network_thread,
@@ -139,41 +50,6 @@
     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.
-//
-// If |audio_mixer| is null, an internal audio mixer will be created and used.
-RTC_EXPORT rtc::scoped_refptr<PeerConnectionFactoryInterface>
-CreatePeerConnectionFactoryWithAudioMixer(
-    rtc::Thread* network_thread,
-    rtc::Thread* worker_thread,
-    rtc::Thread* signaling_thread,
-    AudioDeviceModule* default_adm,
-    rtc::scoped_refptr<AudioEncoderFactory> audio_encoder_factory,
-    rtc::scoped_refptr<AudioDecoderFactory> audio_decoder_factory,
-    cricket::WebRtcVideoEncoderFactory* video_encoder_factory,
-    cricket::WebRtcVideoDecoderFactory* video_decoder_factory,
-    rtc::scoped_refptr<AudioMixer> audio_mixer);
-
-// Create a new instance of PeerConnectionFactoryInterface.
-// Same thread is used as worker and network thread.
-RTC_EXPORT inline rtc::scoped_refptr<PeerConnectionFactoryInterface>
-CreatePeerConnectionFactory(
-    rtc::Thread* worker_and_network_thread,
-    rtc::Thread* signaling_thread,
-    AudioDeviceModule* default_adm,
-    rtc::scoped_refptr<AudioEncoderFactory> audio_encoder_factory,
-    rtc::scoped_refptr<AudioDecoderFactory> audio_decoder_factory,
-    cricket::WebRtcVideoEncoderFactory* video_encoder_factory,
-    cricket::WebRtcVideoDecoderFactory* video_decoder_factory) {
-  return CreatePeerConnectionFactory(
-      worker_and_network_thread, worker_and_network_thread, signaling_thread,
-      default_adm, audio_encoder_factory, audio_decoder_factory,
-      video_encoder_factory, video_decoder_factory);
-}
-#endif  // defined(USE_BUILTIN_SW_CODECS)
-
 }  // namespace webrtc
 
 #endif  // API_CREATE_PEERCONNECTION_FACTORY_H_
diff --git a/api/crypto_params.h b/api/crypto_params.h
new file mode 100644
index 0000000..5da352c
--- /dev/null
+++ b/api/crypto_params.h
@@ -0,0 +1,41 @@
+/*
+ *  Copyright (c) 2004 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_CRYPTO_PARAMS_H_
+#define API_CRYPTO_PARAMS_H_
+
+#include <string>
+
+namespace cricket {
+
+// Parameters for SRTP negotiation, as described in RFC 4568.
+// TODO(benwright) - Rename to SrtpCryptoParams as these only apply to SRTP and
+// not generic crypto parameters for WebRTC.
+struct CryptoParams {
+  CryptoParams() : tag(0) {}
+  CryptoParams(int t,
+               const std::string& cs,
+               const std::string& kp,
+               const std::string& sp)
+      : tag(t), cipher_suite(cs), key_params(kp), session_params(sp) {}
+
+  bool Matches(const CryptoParams& params) const {
+    return (tag == params.tag && cipher_suite == params.cipher_suite);
+  }
+
+  int tag;
+  std::string cipher_suite;
+  std::string key_params;
+  std::string session_params;
+};
+
+}  // namespace cricket
+
+#endif  // API_CRYPTO_PARAMS_H_
diff --git a/api/data_channel_interface.cc b/api/data_channel_interface.cc
new file mode 100644
index 0000000..240ccbe
--- /dev/null
+++ b/api/data_channel_interface.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/data_channel_interface.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/data_channel_interface.h b/api/data_channel_interface.h
new file mode 100644
index 0000000..91a9804
--- /dev/null
+++ b/api/data_channel_interface.h
@@ -0,0 +1,180 @@
+/*
+ *  Copyright 2012 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 interfaces for DataChannels
+// http://dev.w3.org/2011/webrtc/editor/webrtc.html#rtcdatachannel
+
+#ifndef API_DATA_CHANNEL_INTERFACE_H_
+#define API_DATA_CHANNEL_INTERFACE_H_
+
+#include <stddef.h>
+#include <stdint.h>
+#include <string>
+
+#include "rtc_base/checks.h"
+#include "rtc_base/copy_on_write_buffer.h"
+#include "rtc_base/ref_count.h"
+
+namespace webrtc {
+
+// C++ version of: https://www.w3.org/TR/webrtc/#idl-def-rtcdatachannelinit
+// TODO(deadbeef): Use absl::optional for the "-1 if unset" things.
+struct DataChannelInit {
+  // Deprecated. Reliability is assumed, and channel will be unreliable if
+  // maxRetransmitTime or MaxRetransmits is set.
+  bool reliable = false;
+
+  // True if ordered delivery is required.
+  bool ordered = true;
+
+  // The max period of time in milliseconds in which retransmissions will be
+  // sent. After this time, no more retransmissions will be sent. -1 if unset.
+  //
+  // Cannot be set along with |maxRetransmits|.
+  int maxRetransmitTime = -1;
+
+  // The max number of retransmissions. -1 if unset.
+  //
+  // Cannot be set along with |maxRetransmitTime|.
+  int maxRetransmits = -1;
+
+  // This is set by the application and opaque to the WebRTC implementation.
+  std::string protocol;
+
+  // True if the channel has been externally negotiated and we do not send an
+  // in-band signalling in the form of an "open" message. If this is true, |id|
+  // below must be set; otherwise it should be unset and will be negotiated
+  // in-band.
+  bool negotiated = false;
+
+  // The stream id, or SID, for SCTP data channels. -1 if unset (see above).
+  int id = -1;
+};
+
+// At the JavaScript level, data can be passed in as a string or a blob, so
+// this structure's |binary| flag tells whether the data should be interpreted
+// as binary or text.
+struct DataBuffer {
+  DataBuffer(const rtc::CopyOnWriteBuffer& data, bool binary)
+      : data(data), binary(binary) {}
+  // For convenience for unit tests.
+  explicit DataBuffer(const std::string& text)
+      : data(text.data(), text.length()), binary(false) {}
+  size_t size() const { return data.size(); }
+
+  rtc::CopyOnWriteBuffer data;
+  // Indicates if the received data contains UTF-8 or binary data.
+  // Note that the upper layers are left to verify the UTF-8 encoding.
+  // TODO(jiayl): prefer to use an enum instead of a bool.
+  bool binary;
+};
+
+// Used to implement RTCDataChannel events.
+//
+// The code responding to these callbacks should unwind the stack before
+// using any other webrtc APIs; re-entrancy is not supported.
+class DataChannelObserver {
+ public:
+  // The data channel state have changed.
+  virtual void OnStateChange() = 0;
+  //  A data buffer was successfully received.
+  virtual void OnMessage(const DataBuffer& buffer) = 0;
+  // The data channel's buffered_amount has changed.
+  virtual void OnBufferedAmountChange(uint64_t previous_amount) {}
+
+ protected:
+  virtual ~DataChannelObserver() = default;
+};
+
+class DataChannelInterface : public rtc::RefCountInterface {
+ public:
+  // C++ version of: https://www.w3.org/TR/webrtc/#idl-def-rtcdatachannelstate
+  // Unlikely to change, but keep in sync with DataChannel.java:State and
+  // RTCDataChannel.h:RTCDataChannelState.
+  enum DataState {
+    kConnecting,
+    kOpen,  // The DataChannel is ready to send data.
+    kClosing,
+    kClosed
+  };
+
+  static const char* DataStateString(DataState state) {
+    switch (state) {
+      case kConnecting:
+        return "connecting";
+      case kOpen:
+        return "open";
+      case kClosing:
+        return "closing";
+      case kClosed:
+        return "closed";
+    }
+    RTC_CHECK(false) << "Unknown DataChannel state: " << state;
+    return "";
+  }
+
+  // Used to receive events from the data channel. Only one observer can be
+  // registered at a time. UnregisterObserver should be called before the
+  // observer object is destroyed.
+  virtual void RegisterObserver(DataChannelObserver* observer) = 0;
+  virtual void UnregisterObserver() = 0;
+
+  // The label attribute represents a label that can be used to distinguish this
+  // DataChannel object from other DataChannel objects.
+  virtual std::string label() const = 0;
+
+  // The accessors below simply return the properties from the DataChannelInit
+  // the data channel was constructed with.
+  virtual bool reliable() const = 0;
+  // 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;
+  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
+  // determined, and until then this will return -1.
+  virtual int id() const = 0;
+  virtual DataState state() const = 0;
+  virtual uint32_t messages_sent() const = 0;
+  virtual uint64_t bytes_sent() const = 0;
+  virtual uint32_t messages_received() const = 0;
+  virtual uint64_t bytes_received() const = 0;
+
+  // Returns the number of bytes of application data (UTF-8 text and binary
+  // data) that have been queued using Send but have not yet been processed at
+  // the SCTP level. See comment above Send below.
+  virtual uint64_t buffered_amount() const = 0;
+
+  // Begins the graceful data channel closing procedure. See:
+  // https://tools.ietf.org/html/draft-ietf-rtcweb-data-channel-13#section-6.7
+  virtual void Close() = 0;
+
+  // Sends |data| to the remote peer. If the data can't be sent at the SCTP
+  // level (due to congestion control), it's buffered at the data channel level,
+  // up to a maximum of 16MB. If Send is called while this buffer is full, the
+  // data channel will be closed abruptly.
+  //
+  // So, it's important to use buffered_amount() and OnBufferedAmountChange to
+  // ensure the data channel is used efficiently but without filling this
+  // buffer.
+  virtual bool Send(const DataBuffer& buffer) = 0;
+
+ protected:
+  ~DataChannelInterface() override = default;
+};
+
+}  // namespace webrtc
+
+#endif  // API_DATA_CHANNEL_INTERFACE_H_
diff --git a/api/dtls_transport_interface.h b/api/dtls_transport_interface.h
new file mode 100644
index 0000000..7f35a23
--- /dev/null
+++ b/api/dtls_transport_interface.h
@@ -0,0 +1,76 @@
+/*
+ *  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_DTLS_TRANSPORT_INTERFACE_H_
+#define API_DTLS_TRANSPORT_INTERFACE_H_
+
+#include "api/ice_transport_interface.h"
+#include "api/rtc_error.h"
+#include "api/scoped_refptr.h"
+#include "rtc_base/ref_count.h"
+
+namespace webrtc {
+
+// States of a DTLS transport, corresponding to the JS API specification.
+// http://w3c.github.io/webrtc-pc/#dom-rtcdtlstransportstate
+enum class DtlsTransportState {
+  kNew,         // Has not started negotiating yet.
+  kConnecting,  // In the process of negotiating a secure connection.
+  kConnected,   // Completed negotiation and verified fingerprints.
+  kClosed,      // Intentionally closed.
+  kFailed,      // Failure due to an error or failing to verify a remote
+                // fingerprint.
+  kNumValues
+};
+
+// This object gives snapshot information about the changeable state of a
+// DTLSTransport.
+class DtlsTransportInformation {
+ public:
+  explicit DtlsTransportInformation(DtlsTransportState state) : state_(state) {}
+  DtlsTransportState state() const { return state_; }
+  // TODO(hta): Add remote certificate access
+ private:
+  DtlsTransportState state_;
+};
+
+class DtlsTransportObserverInterface {
+ public:
+  // This callback carries information about the state of the transport.
+  // The argument is a pass-by-value snapshot of the state.
+  virtual void OnStateChange(DtlsTransportInformation info) = 0;
+  // This callback is called when an error occurs, causing the transport
+  // to go to the kFailed state.
+  virtual void OnError(RTCError error) = 0;
+
+ protected:
+  virtual ~DtlsTransportObserverInterface() = default;
+};
+
+// A DTLS transport, as represented to the outside world.
+// This object is created on the network thread, and can only be
+// accessed on that thread, except for functions explicitly marked otherwise.
+// References can be held by other threads, and destruction can therefore
+// be initiated by other threads.
+class DtlsTransportInterface : public rtc::RefCountInterface {
+ public:
+  // Returns a pointer to the ICE transport that is owned by the DTLS transport.
+  virtual rtc::scoped_refptr<IceTransportInterface> ice_transport() = 0;
+  // Returns information on the state of the DtlsTransport.
+  // This function can be called from other threads.
+  virtual DtlsTransportInformation Information() = 0;
+  // Observer management.
+  virtual void RegisterObserver(DtlsTransportObserverInterface* observer) = 0;
+  virtual void UnregisterObserver() = 0;
+};
+
+}  // namespace webrtc
+
+#endif  // API_DTLS_TRANSPORT_INTERFACE_H_
diff --git a/api/dtmf_sender_interface.h b/api/dtmf_sender_interface.h
new file mode 100644
index 0000000..9cdfba1
--- /dev/null
+++ b/api/dtmf_sender_interface.h
@@ -0,0 +1,100 @@
+/*
+ *  Copyright 2012 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_DTMF_SENDER_INTERFACE_H_
+#define API_DTMF_SENDER_INTERFACE_H_
+
+#include <string>
+
+#include "api/media_stream_interface.h"
+#include "rtc_base/ref_count.h"
+
+namespace webrtc {
+
+// DtmfSender callback interface, used to implement RTCDtmfSender events.
+// Applications should implement this interface to get notifications from the
+// DtmfSender.
+class DtmfSenderObserverInterface {
+ public:
+  // Triggered when DTMF |tone| is sent.
+  // If |tone| is empty that means the DtmfSender has sent out all the given
+  // tones.
+  // The callback includes the state of the tone buffer at the time when
+  // the tone finished playing.
+  virtual void OnToneChange(const std::string& tone,
+                            const std::string& tone_buffer) {}
+  // DEPRECATED: Older API without tone buffer.
+  // TODO(bugs.webrtc.org/9725): Remove old API and default implementation
+  // when old callers are gone.
+  virtual void OnToneChange(const std::string& tone) {}
+
+ protected:
+  virtual ~DtmfSenderObserverInterface() = default;
+};
+
+// The interface of native implementation of the RTCDTMFSender defined by the
+// WebRTC W3C Editor's Draft.
+// See: https://www.w3.org/TR/webrtc/#peer-to-peer-dtmf
+class DtmfSenderInterface : public rtc::RefCountInterface {
+ public:
+  // Used to receive events from the DTMF sender. Only one observer can be
+  // registered at a time. UnregisterObserver should be called before the
+  // observer object is destroyed.
+  virtual void RegisterObserver(DtmfSenderObserverInterface* observer) = 0;
+  virtual void UnregisterObserver() = 0;
+
+  // Returns true if this DtmfSender is capable of sending DTMF. Otherwise
+  // returns false. To be able to send DTMF, the associated RtpSender must be
+  // able to send packets, and a "telephone-event" codec must be negotiated.
+  virtual bool CanInsertDtmf() = 0;
+
+  // Queues a task that sends the DTMF |tones|. The |tones| parameter is treated
+  // as a series of characters. The characters 0 through 9, A through D, #, and
+  // * generate the associated DTMF tones. The characters a to d are equivalent
+  // to A to D. The character ',' indicates a delay of 2 seconds before
+  // processing the next character in the tones parameter.
+  //
+  // Unrecognized characters are ignored.
+  //
+  // The |duration| parameter indicates the duration in ms to use for each
+  // character passed in the |tones| parameter. The duration cannot be more
+  // than 6000 or less than 70.
+  //
+  // The |inter_tone_gap| parameter indicates the gap between tones in ms. The
+  // |inter_tone_gap| must be at least 50 ms but should be as short as
+  // possible.
+  //
+  // If InsertDtmf is called on the same object while an existing task for this
+  // object to generate DTMF is still running, the previous task is canceled.
+  // Returns true on success and false on failure.
+  virtual bool InsertDtmf(const std::string& tones,
+                          int duration,
+                          int inter_tone_gap) = 0;
+
+  // Returns the tones remaining to be played out.
+  virtual std::string tones() const = 0;
+
+  // Returns the current tone duration value in ms.
+  // This value will be the value last set via the InsertDtmf() method, or the
+  // default value of 100 ms if InsertDtmf() was never called.
+  virtual int duration() const = 0;
+
+  // Returns the current value of the between-tone gap in ms.
+  // This value will be the value last set via the InsertDtmf() method, or the
+  // default value of 50 ms if InsertDtmf() was never called.
+  virtual int inter_tone_gap() const = 0;
+
+ protected:
+  ~DtmfSenderInterface() override = default;
+};
+
+}  // namespace webrtc
+
+#endif  // API_DTMF_SENDER_INTERFACE_H_
diff --git a/api/ice_transport_factory.cc b/api/ice_transport_factory.cc
new file mode 100644
index 0000000..6cc399a
--- /dev/null
+++ b/api/ice_transport_factory.cc
@@ -0,0 +1,58 @@
+/*
+ *  Copyright 2019 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "api/ice_transport_factory.h"
+
+#include <memory>
+#include <utility>
+
+#include "absl/memory/memory.h"
+#include "p2p/base/ice_transport_internal.h"
+#include "p2p/base/p2p_transport_channel.h"
+#include "p2p/base/port_allocator.h"
+#include "rtc_base/thread.h"
+
+namespace webrtc {
+
+namespace {
+
+// This implementation of IceTransportInterface is used in cases where
+// the only reference to the P2PTransport will be through this class.
+// It must be constructed, accessed and destroyed on the signaling thread.
+class IceTransportWithTransportChannel : public IceTransportInterface {
+ public:
+  IceTransportWithTransportChannel(
+      std::unique_ptr<cricket::IceTransportInternal> internal)
+      : internal_(std::move(internal)) {}
+
+  ~IceTransportWithTransportChannel() override {
+    RTC_DCHECK_RUN_ON(&thread_checker_);
+  }
+
+  cricket::IceTransportInternal* internal() override {
+    RTC_DCHECK_RUN_ON(&thread_checker_);
+    return internal_.get();
+  }
+
+ private:
+  const rtc::ThreadChecker thread_checker_{};
+  const std::unique_ptr<cricket::IceTransportInternal> internal_
+      RTC_GUARDED_BY(thread_checker_);
+};
+
+}  // namespace
+
+rtc::scoped_refptr<IceTransportInterface> CreateIceTransport(
+    cricket::PortAllocator* port_allocator) {
+  return new rtc::RefCountedObject<IceTransportWithTransportChannel>(
+      absl::make_unique<cricket::P2PTransportChannel>("", 0, port_allocator));
+}
+
+}  // namespace webrtc
diff --git a/api/ice_transport_factory.h b/api/ice_transport_factory.h
new file mode 100644
index 0000000..a8330df
--- /dev/null
+++ b/api/ice_transport_factory.h
@@ -0,0 +1,33 @@
+/*
+ *  Copyright 2019 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef API_ICE_TRANSPORT_FACTORY_H_
+#define API_ICE_TRANSPORT_FACTORY_H_
+
+#include "api/ice_transport_interface.h"
+#include "api/scoped_refptr.h"
+
+namespace cricket {
+class PortAllocator;
+}
+
+namespace webrtc {
+
+// Static factory for an IceTransport object that can be created
+// without using a webrtc::PeerConnection.
+// The returned object must be accessed and destroyed on the thread that
+// created it.
+// The PortAllocator must outlive the created IceTransportInterface object.
+rtc::scoped_refptr<IceTransportInterface> CreateIceTransport(
+    cricket::PortAllocator* port_allocator);
+
+}  // namespace webrtc
+
+#endif  // API_ICE_TRANSPORT_FACTORY_H_
diff --git a/api/ice_transport_interface.h b/api/ice_transport_interface.h
new file mode 100644
index 0000000..6e63045
--- /dev/null
+++ b/api/ice_transport_interface.h
@@ -0,0 +1,38 @@
+/*
+ *  Copyright 2019 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef API_ICE_TRANSPORT_INTERFACE_H_
+#define API_ICE_TRANSPORT_INTERFACE_H_
+
+#include "api/rtc_error.h"
+#include "api/scoped_refptr.h"
+#include "rtc_base/ref_count.h"
+
+namespace cricket {
+class IceTransportInternal;
+}  // namespace cricket
+
+namespace webrtc {
+
+// An ICE transport, as represented to the outside world.
+// This object is refcounted, and is therefore alive until the
+// last holder has released it.
+class IceTransportInterface : public rtc::RefCountInterface {
+ public:
+  // Accessor for the internal representation of an ICE transport.
+  // The returned object can only be safely used on the signalling thread.
+  // TODO(crbug.com/907849): Add API calls for the functions that have to
+  // be exposed to clients, and stop allowing access to the
+  // cricket::IceTransportInternal API.
+  virtual cricket::IceTransportInternal* internal() = 0;
+};
+
+}  // namespace webrtc
+#endif  // API_ICE_TRANSPORT_INTERFACE_H_
diff --git a/api/jsep.h b/api/jsep.h
index 1c50455..6da7827 100644
--- a/api/jsep.h
+++ b/api/jsep.h
@@ -27,8 +27,8 @@
 #include <vector>
 
 #include "absl/types/optional.h"
-#include "api/rtcerror.h"
-#include "rtc_base/refcount.h"
+#include "api/rtc_error.h"
+#include "rtc_base/ref_count.h"
 #include "rtc_base/system/rtc_export.h"
 
 namespace cricket {
diff --git a/api/jsep_ice_candidate.cc b/api/jsep_ice_candidate.cc
new file mode 100644
index 0000000..59da4e4
--- /dev/null
+++ b/api/jsep_ice_candidate.cc
@@ -0,0 +1,86 @@
+/*
+ *  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/jsep_ice_candidate.h"
+
+#include <algorithm>
+#include <utility>
+
+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/jsep_ice_candidate.h b/api/jsep_ice_candidate.h
new file mode 100644
index 0000000..5b22454
--- /dev/null
+++ b/api/jsep_ice_candidate.h
@@ -0,0 +1,85 @@
+/*
+ *  Copyright 2012 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.
+ */
+
+// TODO(deadbeef): Move this out of api/; it's an implementation detail and
+// shouldn't be used externally.
+
+#ifndef API_JSEP_ICE_CANDIDATE_H_
+#define API_JSEP_ICE_CANDIDATE_H_
+
+#include <stddef.h>
+#include <string>
+#include <vector>
+
+#include "api/candidate.h"
+#include "api/jsep.h"
+#include "rtc_base/constructor_magic.h"
+
+namespace webrtc {
+
+// Implementation of IceCandidateInterface.
+class JsepIceCandidate : public IceCandidateInterface {
+ public:
+  JsepIceCandidate(const std::string& sdp_mid, int sdp_mline_index);
+  JsepIceCandidate(const std::string& sdp_mid,
+                   int sdp_mline_index,
+                   const cricket::Candidate& candidate);
+  ~JsepIceCandidate() override;
+  // |err| may be null.
+  bool Initialize(const std::string& sdp, SdpParseError* err);
+  void SetCandidate(const cricket::Candidate& candidate) {
+    candidate_ = candidate;
+  }
+
+  std::string sdp_mid() const override;
+  int sdp_mline_index() const override;
+  const cricket::Candidate& candidate() const override;
+
+  std::string server_url() const override;
+
+  bool ToString(std::string* out) const override;
+
+ private:
+  std::string sdp_mid_;
+  int sdp_mline_index_;
+  cricket::Candidate candidate_;
+
+  RTC_DISALLOW_COPY_AND_ASSIGN(JsepIceCandidate);
+};
+
+// Implementation of IceCandidateCollection which stores JsepIceCandidates.
+class JsepCandidateCollection : public IceCandidateCollection {
+ public:
+  JsepCandidateCollection();
+  // Move constructor is defined so that a vector of JsepCandidateCollections
+  // can be resized.
+  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);
+  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.
+  size_t remove(const cricket::Candidate& candidate);
+
+ private:
+  std::vector<JsepIceCandidate*> candidates_;
+
+  RTC_DISALLOW_COPY_AND_ASSIGN(JsepCandidateCollection);
+};
+
+}  // namespace webrtc
+
+#endif  // API_JSEP_ICE_CANDIDATE_H_
diff --git a/api/jsep_session_description.h b/api/jsep_session_description.h
new file mode 100644
index 0000000..75ae0cd
--- /dev/null
+++ b/api/jsep_session_description.h
@@ -0,0 +1,91 @@
+/*
+ *  Copyright 2012 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.
+ */
+
+// TODO(deadbeef): Move this out of api/; it's an implementation detail and
+// shouldn't be used externally.
+
+#ifndef API_JSEP_SESSION_DESCRIPTION_H_
+#define API_JSEP_SESSION_DESCRIPTION_H_
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "absl/strings/string_view.h"
+#include "api/candidate.h"
+#include "api/jsep.h"
+#include "api/jsep_ice_candidate.h"
+#include "rtc_base/constructor_magic.h"
+
+namespace cricket {
+class SessionDescription;
+}
+
+namespace webrtc {
+
+// Implementation of SessionDescriptionInterface.
+class JsepSessionDescription : public SessionDescriptionInterface {
+ public:
+  explicit JsepSessionDescription(SdpType type);
+  // TODO(steveanton): Remove this once callers have switched to SdpType.
+  explicit JsepSessionDescription(const std::string& type);
+  JsepSessionDescription(
+      SdpType type,
+      std::unique_ptr<cricket::SessionDescription> description,
+      absl::string_view session_id,
+      absl::string_view session_version);
+  virtual ~JsepSessionDescription();
+
+  // Takes ownership of |description|.
+  // TODO(deadbeef): Make this use an std::unique_ptr<>, so ownership logic is
+  // more clear.
+  bool Initialize(cricket::SessionDescription* description,
+                  const std::string& session_id,
+                  const std::string& session_version);
+
+  virtual cricket::SessionDescription* description() {
+    return description_.get();
+  }
+  virtual const cricket::SessionDescription* description() const {
+    return description_.get();
+  }
+  virtual std::string session_id() const { return session_id_; }
+  virtual std::string session_version() const { return session_version_; }
+  virtual SdpType GetType() const { return type_; }
+  virtual std::string type() const { return SdpTypeToString(type_); }
+  // Allows changing the type. Used for testing.
+  virtual bool AddCandidate(const IceCandidateInterface* candidate);
+  virtual size_t RemoveCandidates(
+      const std::vector<cricket::Candidate>& candidates);
+  virtual size_t number_of_mediasections() const;
+  virtual const IceCandidateCollection* candidates(
+      size_t mediasection_index) const;
+  virtual bool ToString(std::string* out) const;
+
+  static const int kDefaultVideoCodecId;
+  static const char kDefaultVideoCodecName[];
+
+ private:
+  std::unique_ptr<cricket::SessionDescription> description_;
+  std::string session_id_;
+  std::string session_version_;
+  SdpType type_;
+  std::vector<JsepCandidateCollection> candidate_collection_;
+
+  bool GetMediasectionIndex(const IceCandidateInterface* candidate,
+                            size_t* index);
+  int GetMediasectionIndex(const cricket::Candidate& candidate);
+
+  RTC_DISALLOW_COPY_AND_ASSIGN(JsepSessionDescription);
+};
+
+}  // namespace webrtc
+
+#endif  // API_JSEP_SESSION_DESCRIPTION_H_
diff --git a/api/media_stream_interface.cc b/api/media_stream_interface.cc
new file mode 100644
index 0000000..cf994cb
--- /dev/null
+++ b/api/media_stream_interface.cc
@@ -0,0 +1,39 @@
+/*
+ *  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 "api/media_stream_interface.h"
+
+namespace webrtc {
+
+const char MediaStreamTrackInterface::kVideoKind[] = "video";
+const char MediaStreamTrackInterface::kAudioKind[] = "audio";
+
+VideoTrackInterface::ContentHint VideoTrackInterface::content_hint() const {
+  return ContentHint::kNone;
+}
+
+bool AudioTrackInterface::GetSignalLevel(int* level) {
+  return false;
+}
+
+rtc::scoped_refptr<AudioProcessorInterface>
+AudioTrackInterface::GetAudioProcessor() {
+  return nullptr;
+}
+
+const cricket::AudioOptions AudioSourceInterface::options() const {
+  return {};
+}
+
+double MediaSourceInterface::GetLatency() const {
+  return 0.0;
+}
+
+}  // namespace webrtc
diff --git a/api/media_stream_interface.h b/api/media_stream_interface.h
new file mode 100644
index 0000000..1249b85
--- /dev/null
+++ b/api/media_stream_interface.h
@@ -0,0 +1,304 @@
+/*
+ *  Copyright 2012 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 interfaces for MediaStream, MediaTrack and MediaSource.
+// These interfaces are used for implementing MediaStream and MediaTrack as
+// defined in http://dev.w3.org/2011/webrtc/editor/webrtc.html#stream-api. These
+// interfaces must be used only with PeerConnection. PeerConnectionManager
+// interface provides the factory methods to create MediaStream and MediaTracks.
+
+#ifndef API_MEDIA_STREAM_INTERFACE_H_
+#define API_MEDIA_STREAM_INTERFACE_H_
+
+#include <stddef.h>
+
+#include <string>
+#include <vector>
+
+#include "absl/types/optional.h"
+#include "api/audio_options.h"
+#include "api/scoped_refptr.h"
+#include "api/video/video_frame.h"
+#include "api/video/video_sink_interface.h"
+#include "api/video/video_source_interface.h"
+#include "modules/audio_processing/include/audio_processing_statistics.h"
+#include "rtc_base/ref_count.h"
+
+namespace webrtc {
+
+// Generic observer interface.
+class ObserverInterface {
+ public:
+  virtual void OnChanged() = 0;
+
+ protected:
+  virtual ~ObserverInterface() {}
+};
+
+class NotifierInterface {
+ public:
+  virtual void RegisterObserver(ObserverInterface* observer) = 0;
+  virtual void UnregisterObserver(ObserverInterface* observer) = 0;
+
+  virtual ~NotifierInterface() {}
+};
+
+// Base class for sources. A MediaStreamTrack has an underlying source that
+// provides media. A source can be shared by multiple tracks.
+class MediaSourceInterface : public rtc::RefCountInterface,
+                             public NotifierInterface {
+ public:
+  enum SourceState { kInitializing, kLive, kEnded, kMuted };
+
+  virtual SourceState state() const = 0;
+
+  virtual bool remote() const = 0;
+
+  // Sets the minimum latency of the remote source until audio playout. Actual
+  // observered latency may differ depending on the source. |latency| is in the
+  // range of [0.0, 10.0] seconds.
+  // TODO(kuddai) make pure virtual once not only remote tracks support latency.
+  virtual void SetLatency(double latency) {}
+  virtual double GetLatency() const;
+
+ protected:
+  ~MediaSourceInterface() override = default;
+};
+
+// C++ version of MediaStreamTrack.
+// See: https://www.w3.org/TR/mediacapture-streams/#mediastreamtrack
+class MediaStreamTrackInterface : public rtc::RefCountInterface,
+                                  public NotifierInterface {
+ public:
+  enum TrackState {
+    kLive,
+    kEnded,
+  };
+
+  static const char kAudioKind[];
+  static const char kVideoKind[];
+
+  // The kind() method must return kAudioKind only if the object is a
+  // subclass of AudioTrackInterface, and kVideoKind only if the
+  // object is a subclass of VideoTrackInterface. It is typically used
+  // to protect a static_cast<> to the corresponding subclass.
+  virtual std::string kind() const = 0;
+
+  // Track identifier.
+  virtual std::string id() const = 0;
+
+  // A disabled track will produce silence (if audio) or black frames (if
+  // video). Can be disabled and re-enabled.
+  virtual bool enabled() const = 0;
+  virtual bool set_enabled(bool enable) = 0;
+
+  // Live or ended. A track will never be live again after becoming ended.
+  virtual TrackState state() const = 0;
+
+ protected:
+  ~MediaStreamTrackInterface() override = default;
+};
+
+// VideoTrackSourceInterface is a reference counted source used for
+// VideoTracks. The same source can be used by multiple VideoTracks.
+// VideoTrackSourceInterface is designed to be invoked on the signaling thread
+// except for rtc::VideoSourceInterface<VideoFrame> methods that will be invoked
+// on the worker thread via a VideoTrack. A custom implementation of a source
+// can inherit AdaptedVideoTrackSource instead of directly implementing this
+// interface.
+class VideoTrackSourceInterface : public MediaSourceInterface,
+                                  public rtc::VideoSourceInterface<VideoFrame> {
+ public:
+  struct Stats {
+    // Original size of captured frame, before video adaptation.
+    int input_width;
+    int input_height;
+  };
+
+  // Indicates that parameters suitable for screencasts should be automatically
+  // applied to RtpSenders.
+  // TODO(perkj): Remove these once all known applications have moved to
+  // explicitly setting suitable parameters for screencasts and don't need this
+  // implicit behavior.
+  virtual bool is_screencast() const = 0;
+
+  // Indicates that the encoder should denoise video before encoding it.
+  // If it is not set, the default configuration is used which is different
+  // depending on video codec.
+  // TODO(perkj): Remove this once denoising is done by the source, and not by
+  // the encoder.
+  virtual absl::optional<bool> needs_denoising() const = 0;
+
+  // Returns false if no stats are available, e.g, for a remote source, or a
+  // source which has not seen its first frame yet.
+  //
+  // Implementation should avoid blocking.
+  virtual bool GetStats(Stats* stats) = 0;
+
+ protected:
+  ~VideoTrackSourceInterface() override = default;
+};
+
+// VideoTrackInterface is designed to be invoked on the signaling thread except
+// for rtc::VideoSourceInterface<VideoFrame> methods that must be invoked
+// on the worker thread.
+// PeerConnectionFactory::CreateVideoTrack can be used for creating a VideoTrack
+// that ensures thread safety and that all methods are called on the right
+// thread.
+class VideoTrackInterface : public MediaStreamTrackInterface,
+                            public rtc::VideoSourceInterface<VideoFrame> {
+ public:
+  // Video track content hint, used to override the source is_screencast
+  // property.
+  // See https://crbug.com/653531 and https://w3c.github.io/mst-content-hint.
+  enum class ContentHint { kNone, kFluid, kDetailed, kText };
+
+  // Register a video sink for this track. Used to connect the track to the
+  // underlying video engine.
+  void AddOrUpdateSink(rtc::VideoSinkInterface<VideoFrame>* sink,
+                       const rtc::VideoSinkWants& wants) override {}
+  void RemoveSink(rtc::VideoSinkInterface<VideoFrame>* sink) override {}
+
+  virtual VideoTrackSourceInterface* GetSource() const = 0;
+
+  virtual ContentHint content_hint() const;
+  virtual void set_content_hint(ContentHint hint) {}
+
+ protected:
+  ~VideoTrackInterface() override = default;
+};
+
+// Interface for receiving audio data from a AudioTrack.
+class AudioTrackSinkInterface {
+ public:
+  virtual void OnData(const void* audio_data,
+                      int bits_per_sample,
+                      int sample_rate,
+                      size_t number_of_channels,
+                      size_t number_of_frames) = 0;
+
+ protected:
+  virtual ~AudioTrackSinkInterface() {}
+};
+
+// AudioSourceInterface is a reference counted source used for AudioTracks.
+// The same source can be used by multiple AudioTracks.
+class AudioSourceInterface : public MediaSourceInterface {
+ public:
+  class AudioObserver {
+   public:
+    virtual void OnSetVolume(double volume) = 0;
+
+   protected:
+    virtual ~AudioObserver() {}
+  };
+
+  // TODO(deadbeef): Makes all the interfaces pure virtual after they're
+  // implemented in chromium.
+
+  // Sets the volume of the source. |volume| is in  the range of [0, 10].
+  // TODO(tommi): This method should be on the track and ideally volume should
+  // be applied in the track in a way that does not affect clones of the track.
+  virtual void SetVolume(double volume) {}
+
+  // Registers/unregisters observers to the audio source.
+  virtual void RegisterAudioObserver(AudioObserver* observer) {}
+  virtual void UnregisterAudioObserver(AudioObserver* observer) {}
+
+  // TODO(tommi): Make pure virtual.
+  virtual void AddSink(AudioTrackSinkInterface* sink) {}
+  virtual void RemoveSink(AudioTrackSinkInterface* sink) {}
+
+  // Returns options for the AudioSource.
+  // (for some of the settings this approach is broken, e.g. setting
+  // audio network adaptation on the source is the wrong layer of abstraction).
+  virtual const cricket::AudioOptions options() const;
+};
+
+// Interface of the audio processor used by the audio track to collect
+// statistics.
+class AudioProcessorInterface : public rtc::RefCountInterface {
+ public:
+  struct AudioProcessorStatistics {
+    bool typing_noise_detected = false;
+    AudioProcessingStats apm_statistics;
+  };
+
+  // Get audio processor statistics. The |has_remote_tracks| argument should be
+  // set if there are active remote tracks (this would usually be true during
+  // a call). If there are no remote tracks some of the stats will not be set by
+  // the AudioProcessor, because they only make sense if there is at least one
+  // remote track.
+  virtual AudioProcessorStatistics GetStats(bool has_remote_tracks) = 0;
+
+ protected:
+  ~AudioProcessorInterface() override = default;
+};
+
+class AudioTrackInterface : public MediaStreamTrackInterface {
+ public:
+  // TODO(deadbeef): Figure out if the following interface should be const or
+  // not.
+  virtual AudioSourceInterface* GetSource() const = 0;
+
+  // Add/Remove a sink that will receive the audio data from the track.
+  virtual void AddSink(AudioTrackSinkInterface* sink) = 0;
+  virtual void RemoveSink(AudioTrackSinkInterface* sink) = 0;
+
+  // Get the signal level from the audio track.
+  // Return true on success, otherwise false.
+  // TODO(deadbeef): Change the interface to int GetSignalLevel() and pure
+  // virtual after it's implemented in chromium.
+  virtual bool GetSignalLevel(int* level);
+
+  // Get the audio processor used by the audio track. Return null if the track
+  // does not have any processor.
+  // TODO(deadbeef): Make the interface pure virtual.
+  virtual rtc::scoped_refptr<AudioProcessorInterface> GetAudioProcessor();
+
+ protected:
+  ~AudioTrackInterface() override = default;
+};
+
+typedef std::vector<rtc::scoped_refptr<AudioTrackInterface> > AudioTrackVector;
+typedef std::vector<rtc::scoped_refptr<VideoTrackInterface> > VideoTrackVector;
+
+// C++ version of https://www.w3.org/TR/mediacapture-streams/#mediastream.
+//
+// A major difference is that remote audio/video tracks (received by a
+// PeerConnection/RtpReceiver) are not synchronized simply by adding them to
+// the same stream; a session description with the correct "a=msid" attributes
+// must be pushed down.
+//
+// Thus, this interface acts as simply a container for tracks.
+class MediaStreamInterface : public rtc::RefCountInterface,
+                             public NotifierInterface {
+ public:
+  virtual std::string id() const = 0;
+
+  virtual AudioTrackVector GetAudioTracks() = 0;
+  virtual VideoTrackVector GetVideoTracks() = 0;
+  virtual rtc::scoped_refptr<AudioTrackInterface> FindAudioTrack(
+      const std::string& track_id) = 0;
+  virtual rtc::scoped_refptr<VideoTrackInterface> FindVideoTrack(
+      const std::string& track_id) = 0;
+
+  virtual bool AddTrack(AudioTrackInterface* track) = 0;
+  virtual bool AddTrack(VideoTrackInterface* track) = 0;
+  virtual bool RemoveTrack(AudioTrackInterface* track) = 0;
+  virtual bool RemoveTrack(VideoTrackInterface* track) = 0;
+
+ protected:
+  ~MediaStreamInterface() override = default;
+};
+
+}  // namespace webrtc
+
+#endif  // API_MEDIA_STREAM_INTERFACE_H_
diff --git a/api/media_stream_proxy.h b/api/media_stream_proxy.h
new file mode 100644
index 0000000..5169679
--- /dev/null
+++ b/api/media_stream_proxy.h
@@ -0,0 +1,44 @@
+/*
+ *  Copyright 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
+ *  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_MEDIA_STREAM_PROXY_H_
+#define API_MEDIA_STREAM_PROXY_H_
+
+#include <string>
+
+#include "api/media_stream_interface.h"
+#include "api/proxy.h"
+
+namespace webrtc {
+
+// TODO(deadbeef): Move this to .cc file and out of api/. What threads methods
+// are called on is an implementation detail.
+BEGIN_SIGNALING_PROXY_MAP(MediaStream)
+PROXY_SIGNALING_THREAD_DESTRUCTOR()
+PROXY_CONSTMETHOD0(std::string, id)
+PROXY_METHOD0(AudioTrackVector, GetAudioTracks)
+PROXY_METHOD0(VideoTrackVector, GetVideoTracks)
+PROXY_METHOD1(rtc::scoped_refptr<AudioTrackInterface>,
+              FindAudioTrack,
+              const std::string&)
+PROXY_METHOD1(rtc::scoped_refptr<VideoTrackInterface>,
+              FindVideoTrack,
+              const std::string&)
+PROXY_METHOD1(bool, AddTrack, AudioTrackInterface*)
+PROXY_METHOD1(bool, AddTrack, VideoTrackInterface*)
+PROXY_METHOD1(bool, RemoveTrack, AudioTrackInterface*)
+PROXY_METHOD1(bool, RemoveTrack, VideoTrackInterface*)
+PROXY_METHOD1(void, RegisterObserver, ObserverInterface*)
+PROXY_METHOD1(void, UnregisterObserver, ObserverInterface*)
+END_PROXY_MAP()
+
+}  // namespace webrtc
+
+#endif  // API_MEDIA_STREAM_PROXY_H_
diff --git a/api/media_stream_track_proxy.h b/api/media_stream_track_proxy.h
new file mode 100644
index 0000000..d3dc255
--- /dev/null
+++ b/api/media_stream_track_proxy.h
@@ -0,0 +1,65 @@
+/*
+ *  Copyright 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
+ *  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 includes proxy classes for tracks. The purpose is
+// to make sure tracks are only accessed from the signaling thread.
+
+#ifndef API_MEDIA_STREAM_TRACK_PROXY_H_
+#define API_MEDIA_STREAM_TRACK_PROXY_H_
+
+#include <string>
+
+#include "api/media_stream_interface.h"
+#include "api/proxy.h"
+
+namespace webrtc {
+
+// TODO(deadbeef): Move this to .cc file and out of api/. What threads methods
+// are called on is an implementation detail.
+
+BEGIN_SIGNALING_PROXY_MAP(AudioTrack)
+PROXY_SIGNALING_THREAD_DESTRUCTOR()
+PROXY_CONSTMETHOD0(std::string, kind)
+PROXY_CONSTMETHOD0(std::string, id)
+PROXY_CONSTMETHOD0(TrackState, state)
+PROXY_CONSTMETHOD0(bool, enabled)
+PROXY_CONSTMETHOD0(AudioSourceInterface*, GetSource)
+PROXY_METHOD1(void, AddSink, AudioTrackSinkInterface*)
+PROXY_METHOD1(void, RemoveSink, AudioTrackSinkInterface*)
+PROXY_METHOD1(bool, GetSignalLevel, int*)
+PROXY_METHOD0(rtc::scoped_refptr<AudioProcessorInterface>, GetAudioProcessor)
+PROXY_METHOD1(bool, set_enabled, bool)
+PROXY_METHOD1(void, RegisterObserver, ObserverInterface*)
+PROXY_METHOD1(void, UnregisterObserver, ObserverInterface*)
+END_PROXY_MAP()
+
+BEGIN_PROXY_MAP(VideoTrack)
+PROXY_SIGNALING_THREAD_DESTRUCTOR()
+PROXY_CONSTMETHOD0(std::string, kind)
+PROXY_CONSTMETHOD0(std::string, id)
+PROXY_CONSTMETHOD0(TrackState, state)
+PROXY_CONSTMETHOD0(bool, enabled)
+PROXY_METHOD1(bool, set_enabled, bool)
+PROXY_CONSTMETHOD0(ContentHint, content_hint)
+PROXY_METHOD1(void, set_content_hint, ContentHint)
+PROXY_WORKER_METHOD2(void,
+                     AddOrUpdateSink,
+                     rtc::VideoSinkInterface<VideoFrame>*,
+                     const rtc::VideoSinkWants&)
+PROXY_WORKER_METHOD1(void, RemoveSink, rtc::VideoSinkInterface<VideoFrame>*)
+PROXY_CONSTMETHOD0(VideoTrackSourceInterface*, GetSource)
+
+PROXY_METHOD1(void, RegisterObserver, ObserverInterface*)
+PROXY_METHOD1(void, UnregisterObserver, ObserverInterface*)
+END_PROXY_MAP()
+
+}  // namespace webrtc
+
+#endif  // API_MEDIA_STREAM_TRACK_PROXY_H_
diff --git a/api/media_transport_interface.cc b/api/media_transport_interface.cc
index ef223aa..20bbe26 100644
--- a/api/media_transport_interface.cc
+++ b/api/media_transport_interface.cc
@@ -29,71 +29,9 @@
     const MediaTransportSettings&) = default;
 MediaTransportSettings::~MediaTransportSettings() = default;
 
-MediaTransportEncodedAudioFrame::~MediaTransportEncodedAudioFrame() {}
-
-MediaTransportEncodedAudioFrame::MediaTransportEncodedAudioFrame(
-    int sampling_rate_hz,
-    int starting_sample_index,
-    int samples_per_channel,
-    int sequence_number,
-    FrameType frame_type,
-    uint8_t payload_type,
-    std::vector<uint8_t> encoded_data)
-    : sampling_rate_hz_(sampling_rate_hz),
-      starting_sample_index_(starting_sample_index),
-      samples_per_channel_(samples_per_channel),
-      sequence_number_(sequence_number),
-      frame_type_(frame_type),
-      payload_type_(payload_type),
-      encoded_data_(std::move(encoded_data)) {}
-
-MediaTransportEncodedAudioFrame& MediaTransportEncodedAudioFrame::operator=(
-    const MediaTransportEncodedAudioFrame&) = default;
-
-MediaTransportEncodedAudioFrame& MediaTransportEncodedAudioFrame::operator=(
-    MediaTransportEncodedAudioFrame&&) = default;
-
-MediaTransportEncodedAudioFrame::MediaTransportEncodedAudioFrame(
-    const MediaTransportEncodedAudioFrame&) = default;
-
-MediaTransportEncodedAudioFrame::MediaTransportEncodedAudioFrame(
-    MediaTransportEncodedAudioFrame&&) = default;
-
-MediaTransportEncodedVideoFrame::~MediaTransportEncodedVideoFrame() {}
-
-MediaTransportEncodedVideoFrame::MediaTransportEncodedVideoFrame(
-    int64_t frame_id,
-    std::vector<int64_t> referenced_frame_ids,
-    VideoCodecType codec_type,
-    const webrtc::EncodedImage& encoded_image)
-    : codec_type_(codec_type),
-      encoded_image_(encoded_image),
-      frame_id_(frame_id),
-      referenced_frame_ids_(std::move(referenced_frame_ids)) {}
-
-MediaTransportEncodedVideoFrame& MediaTransportEncodedVideoFrame::operator=(
-    const MediaTransportEncodedVideoFrame&) = default;
-
-MediaTransportEncodedVideoFrame& MediaTransportEncodedVideoFrame::operator=(
-    MediaTransportEncodedVideoFrame&&) = default;
-
-MediaTransportEncodedVideoFrame::MediaTransportEncodedVideoFrame(
-    const MediaTransportEncodedVideoFrame&) = default;
-
-MediaTransportEncodedVideoFrame::MediaTransportEncodedVideoFrame(
-    MediaTransportEncodedVideoFrame&&) = default;
 
 SendDataParams::SendDataParams() = default;
-
-RTCErrorOr<std::unique_ptr<MediaTransportInterface>>
-MediaTransportFactory::CreateMediaTransport(
-    rtc::PacketTransportInternal* packet_transport,
-    rtc::Thread* network_thread,
-    bool is_caller) {
-  MediaTransportSettings settings;
-  settings.is_caller = is_caller;
-  return CreateMediaTransport(packet_transport, network_thread, settings);
-}
+SendDataParams::SendDataParams(const SendDataParams&) = default;
 
 RTCErrorOr<std::unique_ptr<MediaTransportInterface>>
 MediaTransportFactory::CreateMediaTransport(
@@ -103,22 +41,60 @@
   return std::unique_ptr<MediaTransportInterface>(nullptr);
 }
 
+RTCErrorOr<std::unique_ptr<MediaTransportInterface>>
+MediaTransportFactory::CreateMediaTransport(
+    rtc::Thread* network_thread,
+    const MediaTransportSettings& settings) {
+  return std::unique_ptr<MediaTransportInterface>(nullptr);
+}
+
+std::string MediaTransportFactory::GetTransportName() const {
+  return "";
+}
+
+MediaTransportInterface::MediaTransportInterface() = default;
+MediaTransportInterface::~MediaTransportInterface() = default;
+
+absl::optional<std::string>
+MediaTransportInterface::GetTransportParametersOffer() const {
+  return absl::nullopt;
+}
+
+void MediaTransportInterface::Connect(
+    rtc::PacketTransportInternal* packet_transport) {}
+
+void MediaTransportInterface::SetKeyFrameRequestCallback(
+    MediaTransportKeyFrameRequestCallback* callback) {}
+
 absl::optional<TargetTransferRate>
 MediaTransportInterface::GetLatestTargetTransferRate() {
   return absl::nullopt;
 }
 
-void MediaTransportInterface::SetNetworkChangeCallback(
+void MediaTransportInterface::AddNetworkChangeCallback(
     MediaTransportNetworkChangeCallback* callback) {}
 
-void MediaTransportInterface::RemoveTargetTransferRateObserver(
-    webrtc::TargetTransferRateObserver* observer) {}
+void MediaTransportInterface::RemoveNetworkChangeCallback(
+    MediaTransportNetworkChangeCallback* callback) {}
+
+void MediaTransportInterface::SetFirstAudioPacketReceivedObserver(
+    AudioPacketReceivedObserver* observer) {}
 
 void MediaTransportInterface::AddTargetTransferRateObserver(
-    webrtc::TargetTransferRateObserver* observer) {}
+    TargetTransferRateObserver* observer) {}
+void MediaTransportInterface::RemoveTargetTransferRateObserver(
+    TargetTransferRateObserver* observer) {}
+
+void MediaTransportInterface::AddRttObserver(
+    MediaTransportRttObserver* observer) {}
+void MediaTransportInterface::RemoveRttObserver(
+    MediaTransportRttObserver* observer) {}
 
 size_t MediaTransportInterface::GetAudioPacketOverhead() const {
   return 0;
 }
 
+void MediaTransportInterface::SetAllocatedBitrateLimits(
+    const MediaTransportAllocatedBitrateLimits& limits) {}
+
 }  // namespace webrtc
diff --git a/api/media_transport_interface.h b/api/media_transport_interface.h
index b10dd63..d333bec 100644
--- a/api/media_transport_interface.h
+++ b/api/media_transport_interface.h
@@ -21,14 +21,15 @@
 #include <memory>
 #include <string>
 #include <utility>
-#include <vector>
 
 #include "absl/types/optional.h"
 #include "api/array_view.h"
-#include "api/rtcerror.h"
-#include "api/video/encoded_image.h"
-#include "rtc_base/copyonwritebuffer.h"
-#include "rtc_base/networkroute.h"
+#include "api/rtc_error.h"
+#include "api/transport/media/audio_transport.h"
+#include "api/transport/media/video_transport.h"
+#include "api/units/data_rate.h"
+#include "rtc_base/copy_on_write_buffer.h"
+#include "rtc_base/network_route.h"
 
 namespace rtc {
 class PacketTransportInternal;
@@ -37,6 +38,23 @@
 
 namespace webrtc {
 
+class RtcEventLog;
+
+class AudioPacketReceivedObserver {
+ public:
+  virtual ~AudioPacketReceivedObserver() = default;
+
+  // Invoked for the first received audio packet on a given channel id.
+  // It will be invoked once for each channel id.
+  virtual void OnFirstAudioPacketReceived(int64_t channel_id) = 0;
+};
+
+struct MediaTransportAllocatedBitrateLimits {
+  DataRate min_pacing_rate = DataRate::Zero();
+  DataRate max_padding_bitrate = DataRate::Zero();
+  DataRate max_total_allocated_bitrate = DataRate::Zero();
+};
+
 // A collection of settings for creation of media transport.
 struct MediaTransportSettings final {
   MediaTransportSettings();
@@ -52,91 +70,15 @@
   // TODO(bugs.webrtc.org/9944): This should become zero buffer in the distant
   // future.
   absl::optional<std::string> pre_shared_key;
-};
 
-// Represents encoded audio frame in any encoding (type of encoding is opaque).
-// To avoid copying of encoded data use move semantics when passing by value.
-class MediaTransportEncodedAudioFrame final {
- public:
-  enum class FrameType {
-    // Normal audio frame (equivalent to webrtc::kAudioFrameSpeech).
-    kSpeech,
+  // If present, this is a config passed from the caller to the answerer in the
+  // offer. Each media transport knows how to understand its own parameters.
+  absl::optional<std::string> remote_transport_parameters;
 
-    // DTX frame (equivalent to webrtc::kAudioFrameCN).
-    // DTX frame (equivalent to webrtc::kAudioFrameCN).
-    kDiscontinuousTransmission,
-    // TODO(nisse): Mis-spelled version, update users, then delete.
-    kDiscountinuousTransmission = kDiscontinuousTransmission,
-  };
-
-  MediaTransportEncodedAudioFrame(
-      // Audio sampling rate, for example 48000.
-      int sampling_rate_hz,
-
-      // Starting sample index of the frame, i.e. how many audio samples were
-      // before this frame since the beginning of the call or beginning of time
-      // in one channel (the starting point should not matter for NetEq). In
-      // WebRTC it is used as a timestamp of the frame.
-      // TODO(sukhanov): Starting_sample_index is currently adjusted on the
-      // receiver side in RTP path. Non-RTP implementations should preserve it.
-      // For NetEq initial offset should not matter so we should consider fixing
-      // RTP path.
-      int starting_sample_index,
-
-      // Number of audio samples in audio frame in 1 channel.
-      int samples_per_channel,
-
-      // Sequence number of the frame in the order sent, it is currently
-      // required by NetEq, but we can fix NetEq, because starting_sample_index
-      // should be enough.
-      int sequence_number,
-
-      // If audio frame is a speech or discontinued transmission.
-      FrameType frame_type,
-
-      // Opaque payload type. In RTP codepath payload type is stored in RTP
-      // header. In other implementations it should be simply passed through the
-      // wire -- it's needed for decoder.
-      uint8_t payload_type,
-
-      // Vector with opaque encoded data.
-      std::vector<uint8_t> encoded_data);
-
-  ~MediaTransportEncodedAudioFrame();
-  MediaTransportEncodedAudioFrame(const MediaTransportEncodedAudioFrame&);
-  MediaTransportEncodedAudioFrame& operator=(
-      const MediaTransportEncodedAudioFrame& other);
-  MediaTransportEncodedAudioFrame& operator=(
-      MediaTransportEncodedAudioFrame&& other);
-  MediaTransportEncodedAudioFrame(MediaTransportEncodedAudioFrame&&);
-
-  // Getters.
-  int sampling_rate_hz() const { return sampling_rate_hz_; }
-  int starting_sample_index() const { return starting_sample_index_; }
-  int samples_per_channel() const { return samples_per_channel_; }
-  int sequence_number() const { return sequence_number_; }
-
-  uint8_t payload_type() const { return payload_type_; }
-  FrameType frame_type() const { return frame_type_; }
-
-  rtc::ArrayView<const uint8_t> encoded_data() const { return encoded_data_; }
-
- private:
-  int sampling_rate_hz_;
-  int starting_sample_index_;
-  int samples_per_channel_;
-
-  // TODO(sukhanov): Refactor NetEq so we don't need sequence number.
-  // Having sample_index and samples_per_channel should be enough.
-  int sequence_number_;
-
-  FrameType frame_type_;
-
-  // TODO(sukhanov): Consider enumerating allowed encodings and store enum
-  // instead of uint payload_type.
-  uint8_t payload_type_;
-
-  std::vector<uint8_t> encoded_data_;
+  // If present, provides the event log that media transport should use.
+  // Media transport does not own it. The lifetime of |event_log| will exceed
+  // the lifetime of the instance of MediaTransportInterface instance.
+  RtcEventLog* event_log = nullptr;
 };
 
 // Callback to notify about network route changes.
@@ -149,79 +91,6 @@
       const rtc::NetworkRoute& new_network_route) = 0;
 };
 
-// Interface for receiving encoded audio frames from MediaTransportInterface
-// implementations.
-class MediaTransportAudioSinkInterface {
- public:
-  virtual ~MediaTransportAudioSinkInterface() = default;
-
-  // Called when new encoded audio frame is received.
-  virtual void OnData(uint64_t channel_id,
-                      MediaTransportEncodedAudioFrame frame) = 0;
-};
-
-// Represents encoded video frame, along with the codec information.
-class MediaTransportEncodedVideoFrame final {
- public:
-  MediaTransportEncodedVideoFrame(int64_t frame_id,
-                                  std::vector<int64_t> referenced_frame_ids,
-                                  VideoCodecType codec_type,
-                                  const webrtc::EncodedImage& encoded_image);
-  ~MediaTransportEncodedVideoFrame();
-  MediaTransportEncodedVideoFrame(const MediaTransportEncodedVideoFrame&);
-  MediaTransportEncodedVideoFrame& operator=(
-      const MediaTransportEncodedVideoFrame& other);
-  MediaTransportEncodedVideoFrame& operator=(
-      MediaTransportEncodedVideoFrame&& other);
-  MediaTransportEncodedVideoFrame(MediaTransportEncodedVideoFrame&&);
-
-  VideoCodecType codec_type() const { return codec_type_; }
-  const webrtc::EncodedImage& encoded_image() const { return encoded_image_; }
-
-  int64_t frame_id() const { return frame_id_; }
-  const std::vector<int64_t>& referenced_frame_ids() const {
-    return referenced_frame_ids_;
-  }
-
- private:
-  VideoCodecType codec_type_;
-
-  // The buffer is not owned by the encoded image by default. On the sender it
-  // means that it will need to make a copy of it if it wants to deliver it
-  // asynchronously.
-  webrtc::EncodedImage encoded_image_;
-
-  // Frame id uniquely identifies a frame in a stream. It needs to be unique in
-  // a given time window (i.e. technically unique identifier for the lifetime of
-  // the connection is not needed, but you need to guarantee that remote side
-  // got rid of the previous frame_id if you plan to reuse it).
-  //
-  // It is required by a remote jitter buffer, and is the same as
-  // EncodedFrame::id::picture_id.
-  //
-  // This data must be opaque to the media transport, and media transport should
-  // itself not make any assumptions about what it is and its uniqueness.
-  int64_t frame_id_;
-
-  // A single frame might depend on other frames. This is set of identifiers on
-  // which the current frame depends.
-  std::vector<int64_t> referenced_frame_ids_;
-};
-
-// Interface for receiving encoded video frames from MediaTransportInterface
-// implementations.
-class MediaTransportVideoSinkInterface {
- public:
-  virtual ~MediaTransportVideoSinkInterface() = default;
-
-  // Called when new encoded video frame is received.
-  virtual void OnData(uint64_t channel_id,
-                      MediaTransportEncodedVideoFrame frame) = 0;
-
-  // Called when the request for keyframe is received.
-  virtual void OnKeyFrameRequested(uint64_t channel_id) = 0;
-};
-
 // State of the media transport.  Media transport begins in the pending state.
 // It transitions to writable when it is ready to send media.  It may transition
 // back to pending if the connection is blocked.  It may transition to closed at
@@ -241,6 +110,19 @@
   virtual void OnStateChanged(MediaTransportState state) = 0;
 };
 
+// Callback for RTT measurements on the receive side.
+// TODO(nisse): Related interfaces: CallStatsObserver and RtcpRttStats. It's
+// somewhat unclear what type of measurement is needed. It's used to configure
+// NACK generation and playout buffer. Either raw measurement values or recent
+// maximum would make sense for this use. Need consolidation of RTT signalling.
+class MediaTransportRttObserver {
+ public:
+  virtual ~MediaTransportRttObserver() = default;
+
+  // Invoked when a new RTT measurement is available, typically once per ACK.
+  virtual void OnRttUpdated(int64_t rtt_ms) = 0;
+};
+
 // Supported types of application data messages.
 enum class DataMessageType {
   // Application data buffer with the binary bit unset.
@@ -259,6 +141,7 @@
 // unreliable delivery.
 struct SendDataParams {
   SendDataParams();
+  SendDataParams(const SendDataParams&);
 
   DataMessageType type = DataMessageType::kText;
 
@@ -305,7 +188,29 @@
 // and receiving bandwidth estimate update from congestion control.
 class MediaTransportInterface {
  public:
-  virtual ~MediaTransportInterface() = default;
+  MediaTransportInterface();
+  virtual ~MediaTransportInterface();
+
+  // Retrieves callers config (i.e. media transport offer) that should be passed
+  // to the callee, before the call is connected. Such config is opaque to SDP
+  // (sdp just passes it through). The config is a binary blob, so SDP may
+  // choose to use base64 to serialize it (or any other approach that guarantees
+  // that the binary blob goes through). This should only be called for the
+  // caller's perspective.
+  //
+  // This may return an unset optional, which means that the given media
+  // transport is not supported / disabled and shouldn't be reported in SDP.
+  //
+  // It may also return an empty string, in which case the media transport is
+  // supported, but without any extra settings.
+  // TODO(psla): Make abstract.
+  virtual absl::optional<std::string> GetTransportParametersOffer() const;
+
+  // Connect the media transport to the ICE transport.
+  // The implementation must be able to ignore incoming packets that don't
+  // belong to it.
+  // TODO(psla): Make abstract.
+  virtual void Connect(rtc::PacketTransportInternal* packet_transport);
 
   // Start asynchronous send of audio frame. The status returned by this method
   // only pertains to the synchronous operations (e.g.
@@ -321,6 +226,10 @@
       uint64_t channel_id,
       const MediaTransportEncodedVideoFrame& frame) = 0;
 
+  // Used by video sender to be notified on key frame requests.
+  virtual void SetKeyFrameRequestCallback(
+      MediaTransportKeyFrameRequestCallback* callback);
+
   // Requests a keyframe for the particular channel (stream). The caller should
   // check that the keyframe is not present in a jitter buffer already (i.e.
   // don't request a keyframe if there is one that you will get from the jitter
@@ -341,12 +250,27 @@
   // A newly registered observer will be called back with the latest recorded
   // target rate, if available.
   virtual void AddTargetTransferRateObserver(
-      webrtc::TargetTransferRateObserver* observer);
+      TargetTransferRateObserver* observer);
 
   // Removes an existing |observer| from observers. If observer was never
   // registered, an error is logged and method does nothing.
   virtual void RemoveTargetTransferRateObserver(
-      webrtc::TargetTransferRateObserver* observer);
+      TargetTransferRateObserver* observer);
+
+  // Sets audio packets observer, which gets informed about incoming audio
+  // packets. Before destruction, the observer must be unregistered by setting
+  // nullptr.
+  //
+  // This method may be temporary, when the multiplexer is implemented (or
+  // multiplexer may use it to demultiplex channel ids).
+  virtual void SetFirstAudioPacketReceivedObserver(
+      AudioPacketReceivedObserver* observer);
+
+  // Intended for receive side. AddRttObserver registers an observer to be
+  // called for each RTT measurement, typically once per ACK. Before media
+  // transport is destructed the observer must be unregistered.
+  virtual void AddRttObserver(MediaTransportRttObserver* observer);
+  virtual void RemoveRttObserver(MediaTransportRttObserver* observer);
 
   // Returns the last known target transfer rate as reported to the above
   // observers.
@@ -358,12 +282,13 @@
   // might not be a very accurate number.
   virtual size_t GetAudioPacketOverhead() const;
 
-  // Sets an observer for network change events. If the network route is already
-  // established when the callback is set, |callback| will be called immediately
-  // with the current network route.
-  // Before media transport is destroyed, the callback must be unregistered by
-  // setting it to nullptr.
-  virtual void SetNetworkChangeCallback(
+  // Registers an observer for network change events. If the network route is
+  // already established when the callback is added, |callback| will be called
+  // immediately with the current network route. Before media transport is
+  // destroyed, the callback must be removed.
+  virtual void AddNetworkChangeCallback(
+      MediaTransportNetworkChangeCallback* callback);
+  virtual void RemoveNetworkChangeCallback(
       MediaTransportNetworkChangeCallback* callback);
 
   // Sets a state observer callback. Before media transport is destroyed, the
@@ -373,6 +298,15 @@
   virtual void SetMediaTransportStateCallback(
       MediaTransportStateCallback* callback) = 0;
 
+  // Updates allocation limits.
+  // TODO(psla): Make abstract when downstream implementation implement it.
+  virtual void SetAllocatedBitrateLimits(
+      const MediaTransportAllocatedBitrateLimits& limits);
+
+  // Opens a data |channel_id| for sending.  May return an error if the
+  // specified |channel_id| is unusable.  Must be called before |SendData|.
+  virtual RTCError OpenChannel(int channel_id) = 0;
+
   // Sends a data buffer to the remote endpoint using the given send parameters.
   // |buffer| may not be larger than 256 KiB. Returns an error if the send
   // fails.
@@ -408,21 +342,28 @@
   // - Does not take ownership of packet_transport or network_thread.
   // - Does not support group calls, in 1:1 call one side must set
   //   is_caller = true and another is_caller = false.
-  // TODO(bugs.webrtc.org/9938) This constructor will be removed and replaced
-  // with the one below.
-  virtual RTCErrorOr<std::unique_ptr<MediaTransportInterface>>
-  CreateMediaTransport(rtc::PacketTransportInternal* packet_transport,
-                       rtc::Thread* network_thread,
-                       bool is_caller);
-
-  // Creates media transport.
-  // - Does not take ownership of packet_transport or network_thread.
-  // TODO(bugs.webrtc.org/9938): remove default implementation once all children
-  // override it.
   virtual RTCErrorOr<std::unique_ptr<MediaTransportInterface>>
   CreateMediaTransport(rtc::PacketTransportInternal* packet_transport,
                        rtc::Thread* network_thread,
                        const MediaTransportSettings& settings);
+
+  // Creates a new Media Transport in a disconnected state. If the media
+  // transport for the caller is created, one can then call
+  // MediaTransportInterface::GetTransportParametersOffer on that new instance.
+  // TODO(psla): Make abstract.
+  virtual RTCErrorOr<std::unique_ptr<webrtc::MediaTransportInterface>>
+  CreateMediaTransport(rtc::Thread* network_thread,
+                       const MediaTransportSettings& settings);
+
+  // Gets a transport name which is supported by the implementation.
+  // Different factories should return different transport names, and at runtime
+  // it will be checked that different names were used.
+  // For example, "rtp" or "generic" may be returned by two different
+  // implementations.
+  // The value returned by this method must never change in the lifetime of the
+  // factory.
+  // TODO(psla): Make abstract.
+  virtual std::string GetTransportName() const;
 };
 
 }  // namespace webrtc
diff --git a/api/media_types.cc b/api/media_types.cc
new file mode 100644
index 0000000..3359f1d
--- /dev/null
+++ b/api/media_types.cc
@@ -0,0 +1,49 @@
+/*
+ *  Copyright 2016 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "api/media_types.h"
+
+#include "api/media_stream_interface.h"
+#include "rtc_base/checks.h"
+
+namespace {
+static const char* kMediaTypeData = "data";
+}  // namespace
+
+namespace cricket {
+
+std::string MediaTypeToString(MediaType type) {
+  switch (type) {
+    case MEDIA_TYPE_AUDIO:
+      return webrtc::MediaStreamTrackInterface::kAudioKind;
+    case MEDIA_TYPE_VIDEO:
+      return webrtc::MediaStreamTrackInterface::kVideoKind;
+    case MEDIA_TYPE_DATA:
+      return kMediaTypeData;
+  }
+  FATAL();
+  // Not reachable; avoids compile warning.
+  return "";
+}
+
+MediaType MediaTypeFromString(const std::string& type_str) {
+  if (type_str == webrtc::MediaStreamTrackInterface::kAudioKind) {
+    return MEDIA_TYPE_AUDIO;
+  } else if (type_str == webrtc::MediaStreamTrackInterface::kVideoKind) {
+    return MEDIA_TYPE_VIDEO;
+  } else if (type_str == kMediaTypeData) {
+    return MEDIA_TYPE_DATA;
+  }
+  FATAL();
+  // Not reachable; avoids compile warning.
+  return static_cast<MediaType>(-1);
+}
+
+}  // namespace cricket
diff --git a/api/media_types.h b/api/media_types.h
new file mode 100644
index 0000000..64e2ebc
--- /dev/null
+++ b/api/media_types.h
@@ -0,0 +1,36 @@
+/*
+ *  Copyright 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_MEDIA_TYPES_H_
+#define API_MEDIA_TYPES_H_
+
+#include <string>
+
+// The cricket and webrtc have separate definitions for what a media type is.
+// They're not compatible. Watch out for this.
+
+namespace cricket {
+
+enum MediaType { MEDIA_TYPE_AUDIO, MEDIA_TYPE_VIDEO, MEDIA_TYPE_DATA };
+
+std::string MediaTypeToString(MediaType type);
+// Aborts on invalid string. Only expected to be used on strings that are
+// guaranteed to be valid, such as MediaStreamTrackInterface::kind().
+MediaType MediaTypeFromString(const std::string& type_str);
+
+}  // namespace cricket
+
+namespace webrtc {
+
+enum class MediaType { ANY, AUDIO, VIDEO, DATA };
+
+}  // namespace webrtc
+
+#endif  // API_MEDIA_TYPES_H_
diff --git a/api/notifier.h b/api/notifier.h
index e5c61c9..c03b104 100644
--- a/api/notifier.h
+++ b/api/notifier.h
@@ -13,7 +13,7 @@
 
 #include <list>
 
-#include "api/mediastreaminterface.h"
+#include "api/media_stream_interface.h"
 #include "rtc_base/checks.h"
 
 namespace webrtc {
diff --git a/api/peer_connection_factory_proxy.h b/api/peer_connection_factory_proxy.h
new file mode 100644
index 0000000..620f1ca
--- /dev/null
+++ b/api/peer_connection_factory_proxy.h
@@ -0,0 +1,65 @@
+/*
+ *  Copyright 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 API_PEER_CONNECTION_FACTORY_PROXY_H_
+#define API_PEER_CONNECTION_FACTORY_PROXY_H_
+
+#include <memory>
+#include <string>
+#include <utility>
+
+#include "api/peer_connection_interface.h"
+#include "api/proxy.h"
+#include "rtc_base/bind.h"
+
+namespace webrtc {
+
+// TODO(deadbeef): Move this to .cc file and out of api/. What threads methods
+// are called on is an implementation detail.
+BEGIN_SIGNALING_PROXY_MAP(PeerConnectionFactory)
+PROXY_SIGNALING_THREAD_DESTRUCTOR()
+PROXY_METHOD1(void, SetOptions, const Options&)
+PROXY_METHOD4(rtc::scoped_refptr<PeerConnectionInterface>,
+              CreatePeerConnection,
+              const PeerConnectionInterface::RTCConfiguration&,
+              std::unique_ptr<cricket::PortAllocator>,
+              std::unique_ptr<rtc::RTCCertificateGeneratorInterface>,
+              PeerConnectionObserver*)
+PROXY_METHOD2(rtc::scoped_refptr<PeerConnectionInterface>,
+              CreatePeerConnection,
+              const PeerConnectionInterface::RTCConfiguration&,
+              PeerConnectionDependencies)
+PROXY_CONSTMETHOD1(webrtc::RtpCapabilities,
+                   GetRtpSenderCapabilities,
+                   cricket::MediaType)
+PROXY_CONSTMETHOD1(webrtc::RtpCapabilities,
+                   GetRtpReceiverCapabilities,
+                   cricket::MediaType)
+PROXY_METHOD1(rtc::scoped_refptr<MediaStreamInterface>,
+              CreateLocalMediaStream,
+              const std::string&)
+PROXY_METHOD1(rtc::scoped_refptr<AudioSourceInterface>,
+              CreateAudioSource,
+              const cricket::AudioOptions&)
+PROXY_METHOD2(rtc::scoped_refptr<VideoTrackInterface>,
+              CreateVideoTrack,
+              const std::string&,
+              VideoTrackSourceInterface*)
+PROXY_METHOD2(rtc::scoped_refptr<AudioTrackInterface>,
+              CreateAudioTrack,
+              const std::string&,
+              AudioSourceInterface*)
+PROXY_METHOD2(bool, StartAecDump, rtc::PlatformFile, int64_t)
+PROXY_METHOD0(void, StopAecDump)
+END_PROXY_MAP()
+
+}  // namespace webrtc
+
+#endif  // API_PEER_CONNECTION_FACTORY_PROXY_H_
diff --git a/api/peer_connection_interface.cc b/api/peer_connection_interface.cc
new file mode 100644
index 0000000..244ee73
--- /dev/null
+++ b/api/peer_connection_interface.cc
@@ -0,0 +1,245 @@
+/*
+ *  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/peer_connection_interface.h"
+#include "api/dtls_transport_interface.h"
+#include "api/sctp_transport_interface.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);
+}
+
+PeerConnectionInterface::IceConnectionState
+PeerConnectionInterface::standardized_ice_connection_state() {
+  return PeerConnectionInterface::IceConnectionState::kIceConnectionFailed;
+}
+
+PeerConnectionInterface::PeerConnectionState
+PeerConnectionInterface::peer_connection_state() {
+  return PeerConnectionInterface::PeerConnectionState::kFailed;
+}
+
+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;
+}
+
+rtc::scoped_refptr<DtlsTransportInterface>
+PeerConnectionInterface::LookupDtlsTransportByMid(const std::string& mid) {
+  RTC_NOTREACHED();
+  return nullptr;
+}
+
+rtc::scoped_refptr<SctpTransportInterface>
+PeerConnectionInterface::GetSctpTransport() const {
+  RTC_NOTREACHED();
+  return nullptr;
+}
+
+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,
+    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 {};
+}
+
+}  // namespace webrtc
diff --git a/api/peer_connection_interface.h b/api/peer_connection_interface.h
new file mode 100644
index 0000000..1d7f96f
--- /dev/null
+++ b/api/peer_connection_interface.h
@@ -0,0 +1,1437 @@
+/*
+ *  Copyright 2012 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 the PeerConnection interface as defined in
+// https://w3c.github.io/webrtc-pc/#peer-to-peer-connections
+//
+// The PeerConnectionFactory class provides factory methods to create
+// PeerConnection, MediaStream and MediaStreamTrack objects.
+//
+// The following steps are needed to setup a typical call using WebRTC:
+//
+// 1. Create a PeerConnectionFactoryInterface. Check constructors for more
+// information about input parameters.
+//
+// 2. Create a PeerConnection object. Provide a configuration struct which
+// points to STUN and/or TURN servers used to generate ICE candidates, and
+// provide an object that implements the PeerConnectionObserver interface,
+// which is used to receive callbacks from the PeerConnection.
+//
+// 3. Create local MediaStreamTracks using the PeerConnectionFactory and add
+// them to PeerConnection by calling AddTrack (or legacy method, AddStream).
+//
+// 4. Create an offer, call SetLocalDescription with it, serialize it, and send
+// it to the remote peer
+//
+// 5. Once an ICE candidate has been gathered, the PeerConnection will call the
+// observer function OnIceCandidate. The candidates must also be serialized and
+// sent to the remote peer.
+//
+// 6. Once an answer is received from the remote peer, call
+// SetRemoteDescription with the remote answer.
+//
+// 7. Once a remote candidate is received from the remote peer, provide it to
+// the PeerConnection by calling AddIceCandidate.
+//
+// The receiver of a call (assuming the application is "call"-based) can decide
+// to accept or reject the call; this decision will be taken by the application,
+// not the PeerConnection.
+//
+// If the application decides to accept the call, it should:
+//
+// 1. Create PeerConnectionFactoryInterface if it doesn't exist.
+//
+// 2. Create a new PeerConnection.
+//
+// 3. Provide the remote offer to the new PeerConnection object by calling
+// SetRemoteDescription.
+//
+// 4. Generate an answer to the remote offer by calling CreateAnswer and send it
+// back to the remote peer.
+//
+// 5. Provide the local answer to the new PeerConnection by calling
+// SetLocalDescription with the answer.
+//
+// 6. Provide the remote ICE candidates by calling AddIceCandidate.
+//
+// 7. Once a candidate has been gathered, the PeerConnection will call the
+// observer function OnIceCandidate. Send these candidates to the remote peer.
+
+#ifndef API_PEER_CONNECTION_INTERFACE_H_
+#define API_PEER_CONNECTION_INTERFACE_H_
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "api/async_resolver_factory.h"
+#include "api/audio/audio_mixer.h"
+#include "api/audio_codecs/audio_decoder_factory.h"
+#include "api/audio_codecs/audio_encoder_factory.h"
+#include "api/audio_options.h"
+#include "api/call/call_factory_interface.h"
+#include "api/crypto/crypto_options.h"
+#include "api/data_channel_interface.h"
+#include "api/fec_controller.h"
+#include "api/jsep.h"
+#include "api/media_stream_interface.h"
+#include "api/media_transport_interface.h"
+#include "api/rtc_error.h"
+#include "api/rtc_event_log_output.h"
+#include "api/rtp_receiver_interface.h"
+#include "api/rtp_sender_interface.h"
+#include "api/rtp_transceiver_interface.h"
+#include "api/set_remote_description_observer_interface.h"
+#include "api/stats/rtc_stats_collector_callback.h"
+#include "api/stats_types.h"
+#include "api/transport/bitrate_settings.h"
+#include "api/transport/network_control.h"
+#include "api/turn_customizer.h"
+#include "logging/rtc_event_log/rtc_event_log_factory_interface.h"
+#include "media/base/media_config.h"
+// 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/media_engine.h"  // nogncheck
+#include "p2p/base/port_allocator.h"  // nogncheck
+// TODO(nisse): The interface for bitrate allocation strategy belongs in api/.
+#include "rtc_base/bitrate_allocation_strategy.h"
+#include "rtc_base/network.h"
+#include "rtc_base/platform_file.h"
+#include "rtc_base/rtc_certificate.h"
+#include "rtc_base/rtc_certificate_generator.h"
+#include "rtc_base/socket_address.h"
+#include "rtc_base/ssl_certificate.h"
+#include "rtc_base/ssl_stream_adapter.h"
+#include "rtc_base/system/rtc_export.h"
+
+namespace rtc {
+class SSLIdentity;
+class Thread;
+}  // namespace rtc
+
+namespace webrtc {
+class AudioDeviceModule;
+class AudioMixer;
+class AudioProcessing;
+class DtlsTransportInterface;
+class SctpTransportInterface;
+class VideoDecoderFactory;
+class VideoEncoderFactory;
+
+// MediaStream container interface.
+class StreamCollectionInterface : public rtc::RefCountInterface {
+ public:
+  // TODO(ronghuawu): Update the function names to c++ style, e.g. find -> Find.
+  virtual size_t count() = 0;
+  virtual MediaStreamInterface* at(size_t index) = 0;
+  virtual MediaStreamInterface* find(const std::string& label) = 0;
+  virtual MediaStreamTrackInterface* FindAudioTrack(const std::string& id) = 0;
+  virtual MediaStreamTrackInterface* FindVideoTrack(const std::string& id) = 0;
+
+ protected:
+  // Dtor protected as objects shouldn't be deleted via this interface.
+  ~StreamCollectionInterface() override = default;
+};
+
+class StatsObserver : public rtc::RefCountInterface {
+ public:
+  virtual void OnComplete(const StatsReports& reports) = 0;
+
+ protected:
+  ~StatsObserver() override = default;
+};
+
+enum class SdpSemantics { kPlanB, kUnifiedPlan };
+
+class PeerConnectionInterface : public rtc::RefCountInterface {
+ public:
+  // See https://w3c.github.io/webrtc-pc/#dom-rtcsignalingstate
+  enum SignalingState {
+    kStable,
+    kHaveLocalOffer,
+    kHaveLocalPrAnswer,
+    kHaveRemoteOffer,
+    kHaveRemotePrAnswer,
+    kClosed,
+  };
+
+  // See https://w3c.github.io/webrtc-pc/#dom-rtcicegatheringstate
+  enum IceGatheringState {
+    kIceGatheringNew,
+    kIceGatheringGathering,
+    kIceGatheringComplete
+  };
+
+  // See https://w3c.github.io/webrtc-pc/#dom-rtcpeerconnectionstate
+  enum class PeerConnectionState {
+    kNew,
+    kConnecting,
+    kConnected,
+    kDisconnected,
+    kFailed,
+    kClosed,
+  };
+
+  // See https://w3c.github.io/webrtc-pc/#dom-rtciceconnectionstate
+  enum IceConnectionState {
+    kIceConnectionNew,
+    kIceConnectionChecking,
+    kIceConnectionConnected,
+    kIceConnectionCompleted,
+    kIceConnectionFailed,
+    kIceConnectionDisconnected,
+    kIceConnectionClosed,
+    kIceConnectionMax,
+  };
+
+  // TLS certificate policy.
+  enum TlsCertPolicy {
+    // For TLS based protocols, ensure the connection is secure by not
+    // circumventing certificate validation.
+    kTlsCertPolicySecure,
+    // For TLS based protocols, disregard security completely by skipping
+    // certificate validation. This is insecure and should never be used unless
+    // security is irrelevant in that particular context.
+    kTlsCertPolicyInsecureNoCheck,
+  };
+
+  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"
+    // part of the URI may contain either an IP address or a hostname.
+    std::string uri;
+    std::vector<std::string> urls;
+    std::string username;
+    std::string password;
+    TlsCertPolicy tls_cert_policy = kTlsCertPolicySecure;
+    // If the URIs in |urls| only contain IP addresses, this field can be used
+    // to indicate the hostname, which may be necessary for TLS (using the SNI
+    // extension). If |urls| itself contains the hostname, this isn't
+    // necessary.
+    std::string hostname;
+    // List of protocols to be used in the TLS ALPN extension.
+    std::vector<std::string> tls_alpn_protocols;
+    // List of elliptic curves to be used in the TLS elliptic curves extension.
+    std::vector<std::string> tls_elliptic_curves;
+
+    bool operator==(const IceServer& o) const {
+      return uri == o.uri && urls == o.urls && username == o.username &&
+             password == o.password && tls_cert_policy == o.tls_cert_policy &&
+             hostname == o.hostname &&
+             tls_alpn_protocols == o.tls_alpn_protocols &&
+             tls_elliptic_curves == o.tls_elliptic_curves;
+    }
+    bool operator!=(const IceServer& o) const { return !(*this == o); }
+  };
+  typedef std::vector<IceServer> IceServers;
+
+  enum IceTransportsType {
+    // TODO(pthatcher): Rename these kTransporTypeXXX, but update
+    // Chromium at the same time.
+    kNone,
+    kRelay,
+    kNoHost,
+    kAll
+  };
+
+  // https://tools.ietf.org/html/draft-ietf-rtcweb-jsep-24#section-4.1.1
+  enum BundlePolicy {
+    kBundlePolicyBalanced,
+    kBundlePolicyMaxBundle,
+    kBundlePolicyMaxCompat
+  };
+
+  // https://tools.ietf.org/html/draft-ietf-rtcweb-jsep-24#section-4.1.1
+  enum RtcpMuxPolicy {
+    kRtcpMuxPolicyNegotiate,
+    kRtcpMuxPolicyRequire,
+  };
+
+  enum TcpCandidatePolicy {
+    kTcpCandidatePolicyEnabled,
+    kTcpCandidatePolicyDisabled
+  };
+
+  enum CandidateNetworkPolicy {
+    kCandidateNetworkPolicyAll,
+    kCandidateNetworkPolicyLowCost
+  };
+
+  enum ContinualGatheringPolicy { GATHER_ONCE, GATHER_CONTINUALLY };
+
+  enum class RTCConfigurationType {
+    // A configuration that is safer to use, despite not having the best
+    // performance. Currently this is the default configuration.
+    kSafe,
+    // An aggressive configuration that has better performance, although it
+    // may be riskier and may need extra support in the application.
+    kAggressive
+  };
+
+  // TODO(hbos): Change into class with private data and public getters.
+  // TODO(nisse): In particular, accessing fields directly from an
+  // application is brittle, since the organization mirrors the
+  // organization of the implementation, which isn't stable. So we
+  // need getters and setters at least for fields which applications
+  // are interested in.
+  struct RTC_EXPORT RTCConfiguration {
+    // This struct is subject to reorganization, both for naming
+    // consistency, and to group settings to match where they are used
+    // in the implementation. To do that, we need getter and setter
+    // methods for all settings which are of interest to applications,
+    // Chrome in particular.
+
+    RTCConfiguration();
+    RTCConfiguration(const RTCConfiguration&);
+    explicit RTCConfiguration(RTCConfigurationType type);
+    ~RTCConfiguration();
+
+    bool operator==(const RTCConfiguration& o) const;
+    bool operator!=(const RTCConfiguration& o) const;
+
+    bool dscp() const { return media_config.enable_dscp; }
+    void set_dscp(bool enable) { media_config.enable_dscp = enable; }
+
+    bool cpu_adaptation() const {
+      return media_config.video.enable_cpu_adaptation;
+    }
+    void set_cpu_adaptation(bool enable) {
+      media_config.video.enable_cpu_adaptation = enable;
+    }
+
+    bool suspend_below_min_bitrate() const {
+      return media_config.video.suspend_below_min_bitrate;
+    }
+    void set_suspend_below_min_bitrate(bool enable) {
+      media_config.video.suspend_below_min_bitrate = enable;
+    }
+
+    bool prerenderer_smoothing() const {
+      return media_config.video.enable_prerenderer_smoothing;
+    }
+    void set_prerenderer_smoothing(bool enable) {
+      media_config.video.enable_prerenderer_smoothing = enable;
+    }
+
+    bool experiment_cpu_load_estimator() const {
+      return media_config.video.experiment_cpu_load_estimator;
+    }
+    void set_experiment_cpu_load_estimator(bool enable) {
+      media_config.video.experiment_cpu_load_estimator = enable;
+    }
+
+    int audio_rtcp_report_interval_ms() const {
+      return media_config.audio.rtcp_report_interval_ms;
+    }
+    void set_audio_rtcp_report_interval_ms(int audio_rtcp_report_interval_ms) {
+      media_config.audio.rtcp_report_interval_ms =
+          audio_rtcp_report_interval_ms;
+    }
+
+    int video_rtcp_report_interval_ms() const {
+      return media_config.video.rtcp_report_interval_ms;
+    }
+    void set_video_rtcp_report_interval_ms(int video_rtcp_report_interval_ms) {
+      media_config.video.rtcp_report_interval_ms =
+          video_rtcp_report_interval_ms;
+    }
+
+    static const int kUndefined = -1;
+    // Default maximum number of packets in the audio jitter buffer.
+    static const int kAudioJitterBufferMaxPackets = 200;
+    // ICE connection receiving timeout for aggressive configuration.
+    static const int kAggressiveIceConnectionReceivingTimeout = 1000;
+
+    ////////////////////////////////////////////////////////////////////////
+    // The below few fields mirror the standard RTCConfiguration dictionary:
+    // https://w3c.github.io/webrtc-pc/#rtcconfiguration-dictionary
+    ////////////////////////////////////////////////////////////////////////
+
+    // TODO(pthatcher): Rename this ice_servers, but update Chromium
+    // at the same time.
+    IceServers servers;
+    // TODO(pthatcher): Rename this ice_transport_type, but update
+    // Chromium at the same time.
+    IceTransportsType type = kAll;
+    BundlePolicy bundle_policy = kBundlePolicyBalanced;
+    RtcpMuxPolicy rtcp_mux_policy = kRtcpMuxPolicyRequire;
+    std::vector<rtc::scoped_refptr<rtc::RTCCertificate>> certificates;
+    int ice_candidate_pool_size = 0;
+
+    //////////////////////////////////////////////////////////////////////////
+    // The below fields correspond to constraints from the deprecated
+    // constraints interface for constructing a PeerConnection.
+    //
+    // absl::optional fields can be "missing", in which case the implementation
+    // default will be used.
+    //////////////////////////////////////////////////////////////////////////
+
+    // If set to true, don't gather IPv6 ICE candidates.
+    // TODO(deadbeef): Remove this? IPv6 support has long stopped being
+    // experimental
+    bool disable_ipv6 = false;
+
+    // If set to true, don't gather IPv6 ICE candidates on Wi-Fi.
+    // Only intended to be used on specific devices. Certain phones disable IPv6
+    // when the screen is turned off and it would be better to just disable the
+    // IPv6 ICE candidates on Wi-Fi in those cases.
+    bool disable_ipv6_on_wifi = false;
+
+    // By default, the PeerConnection will use a limited number of IPv6 network
+    // interfaces, in order to avoid too many ICE candidate pairs being created
+    // and delaying ICE completion.
+    //
+    // Can be set to INT_MAX to effectively disable the limit.
+    int max_ipv6_networks = cricket::kDefaultMaxIPv6Networks;
+
+    // Exclude link-local network interfaces
+    // from considertaion for gathering ICE candidates.
+    bool disable_link_local_networks = false;
+
+    // If set to true, use RTP data channels instead of SCTP.
+    // TODO(deadbeef): Remove this. We no longer commit to supporting RTP data
+    // channels, though some applications are still working on moving off of
+    // them.
+    bool enable_rtp_data_channel = false;
+
+    // Minimum bitrate at which screencast video tracks will be encoded at.
+    // This means adding padding bits up to this bitrate, which can help
+    // when switching from a static scene to one with motion.
+    absl::optional<int> screencast_min_bitrate;
+
+    // Use new combined audio/video bandwidth estimation?
+    absl::optional<bool> combined_audio_video_bwe;
+
+    // TODO(bugs.webrtc.org/9891) - Move to crypto_options
+    // Can be used to disable DTLS-SRTP. This should never be done, but can be
+    // useful for testing purposes, for example in setting up a loopback call
+    // with a single PeerConnection.
+    absl::optional<bool> enable_dtls_srtp;
+
+    /////////////////////////////////////////////////
+    // The below fields are not part of the standard.
+    /////////////////////////////////////////////////
+
+    // Can be used to disable TCP candidate generation.
+    TcpCandidatePolicy tcp_candidate_policy = kTcpCandidatePolicyEnabled;
+
+    // Can be used to avoid gathering candidates for a "higher cost" network,
+    // if a lower cost one exists. For example, if both Wi-Fi and cellular
+    // interfaces are available, this could be used to avoid using the cellular
+    // interface.
+    CandidateNetworkPolicy candidate_network_policy =
+        kCandidateNetworkPolicyAll;
+
+    // The maximum number of packets that can be stored in the NetEq audio
+    // jitter buffer. Can be reduced to lower tolerated audio latency.
+    int audio_jitter_buffer_max_packets = kAudioJitterBufferMaxPackets;
+
+    // Whether to use the NetEq "fast mode" which will accelerate audio quicker
+    // if it falls behind.
+    bool audio_jitter_buffer_fast_accelerate = false;
+
+    // The minimum delay in milliseconds for the audio jitter buffer.
+    int audio_jitter_buffer_min_delay_ms = 0;
+
+    // Whether the audio jitter buffer adapts the delay to retransmitted
+    // packets.
+    bool audio_jitter_buffer_enable_rtx_handling = false;
+
+    // Timeout in milliseconds before an ICE candidate pair is considered to be
+    // "not receiving", after which a lower priority candidate pair may be
+    // selected.
+    int ice_connection_receiving_timeout = kUndefined;
+
+    // Interval in milliseconds at which an ICE "backup" candidate pair will be
+    // pinged. This is a candidate pair which is not actively in use, but may
+    // be switched to if the active candidate pair becomes unusable.
+    //
+    // This is relevant mainly to Wi-Fi/cell handoff; the application may not
+    // want this backup cellular candidate pair pinged frequently, since it
+    // consumes data/battery.
+    int ice_backup_candidate_pair_ping_interval = kUndefined;
+
+    // Can be used to enable continual gathering, which means new candidates
+    // will be gathered as network interfaces change. Note that if continual
+    // gathering is used, the candidate removal API should also be used, to
+    // avoid an ever-growing list of candidates.
+    ContinualGatheringPolicy continual_gathering_policy = GATHER_ONCE;
+
+    // If set to true, candidate pairs will be pinged in order of most likely
+    // to work (which means using a TURN server, generally), rather than in
+    // standard priority order.
+    bool prioritize_most_likely_ice_candidate_pairs = false;
+
+    // Implementation defined settings. A public member only for the benefit of
+    // the implementation. Applications must not access it directly, and should
+    // instead use provided accessor methods, e.g., set_cpu_adaptation.
+    struct cricket::MediaConfig media_config;
+
+    // If set to true, only one preferred TURN allocation will be used per
+    // network interface. UDP is preferred over TCP and IPv6 over IPv4. This
+    // can be used to cut down on the number of candidate pairings.
+    bool prune_turn_ports = false;
+
+    // If set to true, this means the ICE transport should presume TURN-to-TURN
+    // candidate pairs will succeed, even before a binding response is received.
+    // This can be used to optimize the initial connection time, since the DTLS
+    // handshake can begin immediately.
+    bool presume_writable_when_fully_relayed = false;
+
+    // If true, "renomination" will be added to the ice options in the transport
+    // description.
+    // See: https://tools.ietf.org/html/draft-thatcher-ice-renomination-00
+    bool enable_ice_renomination = false;
+
+    // If true, the ICE role is re-determined when the PeerConnection sets a
+    // local transport description that indicates an ICE restart.
+    //
+    // This is standard RFC5245 ICE behavior, but causes unnecessary role
+    // thrashing, so an application may wish to avoid it. This role
+    // re-determining was removed in ICEbis (ICE v2).
+    bool redetermine_role_on_ice_restart = true;
+
+    // The following fields define intervals in milliseconds at which ICE
+    // connectivity checks are sent.
+    //
+    // We consider ICE is "strongly connected" for an agent when there is at
+    // least one candidate pair that currently succeeds in connectivity check
+    // from its direction i.e. sending a STUN ping and receives a STUN ping
+    // response, AND all candidate pairs have sent a minimum number of pings for
+    // connectivity (this number is implementation-specific). Otherwise, ICE is
+    // considered in "weak connectivity".
+    //
+    // Note that the above notion of strong and weak connectivity is not defined
+    // in RFC 5245, and they apply to our current ICE implementation only.
+    //
+    // 1) ice_check_interval_strong_connectivity defines the interval applied to
+    // ALL candidate pairs when ICE is strongly connected, and it overrides the
+    // default value of this interval in the ICE implementation;
+    // 2) ice_check_interval_weak_connectivity defines the counterpart for ALL
+    // pairs when ICE is weakly connected, and it overrides the default value of
+    // this interval in the ICE implementation;
+    // 3) ice_check_min_interval defines the minimal interval (equivalently the
+    // maximum rate) that overrides the above two intervals when either of them
+    // is less.
+    absl::optional<int> ice_check_interval_strong_connectivity;
+    absl::optional<int> ice_check_interval_weak_connectivity;
+    absl::optional<int> ice_check_min_interval;
+
+    // The min time period for which a candidate pair must wait for response to
+    // connectivity checks before it becomes unwritable. This parameter
+    // overrides the default value in the ICE implementation if set.
+    absl::optional<int> ice_unwritable_timeout;
+
+    // The min number of connectivity checks that a candidate pair must sent
+    // without receiving response before it becomes unwritable. This parameter
+    // overrides the default value in the ICE implementation if set.
+    absl::optional<int> ice_unwritable_min_checks;
+
+    // The min time period for which a candidate pair must wait for response to
+    // connectivity checks it becomes inactive. This parameter overrides the
+    // default value in the ICE implementation if set.
+    absl::optional<int> ice_inactive_timeout;
+
+    // The interval in milliseconds at which STUN candidates will resend STUN
+    // binding requests to keep NAT bindings open.
+    absl::optional<int> stun_candidate_keepalive_interval;
+
+    // ICE Periodic Regathering
+    // If set, WebRTC will periodically create and propose candidates without
+    // starting a new ICE generation. The regathering happens continuously with
+    // interval specified in milliseconds by the uniform distribution [a, b].
+    absl::optional<rtc::IntervalRange> ice_regather_interval_range;
+
+    // Optional TurnCustomizer.
+    // With this class one can modify outgoing TURN messages.
+    // The object passed in must remain valid until PeerConnection::Close() is
+    // called.
+    webrtc::TurnCustomizer* turn_customizer = nullptr;
+
+    // Preferred network interface.
+    // A candidate pair on a preferred network has a higher precedence in ICE
+    // than one on an un-preferred network, regardless of priority or network
+    // cost.
+    absl::optional<rtc::AdapterType> network_preference;
+
+    // Configure the SDP semantics used by this PeerConnection. Note that the
+    // WebRTC 1.0 specification requires kUnifiedPlan semantics. The
+    // RtpTransceiver API is only available with kUnifiedPlan semantics.
+    //
+    // kPlanB will cause PeerConnection to create offers and answers with at
+    // most one audio and one video m= section with multiple RtpSenders and
+    // RtpReceivers specified as multiple a=ssrc lines within the section. This
+    // will also cause PeerConnection to ignore all but the first m= section of
+    // the same media type.
+    //
+    // kUnifiedPlan will cause PeerConnection to create offers and answers with
+    // multiple m= sections where each m= section maps to one RtpSender and one
+    // RtpReceiver (an RtpTransceiver), either both audio or both video. This
+    // will also cause PeerConnection to ignore all but the first a=ssrc lines
+    // that form a Plan B stream.
+    //
+    // For users who wish to send multiple audio/video streams and need to stay
+    // interoperable with legacy WebRTC implementations or use legacy APIs,
+    // specify kPlanB.
+    //
+    // For all other users, specify kUnifiedPlan.
+    SdpSemantics sdp_semantics = SdpSemantics::kPlanB;
+
+    // TODO(bugs.webrtc.org/9891) - Move to crypto_options or remove.
+    // Actively reset the SRTP parameters whenever the DTLS transports
+    // underneath are reset for every offer/answer negotiation.
+    // This is only intended to be a workaround for crbug.com/835958
+    // WARNING: This would cause RTP/RTCP packets decryption failure if not used
+    // correctly. This flag will be deprecated soon. Do not rely on it.
+    bool active_reset_srtp_params = false;
+
+    // If MediaTransportFactory is provided in PeerConnectionFactory, this flag
+    // informs PeerConnection that it should use the MediaTransportInterface for
+    // media (audio/video). It's invalid to set it to |true| if the
+    // MediaTransportFactory wasn't provided.
+    bool use_media_transport = false;
+
+    // If MediaTransportFactory is provided in PeerConnectionFactory, this flag
+    // informs PeerConnection that it should use the MediaTransportInterface for
+    // data channels.  It's invalid to set it to |true| if the
+    // MediaTransportFactory wasn't provided.  Data channels over media
+    // transport are not compatible with RTP or SCTP data channels.  Setting
+    // both |use_media_transport_for_data_channels| and
+    // |enable_rtp_data_channel| is invalid.
+    bool use_media_transport_for_data_channels = false;
+
+    // Defines advanced optional cryptographic settings related to SRTP and
+    // frame encryption for native WebRTC. Setting this will overwrite any
+    // settings set in PeerConnectionFactory (which is deprecated).
+    absl::optional<CryptoOptions> crypto_options;
+
+    // Configure if we should include the SDP attribute extmap-allow-mixed in
+    // our offer. Although we currently do support this, it's not included in
+    // our offer by default due to a previous bug that caused the SDP parser to
+    // abort parsing if this attribute was present. This is fixed in Chrome 71.
+    // TODO(webrtc:9985): Change default to true once sufficient time has
+    // passed.
+    bool offer_extmap_allow_mixed = false;
+
+    //
+    // Don't forget to update operator== if adding something.
+    //
+  };
+
+  // See: https://www.w3.org/TR/webrtc/#idl-def-rtcofferansweroptions
+  struct RTCOfferAnswerOptions {
+    static const int kUndefined = -1;
+    static const int kMaxOfferToReceiveMedia = 1;
+
+    // The default value for constraint offerToReceiveX:true.
+    static const int kOfferToReceiveMediaTrue = 1;
+
+    // These options are left as backwards compatibility for clients who need
+    // "Plan B" semantics. Clients who have switched to "Unified Plan" semantics
+    // should use the RtpTransceiver API (AddTransceiver) instead.
+    //
+    // offer_to_receive_X set to 1 will cause a media description to be
+    // generated in the offer, even if no tracks of that type have been added.
+    // Values greater than 1 are treated the same.
+    //
+    // If set to 0, the generated directional attribute will not include the
+    // "recv" direction (meaning it will be "sendonly" or "inactive".
+    int offer_to_receive_video = kUndefined;
+    int offer_to_receive_audio = kUndefined;
+
+    bool voice_activity_detection = true;
+    bool ice_restart = false;
+
+    // If true, will offer to BUNDLE audio/video/data together. Not to be
+    // 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,
+                          int offer_to_receive_audio,
+                          bool voice_activity_detection,
+                          bool ice_restart,
+                          bool use_rtp_mux)
+        : offer_to_receive_video(offer_to_receive_video),
+          offer_to_receive_audio(offer_to_receive_audio),
+          voice_activity_detection(voice_activity_detection),
+          ice_restart(ice_restart),
+          use_rtp_mux(use_rtp_mux) {}
+  };
+
+  // Used by GetStats to decide which stats to include in the stats reports.
+  // |kStatsOutputLevelStandard| includes the standard stats for Javascript API;
+  // |kStatsOutputLevelDebug| includes both the standard stats and additional
+  // stats for debugging purposes.
+  enum StatsOutputLevel {
+    kStatsOutputLevelStandard,
+    kStatsOutputLevelDebug,
+  };
+
+  // Accessor methods to active local streams.
+  // This method is not supported with kUnifiedPlan semantics. Please use
+  // GetSenders() instead.
+  virtual rtc::scoped_refptr<StreamCollectionInterface> local_streams() = 0;
+
+  // Accessor methods to remote streams.
+  // This method is not supported with kUnifiedPlan semantics. Please use
+  // GetReceivers() instead.
+  virtual rtc::scoped_refptr<StreamCollectionInterface> remote_streams() = 0;
+
+  // Add a new MediaStream to be sent on this PeerConnection.
+  // Note that a SessionDescription negotiation is needed before the
+  // remote peer can receive the stream.
+  //
+  // This has been removed from the standard in favor of a track-based API. So,
+  // this is equivalent to simply calling AddTrack for each track within the
+  // stream, with the one difference that if "stream->AddTrack(...)" is called
+  // later, the PeerConnection will automatically pick up the new track. Though
+  // this functionality will be deprecated in the future.
+  //
+  // This method is not supported with kUnifiedPlan semantics. Please use
+  // AddTrack instead.
+  virtual bool AddStream(MediaStreamInterface* stream) = 0;
+
+  // Remove a MediaStream from this PeerConnection.
+  // Note that a SessionDescription negotiation is needed before the
+  // remote peer is notified.
+  //
+  // This method is not supported with kUnifiedPlan semantics. Please use
+  // RemoveTrack instead.
+  virtual void RemoveStream(MediaStreamInterface* stream) = 0;
+
+  // Add a new MediaStreamTrack to be sent on this PeerConnection, and return
+  // the newly created RtpSender. The RtpSender will be associated with the
+  // streams specified in the |stream_ids| list.
+  //
+  // Errors:
+  // - INVALID_PARAMETER: |track| is null, has a kind other than audio or video,
+  //       or a sender already exists for the track.
+  // - 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);
+
+  // Remove an RtpSender from this PeerConnection.
+  // Returns true on success.
+  // 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
+  // to add a media description for the corresponding transceiver.
+  //
+  // The initial value of |mid| in the returned transceiver is null. Setting a
+  // new session description may change it to a non-null value.
+  //
+  // https://w3c.github.io/webrtc-pc/#dom-rtcpeerconnection-addtransceiver
+  //
+  // Optionally, an RtpTransceiverInit structure can be specified to configure
+  // the transceiver from construction. If not specified, the transceiver will
+  // default to having a direction of kSendRecv and not be part of any streams.
+  //
+  // These methods are only available when Unified Plan is enabled (see
+  // RTCConfiguration).
+  //
+  // Common errors:
+  // - INTERNAL_ERROR: The configuration does not have Unified Plan enabled.
+  // TODO(steveanton): Make these pure virtual once downstream projects have
+  // updated.
+
+  // Adds a transceiver with a sender set to transmit the given track. The kind
+  // of the transceiver (and sender/receiver) will be derived from the kind of
+  // the track.
+  // Errors:
+  // - INVALID_PARAMETER: |track| is null.
+  virtual RTCErrorOr<rtc::scoped_refptr<RtpTransceiverInterface>>
+  AddTransceiver(rtc::scoped_refptr<MediaStreamTrackInterface> track);
+  virtual RTCErrorOr<rtc::scoped_refptr<RtpTransceiverInterface>>
+  AddTransceiver(rtc::scoped_refptr<MediaStreamTrackInterface> track,
+                 const RtpTransceiverInit& init);
+
+  // Adds a transceiver with the given kind. Can either be MEDIA_TYPE_AUDIO or
+  // MEDIA_TYPE_VIDEO.
+  // Errors:
+  // - INVALID_PARAMETER: |media_type| is not MEDIA_TYPE_AUDIO or
+  //                      MEDIA_TYPE_VIDEO.
+  virtual RTCErrorOr<rtc::scoped_refptr<RtpTransceiverInterface>>
+  AddTransceiver(cricket::MediaType media_type);
+  virtual RTCErrorOr<rtc::scoped_refptr<RtpTransceiverInterface>>
+  AddTransceiver(cricket::MediaType media_type, const RtpTransceiverInit& init);
+
+  // TODO(deadbeef): Make these pure virtual once all subclasses implement them.
+
+  // Creates a sender without a track. Can be used for "early media"/"warmup"
+  // use cases, where the application may want to negotiate video attributes
+  // before a track is available to send.
+  //
+  // The standard way to do this would be through "addTransceiver", but we
+  // don't support that API yet.
+  //
+  // |kind| must be "audio" or "video".
+  //
+  // |stream_id| is used to populate the msid attribute; if empty, one will
+  // be generated automatically.
+  //
+  // This method is not supported with kUnifiedPlan semantics. Please use
+  // AddTransceiver instead.
+  virtual rtc::scoped_refptr<RtpSenderInterface> CreateSender(
+      const std::string& kind,
+      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
+  // media type share the same media description.
+  //
+  // If Unified Plan semantics are specified, gets the RtpSender for each
+  // RtpTransceiver.
+  virtual std::vector<rtc::scoped_refptr<RtpSenderInterface>> GetSenders()
+      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
+  // the same media description. It is also possible to have a media description
+  // with no associated RtpReceivers, if the directional attribute does not
+  // indicate that the remote peer is sending any media.
+  //
+  // If Unified Plan semantics are specified, gets the RtpReceiver for each
+  // RtpTransceiver.
+  virtual std::vector<rtc::scoped_refptr<RtpReceiverInterface>> GetReceivers()
+      const;
+
+  // Get all RtpTransceivers, created either through AddTransceiver, AddTrack or
+  // by a remote description applied with SetRemoteDescription.
+  //
+  // Note: This method is only available when Unified Plan is enabled (see
+  // RTCConfiguration).
+  virtual std::vector<rtc::scoped_refptr<RtpTransceiverInterface>>
+  GetTransceivers() const;
+
+  // The legacy non-compliant GetStats() API. This correspond to the
+  // callback-based version of getStats() in JavaScript. The returned metrics
+  // are UNDOCUMENTED and many of them rely on implementation-specific details.
+  // The goal is to DELETE THIS VERSION but we can't today because it is heavily
+  // relied upon by third parties. See https://crbug.com/822696.
+  //
+  // This version is wired up into Chrome. Any stats implemented are
+  // automatically exposed to the Web Platform. This has BYPASSED the Chrome
+  // release processes for years and lead to cross-browser incompatibility
+  // issues and web application reliance on Chrome-only behavior.
+  //
+  // This API is in "maintenance mode", serious regressions should be fixed but
+  // adding new stats is highly discouraged.
+  //
+  // TODO(hbos): Deprecate and remove this when third parties have migrated to
+  // the spec-compliant GetStats() API. https://crbug.com/822696
+  virtual bool GetStats(StatsObserver* observer,
+                        MediaStreamTrackInterface* track,  // Optional
+                        StatsOutputLevel level) = 0;
+  // The spec-compliant GetStats() API. This correspond to the promise-based
+  // version of getStats() in JavaScript. Implementation status is described in
+  // api/stats/rtcstats_objects.h. For more details on stats, see spec:
+  // https://w3c.github.io/webrtc-pc/#dom-rtcpeerconnection-getstats
+  // TODO(hbos): Takes shared ownership, use rtc::scoped_refptr<> instead. This
+  // requires stop overriding the current version in third party or making third
+  // party calls explicit to avoid ambiguity during switch. Make the future
+  // version abstract as soon as third party projects implement it.
+  virtual void GetStats(RTCStatsCollectorCallback* callback) {}
+  // Spec-compliant getStats() performing the stats selection algorithm with the
+  // sender. https://w3c.github.io/webrtc-pc/#dom-rtcrtpsender-getstats
+  // TODO(hbos): Make abstract as soon as third party projects implement it.
+  virtual void GetStats(
+      rtc::scoped_refptr<RtpSenderInterface> selector,
+      rtc::scoped_refptr<RTCStatsCollectorCallback> callback) {}
+  // Spec-compliant getStats() performing the stats selection algorithm with the
+  // receiver. https://w3c.github.io/webrtc-pc/#dom-rtcrtpreceiver-getstats
+  // TODO(hbos): Make abstract as soon as third party projects implement it.
+  virtual void GetStats(
+      rtc::scoped_refptr<RtpReceiverInterface> selector,
+      rtc::scoped_refptr<RTCStatsCollectorCallback> callback) {}
+  // Clear cached stats in the RTCStatsCollector.
+  // Exposed for testing while waiting for automatic cache clear to work.
+  // https://bugs.webrtc.org/8693
+  virtual void ClearStatsCache() {}
+
+  // Create a data channel with the provided config, or default config if none
+  // is provided. Note that an offer/answer negotiation is still necessary
+  // before the data channel can be used.
+  //
+  // Also, calling CreateDataChannel is the only way to get a data "m=" section
+  // in SDP, so it should be done before CreateOffer is called, if the
+  // application plans to use data channels.
+  virtual rtc::scoped_refptr<DataChannelInterface> CreateDataChannel(
+      const std::string& label,
+      const DataChannelInit* config) = 0;
+
+  // Returns the more recently applied description; "pending" if it exists, and
+  // otherwise "current". See below.
+  virtual const SessionDescriptionInterface* local_description() const = 0;
+  virtual const SessionDescriptionInterface* remote_description() const = 0;
+
+  // A "current" description the one currently negotiated from a complete
+  // offer/answer exchange.
+  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;
+  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 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) = 0;
+
+  // Sets the local session description.
+  // The PeerConnection takes the ownership of |desc| even if it fails.
+  // The |observer| callback will be called when done.
+  // TODO(deadbeef): Change |desc| to be a unique_ptr, to make it clear
+  // that this method always takes ownership of it.
+  virtual void SetLocalDescription(SetSessionDescriptionObserver* observer,
+                                   SessionDescriptionInterface* desc) = 0;
+  // Sets the remote session description.
+  // The PeerConnection takes the ownership of |desc| even if it fails.
+  // The |observer| callback will be called when done.
+  // TODO(hbos): Remove when Chrome implements the new signature.
+  virtual void SetRemoteDescription(SetSessionDescriptionObserver* observer,
+                                    SessionDescriptionInterface* desc) {}
+  // TODO(hbos): Make pure virtual when Chrome has updated its signature.
+  virtual void SetRemoteDescription(
+      std::unique_ptr<SessionDescriptionInterface> desc,
+      rtc::scoped_refptr<SetRemoteDescriptionObserverInterface> observer) {}
+
+  // TODO(deadbeef): Make this pure virtual once all Chrome subclasses of
+  // PeerConnectionInterface implement it.
+  virtual PeerConnectionInterface::RTCConfiguration GetConfiguration();
+
+  // Sets the PeerConnection's global configuration to |config|.
+  //
+  // The members of |config| that may be changed are |type|, |servers|,
+  // |ice_candidate_pool_size| and |prune_turn_ports| (though the candidate
+  // pool size can't be changed after the first call to SetLocalDescription).
+  // Note that this means the BUNDLE and RTCP-multiplexing policies cannot be
+  // changed with this method.
+  //
+  // Any changes to STUN/TURN servers or ICE candidate policy will affect the
+  // next gathering phase, and cause the next call to createOffer to generate
+  // new ICE credentials, as described in JSEP. This also occurs when
+  // |prune_turn_ports| changes, for the same reasoning.
+  //
+  // If an error occurs, returns false and populates |error| if non-null:
+  // - INVALID_MODIFICATION if |config| contains a modified parameter other
+  //   than one of the parameters listed above.
+  // - INVALID_RANGE if |ice_candidate_pool_size| is out of range.
+  // - SYNTAX_ERROR if parsing an ICE server URL failed.
+  // - INVALID_PARAMETER if a TURN server is missing |username| or |password|.
+  // - INTERNAL_ERROR if an unexpected error occurred.
+  //
+  // TODO(deadbeef): Make this pure virtual once all Chrome subclasses of
+  // PeerConnectionInterface implement it.
+  virtual bool SetConfiguration(
+      const PeerConnectionInterface::RTCConfiguration& config,
+      RTCError* error);
+
+  // Version without error output param for backwards compatibility.
+  // TODO(deadbeef): Remove once chromium is updated.
+  virtual bool SetConfiguration(
+      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
+  // description. So the caller of this method still has the ownership of the
+  // |candidate|.
+  virtual bool AddIceCandidate(const IceCandidateInterface* candidate) = 0;
+
+  // Removes a group of remote candidates from the ICE agent. Needed mainly for
+  // continual gathering, to avoid an ever-growing list of candidates as
+  // networks come and go.
+  virtual bool RemoveIceCandidates(
+      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;
+  };
+
+  // SetBitrate limits the bandwidth allocated for all RTP streams sent by
+  // this PeerConnection. Other limitations might affect these limits and
+  // are respected (for example "b=AS" in SDP).
+  //
+  // Setting |current_bitrate_bps| will reset the current bitrate estimate
+  // to the provided value.
+  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);
+
+  // Sets current strategy. If not set default WebRTC allocator will be used.
+  // May be changed during an active session. The strategy
+  // ownership is passed with std::unique_ptr
+  // TODO(alexnarest): Make this pure virtual when tests will be updated
+  virtual void SetBitrateAllocationStrategy(
+      std::unique_ptr<rtc::BitrateAllocationStrategy>
+          bitrate_allocation_strategy) {}
+
+  // Enable/disable playout of received audio streams. Enabled by default. Note
+  // that even if playout is enabled, streams will only be played out if the
+  // appropriate SDP is also applied. Setting |playout| to false will stop
+  // playout of the underlying audio device but starts a task which will poll
+  // for audio data every 10ms to ensure that audio processing happens and the
+  // audio statistics are updated.
+  // TODO(henrika): deprecate and remove this.
+  virtual void SetAudioPlayout(bool playout) {}
+
+  // Enable/disable recording of transmitted audio streams. Enabled by default.
+  // Note that even if recording is enabled, streams will only be recorded if
+  // the appropriate SDP is also applied.
+  // TODO(henrika): deprecate and remove this.
+  virtual void SetAudioRecording(bool recording) {}
+
+  // Looks up the DtlsTransport associated with a MID value.
+  // In the Javascript API, DtlsTransport is a property of a sender, but
+  // because the PeerConnection owns the DtlsTransport in this implementation,
+  // it is better to look them up on the PeerConnection.
+  // TODO(hta): Remove default implementation after updating Chrome.
+  virtual rtc::scoped_refptr<DtlsTransportInterface> LookupDtlsTransportByMid(
+      const std::string& mid);
+
+  // Returns the SCTP transport, if any.
+  // TODO(hta): Remove default implementation after updating Chrome.
+  virtual rtc::scoped_refptr<SctpTransportInterface> GetSctpTransport() const;
+
+  // Returns the current SignalingState.
+  virtual SignalingState signaling_state() = 0;
+
+  // Returns an aggregate state of all ICE *and* DTLS transports.
+  // This is left in place to avoid breaking native clients who expect our old,
+  // nonstandard behavior.
+  // TODO(jonasolsson): deprecate and remove this.
+  virtual IceConnectionState ice_connection_state() = 0;
+
+  // Returns an aggregated state of all ICE transports.
+  virtual IceConnectionState standardized_ice_connection_state();
+
+  // Returns an aggregated state of all ICE and DTLS transports.
+  virtual PeerConnectionState peer_connection_state();
+
+  virtual IceGatheringState ice_gathering_state() = 0;
+
+  // Starts RtcEventLog using existing file. Takes ownership of |file| and
+  // passes it on to Call, which will take the ownership. If the
+  // operation fails the file will be closed.
+  // The logging will stop when |max_size_bytes| is reached or when the
+  // StopRtcEventLog function is called.
+  // TODO(eladalon): Deprecate and remove this.
+  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);
+
+  // Stops logging the RtcEventLog.
+  // TODO(ivoc): Make this pure virtual when Chrome is updated.
+  virtual void StopRtcEventLog() {}
+
+  // Terminates all media, closes the transports, and in general releases any
+  // resources used by the PeerConnection. This is an irreversible operation.
+  //
+  // Note that after this method completes, the PeerConnection will no longer
+  // use the PeerConnectionObserver interface passed in on construction, and
+  // thus the observer object can be safely destroyed.
+  virtual void Close() = 0;
+
+ protected:
+  // Dtor protected as objects shouldn't be deleted via this interface.
+  ~PeerConnectionInterface() override = default;
+};
+
+// PeerConnection callback interface, used for RTCPeerConnection events.
+// Application should implement these methods.
+class PeerConnectionObserver {
+ public:
+  virtual ~PeerConnectionObserver() = default;
+
+  // Triggered when the SignalingState changed.
+  virtual void OnSignalingChange(
+      PeerConnectionInterface::SignalingState new_state) = 0;
+
+  // Triggered when media is received on a new stream from remote peer.
+  virtual void OnAddStream(rtc::scoped_refptr<MediaStreamInterface> stream) {}
+
+  // Triggered when a remote peer closes a stream.
+  virtual void OnRemoveStream(rtc::scoped_refptr<MediaStreamInterface> stream) {
+  }
+
+  // Triggered when a remote peer opens a data channel.
+  virtual void OnDataChannel(
+      rtc::scoped_refptr<DataChannelInterface> data_channel) = 0;
+
+  // Triggered when renegotiation is needed. For example, an ICE restart
+  // has begun.
+  virtual void OnRenegotiationNeeded() = 0;
+
+  // Called any time the legacy IceConnectionState changes.
+  //
+  // Note that our ICE states lag behind the standard slightly. The most
+  // notable differences include the fact that "failed" occurs after 15
+  // seconds, not 30, and this actually represents a combination ICE + DTLS
+  // state, so it may be "failed" if DTLS fails while ICE succeeds.
+  //
+  // TODO(jonasolsson): deprecate and remove this.
+  virtual void OnIceConnectionChange(
+      PeerConnectionInterface::IceConnectionState new_state) = 0;
+
+  // Called any time the standards-compliant IceConnectionState changes.
+  virtual void OnStandardizedIceConnectionChange(
+      PeerConnectionInterface::IceConnectionState new_state) {}
+
+  // Called any time the PeerConnectionState changes.
+  virtual void OnConnectionChange(
+      PeerConnectionInterface::PeerConnectionState new_state) {}
+
+  // Called any time the IceGatheringState changes.
+  virtual void OnIceGatheringChange(
+      PeerConnectionInterface::IceGatheringState new_state) = 0;
+
+  // A new ICE candidate has been gathered.
+  virtual void OnIceCandidate(const IceCandidateInterface* candidate) = 0;
+
+  // Ice candidates have been removed.
+  // TODO(honghaiz): Make this a pure virtual method when all its subclasses
+  // implement it.
+  virtual void OnIceCandidatesRemoved(
+      const std::vector<cricket::Candidate>& candidates) {}
+
+  // Called when the ICE connection receiving status changes.
+  virtual void OnIceConnectionReceivingChange(bool receiving) {}
+
+  // This is called when a receiver and its track are created.
+  // TODO(zhihuang): Make this pure virtual when all subclasses implement it.
+  // Note: This is called with both Plan B and Unified Plan semantics. Unified
+  // Plan users should prefer OnTrack, OnAddTrack is only called as backwards
+  // compatibility (and is called in the exact same situations as OnTrack).
+  virtual void OnAddTrack(
+      rtc::scoped_refptr<RtpReceiverInterface> receiver,
+      const std::vector<rtc::scoped_refptr<MediaStreamInterface>>& streams) {}
+
+  // This is called when signaling indicates a transceiver will be receiving
+  // media from the remote endpoint. This is fired during a call to
+  // SetRemoteDescription. The receiving track can be accessed by:
+  // |transceiver->receiver()->track()| and its associated streams by
+  // |transceiver->receiver()->streams()|.
+  // Note: This will only be called if Unified Plan semantics are specified.
+  // This behavior is specified in section 2.2.8.2.5 of the "Set the
+  // RTCSessionDescription" algorithm:
+  // https://w3c.github.io/webrtc-pc/#set-description
+  virtual void OnTrack(
+      rtc::scoped_refptr<RtpTransceiverInterface> transceiver) {}
+
+  // Called when signaling indicates that media will no longer be received on a
+  // track.
+  // With Plan B semantics, the given receiver will have been removed from the
+  // PeerConnection and the track muted.
+  // With Unified Plan semantics, the receiver will remain but the transceiver
+  // will have changed direction to either sendonly or inactive.
+  // https://w3c.github.io/webrtc-pc/#process-remote-track-removal
+  // 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.
+// A dependency is distinct from a configuration as it defines significant
+// executable code that can be provided by a user of the API.
+//
+// All new dependencies should be added as a unique_ptr to allow the
+// PeerConnection object to be the definitive owner of the dependencies
+// lifetime making injection safer.
+struct PeerConnectionDependencies final {
+  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&&);
+  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;
+};
+
+// PeerConnectionFactoryDependencies holds all of the PeerConnectionFactory
+// dependencies. All new dependencies should be added here instead of
+// overloading the function. This simplifies dependency injection and makes it
+// clear which are mandatory and optional. If possible please allow the peer
+// connection factory to take ownership of the dependency by adding a unique_ptr
+// to this structure.
+struct PeerConnectionFactoryDependencies final {
+  PeerConnectionFactoryDependencies();
+  // This object is not copyable or assignable.
+  PeerConnectionFactoryDependencies(const PeerConnectionFactoryDependencies&) =
+      delete;
+  PeerConnectionFactoryDependencies& operator=(
+      const PeerConnectionFactoryDependencies&) = delete;
+  // This object is only moveable.
+  PeerConnectionFactoryDependencies(PeerConnectionFactoryDependencies&&);
+  PeerConnectionFactoryDependencies& operator=(
+      PeerConnectionFactoryDependencies&&) = default;
+  ~PeerConnectionFactoryDependencies();
+
+  // Optional dependencies
+  rtc::Thread* network_thread = nullptr;
+  rtc::Thread* worker_thread = nullptr;
+  rtc::Thread* signaling_thread = nullptr;
+  std::unique_ptr<cricket::MediaEngineInterface> media_engine;
+  std::unique_ptr<CallFactoryInterface> call_factory;
+  std::unique_ptr<RtcEventLogFactoryInterface> event_log_factory;
+  std::unique_ptr<FecControllerFactoryInterface> fec_controller_factory;
+  std::unique_ptr<NetworkControllerFactoryInterface> network_controller_factory;
+  std::unique_ptr<MediaTransportFactory> media_transport_factory;
+};
+
+// PeerConnectionFactoryInterface is the factory interface used for creating
+// PeerConnection, MediaStream and MediaStreamTrack objects.
+//
+// The simplest method for obtaiing one, CreatePeerConnectionFactory will
+// create the required libjingle threads, socket and network manager factory
+// classes for networking if none are provided, though it requires that the
+// application runs a message loop on the thread that called the method (see
+// explanation below)
+//
+// If an application decides to provide its own threads and/or implementation
+// of networking classes, it should use the alternate
+// CreatePeerConnectionFactory method which accepts threads as input, and use
+// the CreatePeerConnection version that takes a PortAllocator as an argument.
+class PeerConnectionFactoryInterface : public rtc::RefCountInterface {
+ public:
+  class Options {
+   public:
+    Options() {}
+
+    // If set to true, created PeerConnections won't enforce any SRTP
+    // requirement, allowing unsecured media. Should only be used for
+    // testing/debugging.
+    bool disable_encryption = false;
+
+    // Deprecated. The only effect of setting this to true is that
+    // CreateDataChannel will fail, which is not that useful.
+    bool disable_sctp_data_channels = false;
+
+    // If set to true, any platform-supported network monitoring capability
+    // won't be used, and instead networks will only be updated via polling.
+    //
+    // This only has an effect if a PeerConnection is created with the default
+    // PortAllocator implementation.
+    bool disable_network_monitor = false;
+
+    // Sets the network types to ignore. For instance, calling this with
+    // ADAPTER_TYPE_ETHERNET | ADAPTER_TYPE_LOOPBACK will ignore Ethernet and
+    // loopback interfaces.
+    int network_ignore_mask = rtc::kDefaultNetworkIgnoreMask;
+
+    // Sets the maximum supported protocol version. The highest version
+    // supported by both ends will be used for the connection, i.e. if one
+    // party supports DTLS 1.0 and the other DTLS 1.2, DTLS 1.0 will be used.
+    rtc::SSLProtocolVersion ssl_max_version = rtc::SSL_PROTOCOL_DTLS_12;
+
+    // Sets crypto related options, e.g. enabled cipher suites.
+    CryptoOptions crypto_options = CryptoOptions::NoGcm();
+  };
+
+  // Set the options to be used for subsequently created PeerConnections.
+  virtual void SetOptions(const Options& options) = 0;
+
+  // The preferred way to create a new peer connection. Simply provide the
+  // configuration and a PeerConnectionDependencies structure.
+  // TODO(benwright): Make pure virtual once downstream mock PC factory classes
+  // are updated.
+  virtual rtc::scoped_refptr<PeerConnectionInterface> CreatePeerConnection(
+      const PeerConnectionInterface::RTCConfiguration& configuration,
+      PeerConnectionDependencies dependencies);
+
+  // Deprecated; |allocator| and |cert_generator| may be null, in which case
+  // default implementations will be used.
+  //
+  // |observer| must not be null.
+  //
+  // Note that this method does not take ownership of |observer|; it's the
+  // responsibility of the caller to delete it. It can be safely deleted after
+  // Close has been called on the returned PeerConnection, which ensures no
+  // more observer callbacks will be invoked.
+  virtual rtc::scoped_refptr<PeerConnectionInterface> CreatePeerConnection(
+      const PeerConnectionInterface::RTCConfiguration& configuration,
+      std::unique_ptr<cricket::PortAllocator> allocator,
+      std::unique_ptr<rtc::RTCCertificateGeneratorInterface> cert_generator,
+      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;
+
+  // 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;
+
+  virtual rtc::scoped_refptr<MediaStreamInterface> CreateLocalMediaStream(
+      const std::string& stream_id) = 0;
+
+  // Creates an AudioSourceInterface.
+  // |options| decides audio processing settings.
+  virtual rtc::scoped_refptr<AudioSourceInterface> CreateAudioSource(
+      const cricket::AudioOptions& options) = 0;
+
+  // Creates a new local VideoTrack. The same |source| can be used in several
+  // tracks.
+  virtual rtc::scoped_refptr<VideoTrackInterface> CreateVideoTrack(
+      const std::string& label,
+      VideoTrackSourceInterface* source) = 0;
+
+  // Creates an new AudioTrack. At the moment |source| can be null.
+  virtual rtc::scoped_refptr<AudioTrackInterface> CreateAudioTrack(
+      const std::string& label,
+      AudioSourceInterface* source) = 0;
+
+  // Starts AEC dump using existing file. Takes ownership of |file| and passes
+  // it on to VoiceEngine (via other objects) immediately, which will take
+  // the ownerhip. If the operation fails, the file will be closed.
+  // A maximum file size in bytes can be specified. When the file size limit is
+  // reached, logging is stopped automatically. If max_size_bytes is set to a
+  // value <= 0, no limit will be used, and logging will continue until the
+  // StopAecDump function is called.
+  virtual bool StartAecDump(rtc::PlatformFile file, int64_t max_size_bytes) = 0;
+
+  // Stops logging the AEC dump.
+  virtual void StopAecDump() = 0;
+
+ protected:
+  // Dtor and ctor protected as objects shouldn't be created or deleted via
+  // this interface.
+  PeerConnectionFactoryInterface() {}
+  ~PeerConnectionFactoryInterface() override = default;
+};
+
+// This is a lower-level version of the CreatePeerConnectionFactory functions
+// above. It's implemented in the "peerconnection" build target, whereas the
+// above methods are only implemented in the broader "libjingle_peerconnection"
+// build target, which pulls in the implementations of every module webrtc may
+// use.
+//
+// If an application knows it will only require certain modules, it can reduce
+// webrtc's impact on its binary size by depending only on the "peerconnection"
+// target and the modules the application requires, using
+// CreateModularPeerConnectionFactory instead of one of the
+// CreatePeerConnectionFactory methods above. For example, if an application
+// only uses WebRTC for audio, it can pass in null pointers for the
+// video-specific interfaces, and omit the corresponding modules from its
+// build.
+//
+// If |network_thread| or |worker_thread| are null, the PeerConnectionFactory
+// will create the necessary thread internally. If |signaling_thread| is null,
+// the PeerConnectionFactory will use the thread on which this method is called
+// as the signaling thread, wrapping it in an rtc::Thread object if needed.
+//
+// If non-null, a reference is added to |default_adm|, and ownership of
+// |video_encoder_factory| and |video_decoder_factory| is transferred to the
+// returned factory.
+//
+// If |audio_mixer| is null, an internal audio mixer will be created and used.
+//
+// TODO(deadbeef): Use rtc::scoped_refptr<> and std::unique_ptr<> to make this
+// ownership transfer and ref counting more obvious.
+//
+// TODO(deadbeef): Encapsulate these modules in a struct, so that when a new
+// module is inevitably exposed, we can just add a field to the struct instead
+// of adding a whole new CreateModularPeerConnectionFactory overload.
+rtc::scoped_refptr<PeerConnectionFactoryInterface>
+CreateModularPeerConnectionFactory(
+    rtc::Thread* network_thread,
+    rtc::Thread* worker_thread,
+    rtc::Thread* signaling_thread,
+    std::unique_ptr<cricket::MediaEngineInterface> media_engine,
+    std::unique_ptr<CallFactoryInterface> call_factory,
+    std::unique_ptr<RtcEventLogFactoryInterface> event_log_factory);
+
+rtc::scoped_refptr<PeerConnectionFactoryInterface>
+CreateModularPeerConnectionFactory(
+    rtc::Thread* network_thread,
+    rtc::Thread* worker_thread,
+    rtc::Thread* signaling_thread,
+    std::unique_ptr<cricket::MediaEngineInterface> media_engine,
+    std::unique_ptr<CallFactoryInterface> call_factory,
+    std::unique_ptr<RtcEventLogFactoryInterface> event_log_factory,
+    std::unique_ptr<FecControllerFactoryInterface> fec_controller_factory,
+    std::unique_ptr<NetworkControllerFactoryInterface>
+        network_controller_factory = nullptr);
+
+rtc::scoped_refptr<PeerConnectionFactoryInterface>
+CreateModularPeerConnectionFactory(
+    PeerConnectionFactoryDependencies dependencies);
+
+}  // namespace webrtc
+
+#endif  // API_PEER_CONNECTION_INTERFACE_H_
diff --git a/api/peer_connection_proxy.h b/api/peer_connection_proxy.h
new file mode 100644
index 0000000..61058b5
--- /dev/null
+++ b/api/peer_connection_proxy.h
@@ -0,0 +1,145 @@
+/*
+ *  Copyright 2012 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_PEER_CONNECTION_PROXY_H_
+#define API_PEER_CONNECTION_PROXY_H_
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "api/peer_connection_interface.h"
+#include "api/proxy.h"
+
+namespace webrtc {
+
+// TODO(deadbeef): Move this to .cc file and out of api/. What threads methods
+// are called on is an implementation detail.
+BEGIN_SIGNALING_PROXY_MAP(PeerConnection)
+PROXY_SIGNALING_THREAD_DESTRUCTOR()
+PROXY_METHOD0(rtc::scoped_refptr<StreamCollectionInterface>, local_streams)
+PROXY_METHOD0(rtc::scoped_refptr<StreamCollectionInterface>, remote_streams)
+PROXY_METHOD1(bool, AddStream, MediaStreamInterface*)
+PROXY_METHOD1(void, RemoveStream, MediaStreamInterface*)
+PROXY_METHOD2(RTCErrorOr<rtc::scoped_refptr<RtpSenderInterface>>,
+              AddTrack,
+              rtc::scoped_refptr<MediaStreamTrackInterface>,
+              const std::vector<std::string>&)
+PROXY_METHOD1(bool, RemoveTrack, RtpSenderInterface*)
+PROXY_METHOD1(RTCError, RemoveTrackNew, rtc::scoped_refptr<RtpSenderInterface>)
+PROXY_METHOD1(RTCErrorOr<rtc::scoped_refptr<RtpTransceiverInterface>>,
+              AddTransceiver,
+              rtc::scoped_refptr<MediaStreamTrackInterface>)
+PROXY_METHOD2(RTCErrorOr<rtc::scoped_refptr<RtpTransceiverInterface>>,
+              AddTransceiver,
+              rtc::scoped_refptr<MediaStreamTrackInterface>,
+              const RtpTransceiverInit&)
+PROXY_METHOD1(RTCErrorOr<rtc::scoped_refptr<RtpTransceiverInterface>>,
+              AddTransceiver,
+              cricket::MediaType)
+PROXY_METHOD2(RTCErrorOr<rtc::scoped_refptr<RtpTransceiverInterface>>,
+              AddTransceiver,
+              cricket::MediaType,
+              const RtpTransceiverInit&)
+PROXY_METHOD2(rtc::scoped_refptr<RtpSenderInterface>,
+              CreateSender,
+              const std::string&,
+              const std::string&)
+PROXY_CONSTMETHOD0(std::vector<rtc::scoped_refptr<RtpSenderInterface>>,
+                   GetSenders)
+PROXY_CONSTMETHOD0(std::vector<rtc::scoped_refptr<RtpReceiverInterface>>,
+                   GetReceivers)
+PROXY_CONSTMETHOD0(std::vector<rtc::scoped_refptr<RtpTransceiverInterface>>,
+                   GetTransceivers)
+PROXY_METHOD3(bool,
+              GetStats,
+              StatsObserver*,
+              MediaStreamTrackInterface*,
+              StatsOutputLevel)
+PROXY_METHOD1(void, GetStats, RTCStatsCollectorCallback*)
+PROXY_METHOD2(void,
+              GetStats,
+              rtc::scoped_refptr<RtpSenderInterface>,
+              rtc::scoped_refptr<RTCStatsCollectorCallback>)
+PROXY_METHOD2(void,
+              GetStats,
+              rtc::scoped_refptr<RtpReceiverInterface>,
+              rtc::scoped_refptr<RTCStatsCollectorCallback>)
+PROXY_METHOD2(rtc::scoped_refptr<DataChannelInterface>,
+              CreateDataChannel,
+              const std::string&,
+              const DataChannelInit*)
+PROXY_CONSTMETHOD0(const SessionDescriptionInterface*, local_description)
+PROXY_CONSTMETHOD0(const SessionDescriptionInterface*, remote_description)
+PROXY_CONSTMETHOD0(const SessionDescriptionInterface*,
+                   current_local_description)
+PROXY_CONSTMETHOD0(const SessionDescriptionInterface*,
+                   current_remote_description)
+PROXY_CONSTMETHOD0(const SessionDescriptionInterface*,
+                   pending_local_description)
+PROXY_CONSTMETHOD0(const SessionDescriptionInterface*,
+                   pending_remote_description)
+PROXY_METHOD2(void,
+              CreateOffer,
+              CreateSessionDescriptionObserver*,
+              const RTCOfferAnswerOptions&)
+PROXY_METHOD2(void,
+              CreateAnswer,
+              CreateSessionDescriptionObserver*,
+              const RTCOfferAnswerOptions&)
+PROXY_METHOD2(void,
+              SetLocalDescription,
+              SetSessionDescriptionObserver*,
+              SessionDescriptionInterface*)
+PROXY_METHOD2(void,
+              SetRemoteDescription,
+              SetSessionDescriptionObserver*,
+              SessionDescriptionInterface*)
+PROXY_METHOD2(void,
+              SetRemoteDescription,
+              std::unique_ptr<SessionDescriptionInterface>,
+              rtc::scoped_refptr<SetRemoteDescriptionObserverInterface>)
+PROXY_METHOD0(PeerConnectionInterface::RTCConfiguration, GetConfiguration)
+PROXY_METHOD2(bool,
+              SetConfiguration,
+              const PeerConnectionInterface::RTCConfiguration&,
+              RTCError*)
+PROXY_METHOD1(bool,
+              SetConfiguration,
+              const PeerConnectionInterface::RTCConfiguration&)
+PROXY_METHOD1(bool, AddIceCandidate, const IceCandidateInterface*)
+PROXY_METHOD1(bool, RemoveIceCandidates, const std::vector<cricket::Candidate>&)
+PROXY_METHOD1(RTCError, SetBitrate, const BitrateSettings&)
+PROXY_METHOD1(void,
+              SetBitrateAllocationStrategy,
+              std::unique_ptr<rtc::BitrateAllocationStrategy>)
+PROXY_METHOD1(void, SetAudioPlayout, bool)
+PROXY_METHOD1(void, SetAudioRecording, bool)
+PROXY_METHOD1(rtc::scoped_refptr<DtlsTransportInterface>,
+              LookupDtlsTransportByMid,
+              const std::string&)
+PROXY_CONSTMETHOD0(rtc::scoped_refptr<SctpTransportInterface>, GetSctpTransport)
+PROXY_METHOD0(SignalingState, signaling_state)
+PROXY_METHOD0(IceConnectionState, ice_connection_state)
+PROXY_METHOD0(IceConnectionState, standardized_ice_connection_state)
+PROXY_METHOD0(PeerConnectionState, peer_connection_state)
+PROXY_METHOD0(IceGatheringState, ice_gathering_state)
+PROXY_METHOD2(bool, StartRtcEventLog, rtc::PlatformFile, int64_t)
+PROXY_METHOD2(bool,
+              StartRtcEventLog,
+              std::unique_ptr<RtcEventLogOutput>,
+              int64_t)
+PROXY_METHOD0(void, StopRtcEventLog)
+PROXY_METHOD0(void, Close)
+END_PROXY_MAP()
+
+}  // namespace webrtc
+
+#endif  // API_PEER_CONNECTION_PROXY_H_
diff --git a/api/proxy.h b/api/proxy.h
index 9916051..6627aac 100644
--- a/api/proxy.h
+++ b/api/proxy.h
@@ -53,12 +53,20 @@
 #define API_PROXY_H_
 
 #include <memory>
+#include <string>
 #include <utility>
 
+#include "api/scoped_refptr.h"
 #include "rtc_base/event.h"
-#include "rtc_base/refcountedobject.h"
+#include "rtc_base/message_handler.h"
+#include "rtc_base/message_queue.h"
+#include "rtc_base/ref_counted_object.h"
 #include "rtc_base/thread.h"
 
+namespace rtc {
+class Location;
+}
+
 namespace webrtc {
 
 template <typename R>
diff --git a/api/ref_counted_base.h b/api/ref_counted_base.h
new file mode 100644
index 0000000..a1761db
--- /dev/null
+++ b/api/ref_counted_base.h
@@ -0,0 +1,43 @@
+/*
+ *  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.
+ */
+#ifndef API_REF_COUNTED_BASE_H_
+#define API_REF_COUNTED_BASE_H_
+
+#include "rtc_base/constructor_magic.h"
+#include "rtc_base/ref_count.h"
+#include "rtc_base/ref_counter.h"
+
+namespace rtc {
+
+class RefCountedBase {
+ public:
+  RefCountedBase() = default;
+
+  void AddRef() const { ref_count_.IncRef(); }
+  RefCountReleaseStatus Release() const {
+    const auto status = ref_count_.DecRef();
+    if (status == RefCountReleaseStatus::kDroppedLastRef) {
+      delete this;
+    }
+    return status;
+  }
+
+ protected:
+  virtual ~RefCountedBase() = default;
+
+ private:
+  mutable webrtc::webrtc_impl::RefCounter ref_count_{0};
+
+  RTC_DISALLOW_COPY_AND_ASSIGN(RefCountedBase);
+};
+
+}  // namespace rtc
+
+#endif  // API_REF_COUNTED_BASE_H_
diff --git a/api/rtc_error.cc b/api/rtc_error.cc
new file mode 100644
index 0000000..51fd07f
--- /dev/null
+++ b/api/rtc_error.cc
@@ -0,0 +1,61 @@
+/*
+ *  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 "api/rtc_error.h"
+
+#include "absl/strings/string_view.h"
+#include "rtc_base/arraysize.h"
+
+namespace {
+
+const absl::string_view kRTCErrorTypeNames[] = {
+    "NONE",
+    "UNSUPPORTED_OPERATION",
+    "UNSUPPORTED_PARAMETER",
+    "INVALID_PARAMETER",
+    "INVALID_RANGE",
+    "SYNTAX_ERROR",
+    "INVALID_STATE",
+    "INVALID_MODIFICATION",
+    "NETWORK_ERROR",
+    "RESOURCE_EXHAUSTED",
+    "INTERNAL_ERROR",
+};
+static_assert(static_cast<int>(webrtc::RTCErrorType::INTERNAL_ERROR) ==
+                  (arraysize(kRTCErrorTypeNames) - 1),
+              "kRTCErrorTypeNames must have as many strings as RTCErrorType "
+              "has values.");
+
+}  // namespace
+
+namespace webrtc {
+
+RTCError::RTCError(RTCError&& other) = default;
+RTCError& RTCError::operator=(RTCError&& other) = default;
+
+// static
+RTCError RTCError::OK() {
+  return RTCError();
+}
+
+const char* RTCError::message() const {
+  return message_.c_str();
+}
+
+void RTCError::set_message(std::string message) {
+  message_ = std::move(message);
+}
+
+absl::string_view ToString(RTCErrorType error) {
+  int index = static_cast<int>(error);
+  return kRTCErrorTypeNames[index];
+}
+
+}  // namespace webrtc
diff --git a/api/rtc_error.h b/api/rtc_error.h
new file mode 100644
index 0000000..904a619
--- /dev/null
+++ b/api/rtc_error.h
@@ -0,0 +1,297 @@
+/*
+ *  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.
+ */
+
+#ifndef API_RTC_ERROR_H_
+#define API_RTC_ERROR_H_
+
+#ifdef UNIT_TEST
+#include <ostream>
+#endif  // UNIT_TEST
+#include <string>
+#include <utility>  // For std::move.
+
+#include "absl/strings/string_view.h"
+#include "rtc_base/checks.h"
+#include "rtc_base/logging.h"
+
+namespace webrtc {
+
+// Enumeration to represent distinct classes of errors that an application
+// may wish to act upon differently. These roughly map to DOMExceptions or
+// RTCError "errorDetailEnum" values in the web API, as described in the
+// comments below.
+enum class RTCErrorType {
+  // No error.
+  NONE,
+
+  // An operation is valid, but currently unsupported.
+  // Maps to OperationError DOMException.
+  UNSUPPORTED_OPERATION,
+
+  // A supplied parameter is valid, but currently unsupported.
+  // Maps to OperationError DOMException.
+  UNSUPPORTED_PARAMETER,
+
+  // General error indicating that a supplied parameter is invalid.
+  // Maps to InvalidAccessError or TypeError DOMException depending on context.
+  INVALID_PARAMETER,
+
+  // Slightly more specific than INVALID_PARAMETER; a parameter's value was
+  // outside the allowed range.
+  // Maps to RangeError DOMException.
+  INVALID_RANGE,
+
+  // Slightly more specific than INVALID_PARAMETER; an error occurred while
+  // parsing string input.
+  // Maps to SyntaxError DOMException.
+  SYNTAX_ERROR,
+
+  // The object does not support this operation in its current state.
+  // Maps to InvalidStateError DOMException.
+  INVALID_STATE,
+
+  // An attempt was made to modify the object in an invalid way.
+  // Maps to InvalidModificationError DOMException.
+  INVALID_MODIFICATION,
+
+  // An error occurred within an underlying network protocol.
+  // Maps to NetworkError DOMException.
+  NETWORK_ERROR,
+
+  // Some resource has been exhausted; file handles, hardware resources, ports,
+  // etc.
+  // Maps to OperationError DOMException.
+  RESOURCE_EXHAUSTED,
+
+  // The operation failed due to an internal error.
+  // Maps to OperationError DOMException.
+  INTERNAL_ERROR,
+};
+
+// Roughly corresponds to RTCError in the web api. Holds an error type, a
+// message, and possibly additional information specific to that error.
+//
+// Doesn't contain anything beyond a type and message now, but will in the
+// future as more errors are implemented.
+class RTCError {
+ public:
+  // Constructors.
+
+  // Creates a "no error" error.
+  RTCError() {}
+  explicit RTCError(RTCErrorType type) : type_(type) {}
+
+  RTCError(RTCErrorType type, std::string message)
+      : type_(type), message_(std::move(message)) {}
+
+  // Delete the copy constructor and assignment operator; there aren't any use
+  // cases where you should need to copy an RTCError, as opposed to moving it.
+  // Can revisit this decision if use cases arise in the future.
+  RTCError(const RTCError& other) = delete;
+  RTCError& operator=(const RTCError& other) = delete;
+
+  // Move constructor and move-assignment operator.
+  RTCError(RTCError&& other);
+  RTCError& operator=(RTCError&& other);
+
+  // Identical to default constructed error.
+  //
+  // Preferred over the default constructor for code readability.
+  static RTCError OK();
+
+  // Error type.
+  RTCErrorType type() const { return type_; }
+  void set_type(RTCErrorType type) { type_ = type; }
+
+  // Human-readable message describing the error. Shouldn't be used for
+  // anything but logging/diagnostics, since messages are not guaranteed to be
+  // stable.
+  const char* message() const;
+
+  void set_message(std::string message);
+
+  // Convenience method for situations where you only care whether or not an
+  // error occurred.
+  bool ok() const { return type_ == RTCErrorType::NONE; }
+
+ private:
+  RTCErrorType type_ = RTCErrorType::NONE;
+  std::string message_;
+};
+
+// Outputs the error as a friendly string. Update this method when adding a new
+// error type.
+//
+// Only intended to be used for logging/diagnostics. The string_view points
+// to literal string that lives for the whole duration of the program.
+absl::string_view ToString(RTCErrorType error);
+
+#ifdef UNIT_TEST
+inline std::ostream& operator<<(  // no-presubmit-check TODO(webrtc:8982)
+    std::ostream& stream,         // no-presubmit-check TODO(webrtc:8982)
+    RTCErrorType error) {
+  return stream << ToString(error);
+}
+#endif  // UNIT_TEST
+
+// Helper macro that can be used by implementations to create an error with a
+// message and log it. |message| should be a string literal or movable
+// std::string.
+#define LOG_AND_RETURN_ERROR_EX(type, message, severity)           \
+  {                                                                \
+    RTC_DCHECK(type != RTCErrorType::NONE);                        \
+    RTC_LOG(severity) << message << " (" << ToString(type) << ")"; \
+    return webrtc::RTCError(type, message);                        \
+  }
+
+#define LOG_AND_RETURN_ERROR(type, message) \
+  LOG_AND_RETURN_ERROR_EX(type, message, LS_ERROR)
+
+// RTCErrorOr<T> is the union of an RTCError object and a T object. RTCErrorOr
+// models the concept of an object that is either a usable value, or an error
+// Status explaining why such a value is not present. To this end RTCErrorOr<T>
+// does not allow its RTCErrorType value to be RTCErrorType::NONE. This is
+// enforced by a debug check in most cases.
+//
+// The primary use-case for RTCErrorOr<T> is as the return value of a function
+// which may fail. For example, CreateRtpSender will fail if the parameters
+// could not be successfully applied at the media engine level, but if
+// successful will return a unique_ptr to an RtpSender.
+//
+// Example client usage for a RTCErrorOr<std::unique_ptr<T>>:
+//
+//  RTCErrorOr<std::unique_ptr<Foo>> result = FooFactory::MakeNewFoo(arg);
+//  if (result.ok()) {
+//    std::unique_ptr<Foo> foo = result.ConsumeValue();
+//    foo->DoSomethingCool();
+//  } else {
+//    RTC_LOG(LS_ERROR) << result.error();
+//  }
+//
+// Example factory implementation returning RTCErrorOr<std::unique_ptr<T>>:
+//
+//  RTCErrorOr<std::unique_ptr<Foo>> FooFactory::MakeNewFoo(int arg) {
+//    if (arg <= 0) {
+//      return RTCError(RTCErrorType::INVALID_RANGE, "Arg must be positive");
+//    } else {
+//      return std::unique_ptr<Foo>(new Foo(arg));
+//    }
+//  }
+//
+template <typename T>
+class RTCErrorOr {
+  // Used to convert between RTCErrorOr<Foo>/RtcErrorOr<Bar>, when an implicit
+  // conversion from Foo to Bar exists.
+  template <typename U>
+  friend class RTCErrorOr;
+
+ public:
+  typedef T element_type;
+
+  // Constructs a new RTCErrorOr with RTCErrorType::INTERNAL_ERROR error. This
+  // is marked 'explicit' to try to catch cases like 'return {};', where people
+  // think RTCErrorOr<std::vector<int>> will be initialized with an empty
+  // vector, instead of a RTCErrorType::INTERNAL_ERROR error.
+  RTCErrorOr() : error_(RTCErrorType::INTERNAL_ERROR) {}
+
+  // Constructs a new RTCErrorOr with the given non-ok error. After calling
+  // this constructor, calls to value() will DCHECK-fail.
+  //
+  // NOTE: Not explicit - we want to use RTCErrorOr<T> as a return
+  // value, so it is convenient and sensible to be able to do 'return
+  // RTCError(...)' when the return type is RTCErrorOr<T>.
+  //
+  // REQUIRES: !error.ok(). This requirement is DCHECKed.
+  RTCErrorOr(RTCError&& error) : error_(std::move(error)) {  // NOLINT
+    RTC_DCHECK(!error.ok());
+  }
+
+  // Constructs a new RTCErrorOr with the given value. After calling this
+  // constructor, calls to value() will succeed, and calls to error() will
+  // return a default-constructed RTCError.
+  //
+  // NOTE: Not explicit - we want to use RTCErrorOr<T> as a return type
+  // so it is convenient and sensible to be able to do 'return T()'
+  // when the return type is RTCErrorOr<T>.
+  RTCErrorOr(const T& value) : value_(value) {}        // NOLINT
+  RTCErrorOr(T&& value) : value_(std::move(value)) {}  // NOLINT
+
+  // Delete the copy constructor and assignment operator; there aren't any use
+  // cases where you should need to copy an RTCErrorOr, as opposed to moving
+  // it. Can revisit this decision if use cases arise in the future.
+  RTCErrorOr(const RTCErrorOr& other) = delete;
+  RTCErrorOr& operator=(const RTCErrorOr& other) = delete;
+
+  // Move constructor and move-assignment operator.
+  //
+  // Visual Studio doesn't support "= default" with move constructors or
+  // assignment operators (even though they compile, they segfault), so define
+  // them explicitly.
+  RTCErrorOr(RTCErrorOr&& other)
+      : error_(std::move(other.error_)), value_(std::move(other.value_)) {}
+  RTCErrorOr& operator=(RTCErrorOr&& other) {
+    error_ = std::move(other.error_);
+    value_ = std::move(other.value_);
+    return *this;
+  }
+
+  // Conversion constructor and assignment operator; T must be copy or move
+  // constructible from U.
+  template <typename U>
+  RTCErrorOr(RTCErrorOr<U> other)  // NOLINT
+      : error_(std::move(other.error_)), value_(std::move(other.value_)) {}
+  template <typename U>
+  RTCErrorOr& operator=(RTCErrorOr<U> other) {
+    error_ = std::move(other.error_);
+    value_ = std::move(other.value_);
+    return *this;
+  }
+
+  // Returns a reference to our error. If this contains a T, then returns
+  // default-constructed RTCError.
+  const RTCError& error() const { return error_; }
+
+  // Moves the error. Can be useful if, say "CreateFoo" returns an
+  // RTCErrorOr<Foo>, and internally calls "CreateBar" which returns an
+  // RTCErrorOr<Bar>, and wants to forward the error up the stack.
+  RTCError MoveError() { return std::move(error_); }
+
+  // Returns this->error().ok()
+  bool ok() const { return error_.ok(); }
+
+  // Returns a reference to our current value, or DCHECK-fails if !this->ok().
+  //
+  // Can be convenient for the implementation; for example, a method may want
+  // to access the value in some way before returning it to the next method on
+  // the stack.
+  const T& value() const {
+    RTC_DCHECK(ok());
+    return value_;
+  }
+  T& value() {
+    RTC_DCHECK(ok());
+    return value_;
+  }
+
+  // Moves our current value out of this object and returns it, or DCHECK-fails
+  // if !this->ok().
+  T MoveValue() {
+    RTC_DCHECK(ok());
+    return std::move(value_);
+  }
+
+ private:
+  RTCError error_;
+  T value_;
+};
+
+}  // namespace webrtc
+
+#endif  // API_RTC_ERROR_H_
diff --git a/api/rtc_error_unittest.cc b/api/rtc_error_unittest.cc
new file mode 100644
index 0000000..e9beb00
--- /dev/null
+++ b/api/rtc_error_unittest.cc
@@ -0,0 +1,241 @@
+/*
+ *  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 <utility>
+
+#include "api/rtc_error.h"
+#include "test/gtest.h"
+
+namespace {
+
+const int kDefaultMoveOnlyIntValue = 0xbadf00d;
+
+// Class that has no copy constructor, ensuring that RTCErrorOr can
+struct MoveOnlyInt {
+  MoveOnlyInt() {}
+  explicit MoveOnlyInt(int value) : value(value) {}
+  MoveOnlyInt(const MoveOnlyInt& other) = delete;
+  MoveOnlyInt& operator=(const MoveOnlyInt& other) = delete;
+  MoveOnlyInt(MoveOnlyInt&& other) : value(other.value) {}
+  MoveOnlyInt& operator=(MoveOnlyInt&& other) {
+    value = other.value;
+    return *this;
+  }
+
+  int value = kDefaultMoveOnlyIntValue;
+};
+
+// Same as above. Used to test conversion from RTCErrorOr<A> to RTCErrorOr<B>
+// when A can be converted to B.
+struct MoveOnlyInt2 {
+  MoveOnlyInt2() {}
+  explicit MoveOnlyInt2(int value) : value(value) {}
+  MoveOnlyInt2(const MoveOnlyInt2& other) = delete;
+  MoveOnlyInt2& operator=(const MoveOnlyInt2& other) = delete;
+  MoveOnlyInt2(MoveOnlyInt2&& other) : value(other.value) {}
+  MoveOnlyInt2& operator=(MoveOnlyInt2&& other) {
+    value = other.value;
+    return *this;
+  }
+
+  explicit MoveOnlyInt2(MoveOnlyInt&& other) : value(other.value) {}
+  MoveOnlyInt2& operator=(MoveOnlyInt&& other) {
+    value = other.value;
+    return *this;
+  }
+
+  int value = kDefaultMoveOnlyIntValue;
+};
+
+}  // namespace
+
+namespace webrtc {
+
+// Test that the default constructor creates a "no error" error.
+TEST(RTCErrorTest, DefaultConstructor) {
+  RTCError e;
+  EXPECT_EQ(RTCErrorType::NONE, e.type());
+  EXPECT_EQ(std::string(), e.message());
+  EXPECT_TRUE(e.ok());
+}
+
+TEST(RTCErrorTest, NormalConstructors) {
+  RTCError a(RTCErrorType::INVALID_PARAMETER);
+  EXPECT_EQ(RTCErrorType::INVALID_PARAMETER, a.type());
+  EXPECT_EQ(std::string(), a.message());
+
+  // Constructor that takes const char* message.
+  RTCError b(RTCErrorType::UNSUPPORTED_PARAMETER, "foobar");
+  EXPECT_EQ(RTCErrorType::UNSUPPORTED_PARAMETER, b.type());
+  EXPECT_EQ(std::string("foobar"), b.message());
+
+  // Constructor that takes std::string message.
+  RTCError c(RTCErrorType::INVALID_RANGE, std::string("new"));
+  EXPECT_EQ(RTCErrorType::INVALID_RANGE, c.type());
+  EXPECT_EQ(std::string("new"), c.message());
+}
+
+TEST(RTCErrorTest, MoveConstructor) {
+  // Static string.
+  RTCError a(RTCErrorType::INVALID_PARAMETER, "foo");
+  RTCError b(std::move(a));
+  EXPECT_EQ(RTCErrorType::INVALID_PARAMETER, b.type());
+  EXPECT_EQ(std::string("foo"), b.message());
+
+  // Non-static string.
+  RTCError c(RTCErrorType::UNSUPPORTED_PARAMETER, std::string("bar"));
+  RTCError d(std::move(c));
+  EXPECT_EQ(RTCErrorType::UNSUPPORTED_PARAMETER, d.type());
+  EXPECT_EQ(std::string("bar"), d.message());
+}
+
+TEST(RTCErrorTest, MoveAssignment) {
+  // Try all combinations of "is static string"/"is non-static string" moves.
+  RTCError e(RTCErrorType::INVALID_PARAMETER, "foo");
+
+  e = RTCError(RTCErrorType::UNSUPPORTED_PARAMETER, "bar");
+  EXPECT_EQ(RTCErrorType::UNSUPPORTED_PARAMETER, e.type());
+  EXPECT_EQ(std::string("bar"), e.message());
+
+  e = RTCError(RTCErrorType::SYNTAX_ERROR, std::string("baz"));
+  EXPECT_EQ(std::string("baz"), e.message());
+
+  e = RTCError(RTCErrorType::SYNTAX_ERROR, std::string("another"));
+  EXPECT_EQ(std::string("another"), e.message());
+
+  e = RTCError(RTCErrorType::SYNTAX_ERROR, "last");
+  EXPECT_EQ(std::string("last"), e.message());
+}
+
+// Test that the error returned by RTCError::OK() is a "no error" error.
+TEST(RTCErrorTest, OKConstant) {
+  RTCError ok = RTCError::OK();
+  EXPECT_EQ(RTCErrorType::NONE, ok.type());
+  EXPECT_EQ(std::string(), ok.message());
+  EXPECT_TRUE(ok.ok());
+}
+
+// Test that "error.ok()" behaves as expected.
+TEST(RTCErrorTest, OkMethod) {
+  RTCError success;
+  RTCError failure(RTCErrorType::INTERNAL_ERROR);
+  EXPECT_TRUE(success.ok());
+  EXPECT_FALSE(failure.ok());
+}
+
+// Test that a message can be set using either static const strings or
+// std::strings.
+TEST(RTCErrorTest, SetMessage) {
+  RTCError e;
+  // Try all combinations of "is static string"/"is non-static string" calls.
+  e.set_message("foo");
+  EXPECT_EQ(std::string("foo"), e.message());
+
+  e.set_message("bar");
+  EXPECT_EQ(std::string("bar"), e.message());
+
+  e.set_message(std::string("string"));
+  EXPECT_EQ(std::string("string"), e.message());
+
+  e.set_message(std::string("more"));
+  EXPECT_EQ(std::string("more"), e.message());
+
+  e.set_message("love to test");
+  EXPECT_EQ(std::string("love to test"), e.message());
+}
+
+// Test that the default constructor creates an "INTERNAL_ERROR".
+TEST(RTCErrorOrTest, DefaultConstructor) {
+  RTCErrorOr<MoveOnlyInt> e;
+  EXPECT_EQ(RTCErrorType::INTERNAL_ERROR, e.error().type());
+}
+
+// Test that an RTCErrorOr can be implicitly constructed from a value.
+TEST(RTCErrorOrTest, ImplicitValueConstructor) {
+  RTCErrorOr<MoveOnlyInt> e = [] { return MoveOnlyInt(100); }();
+  EXPECT_EQ(100, e.value().value);
+}
+
+// Test that an RTCErrorOr can be implicitly constructed from an RTCError.
+TEST(RTCErrorOrTest, ImplicitErrorConstructor) {
+  RTCErrorOr<MoveOnlyInt> e = [] {
+    return RTCError(RTCErrorType::SYNTAX_ERROR);
+  }();
+  EXPECT_EQ(RTCErrorType::SYNTAX_ERROR, e.error().type());
+}
+
+TEST(RTCErrorOrTest, MoveConstructor) {
+  RTCErrorOr<MoveOnlyInt> a(MoveOnlyInt(5));
+  RTCErrorOr<MoveOnlyInt> b(std::move(a));
+  EXPECT_EQ(5, b.value().value);
+}
+
+TEST(RTCErrorOrTest, MoveAssignment) {
+  RTCErrorOr<MoveOnlyInt> a(MoveOnlyInt(5));
+  RTCErrorOr<MoveOnlyInt> b(MoveOnlyInt(10));
+  a = std::move(b);
+  EXPECT_EQ(10, a.value().value);
+}
+
+TEST(RTCErrorOrTest, ConversionConstructor) {
+  RTCErrorOr<MoveOnlyInt> a(MoveOnlyInt(1));
+  RTCErrorOr<MoveOnlyInt2> b(std::move(a));
+}
+
+TEST(RTCErrorOrTest, ConversionAssignment) {
+  RTCErrorOr<MoveOnlyInt> a(MoveOnlyInt(5));
+  RTCErrorOr<MoveOnlyInt2> b(MoveOnlyInt2(10));
+  b = std::move(a);
+  EXPECT_EQ(5, b.value().value);
+}
+
+TEST(RTCErrorOrTest, OkMethod) {
+  RTCErrorOr<int> success(1337);
+  RTCErrorOr<int> error = RTCError(RTCErrorType::INTERNAL_ERROR);
+  EXPECT_TRUE(success.ok());
+  EXPECT_FALSE(error.ok());
+}
+
+TEST(RTCErrorOrTest, MoveError) {
+  RTCErrorOr<int> e({RTCErrorType::SYNTAX_ERROR, "message"});
+  RTCError err = e.MoveError();
+  EXPECT_EQ(RTCErrorType::SYNTAX_ERROR, err.type());
+  EXPECT_EQ(std::string("message"), err.message());
+}
+
+TEST(RTCErrorOrTest, MoveValue) {
+  RTCErrorOr<MoveOnlyInt> e(MoveOnlyInt(88));
+  MoveOnlyInt value = e.MoveValue();
+  EXPECT_EQ(88, value.value);
+}
+
+// Death tests.
+// Disabled on Android because death tests misbehave on Android, see
+// base/test/gtest_util.h.
+#if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
+
+TEST(RTCErrorOrDeathTest, ConstructWithOkError) {
+  RTCErrorOr<int> err;
+  EXPECT_DEATH(err = RTCError::OK(), "");
+}
+
+TEST(RTCErrorOrDeathTest, DereferenceErrorValue) {
+  RTCErrorOr<int> error = RTCError(RTCErrorType::INTERNAL_ERROR);
+  EXPECT_DEATH(error.value(), "");
+}
+
+TEST(RTCErrorOrDeathTest, MoveErrorValue) {
+  RTCErrorOr<int> error = RTCError(RTCErrorType::INTERNAL_ERROR);
+  EXPECT_DEATH(error.MoveValue(), "");
+}
+
+#endif  // RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
+
+}  // namespace webrtc
diff --git a/api/rtc_event_log_output.h b/api/rtc_event_log_output.h
new file mode 100644
index 0000000..92fb9e8
--- /dev/null
+++ b/api/rtc_event_log_output.h
@@ -0,0 +1,42 @@
+/*
+ *  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.
+ */
+
+#ifndef API_RTC_EVENT_LOG_OUTPUT_H_
+#define API_RTC_EVENT_LOG_OUTPUT_H_
+
+#include <string>
+
+namespace webrtc {
+
+// NOTE: This class is still under development and may change without notice.
+class RtcEventLogOutput {
+ public:
+  virtual ~RtcEventLogOutput() = default;
+
+  // An output normally starts out active, though that might not always be
+  // the case (e.g. failed to open a file for writing).
+  // Once an output has become inactive (e.g. maximum file size reached), it can
+  // never become active again.
+  virtual bool IsActive() const = 0;
+
+  // Write encoded events to an output. Returns true if the output was
+  // successfully written in its entirety. Otherwise, no guarantee is given
+  // about how much data was written, if any. The output sink becomes inactive
+  // after the first time |false| is returned. Write() may not be called on
+  // an inactive output sink.
+  virtual bool Write(const std::string& output) = 0;
+
+  // Indicates that buffers should be written to disk if applicable.
+  virtual void Flush() {}
+};
+
+}  // namespace webrtc
+
+#endif  // API_RTC_EVENT_LOG_OUTPUT_H_
diff --git a/api/rtp_headers.h b/api/rtp_headers.h
index c766899..8ab560c 100644
--- a/api/rtp_headers.h
+++ b/api/rtp_headers.h
@@ -82,6 +82,17 @@
 // Mid represents RtpMid which is a string.
 typedef StringRtpHeaderExtension Mid;
 
+struct FeedbackRequest {
+  // Determines whether the recv delta as specified in
+  // https://tools.ietf.org/html/draft-holmer-rmcat-transport-wide-cc-extensions-01
+  // should be included.
+  bool include_timestamps;
+  // Include feedback of received packets in the range [sequence_number -
+  // sequence_count + 1, sequence_number]. That is, no feedback will be sent if
+  // sequence_count is zero.
+  int sequence_count;
+};
+
 struct RTPHeaderExtension {
   RTPHeaderExtension();
   RTPHeaderExtension(const RTPHeaderExtension& other);
@@ -93,6 +104,7 @@
   uint32_t absoluteSendTime;
   bool hasTransportSequenceNumber;
   uint16_t transportSequenceNumber;
+  absl::optional<FeedbackRequest> feedback_request;
 
   // Audio Level includes both level in dBov and voiced/unvoiced bit. See:
   // https://datatracker.ietf.org/doc/draft-lennox-avt-rtp-audio-level-exthdr/
diff --git a/api/rtp_parameters.cc b/api/rtp_parameters.cc
new file mode 100644
index 0000000..9ba2423
--- /dev/null
+++ b/api/rtp_parameters.cc
@@ -0,0 +1,238 @@
+/*
+ *  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 "api/rtp_parameters.h"
+
+#include <algorithm>
+#include <string>
+
+#include "api/array_view.h"
+#include "rtc_base/strings/string_builder.h"
+
+namespace webrtc {
+
+const double kDefaultBitratePriority = 1.0;
+
+RtcpFeedback::RtcpFeedback() = default;
+RtcpFeedback::RtcpFeedback(RtcpFeedbackType type) : type(type) {}
+RtcpFeedback::RtcpFeedback(RtcpFeedbackType type,
+                           RtcpFeedbackMessageType message_type)
+    : type(type), message_type(message_type) {}
+RtcpFeedback::RtcpFeedback(const RtcpFeedback& rhs) = default;
+RtcpFeedback::~RtcpFeedback() = default;
+
+RtpCodecCapability::RtpCodecCapability() = default;
+RtpCodecCapability::~RtpCodecCapability() = default;
+
+RtpHeaderExtensionCapability::RtpHeaderExtensionCapability() = default;
+RtpHeaderExtensionCapability::RtpHeaderExtensionCapability(
+    const std::string& uri)
+    : uri(uri) {}
+RtpHeaderExtensionCapability::RtpHeaderExtensionCapability(
+    const std::string& uri,
+    int preferred_id)
+    : uri(uri), preferred_id(preferred_id) {}
+RtpHeaderExtensionCapability::~RtpHeaderExtensionCapability() = default;
+
+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() = default;
+
+RtpFecParameters::RtpFecParameters() = default;
+RtpFecParameters::RtpFecParameters(FecMechanism mechanism)
+    : mechanism(mechanism) {}
+RtpFecParameters::RtpFecParameters(FecMechanism mechanism, uint32_t ssrc)
+    : ssrc(ssrc), mechanism(mechanism) {}
+RtpFecParameters::RtpFecParameters(const RtpFecParameters& rhs) = default;
+RtpFecParameters::~RtpFecParameters() = default;
+
+RtpRtxParameters::RtpRtxParameters() = default;
+RtpRtxParameters::RtpRtxParameters(uint32_t ssrc) : ssrc(ssrc) {}
+RtpRtxParameters::RtpRtxParameters(const RtpRtxParameters& rhs) = default;
+RtpRtxParameters::~RtpRtxParameters() = default;
+
+RtpEncodingParameters::RtpEncodingParameters() = default;
+RtpEncodingParameters::RtpEncodingParameters(const RtpEncodingParameters& rhs) =
+    default;
+RtpEncodingParameters::~RtpEncodingParameters() = default;
+
+RtpCodecParameters::RtpCodecParameters() = default;
+RtpCodecParameters::RtpCodecParameters(const RtpCodecParameters& rhs) = default;
+RtpCodecParameters::~RtpCodecParameters() = default;
+
+RtpCapabilities::RtpCapabilities() = default;
+RtpCapabilities::~RtpCapabilities() = default;
+
+RtcpParameters::RtcpParameters() = default;
+RtcpParameters::RtcpParameters(const RtcpParameters& rhs) = default;
+RtcpParameters::~RtcpParameters() = default;
+
+RtpParameters::RtpParameters() = default;
+RtpParameters::RtpParameters(const RtpParameters& rhs) = default;
+RtpParameters::~RtpParameters() = default;
+
+std::string RtpExtension::ToString() const {
+  char buf[256];
+  rtc::SimpleStringBuilder sb(buf);
+  sb << "{uri: " << uri;
+  sb << ", id: " << id;
+  if (encrypt) {
+    sb << ", encrypt";
+  }
+  sb << '}';
+  return sb.str();
+}
+
+const char RtpExtension::kAudioLevelUri[] =
+    "urn:ietf:params:rtp-hdrext:ssrc-audio-level";
+
+const char RtpExtension::kTimestampOffsetUri[] =
+    "urn:ietf:params:rtp-hdrext:toffset";
+
+const char RtpExtension::kAbsSendTimeUri[] =
+    "http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time";
+
+const char RtpExtension::kVideoRotationUri[] = "urn:3gpp:video-orientation";
+
+const char RtpExtension::kTransportSequenceNumberUri[] =
+    "http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01";
+const char RtpExtension::kTransportSequenceNumberV2Uri[] =
+    "http://www.webrtc.org/experiments/rtp-hdrext/transport-wide-cc-02";
+
+// This extension allows applications to adaptively limit the playout delay
+// on frames as per the current needs. For example, a gaming application
+// has very different needs on end-to-end delay compared to a video-conference
+// application.
+const char RtpExtension::kPlayoutDelayUri[] =
+    "http://www.webrtc.org/experiments/rtp-hdrext/playout-delay";
+
+const char RtpExtension::kVideoContentTypeUri[] =
+    "http://www.webrtc.org/experiments/rtp-hdrext/video-content-type";
+
+const char RtpExtension::kVideoTimingUri[] =
+    "http://www.webrtc.org/experiments/rtp-hdrext/video-timing";
+
+const char RtpExtension::kMidUri[] = "urn:ietf:params:rtp-hdrext:sdes:mid";
+
+const char RtpExtension::kFrameMarkingUri[] =
+    "http://tools.ietf.org/html/draft-ietf-avtext-framemarking-07";
+
+const char RtpExtension::kGenericFrameDescriptorUri00[] =
+    "http://www.webrtc.org/experiments/rtp-hdrext/generic-frame-descriptor-00";
+const char RtpExtension::kGenericFrameDescriptorUri01[] =
+    "http://www.webrtc.org/experiments/rtp-hdrext/generic-frame-descriptor-01";
+const char RtpExtension::kGenericFrameDescriptorUri[] =
+    "http://www.webrtc.org/experiments/rtp-hdrext/generic-frame-descriptor-00";
+
+const char RtpExtension::kEncryptHeaderExtensionsUri[] =
+    "urn:ietf:params:rtp-hdrext:encrypt";
+
+const char RtpExtension::kColorSpaceUri[] =
+    "http://www.webrtc.org/experiments/rtp-hdrext/color-space";
+
+const char RtpExtension::kRidUri[] =
+    "urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id";
+
+const char RtpExtension::kRepairedRidUri[] =
+    "urn:ietf:params:rtp-hdrext:sdes:repaired-rtp-stream-id";
+
+constexpr int RtpExtension::kMinId;
+constexpr int RtpExtension::kMaxId;
+constexpr int RtpExtension::kMaxValueSize;
+constexpr int RtpExtension::kOneByteHeaderExtensionMaxId;
+constexpr int RtpExtension::kOneByteHeaderExtensionMaxValueSize;
+
+bool RtpExtension::IsSupportedForAudio(const std::string& uri) {
+  return uri == webrtc::RtpExtension::kAudioLevelUri ||
+         uri == webrtc::RtpExtension::kTransportSequenceNumberUri ||
+         uri == webrtc::RtpExtension::kTransportSequenceNumberV2Uri ||
+         uri == webrtc::RtpExtension::kMidUri ||
+         uri == webrtc::RtpExtension::kRidUri ||
+         uri == webrtc::RtpExtension::kRepairedRidUri;
+}
+
+bool RtpExtension::IsSupportedForVideo(const std::string& uri) {
+  return uri == webrtc::RtpExtension::kTimestampOffsetUri ||
+         uri == webrtc::RtpExtension::kAbsSendTimeUri ||
+         uri == webrtc::RtpExtension::kVideoRotationUri ||
+         uri == webrtc::RtpExtension::kTransportSequenceNumberUri ||
+         uri == webrtc::RtpExtension::kTransportSequenceNumberV2Uri ||
+         uri == webrtc::RtpExtension::kPlayoutDelayUri ||
+         uri == webrtc::RtpExtension::kVideoContentTypeUri ||
+         uri == webrtc::RtpExtension::kVideoTimingUri ||
+         uri == webrtc::RtpExtension::kMidUri ||
+         uri == webrtc::RtpExtension::kFrameMarkingUri ||
+         uri == webrtc::RtpExtension::kGenericFrameDescriptorUri00 ||
+         uri == webrtc::RtpExtension::kGenericFrameDescriptorUri01 ||
+         uri == webrtc::RtpExtension::kColorSpaceUri ||
+         uri == webrtc::RtpExtension::kRidUri ||
+         uri == webrtc::RtpExtension::kRepairedRidUri;
+}
+
+bool RtpExtension::IsEncryptionSupported(const std::string& uri) {
+  return uri == webrtc::RtpExtension::kAudioLevelUri ||
+         uri == webrtc::RtpExtension::kTimestampOffsetUri ||
+#if !defined(ENABLE_EXTERNAL_AUTH)
+         // TODO(jbauch): Figure out a way to always allow "kAbsSendTimeUri"
+         // here and filter out later if external auth is really used in
+         // srtpfilter. External auth is used by Chromium and replaces the
+         // extension header value of "kAbsSendTimeUri", so it must not be
+         // encrypted (which can't be done by Chromium).
+         uri == webrtc::RtpExtension::kAbsSendTimeUri ||
+#endif
+         uri == webrtc::RtpExtension::kVideoRotationUri ||
+         uri == webrtc::RtpExtension::kTransportSequenceNumberUri ||
+         uri == webrtc::RtpExtension::kTransportSequenceNumberV2Uri ||
+         uri == webrtc::RtpExtension::kPlayoutDelayUri ||
+         uri == webrtc::RtpExtension::kVideoContentTypeUri ||
+         uri == webrtc::RtpExtension::kMidUri ||
+         uri == webrtc::RtpExtension::kRidUri ||
+         uri == webrtc::RtpExtension::kRepairedRidUri;
+}
+
+const RtpExtension* RtpExtension::FindHeaderExtensionByUri(
+    const std::vector<RtpExtension>& extensions,
+    const std::string& uri) {
+  for (const auto& extension : extensions) {
+    if (extension.uri == uri) {
+      return &extension;
+    }
+  }
+  return nullptr;
+}
+
+std::vector<RtpExtension> RtpExtension::FilterDuplicateNonEncrypted(
+    const std::vector<RtpExtension>& extensions) {
+  std::vector<RtpExtension> filtered;
+  for (auto extension = extensions.begin(); extension != extensions.end();
+       ++extension) {
+    if (extension->encrypt) {
+      filtered.push_back(*extension);
+      continue;
+    }
+
+    // Only add non-encrypted extension if no encrypted with the same URI
+    // is also present...
+    if (std::find_if(extension + 1, extensions.end(),
+                     [extension](const RtpExtension& check) {
+                       return extension->uri == check.uri;
+                     }) != extensions.end()) {
+      continue;
+    }
+
+    // ...and has not been added before.
+    if (!FindHeaderExtensionByUri(filtered, extension->uri)) {
+      filtered.push_back(*extension);
+    }
+  }
+  return filtered;
+}
+}  // namespace webrtc
diff --git a/api/rtp_parameters.h b/api/rtp_parameters.h
new file mode 100644
index 0000000..b7d7702
--- /dev/null
+++ b/api/rtp_parameters.h
@@ -0,0 +1,664 @@
+/*
+ *  Copyright 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.
+ */
+
+#ifndef API_RTP_PARAMETERS_H_
+#define API_RTP_PARAMETERS_H_
+
+#include <stdint.h>
+#include <string>
+#include <unordered_map>
+#include <vector>
+
+#include "absl/types/optional.h"
+#include "api/media_types.h"
+#include "rtc_base/system/rtc_export.h"
+
+namespace webrtc {
+
+// These structures are intended to mirror those defined by:
+// http://draft.ortc.org/#rtcrtpdictionaries*
+// Contains everything specified as of 2017 Jan 24.
+//
+// They are used when retrieving or modifying the parameters of an
+// RtpSender/RtpReceiver, or retrieving capabilities.
+//
+// Note on conventions: Where ORTC may use "octet", "short" and "unsigned"
+// types, we typically use "int", in keeping with our style guidelines. The
+// parameter's actual valid range will be enforced when the parameters are set,
+// rather than when the parameters struct is built. An exception is made for
+// SSRCs, since they use the full unsigned 32-bit range, and aren't expected to
+// be used for any numeric comparisons/operations.
+//
+// Additionally, where ORTC uses strings, we may use enums for things that have
+// a fixed number of supported values. However, for things that can be extended
+// (such as codecs, by providing an external encoder factory), a string
+// identifier is used.
+
+enum class FecMechanism {
+  RED,
+  RED_AND_ULPFEC,
+  FLEXFEC,
+};
+
+// Used in RtcpFeedback struct.
+enum class RtcpFeedbackType {
+  CCM,
+  NACK,
+  REMB,  // "goog-remb"
+  TRANSPORT_CC,
+};
+
+// Used in RtcpFeedback struct when type is NACK or CCM.
+enum class RtcpFeedbackMessageType {
+  // Equivalent to {type: "nack", parameter: undefined} in ORTC.
+  GENERIC_NACK,
+  PLI,  // Usable with NACK.
+  FIR,  // Usable with CCM.
+};
+
+enum class DtxStatus {
+  DISABLED,
+  ENABLED,
+};
+
+// Based on the spec in
+// https://w3c.github.io/webrtc-pc/#idl-def-rtcdegradationpreference.
+// These options are enforced on a best-effort basis. For instance, all of
+// these options may suffer some frame drops in order to avoid queuing.
+// TODO(sprang): Look into possibility of more strictly enforcing the
+// maintain-framerate option.
+// TODO(deadbeef): Default to "balanced", as the spec indicates?
+enum class DegradationPreference {
+  // Don't take any actions based on over-utilization signals. Not part of the
+  // web API.
+  DISABLED,
+  // On over-use, request lower frame rate, possibly causing frame drops.
+  MAINTAIN_FRAMERATE,
+  // On over-use, request lower resolution, possibly causing down-scaling.
+  MAINTAIN_RESOLUTION,
+  // Try to strike a "pleasing" balance between frame rate or resolution.
+  BALANCED,
+};
+
+extern const double kDefaultBitratePriority;
+
+struct RtcpFeedback {
+  RtcpFeedbackType type = RtcpFeedbackType::CCM;
+
+  // Equivalent to ORTC "parameter" field with slight differences:
+  // 1. It's an enum instead of a string.
+  // 2. Generic NACK feedback is represented by a GENERIC_NACK message type,
+  //    rather than an unset "parameter" value.
+  absl::optional<RtcpFeedbackMessageType> message_type;
+
+  // Constructors for convenience.
+  RtcpFeedback();
+  explicit RtcpFeedback(RtcpFeedbackType type);
+  RtcpFeedback(RtcpFeedbackType type, RtcpFeedbackMessageType message_type);
+  RtcpFeedback(const RtcpFeedback&);
+  ~RtcpFeedback();
+
+  bool operator==(const RtcpFeedback& o) const {
+    return type == o.type && message_type == o.message_type;
+  }
+  bool operator!=(const RtcpFeedback& o) const { return !(*this == o); }
+};
+
+// RtpCodecCapability is to RtpCodecParameters as RtpCapabilities is to
+// RtpParameters. This represents the static capabilities of an endpoint's
+// implementation of a codec.
+struct RtpCodecCapability {
+  RtpCodecCapability();
+  ~RtpCodecCapability();
+
+  // Build MIME "type/subtype" string from |name| and |kind|.
+  std::string mime_type() const { return MediaTypeToString(kind) + "/" + name; }
+
+  // Used to identify the codec. Equivalent to MIME subtype.
+  std::string name;
+
+  // The media type of this codec. Equivalent to MIME top-level type.
+  cricket::MediaType kind = cricket::MEDIA_TYPE_AUDIO;
+
+  // Clock rate in Hertz. If unset, the codec is applicable to any clock rate.
+  absl::optional<int> clock_rate;
+
+  // Default payload type for this codec. Mainly needed for codecs that use
+  // that have statically assigned payload types.
+  absl::optional<int> preferred_payload_type;
+
+  // Maximum packetization time supported by an RtpReceiver for this codec.
+  // TODO(deadbeef): Not implemented.
+  absl::optional<int> max_ptime;
+
+  // Preferred packetization time for an RtpReceiver or RtpSender of this
+  // codec.
+  // TODO(deadbeef): Not implemented.
+  absl::optional<int> ptime;
+
+  // The number of audio channels supported. Unused for video codecs.
+  absl::optional<int> num_channels;
+
+  // Feedback mechanisms supported for this codec.
+  std::vector<RtcpFeedback> rtcp_feedback;
+
+  // Codec-specific parameters that must be signaled to the remote party.
+  //
+  // Corresponds to "a=fmtp" parameters in SDP.
+  //
+  // Contrary to ORTC, these parameters are named using all lowercase strings.
+  // This helps make the mapping to SDP simpler, if an application is using
+  // SDP. Boolean values are represented by the string "1".
+  std::unordered_map<std::string, std::string> parameters;
+
+  // Codec-specific parameters that may optionally be signaled to the remote
+  // party.
+  // TODO(deadbeef): Not implemented.
+  std::unordered_map<std::string, std::string> options;
+
+  // Maximum number of temporal layer extensions supported by this codec.
+  // For example, a value of 1 indicates that 2 total layers are supported.
+  // TODO(deadbeef): Not implemented.
+  int max_temporal_layer_extensions = 0;
+
+  // Maximum number of spatial layer extensions supported by this codec.
+  // For example, a value of 1 indicates that 2 total layers are supported.
+  // TODO(deadbeef): Not implemented.
+  int max_spatial_layer_extensions = 0;
+
+  // Whether the implementation can send/receive SVC layers with distinct
+  // SSRCs. Always false for audio codecs. True for video codecs that support
+  // scalable video coding with MRST.
+  // TODO(deadbeef): Not implemented.
+  bool svc_multi_stream_support = false;
+
+  bool operator==(const RtpCodecCapability& o) const {
+    return name == o.name && kind == o.kind && clock_rate == o.clock_rate &&
+           preferred_payload_type == o.preferred_payload_type &&
+           max_ptime == o.max_ptime && ptime == o.ptime &&
+           num_channels == o.num_channels && rtcp_feedback == o.rtcp_feedback &&
+           parameters == o.parameters && options == o.options &&
+           max_temporal_layer_extensions == o.max_temporal_layer_extensions &&
+           max_spatial_layer_extensions == o.max_spatial_layer_extensions &&
+           svc_multi_stream_support == o.svc_multi_stream_support;
+  }
+  bool operator!=(const RtpCodecCapability& o) const { return !(*this == o); }
+};
+
+// Used in RtpCapabilities; represents the capabilities/preferences of an
+// implementation for a header extension.
+//
+// Just called "RtpHeaderExtension" in ORTC, but the "Capability" suffix was
+// added here for consistency and to avoid confusion with
+// RtpHeaderExtensionParameters.
+//
+// Note that ORTC includes a "kind" field, but we omit this because it's
+// redundant; if you call "RtpReceiver::GetCapabilities(MEDIA_TYPE_AUDIO)",
+// you know you're getting audio capabilities.
+struct RtpHeaderExtensionCapability {
+  // URI of this extension, as defined in RFC8285.
+  std::string uri;
+
+  // Preferred value of ID that goes in the packet.
+  absl::optional<int> preferred_id;
+
+  // If true, it's preferred that the value in the header is encrypted.
+  // TODO(deadbeef): Not implemented.
+  bool preferred_encrypt = false;
+
+  // Constructors for convenience.
+  RtpHeaderExtensionCapability();
+  explicit RtpHeaderExtensionCapability(const std::string& uri);
+  RtpHeaderExtensionCapability(const std::string& uri, int preferred_id);
+  ~RtpHeaderExtensionCapability();
+
+  bool operator==(const RtpHeaderExtensionCapability& o) const {
+    return uri == o.uri && preferred_id == o.preferred_id &&
+           preferred_encrypt == o.preferred_encrypt;
+  }
+  bool operator!=(const RtpHeaderExtensionCapability& o) const {
+    return !(*this == o);
+  }
+};
+
+// RTP header extension, see RFC8285.
+struct RtpExtension {
+  RtpExtension();
+  RtpExtension(const std::string& uri, int id);
+  RtpExtension(const std::string& uri, int id, bool encrypt);
+  ~RtpExtension();
+  std::string ToString() const;
+  bool operator==(const RtpExtension& rhs) const {
+    return uri == rhs.uri && id == rhs.id && encrypt == rhs.encrypt;
+  }
+  static bool IsSupportedForAudio(const std::string& uri);
+  static bool IsSupportedForVideo(const std::string& uri);
+  // Return "true" if the given RTP header extension URI may be encrypted.
+  static bool IsEncryptionSupported(const std::string& uri);
+
+  // Returns the named header extension if found among all extensions,
+  // nullptr otherwise.
+  static const RtpExtension* FindHeaderExtensionByUri(
+      const std::vector<RtpExtension>& extensions,
+      const std::string& uri);
+
+  // Return a list of RTP header extensions with the non-encrypted extensions
+  // removed if both the encrypted and non-encrypted extension is present for
+  // the same URI.
+  static std::vector<RtpExtension> FilterDuplicateNonEncrypted(
+      const std::vector<RtpExtension>& extensions);
+
+  // Header extension for audio levels, as defined in:
+  // http://tools.ietf.org/html/draft-ietf-avtext-client-to-mixer-audio-level-03
+  static const char kAudioLevelUri[];
+
+  // Header extension for RTP timestamp offset, see RFC 5450 for details:
+  // http://tools.ietf.org/html/rfc5450
+  static const char kTimestampOffsetUri[];
+
+  // Header extension for absolute send time, see url for details:
+  // http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
+  static const char kAbsSendTimeUri[];
+
+  // Header extension for coordination of video orientation, see url for
+  // details:
+  // http://www.etsi.org/deliver/etsi_ts/126100_126199/126114/12.07.00_60/ts_126114v120700p.pdf
+  static const char kVideoRotationUri[];
+
+  // Header extension for video content type. E.g. default or screenshare.
+  static const char kVideoContentTypeUri[];
+
+  // Header extension for video timing.
+  static const char kVideoTimingUri[];
+
+  // Header extension for video frame marking.
+  static const char kFrameMarkingUri[];
+
+  // Experimental codec agnostic frame descriptor.
+  static const char kGenericFrameDescriptorUri00[];
+  static const char kGenericFrameDescriptorUri01[];
+  // TODO(bugs.webrtc.org/10243): Remove once dependencies have been updated.
+  static const char kGenericFrameDescriptorUri[];
+
+  // Header extension for transport sequence number, see url for details:
+  // http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions
+  static const char kTransportSequenceNumberUri[];
+  static const char kTransportSequenceNumberV2Uri[];
+
+  static const char kPlayoutDelayUri[];
+
+  // Header extension for identifying media section within a transport.
+  // https://tools.ietf.org/html/draft-ietf-mmusic-sdp-bundle-negotiation-49#section-15
+  static const char kMidUri[];
+
+  // Encryption of Header Extensions, see RFC 6904 for details:
+  // https://tools.ietf.org/html/rfc6904
+  static const char kEncryptHeaderExtensionsUri[];
+
+  // Header extension for color space information.
+  static const char kColorSpaceUri[];
+
+  // Header extension for RIDs and Repaired RIDs
+  // https://tools.ietf.org/html/draft-ietf-avtext-rid-09
+  // https://tools.ietf.org/html/draft-ietf-mmusic-rid-15
+  static const char kRidUri[];
+  static const char kRepairedRidUri[];
+
+  // Inclusive min and max IDs for two-byte header extensions and one-byte
+  // header extensions, per RFC8285 Section 4.2-4.3.
+  static constexpr int kMinId = 1;
+  static constexpr int kMaxId = 255;
+  static constexpr int kMaxValueSize = 255;
+  static constexpr int kOneByteHeaderExtensionMaxId = 14;
+  static constexpr int kOneByteHeaderExtensionMaxValueSize = 16;
+
+  std::string uri;
+  int id = 0;
+  bool encrypt = false;
+};
+
+// TODO(deadbeef): This is missing the "encrypt" flag, which is unimplemented.
+typedef RtpExtension RtpHeaderExtensionParameters;
+
+struct RtpFecParameters {
+  // If unset, a value is chosen by the implementation.
+  // Works just like RtpEncodingParameters::ssrc.
+  absl::optional<uint32_t> ssrc;
+
+  FecMechanism mechanism = FecMechanism::RED;
+
+  // Constructors for convenience.
+  RtpFecParameters();
+  explicit RtpFecParameters(FecMechanism mechanism);
+  RtpFecParameters(FecMechanism mechanism, uint32_t ssrc);
+  RtpFecParameters(const RtpFecParameters&);
+  ~RtpFecParameters();
+
+  bool operator==(const RtpFecParameters& o) const {
+    return ssrc == o.ssrc && mechanism == o.mechanism;
+  }
+  bool operator!=(const RtpFecParameters& o) const { return !(*this == o); }
+};
+
+struct RtpRtxParameters {
+  // If unset, a value is chosen by the implementation.
+  // Works just like RtpEncodingParameters::ssrc.
+  absl::optional<uint32_t> ssrc;
+
+  // Constructors for convenience.
+  RtpRtxParameters();
+  explicit RtpRtxParameters(uint32_t ssrc);
+  RtpRtxParameters(const RtpRtxParameters&);
+  ~RtpRtxParameters();
+
+  bool operator==(const RtpRtxParameters& o) const { return ssrc == o.ssrc; }
+  bool operator!=(const RtpRtxParameters& o) const { return !(*this == o); }
+};
+
+struct RtpEncodingParameters {
+  RtpEncodingParameters();
+  RtpEncodingParameters(const RtpEncodingParameters&);
+  ~RtpEncodingParameters();
+
+  // If unset, a value is chosen by the implementation.
+  //
+  // Note that the chosen value is NOT returned by GetParameters, because it
+  // may change due to an SSRC conflict, in which case the conflict is handled
+  // internally without any event. Another way of looking at this is that an
+  // unset SSRC acts as a "wildcard" SSRC.
+  absl::optional<uint32_t> ssrc;
+
+  // Can be used to reference a codec in the |codecs| member of the
+  // RtpParameters that contains this RtpEncodingParameters. If unset, the
+  // implementation will choose the first possible codec (if a sender), or
+  // prepare to receive any codec (for a receiver).
+  // TODO(deadbeef): Not implemented. Implementation of RtpSender will always
+  // choose the first codec from the list.
+  absl::optional<int> codec_payload_type;
+
+  // Specifies the FEC mechanism, if set.
+  // TODO(deadbeef): Not implemented. Current implementation will use whatever
+  // FEC codecs are available, including red+ulpfec.
+  absl::optional<RtpFecParameters> fec;
+
+  // Specifies the RTX parameters, if set.
+  // TODO(deadbeef): Not implemented with PeerConnection senders/receivers.
+  absl::optional<RtpRtxParameters> rtx;
+
+  // Only used for audio. If set, determines whether or not discontinuous
+  // transmission will be used, if an available codec supports it. If not
+  // set, the implementation default setting will be used.
+  // TODO(deadbeef): Not implemented. Current implementation will use a CN
+  // codec as long as it's present.
+  absl::optional<DtxStatus> dtx;
+
+  // The relative bitrate priority of this encoding. Currently this is
+  // implemented for the entire rtp sender by using the value of the first
+  // encoding parameter.
+  // TODO(webrtc.bugs.org/8630): Implement this per encoding parameter.
+  // Currently there is logic for how bitrate is distributed per simulcast layer
+  // in the VideoBitrateAllocator. This must be updated to incorporate relative
+  // bitrate priority.
+  double bitrate_priority = kDefaultBitratePriority;
+
+  // The relative DiffServ Code Point priority for this encoding, allowing
+  // packets to be marked relatively higher or lower without affecting
+  // bandwidth allocations. See https://w3c.github.io/webrtc-dscp-exp/ . NB
+  // we follow chromium's translation of the allowed string enum values for
+  // this field to 1.0, 0.5, et cetera, similar to bitrate_priority above.
+  // TODO(http://crbug.com/webrtc/8630): Implement this per encoding parameter.
+  double network_priority = kDefaultBitratePriority;
+
+  // Indicates the preferred duration of media represented by a packet in
+  // milliseconds for this encoding. If set, this will take precedence over the
+  // ptime set in the RtpCodecParameters. This could happen if SDP negotiation
+  // creates a ptime for a specific codec, which is later changed in the
+  // RtpEncodingParameters by the application.
+  // TODO(bugs.webrtc.org/8819): Not implemented.
+  absl::optional<int> ptime;
+
+  // If set, this represents the Transport Independent Application Specific
+  // maximum bandwidth defined in RFC3890. If unset, there is no maximum
+  // bitrate. Currently this is implemented for the entire rtp sender by using
+  // the value of the first encoding parameter.
+  //
+  // Just called "maxBitrate" in ORTC spec.
+  //
+  // TODO(deadbeef): With ORTC RtpSenders, this currently sets the total
+  // bandwidth for the entire bandwidth estimator (audio and video). This is
+  // just always how "b=AS" was handled, but it's not correct and should be
+  // fixed.
+  absl::optional<int> max_bitrate_bps;
+
+  // Specifies the minimum bitrate in bps for video.
+  // TODO(asapersson): Not implemented for ORTC API.
+  absl::optional<int> min_bitrate_bps;
+
+  // Specifies the maximum framerate in fps for video.
+  // TODO(asapersson): Different framerates are not supported per simulcast
+  // layer. If set, the maximum |max_framerate| is currently used.
+  // Not supported for screencast.
+  absl::optional<int> max_framerate;
+
+  // Specifies the number of temporal layers for video (if the feature is
+  // supported by the codec implementation).
+  // TODO(asapersson): Different number of temporal layers are not supported
+  // per simulcast layer.
+  // Screencast support is experimental.
+  absl::optional<int> num_temporal_layers;
+
+  // For video, scale the resolution down by this factor.
+  absl::optional<double> scale_resolution_down_by;
+
+  // Scale the framerate down by this factor.
+  // TODO(deadbeef): Not implemented.
+  absl::optional<double> scale_framerate_down_by;
+
+  // For an RtpSender, set to true to cause this encoding to be encoded and
+  // sent, and false for it not to be encoded and sent. This allows control
+  // across multiple encodings of a sender for turning simulcast layers on and
+  // off.
+  // TODO(webrtc.bugs.org/8807): Updating this parameter will trigger an encoder
+  // reset, but this isn't necessarily required.
+  bool active = true;
+
+  // Value to use for RID RTP header extension.
+  // Called "encodingId" in ORTC.
+  std::string rid;
+
+  // RIDs of encodings on which this layer depends.
+  // Called "dependencyEncodingIds" in ORTC spec.
+  // TODO(deadbeef): Not implemented.
+  std::vector<std::string> dependency_rids;
+
+  bool operator==(const RtpEncodingParameters& o) const {
+    return ssrc == o.ssrc && codec_payload_type == o.codec_payload_type &&
+           fec == o.fec && rtx == o.rtx && dtx == o.dtx &&
+           bitrate_priority == o.bitrate_priority &&
+           network_priority == o.network_priority && ptime == o.ptime &&
+           max_bitrate_bps == o.max_bitrate_bps &&
+           min_bitrate_bps == o.min_bitrate_bps &&
+           max_framerate == o.max_framerate &&
+           num_temporal_layers == o.num_temporal_layers &&
+           scale_resolution_down_by == o.scale_resolution_down_by &&
+           scale_framerate_down_by == o.scale_framerate_down_by &&
+           active == o.active && rid == o.rid &&
+           dependency_rids == o.dependency_rids;
+  }
+  bool operator!=(const RtpEncodingParameters& o) const {
+    return !(*this == o);
+  }
+};
+
+struct RtpCodecParameters {
+  RtpCodecParameters();
+  RtpCodecParameters(const RtpCodecParameters&);
+  ~RtpCodecParameters();
+
+  // Build MIME "type/subtype" string from |name| and |kind|.
+  std::string mime_type() const { return MediaTypeToString(kind) + "/" + name; }
+
+  // Used to identify the codec. Equivalent to MIME subtype.
+  std::string name;
+
+  // The media type of this codec. Equivalent to MIME top-level type.
+  cricket::MediaType kind = cricket::MEDIA_TYPE_AUDIO;
+
+  // Payload type used to identify this codec in RTP packets.
+  // This must always be present, and must be unique across all codecs using
+  // the same transport.
+  int payload_type = 0;
+
+  // If unset, the implementation default is used.
+  absl::optional<int> clock_rate;
+
+  // The number of audio channels used. Unset for video codecs. If unset for
+  // audio, the implementation default is used.
+  // TODO(deadbeef): The "implementation default" part isn't fully implemented.
+  // Only defaults to 1, even though some codecs (such as opus) should really
+  // default to 2.
+  absl::optional<int> num_channels;
+
+  // The maximum packetization time to be used by an RtpSender.
+  // If |ptime| is also set, this will be ignored.
+  // TODO(deadbeef): Not implemented.
+  absl::optional<int> max_ptime;
+
+  // The packetization time to be used by an RtpSender.
+  // If unset, will use any time up to max_ptime.
+  // TODO(deadbeef): Not implemented.
+  absl::optional<int> ptime;
+
+  // Feedback mechanisms to be used for this codec.
+  // TODO(deadbeef): Not implemented with PeerConnection senders/receivers.
+  std::vector<RtcpFeedback> rtcp_feedback;
+
+  // Codec-specific parameters that must be signaled to the remote party.
+  //
+  // Corresponds to "a=fmtp" parameters in SDP.
+  //
+  // Contrary to ORTC, these parameters are named using all lowercase strings.
+  // This helps make the mapping to SDP simpler, if an application is using
+  // SDP. Boolean values are represented by the string "1".
+  std::unordered_map<std::string, std::string> parameters;
+
+  bool operator==(const RtpCodecParameters& o) const {
+    return name == o.name && kind == o.kind && payload_type == o.payload_type &&
+           clock_rate == o.clock_rate && num_channels == o.num_channels &&
+           max_ptime == o.max_ptime && ptime == o.ptime &&
+           rtcp_feedback == o.rtcp_feedback && parameters == o.parameters;
+  }
+  bool operator!=(const RtpCodecParameters& o) const { return !(*this == o); }
+};
+
+// RtpCapabilities is used to represent the static capabilities of an
+// endpoint. An application can use these capabilities to construct an
+// RtpParameters.
+struct RtpCapabilities {
+  RtpCapabilities();
+  ~RtpCapabilities();
+
+  // Supported codecs.
+  std::vector<RtpCodecCapability> codecs;
+
+  // Supported RTP header extensions.
+  std::vector<RtpHeaderExtensionCapability> header_extensions;
+
+  // Supported Forward Error Correction (FEC) mechanisms. Note that the RED,
+  // ulpfec and flexfec codecs used by these mechanisms will still appear in
+  // |codecs|.
+  std::vector<FecMechanism> fec;
+
+  bool operator==(const RtpCapabilities& o) const {
+    return codecs == o.codecs && header_extensions == o.header_extensions &&
+           fec == o.fec;
+  }
+  bool operator!=(const RtpCapabilities& o) const { return !(*this == o); }
+};
+
+struct RtcpParameters final {
+  RtcpParameters();
+  RtcpParameters(const RtcpParameters&);
+  ~RtcpParameters();
+
+  // The SSRC to be used in the "SSRC of packet sender" field. If not set, one
+  // will be chosen by the implementation.
+  // TODO(deadbeef): Not implemented.
+  absl::optional<uint32_t> ssrc;
+
+  // The Canonical Name (CNAME) used by RTCP (e.g. in SDES messages).
+  //
+  // If empty in the construction of the RtpTransport, one will be generated by
+  // the implementation, and returned in GetRtcpParameters. Multiple
+  // RtpTransports created by the same OrtcFactory will use the same generated
+  // CNAME.
+  //
+  // If empty when passed into SetParameters, the CNAME simply won't be
+  // modified.
+  std::string cname;
+
+  // Send reduced-size RTCP?
+  bool reduced_size = false;
+
+  // Send RTCP multiplexed on the RTP transport?
+  // Not used with PeerConnection senders/receivers
+  bool mux = true;
+
+  bool operator==(const RtcpParameters& o) const {
+    return ssrc == o.ssrc && cname == o.cname &&
+           reduced_size == o.reduced_size && mux == o.mux;
+  }
+  bool operator!=(const RtcpParameters& o) const { return !(*this == o); }
+};
+
+struct RTC_EXPORT RtpParameters {
+  RtpParameters();
+  RtpParameters(const RtpParameters&);
+  ~RtpParameters();
+
+  // Used when calling getParameters/setParameters with a PeerConnection
+  // RtpSender, to ensure that outdated parameters are not unintentionally
+  // applied successfully.
+  std::string transaction_id;
+
+  // Value to use for MID RTP header extension.
+  // Called "muxId" in ORTC.
+  // TODO(deadbeef): Not implemented.
+  std::string mid;
+
+  std::vector<RtpCodecParameters> codecs;
+
+  std::vector<RtpHeaderExtensionParameters> header_extensions;
+
+  std::vector<RtpEncodingParameters> encodings;
+
+  // Only available with a Peerconnection RtpSender.
+  // In ORTC, our API includes an additional "RtpTransport"
+  // abstraction on which RTCP parameters are set.
+  RtcpParameters rtcp;
+
+  // 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;
+
+  bool operator==(const RtpParameters& o) const {
+    return mid == o.mid && codecs == o.codecs &&
+           header_extensions == o.header_extensions &&
+           encodings == o.encodings && rtcp == o.rtcp &&
+           degradation_preference == o.degradation_preference;
+  }
+  bool operator!=(const RtpParameters& o) const { return !(*this == o); }
+};
+
+}  // namespace webrtc
+
+#endif  // API_RTP_PARAMETERS_H_
diff --git a/api/rtp_parameters_unittest.cc b/api/rtp_parameters_unittest.cc
new file mode 100644
index 0000000..b6f2482
--- /dev/null
+++ b/api/rtp_parameters_unittest.cc
@@ -0,0 +1,49 @@
+/*
+ *  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 "api/rtp_parameters.h"
+#include "test/gtest.h"
+
+namespace webrtc {
+
+using webrtc::RtpExtension;
+
+static const char kExtensionUri1[] = "extension-uri1";
+static const char kExtensionUri2[] = "extension-uri2";
+
+static const RtpExtension kExtension1(kExtensionUri1, 1);
+static const RtpExtension kExtension1Encrypted(kExtensionUri1, 10, true);
+static const RtpExtension kExtension2(kExtensionUri2, 2);
+
+TEST(RtpExtensionTest, FilterDuplicateNonEncrypted) {
+  std::vector<RtpExtension> extensions;
+  std::vector<RtpExtension> filtered;
+
+  extensions.push_back(kExtension1);
+  extensions.push_back(kExtension1Encrypted);
+  filtered = RtpExtension::FilterDuplicateNonEncrypted(extensions);
+  EXPECT_EQ(1u, filtered.size());
+  EXPECT_EQ(std::vector<RtpExtension>{kExtension1Encrypted}, filtered);
+
+  extensions.clear();
+  extensions.push_back(kExtension1Encrypted);
+  extensions.push_back(kExtension1);
+  filtered = RtpExtension::FilterDuplicateNonEncrypted(extensions);
+  EXPECT_EQ(1u, filtered.size());
+  EXPECT_EQ(std::vector<RtpExtension>{kExtension1Encrypted}, filtered);
+
+  extensions.clear();
+  extensions.push_back(kExtension1);
+  extensions.push_back(kExtension2);
+  filtered = RtpExtension::FilterDuplicateNonEncrypted(extensions);
+  EXPECT_EQ(2u, filtered.size());
+  EXPECT_EQ(extensions, filtered);
+}
+}  // namespace webrtc
diff --git a/api/rtp_receiver_interface.cc b/api/rtp_receiver_interface.cc
new file mode 100644
index 0000000..52f72df
--- /dev/null
+++ b/api/rtp_receiver_interface.cc
@@ -0,0 +1,61 @@
+/*
+ *  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/rtp_receiver_interface.h"
+
+namespace webrtc {
+
+RtpSource::RtpSource(int64_t timestamp_ms,
+                     uint32_t source_id,
+                     RtpSourceType source_type)
+    : timestamp_ms_(timestamp_ms),
+      source_id_(source_id),
+      source_type_(source_type) {}
+
+RtpSource::RtpSource(int64_t timestamp_ms,
+                     uint32_t source_id,
+                     RtpSourceType source_type,
+                     uint8_t audio_level)
+    : timestamp_ms_(timestamp_ms),
+      source_id_(source_id),
+      source_type_(source_type),
+      audio_level_(audio_level) {}
+
+RtpSource::RtpSource(const RtpSource&) = default;
+RtpSource& RtpSource::operator=(const RtpSource&) = default;
+RtpSource::~RtpSource() = default;
+
+std::vector<std::string> RtpReceiverInterface::stream_ids() const {
+  return {};
+}
+
+std::vector<rtc::scoped_refptr<MediaStreamInterface>>
+RtpReceiverInterface::streams() const {
+  return {};
+}
+
+std::vector<RtpSource> RtpReceiverInterface::GetSources() const {
+  return {};
+}
+
+void RtpReceiverInterface::SetFrameDecryptor(
+    rtc::scoped_refptr<FrameDecryptorInterface> frame_decryptor) {}
+
+rtc::scoped_refptr<FrameDecryptorInterface>
+RtpReceiverInterface::GetFrameDecryptor() const {
+  return nullptr;
+}
+
+rtc::scoped_refptr<DtlsTransportInterface>
+RtpReceiverInterface::dtls_transport() const {
+  return nullptr;
+}
+
+}  // namespace webrtc
diff --git a/api/rtp_receiver_interface.h b/api/rtp_receiver_interface.h
new file mode 100644
index 0000000..7d9870b
--- /dev/null
+++ b/api/rtp_receiver_interface.h
@@ -0,0 +1,176 @@
+/*
+ *  Copyright 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.
+ */
+
+// This file contains interfaces for RtpReceivers
+// http://w3c.github.io/webrtc-pc/#rtcrtpreceiver-interface
+
+#ifndef API_RTP_RECEIVER_INTERFACE_H_
+#define API_RTP_RECEIVER_INTERFACE_H_
+
+#include <string>
+#include <vector>
+
+#include "api/crypto/frame_decryptor_interface.h"
+#include "api/dtls_transport_interface.h"
+#include "api/media_stream_interface.h"
+#include "api/media_types.h"
+#include "api/proxy.h"
+#include "api/rtp_parameters.h"
+#include "api/scoped_refptr.h"
+#include "rtc_base/ref_count.h"
+
+namespace webrtc {
+
+enum class RtpSourceType {
+  SSRC,
+  CSRC,
+};
+
+class RtpSource {
+ public:
+  RtpSource() = delete;
+  RtpSource(int64_t timestamp_ms,
+            uint32_t source_id,
+            RtpSourceType source_type);
+  RtpSource(int64_t timestamp_ms,
+            uint32_t source_id,
+            RtpSourceType source_type,
+            uint8_t audio_level);
+  RtpSource(const RtpSource&);
+  RtpSource& operator=(const RtpSource&);
+  ~RtpSource();
+
+  int64_t timestamp_ms() const { return timestamp_ms_; }
+  void update_timestamp_ms(int64_t timestamp_ms) {
+    RTC_DCHECK_LE(timestamp_ms_, timestamp_ms);
+    timestamp_ms_ = timestamp_ms;
+  }
+
+  // The identifier of the source can be the CSRC or the SSRC.
+  uint32_t source_id() const { return source_id_; }
+
+  // The source can be either a contributing source or a synchronization source.
+  RtpSourceType source_type() const { return source_type_; }
+
+  absl::optional<uint8_t> audio_level() const { return audio_level_; }
+  void set_audio_level(const absl::optional<uint8_t>& level) {
+    audio_level_ = level;
+  }
+
+  bool operator==(const RtpSource& o) const {
+    return timestamp_ms_ == o.timestamp_ms() && source_id_ == o.source_id() &&
+           source_type_ == o.source_type() && audio_level_ == o.audio_level_;
+  }
+
+ private:
+  int64_t timestamp_ms_;
+  uint32_t source_id_;
+  RtpSourceType source_type_;
+  absl::optional<uint8_t> audio_level_;
+};
+
+class RtpReceiverObserverInterface {
+ public:
+  // Note: Currently if there are multiple RtpReceivers of the same media type,
+  // they will all call OnFirstPacketReceived at once.
+  //
+  // In the future, it's likely that an RtpReceiver will only call
+  // OnFirstPacketReceived when a packet is received specifically for its
+  // SSRC/mid.
+  virtual void OnFirstPacketReceived(cricket::MediaType media_type) = 0;
+
+ protected:
+  virtual ~RtpReceiverObserverInterface() {}
+};
+
+class RtpReceiverInterface : public rtc::RefCountInterface {
+ public:
+  virtual rtc::scoped_refptr<MediaStreamTrackInterface> track() const = 0;
+
+  // The dtlsTransport attribute exposes the DTLS transport on which the
+  // media is received. It may be null.
+  // https://w3c.github.io/webrtc-pc/#dom-rtcrtpreceiver-transport
+  // TODO(https://bugs.webrtc.org/907849) remove default implementation
+  virtual rtc::scoped_refptr<DtlsTransportInterface> dtls_transport() const;
+
+  // The list of streams that |track| is associated with. This is the same as
+  // the [[AssociatedRemoteMediaStreams]] internal slot in the spec.
+  // https://w3c.github.io/webrtc-pc/#dfn-associatedremotemediastreams
+  // TODO(hbos): Make pure virtual as soon as Chromium's mock implements this.
+  // TODO(https://crbug.com/webrtc/9480): Remove streams() in favor of
+  // stream_ids() as soon as downstream projects are no longer dependent on
+  // stream objects.
+  virtual std::vector<std::string> stream_ids() const;
+  virtual std::vector<rtc::scoped_refptr<MediaStreamInterface>> streams() const;
+
+  // Audio or video receiver?
+  virtual cricket::MediaType media_type() const = 0;
+
+  // Not to be confused with "mid", this is a field we can temporarily use
+  // to uniquely identify a receiver until we implement Unified Plan SDP.
+  virtual std::string id() const = 0;
+
+  // The WebRTC specification only defines RTCRtpParameters in terms of senders,
+  // but this API also applies them to receivers, similar to ORTC:
+  // http://ortc.org/wp-content/uploads/2016/03/ortc.html#rtcrtpparameters*.
+  virtual RtpParameters GetParameters() const = 0;
+  // Currently, doesn't support changing any parameters, but may in the future.
+  virtual bool SetParameters(const RtpParameters& parameters) = 0;
+
+  // Does not take ownership of observer.
+  // Must call SetObserver(nullptr) before the observer is destroyed.
+  virtual void SetObserver(RtpReceiverObserverInterface* observer) = 0;
+
+  // TODO(zhihuang): Remove the default implementation once the subclasses
+  // implement this. Currently, the only relevant subclass is the
+  // 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;
+};
+
+// Define proxy for RtpReceiverInterface.
+// TODO(deadbeef): Move this to .cc file and out of api/. What threads methods
+// are called on is an implementation detail.
+BEGIN_SIGNALING_PROXY_MAP(RtpReceiver)
+PROXY_SIGNALING_THREAD_DESTRUCTOR()
+PROXY_CONSTMETHOD0(rtc::scoped_refptr<MediaStreamTrackInterface>, track)
+PROXY_CONSTMETHOD0(rtc::scoped_refptr<DtlsTransportInterface>, dtls_transport)
+PROXY_CONSTMETHOD0(std::vector<std::string>, stream_ids)
+PROXY_CONSTMETHOD0(std::vector<rtc::scoped_refptr<MediaStreamInterface>>,
+                   streams)
+PROXY_CONSTMETHOD0(cricket::MediaType, media_type)
+PROXY_CONSTMETHOD0(std::string, id)
+PROXY_CONSTMETHOD0(RtpParameters, GetParameters)
+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
+
+#endif  // API_RTP_RECEIVER_INTERFACE_H_
diff --git a/api/rtp_sender_interface.cc b/api/rtp_sender_interface.cc
new file mode 100644
index 0000000..d23fd18
--- /dev/null
+++ b/api/rtp_sender_interface.cc
@@ -0,0 +1,33 @@
+/*
+ *  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/rtp_sender_interface.h"
+
+namespace webrtc {
+
+void RtpSenderInterface::SetFrameEncryptor(
+    rtc::scoped_refptr<FrameEncryptorInterface> frame_encryptor) {}
+
+rtc::scoped_refptr<FrameEncryptorInterface>
+RtpSenderInterface::GetFrameEncryptor() const {
+  return nullptr;
+}
+
+std::vector<RtpEncodingParameters> RtpSenderInterface::init_send_encodings()
+    const {
+  return {};
+}
+
+rtc::scoped_refptr<DtlsTransportInterface> RtpSenderInterface::dtls_transport()
+    const {
+  return nullptr;
+}
+
+}  // namespace webrtc
diff --git a/api/rtp_sender_interface.h b/api/rtp_sender_interface.h
new file mode 100644
index 0000000..e0a29a3
--- /dev/null
+++ b/api/rtp_sender_interface.h
@@ -0,0 +1,119 @@
+/*
+ *  Copyright 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.
+ */
+
+// This file contains interfaces for RtpSenders
+// http://w3c.github.io/webrtc-pc/#rtcrtpsender-interface
+
+#ifndef API_RTP_SENDER_INTERFACE_H_
+#define API_RTP_SENDER_INTERFACE_H_
+
+#include <string>
+#include <vector>
+
+#include "api/crypto/frame_encryptor_interface.h"
+#include "api/dtls_transport_interface.h"
+#include "api/dtmf_sender_interface.h"
+#include "api/media_stream_interface.h"
+#include "api/media_types.h"
+#include "api/proxy.h"
+#include "api/rtc_error.h"
+#include "api/rtp_parameters.h"
+#include "api/scoped_refptr.h"
+#include "rtc_base/ref_count.h"
+
+namespace webrtc {
+
+class RtpSenderInterface : public rtc::RefCountInterface {
+ public:
+  // Returns true if successful in setting the track.
+  // Fails if an audio track is set on a video RtpSender, or vice-versa.
+  virtual bool SetTrack(MediaStreamTrackInterface* track) = 0;
+  virtual rtc::scoped_refptr<MediaStreamTrackInterface> track() const = 0;
+
+  // The dtlsTransport attribute exposes the DTLS transport on which the
+  // media is sent. It may be null.
+  // https://w3c.github.io/webrtc-pc/#dom-rtcrtpsender-transport
+  // TODO(https://bugs.webrtc.org/907849) remove default implementation
+  virtual rtc::scoped_refptr<DtlsTransportInterface> dtls_transport() const;
+
+  // Returns primary SSRC used by this sender for sending media.
+  // Returns 0 if not yet determined.
+  // TODO(deadbeef): Change to absl::optional.
+  // TODO(deadbeef): Remove? With GetParameters this should be redundant.
+  virtual uint32_t ssrc() const = 0;
+
+  // Audio or video sender?
+  virtual cricket::MediaType media_type() const = 0;
+
+  // Not to be confused with "mid", this is a field we can temporarily use
+  // to uniquely identify a receiver until we implement Unified Plan SDP.
+  virtual std::string id() const = 0;
+
+  // Returns a list of media stream ids associated with this sender's track.
+  // These are signalled in the SDP so that the remote side can associate
+  // tracks.
+  virtual std::vector<std::string> stream_ids() const = 0;
+
+  // Returns the list of encoding parameters that will be applied when the SDP
+  // local description is set. These initial encoding parameters can be set by
+  // PeerConnection::AddTransceiver, and later updated with Get/SetParameters.
+  // TODO(orphis): Make it pure virtual once Chrome has updated
+  virtual std::vector<RtpEncodingParameters> init_send_encodings() const;
+
+  virtual RtpParameters GetParameters() const = 0;
+  // Note that only a subset of the parameters can currently be changed. See
+  // rtpparameters.h
+  // The encodings are in increasing quality order for simulcast.
+  virtual RTCError SetParameters(const RtpParameters& parameters) = 0;
+
+  // 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:
+  ~RtpSenderInterface() override = default;
+};
+
+// Define proxy for RtpSenderInterface.
+// TODO(deadbeef): Move this to .cc file and out of api/. What threads methods
+// are called on is an implementation detail.
+BEGIN_SIGNALING_PROXY_MAP(RtpSender)
+PROXY_SIGNALING_THREAD_DESTRUCTOR()
+PROXY_METHOD1(bool, SetTrack, MediaStreamTrackInterface*)
+PROXY_CONSTMETHOD0(rtc::scoped_refptr<MediaStreamTrackInterface>, track)
+PROXY_CONSTMETHOD0(rtc::scoped_refptr<DtlsTransportInterface>, dtls_transport)
+PROXY_CONSTMETHOD0(uint32_t, ssrc)
+PROXY_CONSTMETHOD0(cricket::MediaType, media_type)
+PROXY_CONSTMETHOD0(std::string, id)
+PROXY_CONSTMETHOD0(std::vector<std::string>, stream_ids)
+PROXY_CONSTMETHOD0(std::vector<RtpEncodingParameters>, init_send_encodings)
+PROXY_CONSTMETHOD0(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
+
+#endif  // API_RTP_SENDER_INTERFACE_H_
diff --git a/api/rtp_transceiver_interface.cc b/api/rtp_transceiver_interface.cc
new file mode 100644
index 0000000..0504331
--- /dev/null
+++ b/api/rtp_transceiver_interface.cc
@@ -0,0 +1,33 @@
+/*
+ *  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/rtp_transceiver_interface.h"
+
+#include "rtc_base/checks.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;
+}
+
+void RtpTransceiverInterface::SetCodecPreferences(
+    rtc::ArrayView<RtpCodecCapability>) {
+  RTC_NOTREACHED() << "Not implemented";
+}
+
+}  // namespace webrtc
diff --git a/api/rtp_transceiver_interface.h b/api/rtp_transceiver_interface.h
new file mode 100644
index 0000000..aec0d15
--- /dev/null
+++ b/api/rtp_transceiver_interface.h
@@ -0,0 +1,140 @@
+/*
+ *  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.
+ */
+
+#ifndef API_RTP_TRANSCEIVER_INTERFACE_H_
+#define API_RTP_TRANSCEIVER_INTERFACE_H_
+
+#include <string>
+#include <vector>
+
+#include "absl/types/optional.h"
+#include "api/array_view.h"
+#include "api/media_types.h"
+#include "api/rtp_parameters.h"
+#include "api/rtp_receiver_interface.h"
+#include "api/rtp_sender_interface.h"
+#include "api/scoped_refptr.h"
+#include "rtc_base/ref_count.h"
+
+namespace webrtc {
+
+// https://w3c.github.io/webrtc-pc/#dom-rtcrtptransceiverdirection
+enum class RtpTransceiverDirection {
+  kSendRecv,
+  kSendOnly,
+  kRecvOnly,
+  kInactive
+};
+
+// Structure for initializing an RtpTransceiver in a call to
+// 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;
+
+  // The added RtpTransceiver will be added to these streams.
+  std::vector<std::string> stream_ids;
+
+  // TODO(bugs.webrtc.org/7600): Not implemented.
+  std::vector<RtpEncodingParameters> send_encodings;
+};
+
+// The RtpTransceiverInterface maps to the RTCRtpTransceiver defined by the
+// WebRTC specification. A transceiver represents a combination of an RtpSender
+// and an RtpReceiver than share a common mid. As defined in JSEP, an
+// RtpTransceiver is said to be associated with a media description if its mid
+// property is non-null; otherwise, it is said to be disassociated.
+// JSEP: https://tools.ietf.org/html/draft-ietf-rtcweb-jsep-24
+//
+// Note that RtpTransceivers are only supported when using PeerConnection with
+// Unified Plan SDP.
+//
+// This class is thread-safe.
+//
+// WebRTC specification for RTCRtpTransceiver, the JavaScript analog:
+// https://w3c.github.io/webrtc-pc/#dom-rtcrtptransceiver
+class RtpTransceiverInterface : public rtc::RefCountInterface {
+ public:
+  // Media type of the transceiver. Any sender(s)/receiver(s) will have this
+  // type as well.
+  virtual cricket::MediaType media_type() const = 0;
+
+  // The mid attribute is the mid negotiated and present in the local and
+  // remote descriptions. Before negotiation is complete, the mid value may be
+  // null. After rollbacks, the value may change from a non-null value to null.
+  // https://w3c.github.io/webrtc-pc/#dom-rtcrtptransceiver-mid
+  virtual absl::optional<std::string> mid() const = 0;
+
+  // The sender attribute exposes the RtpSender corresponding to the RTP media
+  // that may be sent with the transceiver's mid. The sender is always present,
+  // regardless of the direction of media.
+  // https://w3c.github.io/webrtc-pc/#dom-rtcrtptransceiver-sender
+  virtual rtc::scoped_refptr<RtpSenderInterface> sender() const = 0;
+
+  // The receiver attribute exposes the RtpReceiver corresponding to the RTP
+  // media that may be received with the transceiver's mid. The receiver is
+  // always present, regardless of the direction of media.
+  // https://w3c.github.io/webrtc-pc/#dom-rtcrtptransceiver-receiver
+  virtual rtc::scoped_refptr<RtpReceiverInterface> receiver() const = 0;
+
+  // The stopped attribute indicates that the sender of this transceiver will no
+  // longer send, and that the receiver will no longer receive. It is true if
+  // either stop has been called or if setting the local or remote description
+  // has caused the RtpTransceiver to be stopped.
+  // https://w3c.github.io/webrtc-pc/#dom-rtcrtptransceiver-stopped
+  virtual bool stopped() const = 0;
+
+  // The direction attribute indicates the preferred direction of this
+  // transceiver, which will be used in calls to CreateOffer and CreateAnswer.
+  // https://w3c.github.io/webrtc-pc/#dom-rtcrtptransceiver-direction
+  virtual RtpTransceiverDirection direction() const = 0;
+
+  // Sets the preferred direction of this transceiver. An update of
+  // directionality does not take effect immediately. Instead, future calls to
+  // CreateOffer and CreateAnswer mark the corresponding media descriptions as
+  // sendrecv, sendonly, recvonly, or inactive.
+  // https://w3c.github.io/webrtc-pc/#dom-rtcrtptransceiver-direction
+  virtual void SetDirection(RtpTransceiverDirection new_direction) = 0;
+
+  // The current_direction attribute indicates the current direction negotiated
+  // for this transceiver. If this transceiver has never been represented in an
+  // offer/answer exchange, or if the transceiver is stopped, the value is null.
+  // https://w3c.github.io/webrtc-pc/#dom-rtcrtptransceiver-currentdirection
+  virtual absl::optional<RtpTransceiverDirection> current_direction() const = 0;
+
+  // An internal slot designating for which direction the relevant
+  // PeerConnection events have been fired. This is to ensure that events like
+  // 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;
+
+  // The Stop method irreversibly stops the RtpTransceiver. The sender of this
+  // transceiver will no longer send, the receiver will no longer receive.
+  // https://w3c.github.io/webrtc-pc/#dom-rtcrtptransceiver-stop
+  virtual void Stop() = 0;
+
+  // The SetCodecPreferences method overrides the default codec preferences used
+  // by WebRTC for this transceiver.
+  // https://w3c.github.io/webrtc-pc/#dom-rtcrtptransceiver-setcodecpreferences
+  // TODO(steveanton): Not implemented.
+  virtual void SetCodecPreferences(rtc::ArrayView<RtpCodecCapability> codecs);
+
+ protected:
+  ~RtpTransceiverInterface() override = default;
+};
+
+}  // namespace webrtc
+
+#endif  // API_RTP_TRANSCEIVER_INTERFACE_H_
diff --git a/api/scoped_refptr.h b/api/scoped_refptr.h
index 0993e03..67d179f 100644
--- a/api/scoped_refptr.h
+++ b/api/scoped_refptr.h
@@ -71,6 +71,8 @@
 template <class T>
 class scoped_refptr {
  public:
+  typedef T element_type;
+
   scoped_refptr() : ptr_(nullptr) {}
 
   scoped_refptr(T* p) : ptr_(p) {  // NOLINT(runtime/explicit)
diff --git a/api/sctp_transport_interface.cc b/api/sctp_transport_interface.cc
new file mode 100644
index 0000000..c6c1fbe
--- /dev/null
+++ b/api/sctp_transport_interface.cc
@@ -0,0 +1,32 @@
+/*
+ *  Copyright 2019 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include <utility>
+
+#include "api/sctp_transport_interface.h"
+
+namespace webrtc {
+
+SctpTransportInformation::SctpTransportInformation(SctpTransportState state)
+    : state_(state) {}
+
+SctpTransportInformation::SctpTransportInformation(
+    SctpTransportState state,
+    rtc::scoped_refptr<DtlsTransportInterface> dtls_transport,
+    absl::optional<double> max_message_size,
+    absl::optional<int> max_channels)
+    : state_(state),
+      dtls_transport_(std::move(dtls_transport)),
+      max_message_size_(max_message_size),
+      max_channels_(max_channels) {}
+
+SctpTransportInformation::~SctpTransportInformation() {}
+
+}  // namespace webrtc
diff --git a/api/sctp_transport_interface.h b/api/sctp_transport_interface.h
new file mode 100644
index 0000000..3698fc2
--- /dev/null
+++ b/api/sctp_transport_interface.h
@@ -0,0 +1,90 @@
+/*
+ *  Copyright 2019 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef API_SCTP_TRANSPORT_INTERFACE_H_
+#define API_SCTP_TRANSPORT_INTERFACE_H_
+
+#include "absl/types/optional.h"
+#include "api/dtls_transport_interface.h"
+#include "api/rtc_error.h"
+#include "api/scoped_refptr.h"
+#include "rtc_base/ref_count.h"
+
+namespace webrtc {
+
+// States of a SCTP transport, corresponding to the JS API specification.
+// http://w3c.github.io/webrtc-pc/#dom-rtcsctptransportstate
+enum class SctpTransportState {
+  kNew,         // Has not started negotiating yet. Non-standard state.
+  kConnecting,  // In the process of negotiating an association.
+  kConnected,   // Completed negotiation of an association.
+  kClosed,      // Closed by local or remote party.
+  kNumValues
+};
+
+// This object gives snapshot information about the changeable state of a
+// SctpTransport.
+// It reflects the readonly attributes of the object in the specification.
+// http://w3c.github.io/webrtc-pc/#rtcsctptransport-interface
+class SctpTransportInformation {
+ public:
+  explicit SctpTransportInformation(SctpTransportState state);
+  SctpTransportInformation(
+      SctpTransportState state,
+      rtc::scoped_refptr<DtlsTransportInterface> dtls_transport,
+      absl::optional<double> max_message_size,
+      absl::optional<int> max_channels);
+  ~SctpTransportInformation();
+  // The DTLS transport that supports this SCTP transport.
+  rtc::scoped_refptr<DtlsTransportInterface> dtls_transport() const {
+    return dtls_transport_;
+  }
+  SctpTransportState state() const { return state_; }
+  absl::optional<double> MaxMessageSize() const { return max_message_size_; }
+  absl::optional<int> MaxChannels() const { return max_channels_; }
+
+ private:
+  SctpTransportState state_;
+  rtc::scoped_refptr<DtlsTransportInterface> dtls_transport_;
+  absl::optional<double> max_message_size_;
+  absl::optional<int> max_channels_;
+};
+
+class SctpTransportObserverInterface {
+ public:
+  // This callback carries information about the state of the transport.
+  // The argument is a pass-by-value snapshot of the state.
+  // The callback will be called on the network thread.
+  virtual void OnStateChange(SctpTransportInformation info) = 0;
+
+ protected:
+  virtual ~SctpTransportObserverInterface() = default;
+};
+
+// A SCTP transport, as represented to the outside world.
+// This object is created on the network thread, and can only be
+// accessed on that thread, except for functions explicitly marked otherwise.
+// References can be held by other threads, and destruction can therefore
+// be initiated by other threads.
+class SctpTransportInterface : public rtc::RefCountInterface {
+ public:
+  // This function can be called from other threads.
+  virtual rtc::scoped_refptr<DtlsTransportInterface> dtls_transport() const = 0;
+  // Returns information on the state of the SctpTransport.
+  // This function can be called from other threads.
+  virtual SctpTransportInformation Information() const = 0;
+  // Observer management.
+  virtual void RegisterObserver(SctpTransportObserverInterface* observer) = 0;
+  virtual void UnregisterObserver() = 0;
+};
+
+}  // namespace webrtc
+
+#endif  // API_SCTP_TRANSPORT_INTERFACE_H_
diff --git a/api/set_remote_description_observer_interface.h b/api/set_remote_description_observer_interface.h
new file mode 100644
index 0000000..1782555
--- /dev/null
+++ b/api/set_remote_description_observer_interface.h
@@ -0,0 +1,31 @@
+/*
+ *  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.
+ */
+
+#ifndef API_SET_REMOTE_DESCRIPTION_OBSERVER_INTERFACE_H_
+#define API_SET_REMOTE_DESCRIPTION_OBSERVER_INTERFACE_H_
+
+#include "api/rtc_error.h"
+#include "rtc_base/ref_count.h"
+
+namespace webrtc {
+
+// An observer for PeerConnectionInterface::SetRemoteDescription(). The
+// callback is invoked such that the state of the peer connection can be
+// examined to accurately reflect the effects of the SetRemoteDescription
+// operation.
+class SetRemoteDescriptionObserverInterface : public rtc::RefCountInterface {
+ public:
+  // On success, |error.ok()| is true.
+  virtual void OnSetRemoteDescriptionComplete(RTCError error) = 0;
+};
+
+}  // namespace webrtc
+
+#endif  // API_SET_REMOTE_DESCRIPTION_OBSERVER_INTERFACE_H_
diff --git a/api/stats_types.cc b/api/stats_types.cc
new file mode 100644
index 0000000..71b1f86
--- /dev/null
+++ b/api/stats_types.cc
@@ -0,0 +1,842 @@
+/*
+ *  Copyright 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 "api/stats_types.h"
+
+#include <string.h>
+
+#include "rtc_base/checks.h"
+#include "rtc_base/ref_counted_object.h"
+
+// TODO(tommi): Could we have a static map of value name -> expected type
+// and use this to RTC_DCHECK on correct usage (somewhat strongly typed values)?
+// Alternatively, we could define the names+type in a separate document and
+// generate strongly typed inline C++ code that forces the correct type to be
+// used for a given name at compile time.
+
+using rtc::RefCountedObject;
+
+namespace webrtc {
+namespace {
+
+// The id of StatsReport of type kStatsReportTypeBwe.
+const char kStatsReportVideoBweId[] = "bweforvideo";
+
+// NOTE: These names need to be consistent with an external
+// specification (W3C Stats Identifiers).
+const char* InternalTypeToString(StatsReport::StatsType type) {
+  switch (type) {
+    case StatsReport::kStatsReportTypeSession:
+      return "googLibjingleSession";
+    case StatsReport::kStatsReportTypeBwe:
+      return "VideoBwe";
+    case StatsReport::kStatsReportTypeRemoteSsrc:
+      return "remoteSsrc";
+    case StatsReport::kStatsReportTypeSsrc:
+      return "ssrc";
+    case StatsReport::kStatsReportTypeTrack:
+      return "googTrack";
+    case StatsReport::kStatsReportTypeIceLocalCandidate:
+      return "localcandidate";
+    case StatsReport::kStatsReportTypeIceRemoteCandidate:
+      return "remotecandidate";
+    case StatsReport::kStatsReportTypeTransport:
+      return "transport";
+    case StatsReport::kStatsReportTypeComponent:
+      return "googComponent";
+    case StatsReport::kStatsReportTypeCandidatePair:
+      return "googCandidatePair";
+    case StatsReport::kStatsReportTypeCertificate:
+      return "googCertificate";
+    case StatsReport::kStatsReportTypeDataChannel:
+      return "datachannel";
+  }
+  RTC_NOTREACHED();
+  return nullptr;
+}
+
+class BandwidthEstimationId : public StatsReport::IdBase {
+ public:
+  BandwidthEstimationId()
+      : StatsReport::IdBase(StatsReport::kStatsReportTypeBwe) {}
+  std::string ToString() const override { return kStatsReportVideoBweId; }
+};
+
+class TypedId : public StatsReport::IdBase {
+ public:
+  TypedId(StatsReport::StatsType type, const std::string& id)
+      : StatsReport::IdBase(type), id_(id) {}
+
+  bool Equals(const IdBase& other) const override {
+    return IdBase::Equals(other) &&
+           static_cast<const TypedId&>(other).id_ == id_;
+  }
+
+  std::string ToString() const override {
+    return std::string(InternalTypeToString(type_)) + kSeparator + id_;
+  }
+
+ protected:
+  const std::string id_;
+};
+
+class TypedIntId : public StatsReport::IdBase {
+ public:
+  TypedIntId(StatsReport::StatsType type, int id)
+      : StatsReport::IdBase(type), id_(id) {}
+
+  bool Equals(const IdBase& other) const override {
+    return IdBase::Equals(other) &&
+           static_cast<const TypedIntId&>(other).id_ == id_;
+  }
+
+  std::string ToString() const override {
+    return std::string(InternalTypeToString(type_)) + kSeparator +
+           rtc::ToString(id_);
+  }
+
+ protected:
+  const int id_;
+};
+
+class IdWithDirection : public TypedId {
+ public:
+  IdWithDirection(StatsReport::StatsType type,
+                  const std::string& id,
+                  StatsReport::Direction direction)
+      : TypedId(type, id), direction_(direction) {}
+
+  bool Equals(const IdBase& other) const override {
+    return TypedId::Equals(other) &&
+           static_cast<const IdWithDirection&>(other).direction_ == direction_;
+  }
+
+  std::string ToString() const override {
+    std::string ret(TypedId::ToString());
+    ret += kSeparator;
+    ret += direction_ == StatsReport::kSend ? "send" : "recv";
+    return ret;
+  }
+
+ private:
+  const StatsReport::Direction direction_;
+};
+
+class CandidateId : public TypedId {
+ public:
+  CandidateId(bool local, const std::string& id)
+      : TypedId(local ? StatsReport::kStatsReportTypeIceLocalCandidate
+                      : StatsReport::kStatsReportTypeIceRemoteCandidate,
+                id) {}
+
+  std::string ToString() const override { return "Cand-" + id_; }
+};
+
+class ComponentId : public StatsReport::IdBase {
+ public:
+  ComponentId(const std::string& content_name, int component)
+      : ComponentId(StatsReport::kStatsReportTypeComponent,
+                    content_name,
+                    component) {}
+
+  bool Equals(const IdBase& other) const override {
+    return IdBase::Equals(other) &&
+           static_cast<const ComponentId&>(other).component_ == component_ &&
+           static_cast<const ComponentId&>(other).content_name_ ==
+               content_name_;
+  }
+
+  std::string ToString() const override { return ToString("Channel-"); }
+
+ protected:
+  ComponentId(StatsReport::StatsType type,
+              const std::string& content_name,
+              int component)
+      : IdBase(type), content_name_(content_name), component_(component) {}
+
+  std::string ToString(const char* prefix) const {
+    std::string ret(prefix);
+    ret += content_name_;
+    ret += '-';
+    ret += rtc::ToString(component_);
+    return ret;
+  }
+
+ private:
+  const std::string content_name_;
+  const int component_;
+};
+
+class CandidatePairId : public ComponentId {
+ public:
+  CandidatePairId(const std::string& content_name, int component, int index)
+      : ComponentId(StatsReport::kStatsReportTypeCandidatePair,
+                    content_name,
+                    component),
+        index_(index) {}
+
+  bool Equals(const IdBase& other) const override {
+    return ComponentId::Equals(other) &&
+           static_cast<const CandidatePairId&>(other).index_ == index_;
+  }
+
+  std::string ToString() const override {
+    std::string ret(ComponentId::ToString("Conn-"));
+    ret += '-';
+    ret += rtc::ToString(index_);
+    return ret;
+  }
+
+ private:
+  const int index_;
+};
+
+}  // namespace
+
+StatsReport::IdBase::IdBase(StatsType type) : type_(type) {}
+StatsReport::IdBase::~IdBase() {}
+
+StatsReport::StatsType StatsReport::IdBase::type() const {
+  return type_;
+}
+
+bool StatsReport::IdBase::Equals(const IdBase& other) const {
+  return other.type_ == type_;
+}
+
+StatsReport::Value::Value(StatsValueName name, int64_t value, Type int_type)
+    : name(name), type_(int_type) {
+  RTC_DCHECK(type_ == kInt || type_ == kInt64);
+  type_ == kInt ? value_.int_ = static_cast<int>(value) : value_.int64_ = value;
+}
+
+StatsReport::Value::Value(StatsValueName name, float f)
+    : name(name), type_(kFloat) {
+  value_.float_ = f;
+}
+
+StatsReport::Value::Value(StatsValueName name, const std::string& value)
+    : name(name), type_(kString) {
+  value_.string_ = new std::string(value);
+}
+
+StatsReport::Value::Value(StatsValueName name, const char* value)
+    : name(name), type_(kStaticString) {
+  value_.static_string_ = value;
+}
+
+StatsReport::Value::Value(StatsValueName name, bool b)
+    : name(name), type_(kBool) {
+  value_.bool_ = b;
+}
+
+StatsReport::Value::Value(StatsValueName name, const Id& value)
+    : name(name), type_(kId) {
+  value_.id_ = new Id(value);
+}
+
+StatsReport::Value::~Value() {
+  switch (type_) {
+    case kInt:
+    case kInt64:
+    case kFloat:
+    case kBool:
+    case kStaticString:
+      break;
+    case kString:
+      delete value_.string_;
+      break;
+    case kId:
+      delete value_.id_;
+      break;
+  }
+}
+
+bool StatsReport::Value::Equals(const Value& other) const {
+  if (name != other.name)
+    return false;
+
+  // There's a 1:1 relation between a name and a type, so we don't have to
+  // check that.
+  RTC_DCHECK_EQ(type_, other.type_);
+
+  switch (type_) {
+    case kInt:
+      return value_.int_ == other.value_.int_;
+    case kInt64:
+      return value_.int64_ == other.value_.int64_;
+    case kFloat:
+      return value_.float_ == other.value_.float_;
+    case kStaticString: {
+#if RTC_DCHECK_IS_ON
+      if (value_.static_string_ != other.value_.static_string_) {
+        RTC_DCHECK(strcmp(value_.static_string_, other.value_.static_string_) !=
+                   0)
+            << "Duplicate global?";
+      }
+#endif
+      return value_.static_string_ == other.value_.static_string_;
+    }
+    case kString:
+      return *value_.string_ == *other.value_.string_;
+    case kBool:
+      return value_.bool_ == other.value_.bool_;
+    case kId:
+      return (*value_.id_)->Equals(*other.value_.id_);
+  }
+  RTC_NOTREACHED();
+  return false;
+}
+
+bool StatsReport::Value::operator==(const std::string& value) const {
+  return (type_ == kString && value_.string_->compare(value) == 0) ||
+         (type_ == kStaticString && value.compare(value_.static_string_) == 0);
+}
+
+bool StatsReport::Value::operator==(const char* value) const {
+  if (type_ == kString)
+    return value_.string_->compare(value) == 0;
+  if (type_ != kStaticString)
+    return false;
+#if RTC_DCHECK_IS_ON
+  if (value_.static_string_ != value)
+    RTC_DCHECK(strcmp(value_.static_string_, value) != 0)
+        << "Duplicate global?";
+#endif
+  return value == value_.static_string_;
+}
+
+bool StatsReport::Value::operator==(int64_t value) const {
+  return type_ == kInt ? value_.int_ == static_cast<int>(value)
+                       : (type_ == kInt64 ? value_.int64_ == value : false);
+}
+
+bool StatsReport::Value::operator==(bool value) const {
+  return type_ == kBool && value_.bool_ == value;
+}
+
+bool StatsReport::Value::operator==(float value) const {
+  return type_ == kFloat && value_.float_ == value;
+}
+
+bool StatsReport::Value::operator==(const Id& value) const {
+  return type_ == kId && (*value_.id_)->Equals(value);
+}
+
+int StatsReport::Value::int_val() const {
+  RTC_DCHECK(type_ == kInt);
+  return value_.int_;
+}
+
+int64_t StatsReport::Value::int64_val() const {
+  RTC_DCHECK(type_ == kInt64);
+  return value_.int64_;
+}
+
+float StatsReport::Value::float_val() const {
+  RTC_DCHECK(type_ == kFloat);
+  return value_.float_;
+}
+
+const char* StatsReport::Value::static_string_val() const {
+  RTC_DCHECK(type_ == kStaticString);
+  return value_.static_string_;
+}
+
+const std::string& StatsReport::Value::string_val() const {
+  RTC_DCHECK(type_ == kString);
+  return *value_.string_;
+}
+
+bool StatsReport::Value::bool_val() const {
+  RTC_DCHECK(type_ == kBool);
+  return value_.bool_;
+}
+
+const char* StatsReport::Value::display_name() const {
+  switch (name) {
+    case kStatsValueNameAecDivergentFilterFraction:
+      return "aecDivergentFilterFraction";
+    case kStatsValueNameAudioOutputLevel:
+      return "audioOutputLevel";
+    case kStatsValueNameAudioInputLevel:
+      return "audioInputLevel";
+    case kStatsValueNameBytesSent:
+      return "bytesSent";
+    case kStatsValueNameConcealedSamples:
+      return "concealedSamples";
+    case kStatsValueNameConcealmentEvents:
+      return "concealmentEvents";
+    case kStatsValueNamePacketsSent:
+      return "packetsSent";
+    case kStatsValueNameBytesReceived:
+      return "bytesReceived";
+    case kStatsValueNameLabel:
+      return "label";
+    case kStatsValueNamePacketsReceived:
+      return "packetsReceived";
+    case kStatsValueNamePacketsLost:
+      return "packetsLost";
+    case kStatsValueNameProtocol:
+      return "protocol";
+    case kStatsValueNameTotalSamplesReceived:
+      return "totalSamplesReceived";
+    case kStatsValueNameTransportId:
+      return "transportId";
+    case kStatsValueNameSelectedCandidatePairId:
+      return "selectedCandidatePairId";
+    case kStatsValueNameSsrc:
+      return "ssrc";
+    case kStatsValueNameState:
+      return "state";
+    case kStatsValueNameDataChannelId:
+      return "datachannelid";
+    case kStatsValueNameFramesDecoded:
+      return "framesDecoded";
+    case kStatsValueNameFramesEncoded:
+      return "framesEncoded";
+    case kStatsValueNameJitterBufferDelay:
+      return "jitterBufferDelay";
+    case kStatsValueNameCodecImplementationName:
+      return "codecImplementationName";
+    case kStatsValueNameMediaType:
+      return "mediaType";
+    case kStatsValueNameQpSum:
+      return "qpSum";
+    // 'goog' prefixed constants.
+    case kStatsValueNameAccelerateRate:
+      return "googAccelerateRate";
+    case kStatsValueNameActiveConnection:
+      return "googActiveConnection";
+    case kStatsValueNameActualEncBitrate:
+      return "googActualEncBitrate";
+    case kStatsValueNameAvailableReceiveBandwidth:
+      return "googAvailableReceiveBandwidth";
+    case kStatsValueNameAvailableSendBandwidth:
+      return "googAvailableSendBandwidth";
+    case kStatsValueNameAvgEncodeMs:
+      return "googAvgEncodeMs";
+    case kStatsValueNameBucketDelay:
+      return "googBucketDelay";
+    case kStatsValueNameBandwidthLimitedResolution:
+      return "googBandwidthLimitedResolution";
+    // STUN ping related attributes.
+    //
+    // TODO(zhihuang) Rename these stats to follow the standards.
+    // Connectivity checks.
+    case kStatsValueNameSentPingRequestsTotal:
+      return "requestsSent";
+    case kStatsValueNameSentPingRequestsBeforeFirstResponse:
+      return "consentRequestsSent";
+    case kStatsValueNameSentPingResponses:
+      return "responsesSent";
+    case kStatsValueNameRecvPingRequests:
+      return "requestsReceived";
+    case kStatsValueNameRecvPingResponses:
+      return "responsesReceived";
+    // STUN Keepalive pings.
+    case kStatsValueNameSentStunKeepaliveRequests:
+      return "stunKeepaliveRequestsSent";
+    case kStatsValueNameRecvStunKeepaliveResponses:
+      return "stunKeepaliveResponsesReceived";
+    case kStatsValueNameStunKeepaliveRttTotal:
+      return "stunKeepaliveRttTotal";
+    case kStatsValueNameStunKeepaliveRttSquaredTotal:
+      return "stunKeepaliveRttSquaredTotal";
+
+    // Candidate related attributes. Values are taken from
+    // http://w3c.github.io/webrtc-stats/#rtcstatstype-enum*.
+    case kStatsValueNameCandidateIPAddress:
+      return "ipAddress";
+    case kStatsValueNameCandidateNetworkType:
+      return "networkType";
+    case kStatsValueNameCandidatePortNumber:
+      return "portNumber";
+    case kStatsValueNameCandidatePriority:
+      return "priority";
+    case kStatsValueNameCandidateTransportType:
+      return "transport";
+    case kStatsValueNameCandidateType:
+      return "candidateType";
+
+    case kStatsValueNameChannelId:
+      return "googChannelId";
+    case kStatsValueNameCodecName:
+      return "googCodecName";
+    case kStatsValueNameComponent:
+      return "googComponent";
+    case kStatsValueNameContentName:
+      return "googContentName";
+    case kStatsValueNameContentType:
+      return "googContentType";
+    case kStatsValueNameCpuLimitedResolution:
+      return "googCpuLimitedResolution";
+    case kStatsValueNameDecodingCTSG:
+      return "googDecodingCTSG";
+    case kStatsValueNameDecodingCTN:
+      return "googDecodingCTN";
+    case kStatsValueNameDecodingMutedOutput:
+      return "googDecodingMuted";
+    case kStatsValueNameDecodingNormal:
+      return "googDecodingNormal";
+    case kStatsValueNameDecodingPLC:
+      return "googDecodingPLC";
+    case kStatsValueNameDecodingCNG:
+      return "googDecodingCNG";
+    case kStatsValueNameDecodingPLCCNG:
+      return "googDecodingPLCCNG";
+    case kStatsValueNameDer:
+      return "googDerBase64";
+    case kStatsValueNameDtlsCipher:
+      return "dtlsCipher";
+    case kStatsValueNameEchoDelayMedian:
+      return "googEchoCancellationEchoDelayMedian";
+    case kStatsValueNameEchoDelayStdDev:
+      return "googEchoCancellationEchoDelayStdDev";
+    case kStatsValueNameEchoReturnLoss:
+      return "googEchoCancellationReturnLoss";
+    case kStatsValueNameEchoReturnLossEnhancement:
+      return "googEchoCancellationReturnLossEnhancement";
+    case kStatsValueNameEncodeUsagePercent:
+      return "googEncodeUsagePercent";
+    case kStatsValueNameExpandRate:
+      return "googExpandRate";
+    case kStatsValueNameFingerprint:
+      return "googFingerprint";
+    case kStatsValueNameFingerprintAlgorithm:
+      return "googFingerprintAlgorithm";
+    case kStatsValueNameFirsReceived:
+      return "googFirsReceived";
+    case kStatsValueNameFirsSent:
+      return "googFirsSent";
+    case kStatsValueNameFirstFrameReceivedToDecodedMs:
+      return "googFirstFrameReceivedToDecodedMs";
+    case kStatsValueNameFrameHeightInput:
+      return "googFrameHeightInput";
+    case kStatsValueNameFrameHeightReceived:
+      return "googFrameHeightReceived";
+    case kStatsValueNameFrameHeightSent:
+      return "googFrameHeightSent";
+    case kStatsValueNameFrameRateReceived:
+      return "googFrameRateReceived";
+    case kStatsValueNameFrameRateDecoded:
+      return "googFrameRateDecoded";
+    case kStatsValueNameFrameRateOutput:
+      return "googFrameRateOutput";
+    case kStatsValueNameDecodeMs:
+      return "googDecodeMs";
+    case kStatsValueNameMaxDecodeMs:
+      return "googMaxDecodeMs";
+    case kStatsValueNameCurrentDelayMs:
+      return "googCurrentDelayMs";
+    case kStatsValueNameTargetDelayMs:
+      return "googTargetDelayMs";
+    case kStatsValueNameJitterBufferMs:
+      return "googJitterBufferMs";
+    case kStatsValueNameMinPlayoutDelayMs:
+      return "googMinPlayoutDelayMs";
+    case kStatsValueNameRenderDelayMs:
+      return "googRenderDelayMs";
+    case kStatsValueNameCaptureStartNtpTimeMs:
+      return "googCaptureStartNtpTimeMs";
+    case kStatsValueNameFrameRateInput:
+      return "googFrameRateInput";
+    case kStatsValueNameFrameRateSent:
+      return "googFrameRateSent";
+    case kStatsValueNameFrameWidthInput:
+      return "googFrameWidthInput";
+    case kStatsValueNameFrameWidthReceived:
+      return "googFrameWidthReceived";
+    case kStatsValueNameFrameWidthSent:
+      return "googFrameWidthSent";
+    case kStatsValueNameHasEnteredLowResolution:
+      return "googHasEnteredLowResolution";
+    case kStatsValueNameHugeFramesSent:
+      return "hugeFramesSent";
+    case kStatsValueNameInitiator:
+      return "googInitiator";
+    case kStatsValueNameInterframeDelayMaxMs:
+      return "googInterframeDelayMax";
+    case kStatsValueNameIssuerId:
+      return "googIssuerId";
+    case kStatsValueNameJitterReceived:
+      return "googJitterReceived";
+    case kStatsValueNameLocalAddress:
+      return "googLocalAddress";
+    case kStatsValueNameLocalCandidateId:
+      return "localCandidateId";
+    case kStatsValueNameLocalCandidateType:
+      return "googLocalCandidateType";
+    case kStatsValueNameLocalCertificateId:
+      return "localCertificateId";
+    case kStatsValueNameAdaptationChanges:
+      return "googAdaptationChanges";
+    case kStatsValueNameNacksReceived:
+      return "googNacksReceived";
+    case kStatsValueNameNacksSent:
+      return "googNacksSent";
+    case kStatsValueNamePreemptiveExpandRate:
+      return "googPreemptiveExpandRate";
+    case kStatsValueNamePlisReceived:
+      return "googPlisReceived";
+    case kStatsValueNamePlisSent:
+      return "googPlisSent";
+    case kStatsValueNamePreferredJitterBufferMs:
+      return "googPreferredJitterBufferMs";
+    case kStatsValueNameReceiving:
+      return "googReadable";
+    case kStatsValueNameRemoteAddress:
+      return "googRemoteAddress";
+    case kStatsValueNameRemoteCandidateId:
+      return "remoteCandidateId";
+    case kStatsValueNameRemoteCandidateType:
+      return "googRemoteCandidateType";
+    case kStatsValueNameRemoteCertificateId:
+      return "remoteCertificateId";
+    case kStatsValueNameResidualEchoLikelihood:
+      return "googResidualEchoLikelihood";
+    case kStatsValueNameResidualEchoLikelihoodRecentMax:
+      return "googResidualEchoLikelihoodRecentMax";
+    case kStatsValueNameAnaBitrateActionCounter:
+      return "googAnaBitrateActionCounter";
+    case kStatsValueNameAnaChannelActionCounter:
+      return "googAnaChannelActionCounter";
+    case kStatsValueNameAnaDtxActionCounter:
+      return "googAnaDtxActionCounter";
+    case kStatsValueNameAnaFecActionCounter:
+      return "googAnaFecActionCounter";
+    case kStatsValueNameAnaFrameLengthIncreaseCounter:
+      return "googAnaFrameLengthIncreaseCounter";
+    case kStatsValueNameAnaFrameLengthDecreaseCounter:
+      return "googAnaFrameLengthDecreaseCounter";
+    case kStatsValueNameAnaUplinkPacketLossFraction:
+      return "googAnaUplinkPacketLossFraction";
+    case kStatsValueNameRetransmitBitrate:
+      return "googRetransmitBitrate";
+    case kStatsValueNameRtt:
+      return "googRtt";
+    case kStatsValueNameSecondaryDecodedRate:
+      return "googSecondaryDecodedRate";
+    case kStatsValueNameSecondaryDiscardedRate:
+      return "googSecondaryDiscardedRate";
+    case kStatsValueNameSendPacketsDiscarded:
+      return "packetsDiscardedOnSend";
+    case kStatsValueNameSpeechExpandRate:
+      return "googSpeechExpandRate";
+    case kStatsValueNameSrtpCipher:
+      return "srtpCipher";
+    case kStatsValueNameTargetEncBitrate:
+      return "googTargetEncBitrate";
+    case kStatsValueNameTotalAudioEnergy:
+      return "totalAudioEnergy";
+    case kStatsValueNameTotalSamplesDuration:
+      return "totalSamplesDuration";
+    case kStatsValueNameTransmitBitrate:
+      return "googTransmitBitrate";
+    case kStatsValueNameTransportType:
+      return "googTransportType";
+    case kStatsValueNameTrackId:
+      return "googTrackId";
+    case kStatsValueNameTimingFrameInfo:
+      return "googTimingFrameInfo";
+    case kStatsValueNameTypingNoiseState:
+      return "googTypingNoiseState";
+    case kStatsValueNameWritable:
+      return "googWritable";
+  }
+
+  return nullptr;
+}
+
+std::string StatsReport::Value::ToString() const {
+  switch (type_) {
+    case kInt:
+      return rtc::ToString(value_.int_);
+    case kInt64:
+      return rtc::ToString(value_.int64_);
+    case kFloat:
+      return rtc::ToString(value_.float_);
+    case kStaticString:
+      return std::string(value_.static_string_);
+    case kString:
+      return *value_.string_;
+    case kBool:
+      return value_.bool_ ? "true" : "false";
+    case kId:
+      return (*value_.id_)->ToString();
+  }
+  RTC_NOTREACHED();
+  return std::string();
+}
+
+StatsReport::StatsReport(const Id& id) : id_(id), timestamp_(0.0) {
+  RTC_DCHECK(id_.get());
+}
+
+StatsReport::~StatsReport() = default;
+
+// static
+StatsReport::Id StatsReport::NewBandwidthEstimationId() {
+  return Id(new RefCountedObject<BandwidthEstimationId>());
+}
+
+// static
+StatsReport::Id StatsReport::NewTypedId(StatsType type, const std::string& id) {
+  return Id(new RefCountedObject<TypedId>(type, id));
+}
+
+// static
+StatsReport::Id StatsReport::NewTypedIntId(StatsType type, int id) {
+  return Id(new RefCountedObject<TypedIntId>(type, id));
+}
+
+// static
+StatsReport::Id StatsReport::NewIdWithDirection(
+    StatsType type,
+    const std::string& id,
+    StatsReport::Direction direction) {
+  return Id(new RefCountedObject<IdWithDirection>(type, id, direction));
+}
+
+// static
+StatsReport::Id StatsReport::NewCandidateId(bool local, const std::string& id) {
+  return Id(new RefCountedObject<CandidateId>(local, id));
+}
+
+// static
+StatsReport::Id StatsReport::NewComponentId(const std::string& content_name,
+                                            int component) {
+  return Id(new RefCountedObject<ComponentId>(content_name, component));
+}
+
+// static
+StatsReport::Id StatsReport::NewCandidatePairId(const std::string& content_name,
+                                                int component,
+                                                int index) {
+  return Id(
+      new RefCountedObject<CandidatePairId>(content_name, component, index));
+}
+
+const char* StatsReport::TypeToString() const {
+  return InternalTypeToString(id_->type());
+}
+
+void StatsReport::AddString(StatsReport::StatsValueName name,
+                            const std::string& value) {
+  const Value* found = FindValue(name);
+  if (!found || !(*found == value))
+    values_[name] = ValuePtr(new Value(name, value));
+}
+
+void StatsReport::AddString(StatsReport::StatsValueName name,
+                            const char* value) {
+  const Value* found = FindValue(name);
+  if (!found || !(*found == value))
+    values_[name] = ValuePtr(new Value(name, value));
+}
+
+void StatsReport::AddInt64(StatsReport::StatsValueName name, int64_t value) {
+  const Value* found = FindValue(name);
+  if (!found || !(*found == value))
+    values_[name] = ValuePtr(new Value(name, value, Value::kInt64));
+}
+
+void StatsReport::AddInt(StatsReport::StatsValueName name, int value) {
+  const Value* found = FindValue(name);
+  if (!found || !(*found == static_cast<int64_t>(value)))
+    values_[name] = ValuePtr(new Value(name, value, Value::kInt));
+}
+
+void StatsReport::AddFloat(StatsReport::StatsValueName name, float value) {
+  const Value* found = FindValue(name);
+  if (!found || !(*found == value))
+    values_[name] = ValuePtr(new Value(name, value));
+}
+
+void StatsReport::AddBoolean(StatsReport::StatsValueName name, bool value) {
+  const Value* found = FindValue(name);
+  if (!found || !(*found == value))
+    values_[name] = ValuePtr(new Value(name, value));
+}
+
+void StatsReport::AddId(StatsReport::StatsValueName name, const Id& value) {
+  const Value* found = FindValue(name);
+  if (!found || !(*found == value))
+    values_[name] = ValuePtr(new Value(name, value));
+}
+
+const StatsReport::Value* StatsReport::FindValue(StatsValueName name) const {
+  Values::const_iterator it = values_.find(name);
+  return it == values_.end() ? nullptr : it->second.get();
+}
+
+StatsCollection::StatsCollection() {}
+
+StatsCollection::~StatsCollection() {
+  RTC_DCHECK(thread_checker_.CalledOnValidThread());
+  for (auto* r : list_)
+    delete r;
+}
+
+StatsCollection::const_iterator StatsCollection::begin() const {
+  RTC_DCHECK(thread_checker_.CalledOnValidThread());
+  return list_.begin();
+}
+
+StatsCollection::const_iterator StatsCollection::end() const {
+  RTC_DCHECK(thread_checker_.CalledOnValidThread());
+  return list_.end();
+}
+
+size_t StatsCollection::size() const {
+  RTC_DCHECK(thread_checker_.CalledOnValidThread());
+  return list_.size();
+}
+
+StatsReport* StatsCollection::InsertNew(const StatsReport::Id& id) {
+  RTC_DCHECK(thread_checker_.CalledOnValidThread());
+  RTC_DCHECK(Find(id) == nullptr);
+  StatsReport* report = new StatsReport(id);
+  list_.push_back(report);
+  return report;
+}
+
+StatsReport* StatsCollection::FindOrAddNew(const StatsReport::Id& id) {
+  RTC_DCHECK(thread_checker_.CalledOnValidThread());
+  StatsReport* ret = Find(id);
+  return ret ? ret : InsertNew(id);
+}
+
+StatsReport* StatsCollection::ReplaceOrAddNew(const StatsReport::Id& id) {
+  RTC_DCHECK(thread_checker_.CalledOnValidThread());
+  RTC_DCHECK(id.get());
+  Container::iterator it = std::find_if(
+      list_.begin(), list_.end(),
+      [&id](const StatsReport* r) -> bool { return r->id()->Equals(id); });
+  if (it != end()) {
+    StatsReport* report = new StatsReport((*it)->id());
+    delete *it;
+    *it = report;
+    return report;
+  }
+  return InsertNew(id);
+}
+
+// Looks for a report with the given |id|.  If one is not found, null
+// will be returned.
+StatsReport* StatsCollection::Find(const StatsReport::Id& id) {
+  RTC_DCHECK(thread_checker_.CalledOnValidThread());
+  Container::iterator it = std::find_if(
+      list_.begin(), list_.end(),
+      [&id](const StatsReport* r) -> bool { return r->id()->Equals(id); });
+  return it == list_.end() ? nullptr : *it;
+}
+
+}  // namespace webrtc
diff --git a/api/stats_types.h b/api/stats_types.h
new file mode 100644
index 0000000..0e97eaf
--- /dev/null
+++ b/api/stats_types.h
@@ -0,0 +1,452 @@
+/*
+ *  Copyright 2012 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 structures used for retrieving statistics from an ongoing
+// libjingle session.
+
+#ifndef API_STATS_TYPES_H_
+#define API_STATS_TYPES_H_
+
+#include <algorithm>
+#include <list>
+#include <map>
+#include <string>
+#include <vector>
+
+#include "api/scoped_refptr.h"
+#include "rtc_base/constructor_magic.h"
+#include "rtc_base/ref_count.h"
+#include "rtc_base/string_encode.h"
+#include "rtc_base/thread_checker.h"
+
+namespace webrtc {
+
+class StatsReport {
+ public:
+  // Indicates whether a track is for sending or receiving.
+  // Used in reports for audio/video tracks.
+  enum Direction {
+    kSend = 0,
+    kReceive,
+  };
+
+  enum StatsType {
+    // StatsReport types.
+    // A StatsReport of |type| = "googSession" contains overall information
+    // about the thing libjingle calls a session (which may contain one
+    // or more RTP sessions.
+    kStatsReportTypeSession,
+
+    // A StatsReport of |type| = "googTransport" contains information
+    // about a libjingle "transport".
+    kStatsReportTypeTransport,
+
+    // A StatsReport of |type| = "googComponent" contains information
+    // about a libjingle "channel" (typically, RTP or RTCP for a transport).
+    // This is intended to be the same thing as an ICE "Component".
+    kStatsReportTypeComponent,
+
+    // A StatsReport of |type| = "googCandidatePair" contains information
+    // about a libjingle "connection" - a single source/destination port pair.
+    // This is intended to be the same thing as an ICE "candidate pair".
+    kStatsReportTypeCandidatePair,
+
+    // A StatsReport of |type| = "VideoBWE" is statistics for video Bandwidth
+    // Estimation, which is global per-session.  The |id| field is "bweforvideo"
+    // (will probably change in the future).
+    kStatsReportTypeBwe,
+
+    // A StatsReport of |type| = "ssrc" is statistics for a specific rtp stream.
+    // The |id| field is the SSRC in decimal form of the rtp stream.
+    kStatsReportTypeSsrc,
+
+    // A StatsReport of |type| = "remoteSsrc" is statistics for a specific
+    // rtp stream, generated by the remote end of the connection.
+    kStatsReportTypeRemoteSsrc,
+
+    // A StatsReport of |type| = "googTrack" is statistics for a specific media
+    // track. The |id| field is the track id.
+    kStatsReportTypeTrack,
+
+    // A StatsReport of |type| = "localcandidate" or "remotecandidate" is
+    // attributes on a specific ICE Candidate. It links to its connection pair
+    // by candidate id. The string value is taken from
+    // http://w3c.github.io/webrtc-stats/#rtcstatstype-enum*.
+    kStatsReportTypeIceLocalCandidate,
+    kStatsReportTypeIceRemoteCandidate,
+
+    // A StatsReport of |type| = "googCertificate" contains an SSL certificate
+    // transmitted by one of the endpoints of this connection.  The |id| is
+    // controlled by the fingerprint, and is used to identify the certificate in
+    // the Channel stats (as "googLocalCertificateId" or
+    // "googRemoteCertificateId") and in any child certificates (as
+    // "googIssuerId").
+    kStatsReportTypeCertificate,
+
+    // A StatsReport of |type| = "datachannel" with statistics for a
+    // particular DataChannel.
+    kStatsReportTypeDataChannel,
+  };
+
+  enum StatsValueName {
+    kStatsValueNameActiveConnection,
+    kStatsValueNameAecDivergentFilterFraction,
+    kStatsValueNameAudioInputLevel,
+    kStatsValueNameAudioOutputLevel,
+    kStatsValueNameBytesReceived,
+    kStatsValueNameBytesSent,
+    kStatsValueNameCodecImplementationName,
+    kStatsValueNameConcealedSamples,
+    kStatsValueNameConcealmentEvents,
+    kStatsValueNameDataChannelId,
+    kStatsValueNameFramesDecoded,
+    kStatsValueNameFramesEncoded,
+    kStatsValueNameJitterBufferDelay,
+    kStatsValueNameMediaType,
+    kStatsValueNamePacketsLost,
+    kStatsValueNamePacketsReceived,
+    kStatsValueNamePacketsSent,
+    kStatsValueNameProtocol,
+    kStatsValueNameQpSum,
+    kStatsValueNameReceiving,
+    kStatsValueNameSelectedCandidatePairId,
+    kStatsValueNameSsrc,
+    kStatsValueNameState,
+    kStatsValueNameTotalAudioEnergy,
+    kStatsValueNameTotalSamplesDuration,
+    kStatsValueNameTotalSamplesReceived,
+    kStatsValueNameTransportId,
+    kStatsValueNameSentPingRequestsTotal,
+    kStatsValueNameSentPingRequestsBeforeFirstResponse,
+    kStatsValueNameSentPingResponses,
+    kStatsValueNameRecvPingRequests,
+    kStatsValueNameRecvPingResponses,
+    kStatsValueNameSentStunKeepaliveRequests,
+    kStatsValueNameRecvStunKeepaliveResponses,
+    kStatsValueNameStunKeepaliveRttTotal,
+    kStatsValueNameStunKeepaliveRttSquaredTotal,
+
+    // Internal StatsValue names.
+    kStatsValueNameAccelerateRate,
+    kStatsValueNameActualEncBitrate,
+    kStatsValueNameAdaptationChanges,
+    kStatsValueNameAvailableReceiveBandwidth,
+    kStatsValueNameAvailableSendBandwidth,
+    kStatsValueNameAvgEncodeMs,
+    kStatsValueNameBandwidthLimitedResolution,
+    kStatsValueNameBucketDelay,
+    kStatsValueNameCaptureStartNtpTimeMs,
+    kStatsValueNameCandidateIPAddress,
+    kStatsValueNameCandidateNetworkType,
+    kStatsValueNameCandidatePortNumber,
+    kStatsValueNameCandidatePriority,
+    kStatsValueNameCandidateTransportType,
+    kStatsValueNameCandidateType,
+    kStatsValueNameChannelId,
+    kStatsValueNameCodecName,
+    kStatsValueNameComponent,
+    kStatsValueNameContentName,
+    kStatsValueNameContentType,
+    kStatsValueNameCpuLimitedResolution,
+    kStatsValueNameCurrentDelayMs,
+    kStatsValueNameDecodeMs,
+    kStatsValueNameDecodingCNG,
+    kStatsValueNameDecodingCTN,
+    kStatsValueNameDecodingCTSG,
+    kStatsValueNameDecodingMutedOutput,
+    kStatsValueNameDecodingNormal,
+    kStatsValueNameDecodingPLC,
+    kStatsValueNameDecodingPLCCNG,
+    kStatsValueNameDer,
+    kStatsValueNameDtlsCipher,
+    kStatsValueNameEchoDelayMedian,
+    kStatsValueNameEchoDelayStdDev,
+    kStatsValueNameEchoReturnLoss,
+    kStatsValueNameEchoReturnLossEnhancement,
+    kStatsValueNameEncodeUsagePercent,
+    kStatsValueNameExpandRate,
+    kStatsValueNameFingerprint,
+    kStatsValueNameFingerprintAlgorithm,
+    kStatsValueNameFirsReceived,
+    kStatsValueNameFirsSent,
+    kStatsValueNameFirstFrameReceivedToDecodedMs,
+    kStatsValueNameFrameHeightInput,
+    kStatsValueNameFrameHeightReceived,
+    kStatsValueNameFrameHeightSent,
+    kStatsValueNameFrameRateDecoded,
+    kStatsValueNameFrameRateInput,
+    kStatsValueNameFrameRateOutput,
+    kStatsValueNameFrameRateReceived,
+    kStatsValueNameFrameRateSent,
+    kStatsValueNameFrameWidthInput,
+    kStatsValueNameFrameWidthReceived,
+    kStatsValueNameFrameWidthSent,
+    kStatsValueNameHasEnteredLowResolution,
+    kStatsValueNameHugeFramesSent,
+    kStatsValueNameInitiator,
+    kStatsValueNameInterframeDelayMaxMs,  // Max over last 10 seconds.
+    kStatsValueNameIssuerId,
+    kStatsValueNameJitterBufferMs,
+    kStatsValueNameJitterReceived,
+    kStatsValueNameLabel,
+    kStatsValueNameLocalAddress,
+    kStatsValueNameLocalCandidateId,
+    kStatsValueNameLocalCandidateType,
+    kStatsValueNameLocalCertificateId,
+    kStatsValueNameMaxDecodeMs,
+    kStatsValueNameMinPlayoutDelayMs,
+    kStatsValueNameNacksReceived,
+    kStatsValueNameNacksSent,
+    kStatsValueNamePlisReceived,
+    kStatsValueNamePlisSent,
+    kStatsValueNamePreemptiveExpandRate,
+    kStatsValueNamePreferredJitterBufferMs,
+    kStatsValueNameRemoteAddress,
+    kStatsValueNameRemoteCandidateId,
+    kStatsValueNameRemoteCandidateType,
+    kStatsValueNameRemoteCertificateId,
+    kStatsValueNameRenderDelayMs,
+    kStatsValueNameResidualEchoLikelihood,
+    kStatsValueNameResidualEchoLikelihoodRecentMax,
+    kStatsValueNameAnaBitrateActionCounter,
+    kStatsValueNameAnaChannelActionCounter,
+    kStatsValueNameAnaDtxActionCounter,
+    kStatsValueNameAnaFecActionCounter,
+    kStatsValueNameAnaFrameLengthIncreaseCounter,
+    kStatsValueNameAnaFrameLengthDecreaseCounter,
+    kStatsValueNameAnaUplinkPacketLossFraction,
+    kStatsValueNameRetransmitBitrate,
+    kStatsValueNameRtt,
+    kStatsValueNameSecondaryDecodedRate,
+    kStatsValueNameSecondaryDiscardedRate,
+    kStatsValueNameSendPacketsDiscarded,
+    kStatsValueNameSpeechExpandRate,
+    kStatsValueNameSrtpCipher,
+    kStatsValueNameTargetDelayMs,
+    kStatsValueNameTargetEncBitrate,
+    kStatsValueNameTimingFrameInfo,  // Result of |TimingFrameInfo::ToString|
+    kStatsValueNameTrackId,
+    kStatsValueNameTransmitBitrate,
+    kStatsValueNameTransportType,
+    kStatsValueNameTypingNoiseState,
+    kStatsValueNameWritable,
+  };
+
+  class IdBase : public rtc::RefCountInterface {
+   public:
+    ~IdBase() override;
+    StatsType type() const;
+
+    // Users of IdBase will be using the Id typedef, which is compatible with
+    // this Equals() function.  It simply calls the protected (and overridden)
+    // Equals() method.
+    bool Equals(const rtc::scoped_refptr<IdBase>& other) const {
+      return Equals(*other.get());
+    }
+
+    virtual std::string ToString() const = 0;
+
+   protected:
+    // Protected since users of the IdBase type will be using the Id typedef.
+    virtual bool Equals(const IdBase& other) const;
+
+    explicit IdBase(StatsType type);  // Only meant for derived classes.
+    const StatsType type_;
+
+    static const char kSeparator = '_';
+  };
+
+  typedef rtc::scoped_refptr<IdBase> Id;
+
+  struct Value {
+    enum Type {
+      kInt,           // int.
+      kInt64,         // int64_t.
+      kFloat,         // float.
+      kString,        // std::string
+      kStaticString,  // const char*.
+      kBool,          // bool.
+      kId,            // Id.
+    };
+
+    Value(StatsValueName name, int64_t value, Type int_type);
+    Value(StatsValueName name, float f);
+    Value(StatsValueName name, const std::string& value);
+    Value(StatsValueName name, const char* value);
+    Value(StatsValueName name, bool b);
+    Value(StatsValueName name, const Id& value);
+
+    ~Value();
+
+    // Support ref counting. Note that for performance reasons, we
+    // don't use thread safe operations. Therefore, all operations
+    // affecting the ref count (in practice, creation and copying of
+    // the Values mapping) must occur on webrtc's signalling thread.
+    int AddRef() const {
+      RTC_DCHECK_RUN_ON(&thread_checker_);
+      return ++ref_count_;
+    }
+    int Release() const {
+      RTC_DCHECK_RUN_ON(&thread_checker_);
+      int count = --ref_count_;
+      if (!count)
+        delete this;
+      return count;
+    }
+
+    // TODO(tommi): This compares name as well as value...
+    // I think we should only need to compare the value part and
+    // move the name part into a hash map.
+    bool Equals(const Value& other) const;
+
+    // Comparison operators. Return true iff the current instance is of the
+    // correct type and holds the same value.  No conversion is performed so
+    // a string value of "123" is not equal to an int value of 123 and an int
+    // value of 123 is not equal to a float value of 123.0f.
+    // One exception to this is that types kInt and kInt64 can be compared and
+    // kString and kStaticString too.
+    bool operator==(const std::string& value) const;
+    bool operator==(const char* value) const;
+    bool operator==(int64_t value) const;
+    bool operator==(bool value) const;
+    bool operator==(float value) const;
+    bool operator==(const Id& value) const;
+
+    // Getters that allow getting the native value directly.
+    // The caller must know the type beforehand or else hit a check.
+    int int_val() const;
+    int64_t int64_val() const;
+    float float_val() const;
+    const char* static_string_val() const;
+    const std::string& string_val() const;
+    bool bool_val() const;
+    const Id& id_val() const;
+
+    // Returns the string representation of |name|.
+    const char* display_name() const;
+
+    // Converts the native value to a string representation of the value.
+    std::string ToString() const;
+
+    Type type() const { return type_; }
+
+    // TODO(tommi): Move |name| and |display_name| out of the Value struct.
+    const StatsValueName name;
+
+   private:
+    rtc::ThreadChecker thread_checker_;
+    mutable int ref_count_ RTC_GUARDED_BY(thread_checker_) = 0;
+
+    const Type type_;
+    // TODO(tommi): Use C++ 11 union and make value_ const.
+    union InternalType {
+      int int_;
+      int64_t int64_;
+      float float_;
+      bool bool_;
+      std::string* string_;
+      const char* static_string_;
+      Id* id_;
+    } value_;
+
+    RTC_DISALLOW_COPY_AND_ASSIGN(Value);
+  };
+
+  typedef rtc::scoped_refptr<Value> ValuePtr;
+  typedef std::map<StatsValueName, ValuePtr> Values;
+
+  // Ownership of |id| is passed to |this|.
+  explicit StatsReport(const Id& id);
+  ~StatsReport();
+
+  // Factory functions for various types of stats IDs.
+  static Id NewBandwidthEstimationId();
+  static Id NewTypedId(StatsType type, const std::string& id);
+  static Id NewTypedIntId(StatsType type, int id);
+  static Id NewIdWithDirection(StatsType type,
+                               const std::string& id,
+                               Direction direction);
+  static Id NewCandidateId(bool local, const std::string& id);
+  static Id NewComponentId(const std::string& content_name, int component);
+  static Id NewCandidatePairId(const std::string& content_name,
+                               int component,
+                               int index);
+
+  const Id& id() const { return id_; }
+  StatsType type() const { return id_->type(); }
+  double timestamp() const { return timestamp_; }
+  void set_timestamp(double t) { timestamp_ = t; }
+  bool empty() const { return values_.empty(); }
+  const Values& values() const { return values_; }
+
+  const char* TypeToString() const;
+
+  void AddString(StatsValueName name, const std::string& value);
+  void AddString(StatsValueName name, const char* value);
+  void AddInt64(StatsValueName name, int64_t value);
+  void AddInt(StatsValueName name, int value);
+  void AddFloat(StatsValueName name, float value);
+  void AddBoolean(StatsValueName name, bool value);
+  void AddId(StatsValueName name, const Id& value);
+
+  const Value* FindValue(StatsValueName name) const;
+
+ private:
+  // The unique identifier for this object.
+  // This is used as a key for this report in ordered containers,
+  // so it must never be changed.
+  const Id id_;
+  double timestamp_;  // Time since 1970-01-01T00:00:00Z in milliseconds.
+  Values values_;
+
+  RTC_DISALLOW_COPY_AND_ASSIGN(StatsReport);
+};
+
+// Typedef for an array of const StatsReport pointers.
+// Ownership of the pointers held by this implementation is assumed to lie
+// elsewhere and lifetime guarantees are made by the implementation that uses
+// this type.  In the StatsCollector, object ownership lies with the
+// StatsCollection class.
+typedef std::vector<const StatsReport*> StatsReports;
+
+// A map from the report id to the report.
+// This class wraps an STL container and provides a limited set of
+// functionality in order to keep things simple.
+class StatsCollection {
+ public:
+  StatsCollection();
+  ~StatsCollection();
+
+  typedef std::list<StatsReport*> Container;
+  typedef Container::iterator iterator;
+  typedef Container::const_iterator const_iterator;
+
+  const_iterator begin() const;
+  const_iterator end() const;
+  size_t size() const;
+
+  // Creates a new report object with |id| that does not already
+  // exist in the list of reports.
+  StatsReport* InsertNew(const StatsReport::Id& id);
+  StatsReport* FindOrAddNew(const StatsReport::Id& id);
+  StatsReport* ReplaceOrAddNew(const StatsReport::Id& id);
+
+  // Looks for a report with the given |id|.  If one is not found, null
+  // will be returned.
+  StatsReport* Find(const StatsReport::Id& id);
+
+ private:
+  Container list_;
+  rtc::ThreadChecker thread_checker_;
+};
+
+}  // namespace webrtc
+
+#endif  // API_STATS_TYPES_H_
diff --git a/api/task_queue/default_task_queue_factory.h b/api/task_queue/default_task_queue_factory.h
new file mode 100644
index 0000000..ccdd1eb
--- /dev/null
+++ b/api/task_queue/default_task_queue_factory.h
@@ -0,0 +1,23 @@
+/*
+ *  Copyright 2019 The WebRTC Project Authors. All rights reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+#ifndef API_TASK_QUEUE_DEFAULT_TASK_QUEUE_FACTORY_H_
+#define API_TASK_QUEUE_DEFAULT_TASK_QUEUE_FACTORY_H_
+
+#include <memory>
+
+#include "api/task_queue/task_queue_factory.h"
+
+namespace webrtc {
+
+std::unique_ptr<TaskQueueFactory> CreateDefaultTaskQueueFactory();
+
+}  // namespace webrtc
+
+#endif  // API_TASK_QUEUE_DEFAULT_TASK_QUEUE_FACTORY_H_
diff --git a/api/task_queue/default_task_queue_factory_gcd.cc b/api/task_queue/default_task_queue_factory_gcd.cc
new file mode 100644
index 0000000..7e17b48
--- /dev/null
+++ b/api/task_queue/default_task_queue_factory_gcd.cc
@@ -0,0 +1,21 @@
+/*
+ *  Copyright 2019 The WebRTC Project Authors. All rights reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+#include <memory>
+
+#include "api/task_queue/task_queue_factory.h"
+#include "rtc_base/task_queue_gcd.h"
+
+namespace webrtc {
+
+std::unique_ptr<TaskQueueFactory> CreateDefaultTaskQueueFactory() {
+  return CreateTaskQueueGcdFactory();
+}
+
+}  // namespace webrtc
diff --git a/api/task_queue/default_task_queue_factory_libevent.cc b/api/task_queue/default_task_queue_factory_libevent.cc
new file mode 100644
index 0000000..f2fb418
--- /dev/null
+++ b/api/task_queue/default_task_queue_factory_libevent.cc
@@ -0,0 +1,21 @@
+/*
+ *  Copyright 2019 The WebRTC Project Authors. All rights reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+#include <memory>
+
+#include "api/task_queue/task_queue_factory.h"
+#include "rtc_base/task_queue_libevent.h"
+
+namespace webrtc {
+
+std::unique_ptr<TaskQueueFactory> CreateDefaultTaskQueueFactory() {
+  return CreateTaskQueueLibeventFactory();
+}
+
+}  // namespace webrtc
diff --git a/api/task_queue/default_task_queue_factory_stdlib.cc b/api/task_queue/default_task_queue_factory_stdlib.cc
new file mode 100644
index 0000000..ca7d720
--- /dev/null
+++ b/api/task_queue/default_task_queue_factory_stdlib.cc
@@ -0,0 +1,21 @@
+/*
+ *  Copyright 2019 The WebRTC Project Authors. All rights reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+#include <memory>
+
+#include "api/task_queue/task_queue_factory.h"
+#include "rtc_base/task_queue_stdlib.h"
+
+namespace webrtc {
+
+std::unique_ptr<TaskQueueFactory> CreateDefaultTaskQueueFactory() {
+  return CreateTaskQueueStdlibFactory();
+}
+
+}  // namespace webrtc
diff --git a/api/task_queue/default_task_queue_factory_unittest.cc b/api/task_queue/default_task_queue_factory_unittest.cc
new file mode 100644
index 0000000..92c17d8
--- /dev/null
+++ b/api/task_queue/default_task_queue_factory_unittest.cc
@@ -0,0 +1,24 @@
+/*
+ *  Copyright 2019 The WebRTC Project Authors. All rights reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "api/task_queue/default_task_queue_factory.h"
+
+#include "api/task_queue/task_queue_test.h"
+#include "test/gtest.h"
+
+namespace webrtc {
+namespace {
+
+INSTANTIATE_TEST_SUITE_P(Default,
+                         TaskQueueTest,
+                         ::testing::Values(CreateDefaultTaskQueueFactory));
+
+}  // namespace
+}  // namespace webrtc
diff --git a/api/task_queue/default_task_queue_factory_win.cc b/api/task_queue/default_task_queue_factory_win.cc
new file mode 100644
index 0000000..493ea66
--- /dev/null
+++ b/api/task_queue/default_task_queue_factory_win.cc
@@ -0,0 +1,21 @@
+/*
+ *  Copyright 2019 The WebRTC Project Authors. All rights reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+#include <memory>
+
+#include "api/task_queue/task_queue_factory.h"
+#include "rtc_base/task_queue_win.h"
+
+namespace webrtc {
+
+std::unique_ptr<TaskQueueFactory> CreateDefaultTaskQueueFactory() {
+  return CreateTaskQueueWinFactory();
+}
+
+}  // namespace webrtc
diff --git a/api/task_queue/global_task_queue_factory.cc b/api/task_queue/global_task_queue_factory.cc
new file mode 100644
index 0000000..528d14d
--- /dev/null
+++ b/api/task_queue/global_task_queue_factory.cc
@@ -0,0 +1,40 @@
+/*
+ *  Copyright 2019 The WebRTC Project Authors. All rights reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "api/task_queue/global_task_queue_factory.h"
+
+#include "api/task_queue/default_task_queue_factory.h"
+#include "rtc_base/checks.h"
+
+namespace webrtc {
+namespace {
+
+TaskQueueFactory* GlobalOrDefault(TaskQueueFactory* global) {
+  static TaskQueueFactory* const factory =
+      global ? global : CreateDefaultTaskQueueFactory().release();
+  return factory;
+}
+
+}  // namespace
+
+void SetGlobalTaskQueueFactory(std::unique_ptr<TaskQueueFactory> factory) {
+  RTC_CHECK(factory) << "Can't set nullptr TaskQueueFactory";
+  // Own, but never delete the global factory.
+  TaskQueueFactory* global = factory.release();
+  RTC_CHECK(GlobalOrDefault(global) == global)
+      << "Task queue factory set after another SetFactory or after a task "
+         "queue was created";
+}
+
+TaskQueueFactory& GlobalTaskQueueFactory() {
+  return *GlobalOrDefault(nullptr);
+}
+
+}  // namespace webrtc
diff --git a/api/task_queue/global_task_queue_factory.h b/api/task_queue/global_task_queue_factory.h
new file mode 100644
index 0000000..a580833
--- /dev/null
+++ b/api/task_queue/global_task_queue_factory.h
@@ -0,0 +1,27 @@
+/*
+ *  Copyright 2019 The WebRTC Project Authors. All rights reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+#ifndef API_TASK_QUEUE_GLOBAL_TASK_QUEUE_FACTORY_H_
+#define API_TASK_QUEUE_GLOBAL_TASK_QUEUE_FACTORY_H_
+
+#include <memory>
+
+#include "api/task_queue/task_queue_factory.h"
+
+namespace webrtc {
+
+// May be called at most once, and before any TaskQueue is created.
+void SetGlobalTaskQueueFactory(std::unique_ptr<TaskQueueFactory> factory);
+
+// Returns TaskQueue factory. Always returns the same factory.
+TaskQueueFactory& GlobalTaskQueueFactory();
+
+}  // namespace webrtc
+
+#endif  // API_TASK_QUEUE_GLOBAL_TASK_QUEUE_FACTORY_H_
diff --git a/api/task_queue/module.mk b/api/task_queue/module.mk
new file mode 100644
index 0000000..37c23f4
--- /dev/null
+++ b/api/task_queue/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/api/task_queue/queued_task.h b/api/task_queue/queued_task.h
new file mode 100644
index 0000000..5748628
--- /dev/null
+++ b/api/task_queue/queued_task.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_TASK_QUEUE_QUEUED_TASK_H_
+#define API_TASK_QUEUE_QUEUED_TASK_H_
+
+namespace webrtc {
+
+// Base interface for asynchronously executed tasks.
+// The interface basically consists of a single function, Run(), that executes
+// on the target queue.  For more details see the Run() method and TaskQueue.
+class QueuedTask {
+ public:
+  virtual ~QueuedTask() = default;
+
+  // Main routine that will run when the task is executed on the desired queue.
+  // The task should return |true| to indicate that it should be deleted or
+  // |false| to indicate that the queue should consider ownership of the task
+  // having been transferred.  Returning |false| can be useful if a task has
+  // re-posted itself to a different queue or is otherwise being re-used.
+  virtual bool Run() = 0;
+};
+
+}  // namespace webrtc
+
+#endif  // API_TASK_QUEUE_QUEUED_TASK_H_
diff --git a/api/task_queue/task_queue_base.cc b/api/task_queue/task_queue_base.cc
new file mode 100644
index 0000000..7d3539a
--- /dev/null
+++ b/api/task_queue/task_queue_base.cc
@@ -0,0 +1,79 @@
+/*
+ *  Copyright 2019 The WebRTC Project Authors. All rights reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+#include "api/task_queue/task_queue_base.h"
+
+#include "absl/base/attributes.h"
+#include "absl/base/config.h"
+#include "rtc_base/checks.h"
+
+#if defined(ABSL_HAVE_THREAD_LOCAL)
+
+namespace webrtc {
+namespace {
+
+ABSL_CONST_INIT thread_local TaskQueueBase* current = nullptr;
+
+}  // namespace
+
+TaskQueueBase* TaskQueueBase::Current() {
+  return current;
+}
+
+TaskQueueBase::CurrentTaskQueueSetter::CurrentTaskQueueSetter(
+    TaskQueueBase* task_queue)
+    : previous_(current) {
+  current = task_queue;
+}
+
+TaskQueueBase::CurrentTaskQueueSetter::~CurrentTaskQueueSetter() {
+  current = previous_;
+}
+}  // namespace webrtc
+
+#elif defined(WEBRTC_POSIX)
+
+#include <pthread.h>
+
+namespace webrtc {
+namespace {
+
+ABSL_CONST_INIT pthread_key_t g_queue_ptr_tls = 0;
+
+void InitializeTls() {
+  RTC_CHECK(pthread_key_create(&g_queue_ptr_tls, nullptr) == 0);
+}
+
+pthread_key_t GetQueuePtrTls() {
+  static pthread_once_t init_once = PTHREAD_ONCE_INIT;
+  RTC_CHECK(pthread_once(&init_once, &InitializeTls) == 0);
+  return g_queue_ptr_tls;
+}
+
+}  // namespace
+
+TaskQueueBase* TaskQueueBase::Current() {
+  return static_cast<TaskQueueBase*>(pthread_getspecific(GetQueuePtrTls()));
+}
+
+TaskQueueBase::CurrentTaskQueueSetter::CurrentTaskQueueSetter(
+    TaskQueueBase* task_queue)
+    : previous_(TaskQueueBase::Current()) {
+  pthread_setspecific(GetQueuePtrTls(), task_queue);
+}
+
+TaskQueueBase::CurrentTaskQueueSetter::~CurrentTaskQueueSetter() {
+  pthread_setspecific(GetQueuePtrTls(), previous_);
+}
+
+}  // namespace webrtc
+
+#else
+#error Unsupported platform
+#endif
diff --git a/api/task_queue/task_queue_base.h b/api/task_queue/task_queue_base.h
new file mode 100644
index 0000000..b1b5cc7
--- /dev/null
+++ b/api/task_queue/task_queue_base.h
@@ -0,0 +1,91 @@
+/*
+ *  Copyright 2019 The WebRTC Project Authors. All rights reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+#ifndef API_TASK_QUEUE_TASK_QUEUE_BASE_H_
+#define API_TASK_QUEUE_TASK_QUEUE_BASE_H_
+
+#include <memory>
+
+#include "api/task_queue/queued_task.h"
+
+// TODO(bugs.webrtc.org/10191): Remove when
+// rtc::TaskQueue* rtc::TaskQueue::Current() is unused.
+namespace rtc {
+class TaskQueue;
+}  // namespace rtc
+
+namespace webrtc {
+
+// Asynchronously executes tasks in a way that guarantees that they're executed
+// in FIFO order and that tasks never overlap. Tasks may always execute on the
+// same worker thread and they may not. To DCHECK that tasks are executing on a
+// known task queue, use IsCurrent().
+class TaskQueueBase {
+ public:
+  // Starts destruction of the task queue.
+  // On return ensures no task are running and no new tasks are able to start
+  // on the task queue.
+  // Responsible for deallocation. Deallocation may happen syncrhoniously during
+  // Delete or asynchronously after Delete returns.
+  // Code not running on the TaskQueue should not make any assumption when
+  // TaskQueue is deallocated and thus should not call any methods after Delete.
+  // Code running on the TaskQueue should not call Delete, but can assume
+  // TaskQueue still exists and may call other methods, e.g. PostTask.
+  virtual void Delete() = 0;
+
+  // Schedules a task to execute. Tasks are executed in FIFO order.
+  // If |task->Run()| returns true, task is deleted on the task queue
+  // before next QueuedTask starts executing.
+  // When a TaskQueue is deleted, pending tasks will not be executed but they
+  // will be deleted. The deletion of tasks may happen synchronously on the
+  // TaskQueue or it may happen asynchronously after TaskQueue is deleted.
+  // This may vary from one implementation to the next so assumptions about
+  // lifetimes of pending tasks should not be made.
+  virtual void PostTask(std::unique_ptr<QueuedTask> task) = 0;
+
+  // Schedules a task to execute a specified number of milliseconds from when
+  // the call is made. The precision should be considered as "best effort"
+  // and in some cases, such as on Windows when all high precision timers have
+  // been used up, can be off by as much as 15 millseconds.
+  virtual void PostDelayedTask(std::unique_ptr<QueuedTask> task,
+                               uint32_t milliseconds) = 0;
+
+  // Returns the task queue that is running the current thread.
+  // Returns nullptr if this thread is not associated with any task queue.
+  static TaskQueueBase* Current();
+  bool IsCurrent() const { return Current() == this; }
+
+ protected:
+  class CurrentTaskQueueSetter {
+   public:
+    explicit CurrentTaskQueueSetter(TaskQueueBase* task_queue);
+    CurrentTaskQueueSetter(const CurrentTaskQueueSetter&) = delete;
+    CurrentTaskQueueSetter& operator=(const CurrentTaskQueueSetter&) = delete;
+    ~CurrentTaskQueueSetter();
+
+   private:
+    TaskQueueBase* const previous_;
+  };
+
+  // Users of the TaskQueue should call Delete instead of directly deleting
+  // this object.
+  virtual ~TaskQueueBase() = default;
+
+ private:
+  friend class rtc::TaskQueue;
+  rtc::TaskQueue* task_queue_ = nullptr;
+};
+
+struct TaskQueueDeleter {
+  void operator()(TaskQueueBase* task_queue) const { task_queue->Delete(); }
+};
+
+}  // namespace webrtc
+
+#endif  // API_TASK_QUEUE_TASK_QUEUE_BASE_H_
diff --git a/api/task_queue/task_queue_factory.h b/api/task_queue/task_queue_factory.h
new file mode 100644
index 0000000..b68ab33
--- /dev/null
+++ b/api/task_queue/task_queue_factory.h
@@ -0,0 +1,35 @@
+/*
+ *  Copyright 2019 The WebRTC Project Authors. All rights reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+#ifndef API_TASK_QUEUE_TASK_QUEUE_FACTORY_H_
+#define API_TASK_QUEUE_TASK_QUEUE_FACTORY_H_
+
+#include <memory>
+
+#include "absl/strings/string_view.h"
+#include "api/task_queue/task_queue_base.h"
+
+namespace webrtc {
+
+// The implementation of this interface must be thread-safe.
+class TaskQueueFactory {
+ public:
+  // TaskQueue priority levels. On some platforms these will map to thread
+  // priorities, on others such as Mac and iOS, GCD queue priorities.
+  enum class Priority { NORMAL = 0, HIGH, LOW };
+
+  virtual ~TaskQueueFactory() = default;
+  virtual std::unique_ptr<TaskQueueBase, TaskQueueDeleter> CreateTaskQueue(
+      absl::string_view name,
+      Priority priority) const = 0;
+};
+
+}  // namespace webrtc
+
+#endif  // API_TASK_QUEUE_TASK_QUEUE_FACTORY_H_
diff --git a/api/task_queue/task_queue_test.cc b/api/task_queue/task_queue_test.cc
new file mode 100644
index 0000000..e78dbd2
--- /dev/null
+++ b/api/task_queue/task_queue_test.cc
@@ -0,0 +1,254 @@
+/*
+ *  Copyright 2019 The WebRTC Project Authors. All rights reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+#include "api/task_queue/task_queue_test.h"
+
+#include "absl/memory/memory.h"
+#include "absl/strings/string_view.h"
+#include "rtc_base/event.h"
+#include "rtc_base/task_utils/to_queued_task.h"
+#include "rtc_base/time_utils.h"
+
+namespace webrtc {
+namespace {
+
+std::unique_ptr<TaskQueueBase, TaskQueueDeleter> CreateTaskQueue(
+    const std::unique_ptr<webrtc::TaskQueueFactory>& factory,
+    absl::string_view task_queue_name,
+    TaskQueueFactory::Priority priority = TaskQueueFactory::Priority::NORMAL) {
+  return factory->CreateTaskQueue(task_queue_name, priority);
+}
+
+TEST_P(TaskQueueTest, Construct) {
+  std::unique_ptr<webrtc::TaskQueueFactory> factory = GetParam()();
+  auto queue = CreateTaskQueue(factory, "Construct");
+  EXPECT_FALSE(queue->IsCurrent());
+}
+
+TEST_P(TaskQueueTest, PostAndCheckCurrent) {
+  std::unique_ptr<webrtc::TaskQueueFactory> factory = GetParam()();
+  rtc::Event event;
+  auto queue = CreateTaskQueue(factory, "PostAndCheckCurrent");
+
+  // We're not running a task, so there shouldn't be a current queue.
+  EXPECT_FALSE(queue->IsCurrent());
+  EXPECT_FALSE(TaskQueueBase::Current());
+
+  queue->PostTask(ToQueuedTask([&event, &queue] {
+    EXPECT_TRUE(queue->IsCurrent());
+    event.Set();
+  }));
+  EXPECT_TRUE(event.Wait(1000));
+}
+
+TEST_P(TaskQueueTest, PostCustomTask) {
+  std::unique_ptr<webrtc::TaskQueueFactory> factory = GetParam()();
+  rtc::Event ran;
+  auto queue = CreateTaskQueue(factory, "PostCustomImplementation");
+
+  class CustomTask : public QueuedTask {
+   public:
+    explicit CustomTask(rtc::Event* ran) : ran_(ran) {}
+
+   private:
+    bool Run() override {
+      ran_->Set();
+      return false;  // Do not allow the task to be deleted by the queue.
+    }
+
+    rtc::Event* const ran_;
+  } my_task(&ran);
+
+  queue->PostTask(absl::WrapUnique(&my_task));
+  EXPECT_TRUE(ran.Wait(1000));
+}
+
+TEST_P(TaskQueueTest, PostDelayedZero) {
+  std::unique_ptr<webrtc::TaskQueueFactory> factory = GetParam()();
+  rtc::Event event;
+  auto queue = CreateTaskQueue(factory, "PostDelayedZero");
+
+  queue->PostDelayedTask(ToQueuedTask([&event] { event.Set(); }), 0);
+  EXPECT_TRUE(event.Wait(1000));
+}
+
+TEST_P(TaskQueueTest, PostFromQueue) {
+  std::unique_ptr<webrtc::TaskQueueFactory> factory = GetParam()();
+  rtc::Event event;
+  auto queue = CreateTaskQueue(factory, "PostFromQueue");
+
+  queue->PostTask(ToQueuedTask([&event, &queue] {
+    queue->PostTask(ToQueuedTask([&event] { event.Set(); }));
+  }));
+  EXPECT_TRUE(event.Wait(1000));
+}
+
+TEST_P(TaskQueueTest, PostDelayed) {
+  std::unique_ptr<webrtc::TaskQueueFactory> factory = GetParam()();
+  rtc::Event event;
+  auto queue =
+      CreateTaskQueue(factory, "PostDelayed", TaskQueueFactory::Priority::HIGH);
+
+  int64_t start = rtc::TimeMillis();
+  queue->PostDelayedTask(ToQueuedTask([&event, &queue] {
+                           EXPECT_TRUE(queue->IsCurrent());
+                           event.Set();
+                         }),
+                         100);
+  EXPECT_TRUE(event.Wait(1000));
+  int64_t end = rtc::TimeMillis();
+  // These tests are a little relaxed due to how "powerful" our test bots can
+  // be.  Most recently we've seen windows bots fire the callback after 94-99ms,
+  // which is why we have a little bit of leeway backwards as well.
+  EXPECT_GE(end - start, 90u);
+  EXPECT_NEAR(end - start, 190u, 100u);  // Accept 90-290.
+}
+
+TEST_P(TaskQueueTest, PostMultipleDelayed) {
+  std::unique_ptr<webrtc::TaskQueueFactory> factory = GetParam()();
+  auto queue = CreateTaskQueue(factory, "PostMultipleDelayed");
+
+  std::vector<rtc::Event> events(100);
+  for (int i = 0; i < 100; ++i) {
+    rtc::Event* event = &events[i];
+    queue->PostDelayedTask(ToQueuedTask([event, &queue] {
+                             EXPECT_TRUE(queue->IsCurrent());
+                             event->Set();
+                           }),
+                           i);
+  }
+
+  for (rtc::Event& e : events)
+    EXPECT_TRUE(e.Wait(1000));
+}
+
+TEST_P(TaskQueueTest, PostDelayedAfterDestruct) {
+  std::unique_ptr<webrtc::TaskQueueFactory> factory = GetParam()();
+  rtc::Event run;
+  rtc::Event deleted;
+  auto queue = CreateTaskQueue(factory, "PostDelayedAfterDestruct");
+  queue->PostDelayedTask(
+      ToQueuedTask([&run] { run.Set(); }, [&deleted] { deleted.Set(); }), 100);
+  // Destroy the queue.
+  queue = nullptr;
+  // Task might outlive the TaskQueue, but still should be deleted.
+  EXPECT_TRUE(deleted.Wait(200));
+  EXPECT_FALSE(run.Wait(0));  // and should not run.
+}
+
+TEST_P(TaskQueueTest, PostAndReuse) {
+  std::unique_ptr<webrtc::TaskQueueFactory> factory = GetParam()();
+  rtc::Event event;
+  auto post_queue = CreateTaskQueue(factory, "PostQueue");
+  auto reply_queue = CreateTaskQueue(factory, "ReplyQueue");
+
+  int call_count = 0;
+
+  class ReusedTask : public QueuedTask {
+   public:
+    ReusedTask(int* counter, TaskQueueBase* reply_queue, rtc::Event* event)
+        : counter_(*counter), reply_queue_(reply_queue), event_(*event) {
+      EXPECT_EQ(counter_, 0);
+    }
+
+   private:
+    bool Run() override {
+      if (++counter_ == 1) {
+        reply_queue_->PostTask(absl::WrapUnique(this));
+        // At this point, the object is owned by reply_queue_ and it's
+        // theoratically possible that the object has been deleted (e.g. if
+        // posting wasn't possible).  So, don't touch any member variables here.
+
+        // Indicate to the current queue that ownership has been transferred.
+        return false;
+      } else {
+        EXPECT_EQ(counter_, 2);
+        EXPECT_TRUE(reply_queue_->IsCurrent());
+        event_.Set();
+        return true;  // Indicate that the object should be deleted.
+      }
+    }
+
+    int& counter_;
+    TaskQueueBase* const reply_queue_;
+    rtc::Event& event_;
+  };
+
+  auto task =
+      absl::make_unique<ReusedTask>(&call_count, reply_queue.get(), &event);
+  post_queue->PostTask(std::move(task));
+  EXPECT_TRUE(event.Wait(1000));
+}
+
+// Tests posting more messages than a queue can queue up.
+// In situations like that, tasks will get dropped.
+TEST_P(TaskQueueTest, PostALot) {
+  std::unique_ptr<webrtc::TaskQueueFactory> factory = GetParam()();
+  // To destruct the event after the queue has gone out of scope.
+  rtc::Event event;
+
+  int tasks_executed = 0;
+  int tasks_cleaned_up = 0;
+  static const int kTaskCount = 0xffff;
+
+  {
+    auto queue = CreateTaskQueue(factory, "PostALot");
+
+    // On linux, the limit of pending bytes in the pipe buffer is 0xffff.
+    // So here we post a total of 0xffff+1 messages, which triggers a failure
+    // case inside of the libevent queue implementation.
+
+    queue->PostTask(
+        ToQueuedTask([&event] { event.Wait(rtc::Event::kForever); }));
+    for (int i = 0; i < kTaskCount; ++i)
+      queue->PostTask(
+          ToQueuedTask([&tasks_executed] { ++tasks_executed; },
+                       [&tasks_cleaned_up] { ++tasks_cleaned_up; }));
+    event.Set();  // Unblock the first task.
+  }
+
+  EXPECT_GE(tasks_cleaned_up, tasks_executed);
+  EXPECT_EQ(tasks_cleaned_up, kTaskCount);
+}
+
+// Test posting two tasks that have shared state not protected by a
+// lock. The TaskQueue should guarantee memory read-write order and
+// FIFO task execution order, so the second task should always see the
+// changes that were made by the first task.
+//
+// If the TaskQueue doesn't properly synchronize the execution of
+// tasks, there will be a data race, which is undefined behavior. The
+// EXPECT calls may randomly catch this, but to make the most of this
+// unit test, run it under TSan or some other tool that is able to
+// directly detect data races.
+TEST_P(TaskQueueTest, PostTwoWithSharedUnprotectedState) {
+  std::unique_ptr<webrtc::TaskQueueFactory> factory = GetParam()();
+  struct SharedState {
+    // First task will set this value to 1 and second will assert it.
+    int state = 0;
+  } state;
+
+  auto queue = CreateTaskQueue(factory, "PostTwoWithSharedUnprotectedState");
+  rtc::Event done;
+  queue->PostTask(ToQueuedTask([&state, &queue, &done] {
+    // Post tasks from queue to guarantee, that 1st task won't be
+    // executed before the second one will be posted.
+    queue->PostTask(ToQueuedTask([&state] { state.state = 1; }));
+    queue->PostTask(ToQueuedTask([&state, &done] {
+      EXPECT_EQ(state.state, 1);
+      done.Set();
+    }));
+    // Check, that state changing tasks didn't start yet.
+    EXPECT_EQ(state.state, 0);
+  }));
+  EXPECT_TRUE(done.Wait(1000));
+}
+
+}  // namespace
+}  // namespace webrtc
diff --git a/api/task_queue/task_queue_test.h b/api/task_queue/task_queue_test.h
new file mode 100644
index 0000000..e2e4730
--- /dev/null
+++ b/api/task_queue/task_queue_test.h
@@ -0,0 +1,40 @@
+/*
+ *  Copyright 2019 The WebRTC Project Authors. All rights reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+#ifndef API_TASK_QUEUE_TASK_QUEUE_TEST_H_
+#define API_TASK_QUEUE_TASK_QUEUE_TEST_H_
+
+#include <functional>
+#include <memory>
+
+#include "api/task_queue/task_queue_factory.h"
+#include "test/gtest.h"
+
+namespace webrtc {
+
+// Suite of tests to verify TaskQueue implementation with.
+// Example usage:
+//
+// namespace {
+//
+// using ::testing::Values;
+// using ::webrtc::TaskQueueTest;
+//
+// std::unique_ptr<webrtc::TaskQueueFactory> CreateMyFactory();
+//
+// INSTANTIATE_TEST_SUITE_P(My, TaskQueueTest, Values(CreateMyFactory));
+//
+// }  // namespace
+class TaskQueueTest : public ::testing::TestWithParam<
+                          std::function<std::unique_ptr<TaskQueueFactory>()>> {
+};
+
+}  // namespace webrtc
+
+#endif  // API_TASK_QUEUE_TASK_QUEUE_TEST_H_
diff --git a/api/transport/field_trial_based_config.cc b/api/transport/field_trial_based_config.cc
new file mode 100644
index 0000000..7e6764f
--- /dev/null
+++ b/api/transport/field_trial_based_config.cc
@@ -0,0 +1,17 @@
+/*
+ *  Copyright 2019 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+#include "api/transport/field_trial_based_config.h"
+#include "system_wrappers/include/field_trial.h"
+
+namespace webrtc {
+std::string FieldTrialBasedConfig::Lookup(absl::string_view key) const {
+  return webrtc::field_trial::FindFullName(std::string(key));
+}
+}  // namespace webrtc
diff --git a/api/transport/field_trial_based_config.h b/api/transport/field_trial_based_config.h
new file mode 100644
index 0000000..e0989db
--- /dev/null
+++ b/api/transport/field_trial_based_config.h
@@ -0,0 +1,25 @@
+/*
+ *  Copyright 2019 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+#ifndef API_TRANSPORT_FIELD_TRIAL_BASED_CONFIG_H_
+#define API_TRANSPORT_FIELD_TRIAL_BASED_CONFIG_H_
+
+#include <string>
+#include "absl/strings/string_view.h"
+#include "api/transport/webrtc_key_value_config.h"
+
+namespace webrtc {
+// Implementation using the field trial API fo the key value lookup.
+class FieldTrialBasedConfig : public WebRtcKeyValueConfig {
+ public:
+  std::string Lookup(absl::string_view key) const override;
+};
+}  // namespace webrtc
+
+#endif  // API_TRANSPORT_FIELD_TRIAL_BASED_CONFIG_H_
diff --git a/api/transport/goog_cc_factory.cc b/api/transport/goog_cc_factory.cc
index 119e2dc..92fd4d1 100644
--- a/api/transport/goog_cc_factory.cc
+++ b/api/transport/goog_cc_factory.cc
@@ -10,8 +10,11 @@
 
 #include "api/transport/goog_cc_factory.h"
 
+#include <stdint.h>
+
 #include "absl/memory/memory.h"
 #include "modules/congestion_controller/goog_cc/goog_cc_network_control.h"
+
 namespace webrtc {
 GoogCcNetworkControllerFactory::GoogCcNetworkControllerFactory(
     RtcEventLog* event_log)
diff --git a/api/transport/network_control.h b/api/transport/network_control.h
index 9086260..53ac10e 100644
--- a/api/transport/network_control.h
+++ b/api/transport/network_control.h
@@ -14,6 +14,7 @@
 #include <memory>
 
 #include "api/transport/network_types.h"
+#include "api/transport/webrtc_key_value_config.h"
 
 namespace webrtc {
 
@@ -23,6 +24,9 @@
   // Called to indicate target transfer rate as well as giving information about
   // the current estimate of network parameters.
   virtual void OnTargetTransferRate(TargetTransferRate) = 0;
+  // Called to provide updates to the expected target rate in case it changes
+  // before the first call to OnTargetTransferRate.
+  virtual void OnStartRateUpdate(DataRate) {}
 };
 
 // Configuration sent to factory create function. The parameters here are
@@ -36,6 +40,10 @@
   // Initial stream specific configuration, these are changed at any later time
   // by calls to OnStreamsConfig.
   StreamsConfig stream_based_config;
+
+  // Optional override of configuration of WebRTC internals. Using nullptr here
+  // indicates that the field trial API will be used.
+  const WebRtcKeyValueConfig* key_value_config = nullptr;
 };
 
 // NetworkControllerInterface is implemented by network controllers. A network
diff --git a/api/transport/network_types.cc b/api/transport/network_types.cc
index 80214de..acc9c2b 100644
--- a/api/transport/network_types.cc
+++ b/api/transport/network_types.cc
@@ -81,4 +81,8 @@
          probe_cluster_min_bytes == rhs.probe_cluster_min_bytes;
 }
 
+ProcessInterval::ProcessInterval() = default;
+ProcessInterval::ProcessInterval(const ProcessInterval&) = default;
+ProcessInterval::~ProcessInterval() = default;
+
 }  // namespace webrtc
diff --git a/api/transport/network_types.h b/api/transport/network_types.h
index 0f1d7ab..e26561a 100644
--- a/api/transport/network_types.h
+++ b/api/transport/network_types.h
@@ -31,13 +31,11 @@
   StreamsConfig(const StreamsConfig&);
   ~StreamsConfig();
   Timestamp at_time = Timestamp::PlusInfinity();
-  bool requests_alr_probing = false;
+  absl::optional<bool> requests_alr_probing;
   absl::optional<double> pacing_factor;
   absl::optional<DataRate> min_pacing_rate;
   absl::optional<DataRate> max_padding_rate;
   absl::optional<DataRate> max_total_allocated_bitrate;
-  // The send rate of traffic for which feedback is not received.
-  DataRate unacknowledged_rate_allocation = DataRate::Zero();
 };
 
 struct TargetRateConstraints {
@@ -136,6 +134,7 @@
   ~TransportPacketsFeedback();
 
   Timestamp feedback_time = Timestamp::PlusInfinity();
+  Timestamp first_unacked_send_time = Timestamp::PlusInfinity();
   DataSize data_in_flight = DataSize::Zero();
   DataSize prior_in_flight = DataSize::Zero();
   std::vector<PacketResult> packet_feedbacks;
@@ -177,6 +176,7 @@
   DataRate target_data_rate = DataRate::Zero();
   TimeDelta target_duration = TimeDelta::Zero();
   int32_t target_probe_count = 0;
+  int32_t id = 0;
 };
 
 struct TargetTransferRate {
@@ -201,7 +201,11 @@
 
 // Process control
 struct ProcessInterval {
+  ProcessInterval();
+  ProcessInterval(const ProcessInterval&);
+  ~ProcessInterval();
   Timestamp at_time = Timestamp::PlusInfinity();
+  absl::optional<DataSize> pacer_queue;
 };
 }  // namespace webrtc
 
diff --git a/api/transport/webrtc_key_value_config.h b/api/transport/webrtc_key_value_config.h
new file mode 100644
index 0000000..c6376a9
--- /dev/null
+++ b/api/transport/webrtc_key_value_config.h
@@ -0,0 +1,31 @@
+/*
+ *  Copyright 2019 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+#ifndef API_TRANSPORT_WEBRTC_KEY_VALUE_CONFIG_H_
+#define API_TRANSPORT_WEBRTC_KEY_VALUE_CONFIG_H_
+
+#include <string>
+#include "absl/strings/string_view.h"
+
+namespace webrtc {
+
+// An interface that provides a key-value mapping for configuring internal
+// details of WebRTC. Note that there's no guarantess that the meaning of a
+// particular key value mapping will be preserved over time and no announcements
+// will be made if they are changed. It's up to the library user to ensure that
+// the behavior does not break.
+class WebRtcKeyValueConfig {
+ public:
+  virtual ~WebRtcKeyValueConfig() = default;
+  // The configured value for the given key. Defaults to an empty string.
+  virtual std::string Lookup(absl::string_view key) const = 0;
+};
+}  // namespace webrtc
+
+#endif  // API_TRANSPORT_WEBRTC_KEY_VALUE_CONFIG_H_
diff --git a/api/turn_customizer.h b/api/turn_customizer.h
new file mode 100644
index 0000000..f0bf0d9
--- /dev/null
+++ b/api/turn_customizer.h
@@ -0,0 +1,45 @@
+/*
+ *  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.
+ */
+
+#ifndef API_TURN_CUSTOMIZER_H_
+#define API_TURN_CUSTOMIZER_H_
+
+#include <stdlib.h>
+
+namespace cricket {
+class PortInterface;
+class StunMessage;
+}  // namespace cricket
+
+namespace webrtc {
+
+class TurnCustomizer {
+ public:
+  // This is called before a TURN message is sent.
+  // This could be used to add implementation specific attributes to a request.
+  virtual void MaybeModifyOutgoingStunMessage(
+      cricket::PortInterface* port,
+      cricket::StunMessage* message) = 0;
+
+  // TURN can send data using channel data messages or Send indication.
+  // This method should return false if |data| should be sent using
+  // a Send indication instead of a ChannelData message, even if a
+  // channel is bound.
+  virtual bool AllowChannelData(cricket::PortInterface* port,
+                                const void* data,
+                                size_t size,
+                                bool payload) = 0;
+
+  virtual ~TurnCustomizer() {}
+};
+
+}  // namespace webrtc
+
+#endif  // API_TURN_CUSTOMIZER_H_
diff --git a/api/uma_metrics.h b/api/uma_metrics.h
new file mode 100644
index 0000000..51b0ff0
--- /dev/null
+++ b/api/uma_metrics.h
@@ -0,0 +1,168 @@
+/*
+ *  Copyright 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.
+ */
+
+// This file contains enums related to IPv4/IPv6 metrics.
+
+#ifndef API_UMA_METRICS_H_
+#define API_UMA_METRICS_H_
+
+#include "rtc_base/ref_count.h"
+
+namespace webrtc {
+
+// Currently this contains information related to WebRTC network/transport
+// information.
+
+// The difference between PeerConnectionEnumCounter and
+// PeerConnectionMetricsName is that the "EnumCounter" is only counting the
+// occurrences of events, while "Name" has a value associated with it which is
+// used to form a histogram.
+
+// This enum is backed by Chromium's histograms.xml,
+// chromium/src/tools/metrics/histograms/histograms.xml
+// Existing values cannot be re-ordered and new enums must be added
+// before kBoundary.
+enum PeerConnectionAddressFamilyCounter {
+  kPeerConnection_IPv4,
+  kPeerConnection_IPv6,
+  kBestConnections_IPv4,
+  kBestConnections_IPv6,
+  kPeerConnectionAddressFamilyCounter_Max,
+};
+
+// TODO(guoweis): Keep previous name here until all references are renamed.
+#define kBoundary kPeerConnectionAddressFamilyCounter_Max
+
+// TODO(guoweis): Keep previous name here until all references are renamed.
+typedef PeerConnectionAddressFamilyCounter PeerConnectionUMAMetricsCounter;
+
+// This enum defines types for UMA samples, which will have a range.
+enum PeerConnectionMetricsName {
+  kNetworkInterfaces_IPv4,  // Number of IPv4 interfaces.
+  kNetworkInterfaces_IPv6,  // Number of IPv6 interfaces.
+  kTimeToConnect,           // In milliseconds.
+  kLocalCandidates_IPv4,    // Number of IPv4 local candidates.
+  kLocalCandidates_IPv6,    // Number of IPv6 local candidates.
+  kPeerConnectionMetricsName_Max
+};
+
+// TODO(guoweis): Keep previous name here until all references are renamed.
+typedef PeerConnectionMetricsName PeerConnectionUMAMetricsName;
+
+// The IceCandidatePairType has the format of
+// <local_candidate_type>_<remote_candidate_type>. It is recorded based on the
+// type of candidate pair used when the PeerConnection first goes to a completed
+// state. When BUNDLE is enabled, only the first transport gets recorded.
+enum IceCandidatePairType {
+  // HostHost is deprecated. It was replaced with the set of types at the bottom
+  // to report private or public host IP address.
+  kIceCandidatePairHostHost,
+  kIceCandidatePairHostSrflx,
+  kIceCandidatePairHostRelay,
+  kIceCandidatePairHostPrflx,
+  kIceCandidatePairSrflxHost,
+  kIceCandidatePairSrflxSrflx,
+  kIceCandidatePairSrflxRelay,
+  kIceCandidatePairSrflxPrflx,
+  kIceCandidatePairRelayHost,
+  kIceCandidatePairRelaySrflx,
+  kIceCandidatePairRelayRelay,
+  kIceCandidatePairRelayPrflx,
+  kIceCandidatePairPrflxHost,
+  kIceCandidatePairPrflxSrflx,
+  kIceCandidatePairPrflxRelay,
+
+  // The following 9 types tell whether local and remote hosts have hostname,
+  // private or public IP addresses.
+  kIceCandidatePairHostPrivateHostPrivate,
+  kIceCandidatePairHostPrivateHostPublic,
+  kIceCandidatePairHostPublicHostPrivate,
+  kIceCandidatePairHostPublicHostPublic,
+  kIceCandidatePairHostNameHostName,
+  kIceCandidatePairHostNameHostPrivate,
+  kIceCandidatePairHostNameHostPublic,
+  kIceCandidatePairHostPrivateHostName,
+  kIceCandidatePairHostPublicHostName,
+  kIceCandidatePairMax
+};
+
+enum KeyExchangeProtocolType {
+  kEnumCounterKeyProtocolDtls,
+  kEnumCounterKeyProtocolSdes,
+  kEnumCounterKeyProtocolMax
+};
+
+enum KeyExchangeProtocolMedia {
+  kEnumCounterKeyProtocolMediaTypeDtlsAudio,
+  kEnumCounterKeyProtocolMediaTypeDtlsVideo,
+  kEnumCounterKeyProtocolMediaTypeDtlsData,
+  kEnumCounterKeyProtocolMediaTypeSdesAudio,
+  kEnumCounterKeyProtocolMediaTypeSdesVideo,
+  kEnumCounterKeyProtocolMediaTypeSdesData,
+  kEnumCounterKeyProtocolMediaTypeMax
+};
+
+enum SdpSemanticRequested {
+  kSdpSemanticRequestDefault,
+  kSdpSemanticRequestPlanB,
+  kSdpSemanticRequestUnifiedPlan,
+  kSdpSemanticRequestMax
+};
+
+enum SdpSemanticNegotiated {
+  kSdpSemanticNegotiatedNone,
+  kSdpSemanticNegotiatedPlanB,
+  kSdpSemanticNegotiatedUnifiedPlan,
+  kSdpSemanticNegotiatedMixed,
+  kSdpSemanticNegotiatedMax
+};
+
+// Metric which records the format of the received SDP for tracking how much the
+// difference between Plan B and Unified Plan affect users.
+enum SdpFormatReceived {
+  // No audio or video tracks. This is worth special casing since it seems to be
+  // the most common scenario (data-channel only).
+  kSdpFormatReceivedNoTracks,
+  // No more than one audio and one video track. Should be compatible with both
+  // Plan B and Unified Plan endpoints.
+  kSdpFormatReceivedSimple,
+  // More than one audio track or more than one video track in the Plan B format
+  // (e.g., one audio media section with multiple streams).
+  kSdpFormatReceivedComplexPlanB,
+  // More than one audio track or more than one video track in the Unified Plan
+  // format (e.g., two audio media sections).
+  kSdpFormatReceivedComplexUnifiedPlan,
+  kSdpFormatReceivedMax
+};
+
+// Metric for counting the outcome of adding an ICE candidate
+enum AddIceCandidateResult {
+  kAddIceCandidateSuccess,
+  kAddIceCandidateFailClosed,
+  kAddIceCandidateFailNoRemoteDescription,
+  kAddIceCandidateFailNullCandidate,
+  kAddIceCandidateFailNotValid,
+  kAddIceCandidateFailNotReady,
+  kAddIceCandidateFailInAddition,
+  kAddIceCandidateFailNotUsable,
+  kAddIceCandidateMax
+};
+
+// Metric for recording which api surface was used to enable simulcast.
+enum SimulcastApiVersion {
+  kSimulcastApiVersionNone,
+  kSimulcastApiVersionLegacy,
+  kSimulcastApiVersionSpecCompliant,
+  kSimulcastApiVersionMax,
+};
+
+}  // namespace webrtc
+
+#endif  // API_UMA_METRICS_H_
diff --git a/api/units/data_rate.cc b/api/units/data_rate.cc
index d72d958..f9586c5 100644
--- a/api/units/data_rate.cc
+++ b/api/units/data_rate.cc
@@ -10,6 +10,7 @@
 
 #include "api/units/data_rate.h"
 
+#include "api/array_view.h"
 #include "rtc_base/strings/string_builder.h"
 
 namespace webrtc {
@@ -17,8 +18,10 @@
 std::string ToString(DataRate value) {
   char buf[64];
   rtc::SimpleStringBuilder sb(buf);
-  if (value.IsInfinite()) {
-    sb << "inf bps";
+  if (value.IsPlusInfinity()) {
+    sb << "+inf bps";
+  } else if (value.IsMinusInfinity()) {
+    sb << "-inf bps";
   } else {
     if (value.bps() == 0 || value.bps() % 1000 != 0) {
       sb << value.bps() << " bps";
diff --git a/api/units/data_rate.h b/api/units/data_rate.h
index 7119284..9b09aa9 100644
--- a/api/units/data_rate.h
+++ b/api/units/data_rate.h
@@ -52,10 +52,17 @@
   }
   template <typename T>
   static constexpr DataRate bps(T bits_per_second) {
+    static_assert(std::is_arithmetic<T>::value, "");
     return FromValue(bits_per_second);
   }
   template <typename T>
+  static constexpr DataRate bytes_per_sec(T bytes_per_second) {
+    static_assert(std::is_arithmetic<T>::value, "");
+    return FromFraction<8>(bytes_per_second);
+  }
+  template <typename T>
   static constexpr DataRate kbps(T kilobits_per_sec) {
+    static_assert(std::is_arithmetic<T>::value, "");
     return FromFraction<1000>(kilobits_per_sec);
   }
   template <typename T = int64_t>
@@ -63,6 +70,10 @@
     return ToValue<T>();
   }
   template <typename T = int64_t>
+  constexpr T bytes_per_sec() const {
+    return ToFraction<8, T>();
+  }
+  template <typename T = int64_t>
   T kbps() const {
     return ToFraction<1000, T>();
   }
diff --git a/api/units/data_size.cc b/api/units/data_size.cc
index 8a87786..45487df 100644
--- a/api/units/data_size.cc
+++ b/api/units/data_size.cc
@@ -10,6 +10,7 @@
 
 #include "api/units/data_size.h"
 
+#include "api/array_view.h"
 #include "rtc_base/strings/string_builder.h"
 
 namespace webrtc {
@@ -17,8 +18,10 @@
 std::string ToString(DataSize value) {
   char buf[64];
   rtc::SimpleStringBuilder sb(buf);
-  if (value.IsInfinite()) {
-    sb << "inf bytes";
+  if (value.IsPlusInfinity()) {
+    sb << "+inf bytes";
+  } else if (value.IsMinusInfinity()) {
+    sb << "-inf bytes";
   } else {
     sb << value.bytes() << " bytes";
   }
diff --git a/api/units/data_size.h b/api/units/data_size.h
index b4cbb65..90ef00d 100644
--- a/api/units/data_size.h
+++ b/api/units/data_size.h
@@ -31,14 +31,13 @@
     return FromStaticValue<bytes>();
   }
 
-  template <
-      typename T,
-      typename std::enable_if<std::is_arithmetic<T>::value>::type* = nullptr>
+  template <typename T>
   static DataSize bytes(T bytes) {
+    static_assert(std::is_arithmetic<T>::value, "");
     return FromValue(bytes);
   }
   template <typename T = int64_t>
-  typename std::enable_if<std::is_arithmetic<T>::value, T>::type bytes() const {
+  T bytes() const {
     return ToValue<T>();
   }
 
diff --git a/api/units/time_delta.cc b/api/units/time_delta.cc
index f90451b..9fe1308 100644
--- a/api/units/time_delta.cc
+++ b/api/units/time_delta.cc
@@ -10,6 +10,7 @@
 
 #include "api/units/time_delta.h"
 
+#include "api/array_view.h"
 #include "rtc_base/strings/string_builder.h"
 
 namespace webrtc {
diff --git a/api/units/time_delta.h b/api/units/time_delta.h
index 6458369..e5172f4 100644
--- a/api/units/time_delta.h
+++ b/api/units/time_delta.h
@@ -46,14 +46,17 @@
   }
   template <typename T>
   static TimeDelta seconds(T seconds) {
+    static_assert(std::is_arithmetic<T>::value, "");
     return FromFraction<1000000>(seconds);
   }
   template <typename T>
   static TimeDelta ms(T milliseconds) {
+    static_assert(std::is_arithmetic<T>::value, "");
     return FromFraction<1000>(milliseconds);
   }
   template <typename T>
   static TimeDelta us(T microseconds) {
+    static_assert(std::is_arithmetic<T>::value, "");
     return FromValue(microseconds);
   }
   template <typename T = int64_t>
diff --git a/api/units/timestamp.cc b/api/units/timestamp.cc
index d3417cf..0b9cdd9 100644
--- a/api/units/timestamp.cc
+++ b/api/units/timestamp.cc
@@ -10,14 +10,17 @@
 
 #include "api/units/timestamp.h"
 
+#include "api/array_view.h"
 #include "rtc_base/strings/string_builder.h"
 
 namespace webrtc {
 std::string ToString(Timestamp value) {
   char buf[64];
   rtc::SimpleStringBuilder sb(buf);
-  if (value.IsInfinite()) {
-    sb << "inf ms";
+  if (value.IsPlusInfinity()) {
+    sb << "+inf ms";
+  } else if (value.IsMinusInfinity()) {
+    sb << "-inf ms";
   } else {
     if (value.ms() % 1000 == 0)
       sb << value.seconds() << " s";
diff --git a/api/units/timestamp.h b/api/units/timestamp.h
index a6e450f..370a091 100644
--- a/api/units/timestamp.h
+++ b/api/units/timestamp.h
@@ -45,14 +45,17 @@
 
   template <typename T>
   static Timestamp seconds(T seconds) {
+    static_assert(std::is_arithmetic<T>::value, "");
     return FromFraction<1000000>(seconds);
   }
   template <typename T>
   static Timestamp ms(T milliseconds) {
+    static_assert(std::is_arithmetic<T>::value, "");
     return FromFraction<1000>(milliseconds);
   }
   template <typename T>
   static Timestamp us(T microseconds) {
+    static_assert(std::is_arithmetic<T>::value, "");
     return FromValue(microseconds);
   }
   template <typename T = int64_t>
diff --git a/api/video/builtin_video_bitrate_allocator_factory.cc b/api/video/builtin_video_bitrate_allocator_factory.cc
index 70f6ad0..b01e5c2 100644
--- a/api/video/builtin_video_bitrate_allocator_factory.cc
+++ b/api/video/builtin_video_bitrate_allocator_factory.cc
@@ -11,7 +11,9 @@
 #include "api/video/builtin_video_bitrate_allocator_factory.h"
 
 #include "absl/memory/memory.h"
-#include "media/base/codec.h"
+#include "api/video/video_bitrate_allocator.h"
+#include "api/video_codecs/video_codec.h"
+#include "common_types.h"  // NOLINT(build/include)
 #include "modules/video_coding/codecs/vp9/svc_rate_allocator.h"
 #include "modules/video_coding/utility/default_video_bitrate_allocator.h"
 #include "modules/video_coding/utility/simulcast_rate_allocator.h"
diff --git a/api/video/color_space.cc b/api/video/color_space.cc
index ad138ab..710bb43 100644
--- a/api/video/color_space.cc
+++ b/api/video/color_space.cc
@@ -10,6 +10,7 @@
 
 #include "api/video/color_space.h"
 
+namespace webrtc {
 namespace {
 // Try to convert |enum_value| into the enum class T. |enum_bitmask| is created
 // by the funciton below. Returns true if conversion was successful, false
@@ -50,9 +51,17 @@
   return MakeMask(0, N, values);
 }
 
-}  // namespace
+bool SetChromaSitingFromUint8(uint8_t enum_value,
+                              ColorSpace::ChromaSiting* chroma_siting) {
+  constexpr ColorSpace::ChromaSiting kChromaSitings[] = {
+      ColorSpace::ChromaSiting::kUnspecified,
+      ColorSpace::ChromaSiting::kCollocated, ColorSpace::ChromaSiting::kHalf};
+  constexpr uint64_t enum_bitmask = CreateEnumBitmask(kChromaSitings);
 
-namespace webrtc {
+  return SetFromUint8(enum_value, enum_bitmask, chroma_siting);
+}
+
+}  // namespace
 
 ColorSpace::ColorSpace() = default;
 ColorSpace::ColorSpace(const ColorSpace& other) = default;
@@ -63,17 +72,27 @@
                        TransferID transfer,
                        MatrixID matrix,
                        RangeID range)
-    : ColorSpace(primaries, transfer, matrix, range, nullptr) {}
+    : ColorSpace(primaries,
+                 transfer,
+                 matrix,
+                 range,
+                 ChromaSiting::kUnspecified,
+                 ChromaSiting::kUnspecified,
+                 nullptr) {}
 
 ColorSpace::ColorSpace(PrimaryID primaries,
                        TransferID transfer,
                        MatrixID matrix,
                        RangeID range,
+                       ChromaSiting chroma_siting_horz,
+                       ChromaSiting chroma_siting_vert,
                        const HdrMetadata* hdr_metadata)
     : primaries_(primaries),
       transfer_(transfer),
       matrix_(matrix),
       range_(range),
+      chroma_siting_horizontal_(chroma_siting_horz),
+      chroma_siting_vertical_(chroma_siting_vert),
       hdr_metadata_(hdr_metadata ? absl::make_optional(*hdr_metadata)
                                  : absl::nullopt) {}
 
@@ -93,17 +112,24 @@
   return range_;
 }
 
+ColorSpace::ChromaSiting ColorSpace::chroma_siting_horizontal() const {
+  return chroma_siting_horizontal_;
+}
+
+ColorSpace::ChromaSiting ColorSpace::chroma_siting_vertical() const {
+  return chroma_siting_vertical_;
+}
+
 const HdrMetadata* ColorSpace::hdr_metadata() const {
   return hdr_metadata_ ? &*hdr_metadata_ : nullptr;
 }
 
 bool ColorSpace::set_primaries_from_uint8(uint8_t enum_value) {
   constexpr PrimaryID kPrimaryIds[] = {
-      PrimaryID::kInvalid,    PrimaryID::kBT709,      PrimaryID::kUNSPECIFIED,
-      PrimaryID::kBT470M,     PrimaryID::kBT470BG,    PrimaryID::kSMPTE170M,
-      PrimaryID::kSMPTE240M,  PrimaryID::kFILM,       PrimaryID::kBT2020,
-      PrimaryID::kSMPTEST428, PrimaryID::kSMPTEST431, PrimaryID::kSMPTEST432,
-      PrimaryID::kJEDECP22};
+      PrimaryID::kBT709,      PrimaryID::kUnspecified, PrimaryID::kBT470M,
+      PrimaryID::kBT470BG,    PrimaryID::kSMPTE170M,   PrimaryID::kSMPTE240M,
+      PrimaryID::kFILM,       PrimaryID::kBT2020,      PrimaryID::kSMPTEST428,
+      PrimaryID::kSMPTEST431, PrimaryID::kSMPTEST432,  PrimaryID::kJEDECP22};
   constexpr uint64_t enum_bitmask = CreateEnumBitmask(kPrimaryIds);
 
   return SetFromUint8(enum_value, enum_bitmask, &primaries_);
@@ -111,15 +137,15 @@
 
 bool ColorSpace::set_transfer_from_uint8(uint8_t enum_value) {
   constexpr TransferID kTransferIds[] = {
-      TransferID::kInvalid,      TransferID::kBT709,
-      TransferID::kUNSPECIFIED,  TransferID::kGAMMA22,
-      TransferID::kGAMMA28,      TransferID::kSMPTE170M,
-      TransferID::kSMPTE240M,    TransferID::kLINEAR,
-      TransferID::kLOG,          TransferID::kLOG_SQRT,
-      TransferID::kIEC61966_2_4, TransferID::kBT1361_ECG,
-      TransferID::kIEC61966_2_1, TransferID::kBT2020_10,
-      TransferID::kBT2020_12,    TransferID::kSMPTEST2084,
-      TransferID::kSMPTEST428,   TransferID::kARIB_STD_B67};
+      TransferID::kBT709,       TransferID::kUnspecified,
+      TransferID::kGAMMA22,     TransferID::kGAMMA28,
+      TransferID::kSMPTE170M,   TransferID::kSMPTE240M,
+      TransferID::kLINEAR,      TransferID::kLOG,
+      TransferID::kLOG_SQRT,    TransferID::kIEC61966_2_4,
+      TransferID::kBT1361_ECG,  TransferID::kIEC61966_2_1,
+      TransferID::kBT2020_10,   TransferID::kBT2020_12,
+      TransferID::kSMPTEST2084, TransferID::kSMPTEST428,
+      TransferID::kARIB_STD_B67};
   constexpr uint64_t enum_bitmask = CreateEnumBitmask(kTransferIds);
 
   return SetFromUint8(enum_value, enum_bitmask, &transfer_);
@@ -127,11 +153,11 @@
 
 bool ColorSpace::set_matrix_from_uint8(uint8_t enum_value) {
   constexpr MatrixID kMatrixIds[] = {
-      MatrixID::kRGB,       MatrixID::kBT709,        MatrixID::kUNSPECIFIED,
-      MatrixID::kFCC,       MatrixID::kBT470BG,      MatrixID::kSMPTE170M,
-      MatrixID::kSMPTE240M, MatrixID::kYCOCG,        MatrixID::kBT2020_NCL,
-      MatrixID::kBT2020_CL, MatrixID::kSMPTE2085,    MatrixID::kCDNCLS,
-      MatrixID::kCDCLS,     MatrixID::kBT2100_ICTCP, MatrixID::kInvalid};
+      MatrixID::kRGB,       MatrixID::kBT709,       MatrixID::kUnspecified,
+      MatrixID::kFCC,       MatrixID::kBT470BG,     MatrixID::kSMPTE170M,
+      MatrixID::kSMPTE240M, MatrixID::kYCOCG,       MatrixID::kBT2020_NCL,
+      MatrixID::kBT2020_CL, MatrixID::kSMPTE2085,   MatrixID::kCDNCLS,
+      MatrixID::kCDCLS,     MatrixID::kBT2100_ICTCP};
   constexpr uint64_t enum_bitmask = CreateEnumBitmask(kMatrixIds);
 
   return SetFromUint8(enum_value, enum_bitmask, &matrix_);
@@ -145,6 +171,14 @@
   return SetFromUint8(enum_value, enum_bitmask, &range_);
 }
 
+bool ColorSpace::set_chroma_siting_horizontal_from_uint8(uint8_t enum_value) {
+  return SetChromaSitingFromUint8(enum_value, &chroma_siting_horizontal_);
+}
+
+bool ColorSpace::set_chroma_siting_vertical_from_uint8(uint8_t enum_value) {
+  return SetChromaSitingFromUint8(enum_value, &chroma_siting_vertical_);
+}
+
 void ColorSpace::set_hdr_metadata(const HdrMetadata* hdr_metadata) {
   hdr_metadata_ =
       hdr_metadata ? absl::make_optional(*hdr_metadata) : absl::nullopt;
diff --git a/api/video/color_space.h b/api/video/color_space.h
index 79a15f5..91b4e17 100644
--- a/api/video/color_space.h
+++ b/api/video/color_space.h
@@ -35,9 +35,8 @@
  public:
   enum class PrimaryID : uint8_t {
     // The indices are equal to the values specified in T-REC H.273 Table 2.
-    kInvalid = 0,
     kBT709 = 1,
-    kUNSPECIFIED = 2,
+    kUnspecified = 2,
     kBT470M = 4,
     kBT470BG = 5,
     kSMPTE170M = 6,  // Identical to BT601
@@ -54,9 +53,8 @@
 
   enum class TransferID : uint8_t {
     // The indices are equal to the values specified in T-REC H.273 Table 3.
-    kInvalid = 0,
     kBT709 = 1,
-    kUNSPECIFIED = 2,
+    kUnspecified = 2,
     kGAMMA22 = 4,
     kGAMMA28 = 5,
     kSMPTE170M = 6,
@@ -80,7 +78,7 @@
     // The indices are equal to the values specified in T-REC H.273 Table 4.
     kRGB = 0,
     kBT709 = 1,
-    kUNSPECIFIED = 2,
+    kUnspecified = 2,
     kFCC = 4,
     kBT470BG = 5,
     kSMPTE170M = 6,
@@ -92,7 +90,6 @@
     kCDNCLS = 12,
     kCDCLS = 13,
     kBT2100_ICTCP = 14,
-    kInvalid = 63,
     // When adding/removing entries here, please make sure to do the
     // corresponding change to kMatrixIds.
   };
@@ -111,6 +108,19 @@
     // corresponding change to kRangeIds.
   };
 
+  enum class ChromaSiting {
+    // Chroma siting specifies how chroma is subsampled relative to the luma
+    // samples in a YUV video frame.
+    // The indices are equal to the values specified at
+    // https://www.webmproject.org/docs/container/#colour for the element
+    // ChromaSitingVert and ChromaSitingHorz.
+    kUnspecified = 0,
+    kCollocated = 1,
+    kHalf = 2,
+    // When adding/removing entries here, please make sure to do the
+    // corresponding change to kChromaSitings.
+  };
+
   ColorSpace();
   ColorSpace(const ColorSpace& other);
   ColorSpace(ColorSpace&& other);
@@ -118,40 +128,50 @@
   ColorSpace(PrimaryID primaries,
              TransferID transfer,
              MatrixID matrix,
-             RangeID full_range);
+             RangeID range);
   ColorSpace(PrimaryID primaries,
              TransferID transfer,
              MatrixID matrix,
              RangeID range,
+             ChromaSiting chroma_siting_horizontal,
+             ChromaSiting chroma_siting_vertical,
              const HdrMetadata* hdr_metadata);
-  bool operator==(const ColorSpace& other) const {
-    return primaries_ == other.primaries() && transfer_ == other.transfer() &&
-           matrix_ == other.matrix() && range_ == other.range() &&
-           ((hdr_metadata_.has_value() && other.hdr_metadata() &&
-             *hdr_metadata_ == *other.hdr_metadata()) ||
-            (!hdr_metadata_.has_value() && other.hdr_metadata() == nullptr));
+  friend bool operator==(const ColorSpace& lhs, const ColorSpace& rhs) {
+    return lhs.primaries_ == rhs.primaries_ && lhs.transfer_ == rhs.transfer_ &&
+           lhs.matrix_ == rhs.matrix_ && lhs.range_ == rhs.range_ &&
+           lhs.chroma_siting_horizontal_ == rhs.chroma_siting_horizontal_ &&
+           lhs.chroma_siting_vertical_ == rhs.chroma_siting_vertical_ &&
+           lhs.hdr_metadata_ == rhs.hdr_metadata_;
+  }
+  friend bool operator!=(const ColorSpace& lhs, const ColorSpace& rhs) {
+    return !(lhs == rhs);
   }
 
   PrimaryID primaries() const;
   TransferID transfer() const;
   MatrixID matrix() const;
   RangeID range() const;
+  ChromaSiting chroma_siting_horizontal() const;
+  ChromaSiting chroma_siting_vertical() const;
   const HdrMetadata* hdr_metadata() const;
 
   bool set_primaries_from_uint8(uint8_t enum_value);
   bool set_transfer_from_uint8(uint8_t enum_value);
   bool set_matrix_from_uint8(uint8_t enum_value);
   bool set_range_from_uint8(uint8_t enum_value);
+  bool set_chroma_siting_horizontal_from_uint8(uint8_t enum_value);
+  bool set_chroma_siting_vertical_from_uint8(uint8_t enum_value);
   void set_hdr_metadata(const HdrMetadata* hdr_metadata);
 
  private:
-  PrimaryID primaries_ = PrimaryID::kInvalid;
-  TransferID transfer_ = TransferID::kInvalid;
-  MatrixID matrix_ = MatrixID::kInvalid;
+  PrimaryID primaries_ = PrimaryID::kUnspecified;
+  TransferID transfer_ = TransferID::kUnspecified;
+  MatrixID matrix_ = MatrixID::kUnspecified;
   RangeID range_ = RangeID::kInvalid;
+  ChromaSiting chroma_siting_horizontal_ = ChromaSiting::kUnspecified;
+  ChromaSiting chroma_siting_vertical_ = ChromaSiting::kUnspecified;
   absl::optional<HdrMetadata> hdr_metadata_;
 };
 
 }  // namespace webrtc
-
 #endif  // API_VIDEO_COLOR_SPACE_H_
diff --git a/api/video/encoded_frame.h b/api/video/encoded_frame.h
index b8462c6..fa06568 100644
--- a/api/video/encoded_frame.h
+++ b/api/video/encoded_frame.h
@@ -13,6 +13,9 @@
 
 #include "modules/video_coding/encoded_frame.h"
 
+#include <stddef.h>
+#include <stdint.h>
+
 namespace webrtc {
 namespace video_coding {
 
@@ -56,8 +59,6 @@
   EncodedFrame() = default;
   virtual ~EncodedFrame() {}
 
-  virtual bool GetBitstream(uint8_t* destination) const = 0;
-
   // When this frame was received.
   virtual int64_t ReceivedTime() const = 0;
 
@@ -69,8 +70,6 @@
   //                 been implemented.
   virtual bool delayed_by_retransmission() const;
 
-  size_t size() const { return _length; }
-
   bool is_keyframe() const { return num_references == 0; }
 
   VideoLayerFrameId id;
@@ -80,6 +79,9 @@
   size_t num_references = 0;
   int64_t references[kMaxFrameReferences];
   bool inter_layer_predicted = false;
+  // Is this subframe the last one in the superframe (In RTP stream that would
+  // mean that the last packet has a marker bit set).
+  bool is_last_spatial_layer = true;
 };
 
 }  // namespace video_coding
diff --git a/api/video/encoded_image.cc b/api/video/encoded_image.cc
index e7c6fad..d1fa046 100644
--- a/api/video/encoded_image.cc
+++ b/api/video/encoded_image.cc
@@ -29,10 +29,23 @@
 
 EncodedImage::EncodedImage() : EncodedImage(nullptr, 0, 0) {}
 
+EncodedImage::EncodedImage(EncodedImage&&) = default;
 EncodedImage::EncodedImage(const EncodedImage&) = default;
 
-EncodedImage::EncodedImage(uint8_t* buffer, size_t length, size_t size)
-    : _buffer(buffer), _length(length), _size(size) {}
+EncodedImage::EncodedImage(uint8_t* buffer, size_t size, size_t capacity)
+    : size_(size), buffer_(buffer), capacity_(capacity) {}
+
+EncodedImage::~EncodedImage() = default;
+
+EncodedImage& EncodedImage::operator=(EncodedImage&&) = default;
+EncodedImage& EncodedImage::operator=(const EncodedImage&) = default;
+
+void EncodedImage::Retain() {
+  if (buffer_) {
+    encoded_data_.SetData(buffer_, size_);
+    buffer_ = nullptr;
+  }
+}
 
 void EncodedImage::SetEncodeTime(int64_t encode_start_ms,
                                  int64_t encode_finish_ms) {
diff --git a/api/video/encoded_image.h b/api/video/encoded_image.h
index a7c719c..1d3bd46 100644
--- a/api/video/encoded_image.h
+++ b/api/video/encoded_image.h
@@ -15,13 +15,14 @@
 
 #include "absl/types/optional.h"
 #include "api/video/color_space.h"
-#include "api/video/video_bitrate_allocation.h"
+#include "api/video/video_codec_constants.h"
 #include "api/video/video_codec_type.h"
 #include "api/video/video_content_type.h"
 #include "api/video/video_rotation.h"
 #include "api/video/video_timing.h"
 #include "common_types.h"  // NOLINT(build/include)
 #include "rtc_base/checks.h"
+#include "rtc_base/copy_on_write_buffer.h"
 #include "rtc_base/system/rtc_export.h"
 
 namespace webrtc {
@@ -37,8 +38,16 @@
   static size_t GetBufferPaddingBytes(VideoCodecType codec_type);
 
   EncodedImage();
+  EncodedImage(EncodedImage&&);
+  // Discouraged: potentially expensive.
   EncodedImage(const EncodedImage&);
-  EncodedImage(uint8_t* buffer, size_t length, size_t size);
+  EncodedImage(uint8_t* buffer, size_t length, size_t capacity);
+
+  ~EncodedImage();
+
+  EncodedImage& operator=(EncodedImage&&);
+  // Discouraged: potentially expensive.
+  EncodedImage& operator=(const EncodedImage&);
 
   // TODO(nisse): Change style to timestamp(), set_timestamp(), for consistency
   // with the VideoFrame class.
@@ -62,20 +71,51 @@
   const webrtc::ColorSpace* ColorSpace() const {
     return color_space_ ? &*color_space_ : nullptr;
   }
-  void SetColorSpace(const webrtc::ColorSpace* color_space) {
-    color_space_ =
-        color_space ? absl::make_optional(*color_space) : absl::nullopt;
+  void SetColorSpace(const absl::optional<webrtc::ColorSpace>& color_space) {
+    color_space_ = color_space;
   }
 
+  size_t size() const { return size_; }
+  void set_size(size_t new_size) {
+    RTC_DCHECK_LE(new_size, capacity());
+    size_ = new_size;
+  }
+  size_t capacity() const { return buffer_ ? capacity_ : encoded_data_.size(); }
+
+  void set_buffer(uint8_t* buffer, size_t capacity) {
+    buffer_ = buffer;
+    capacity_ = capacity;
+  }
+
+  void Allocate(size_t capacity) {
+    encoded_data_.SetSize(capacity);
+    buffer_ = nullptr;
+  }
+
+  uint8_t* data() { return buffer_ ? buffer_ : encoded_data_.data(); }
+  const uint8_t* data() const {
+    return buffer_ ? buffer_ : encoded_data_.cdata();
+  }
+  // TODO(nisse): At some places, code accepts a const ref EncodedImage, but
+  // still writes to it, to clear padding at the end of the encoded data.
+  // Padding is required by ffmpeg; the best way to deal with that is likely to
+  // make this class ensure that buffers always have a few zero padding bytes.
+  uint8_t* mutable_data() const { return const_cast<uint8_t*>(data()); }
+
+  // TODO(bugs.webrtc.org/9378): Delete. Used by code that wants to modify a
+  // buffer corresponding to a const EncodedImage. Requires an un-owned buffer.
+  uint8_t* buffer() const { return buffer_; }
+
+  // Hack to workaround lack of ownership of the encoded data. If we don't
+  // already own the underlying data, make an owned copy.
+  void Retain();
+
   uint32_t _encodedWidth = 0;
   uint32_t _encodedHeight = 0;
   // NTP time of the capture time in local timebase in milliseconds.
   int64_t ntp_time_ms_ = 0;
   int64_t capture_time_ms_ = 0;
   FrameType _frameType = kVideoFrameDelta;
-  uint8_t* _buffer;
-  size_t _length;
-  size_t _size;
   VideoRotation rotation_ = kVideoRotation_0;
   VideoContentType content_type_ = VideoContentType::UNSPECIFIED;
   bool _completeFrame = false;
@@ -99,6 +139,14 @@
   } timing_;
 
  private:
+  // TODO(bugs.webrtc.org/9378): We're transitioning to always owning the
+  // encoded data.
+  rtc::CopyOnWriteBuffer encoded_data_;
+  size_t size_;      // Size of encoded frame data.
+  // Non-null when used with an un-owned buffer.
+  uint8_t* buffer_;
+  // Allocated size of _buffer; relevant only if it's non-null.
+  size_t capacity_;
   uint32_t timestamp_rtp_ = 0;
   absl::optional<int> spatial_index_;
   absl::optional<webrtc::ColorSpace> color_space_;
diff --git a/api/video/hdr_metadata.h b/api/video/hdr_metadata.h
index 676a900..e9001a2 100644
--- a/api/video/hdr_metadata.h
+++ b/api/video/hdr_metadata.h
@@ -11,27 +11,47 @@
 #ifndef API_VIDEO_HDR_METADATA_H_
 #define API_VIDEO_HDR_METADATA_H_
 
-#include <stdint.h>
-
 namespace webrtc {
 
 // SMPTE ST 2086 mastering metadata,
 // see https://ieeexplore.ieee.org/document/8353899.
 struct HdrMasteringMetadata {
   struct Chromaticity {
-    // xy chromaticity coordinates must be calculated as specified in ISO
-    // 11664-3:2012 Section 7, and must be specified with four decimal places.
-    // The x coordinate must be in the range [0.0001, 0.7400] and the y
-    // coordinate must be in the range [0.0001, 0.8400].
-    float x = 0.0f;
-    float y = 0.0f;
+    Chromaticity();
+
     bool operator==(const Chromaticity& rhs) const {
       return x == rhs.x && y == rhs.y;
     }
 
-    Chromaticity();
+    bool Validate() const {
+      return x >= 0.0 && x <= 1.0 && y >= 0.0 && y <= 1.0;
+    }
+
+    // xy chromaticity coordinates must be calculated as specified in ISO
+    // 11664-3:2012 Section 7, and must be specified with four decimal places.
+    // The x coordinate should be in the range [0.0001, 0.7400] and the y
+    // coordinate should be in the range [0.0001, 0.8400]. Valid range [0.0000,
+    // 1.0000].
+    float x = 0.0f;
+    float y = 0.0f;
   };
 
+  HdrMasteringMetadata();
+
+  bool operator==(const HdrMasteringMetadata& rhs) const {
+    return ((primary_r == rhs.primary_r) && (primary_g == rhs.primary_g) &&
+            (primary_b == rhs.primary_b) && (white_point == rhs.white_point) &&
+            (luminance_max == rhs.luminance_max) &&
+            (luminance_min == rhs.luminance_min));
+  }
+
+  bool Validate() const {
+    return luminance_max >= 0.0 && luminance_max <= 20000.0 &&
+           luminance_min >= 0.0 && luminance_min <= 5.0 &&
+           primary_r.Validate() && primary_g.Validate() &&
+           primary_b.Validate() && white_point.Validate();
+  }
+
   // The nominal primaries of the mastering display.
   Chromaticity primary_r;
   Chromaticity primary_g;
@@ -41,37 +61,20 @@
   Chromaticity white_point;
 
   // The nominal maximum display luminance of the mastering display. Specified
-  // in the unit candela/m2. The value must be in the range [5, 10000] with zero
-  // decimal places.
+  // in the unit candela/m2. The value should be in the range [5, 10000] with
+  // zero decimal places. Valid range [0, 20000].
   float luminance_max = 0.0f;
 
   // The nominal minimum display luminance of the mastering display. Specified
-  // in the unit candela/m2. The value must be in the range [0.0001, 5.0000]
-  // with four decimal places.
+  // in the unit candela/m2. The value should be in the range [0.0001, 5.0000]
+  // with four decimal places. Valid range [0.0000, 5.0000].
   float luminance_min = 0.0f;
-
-  HdrMasteringMetadata();
-
-  bool operator==(const HdrMasteringMetadata& rhs) const {
-    return ((primary_r == rhs.primary_r) && (primary_g == rhs.primary_g) &&
-            (primary_b == rhs.primary_b) && (white_point == rhs.white_point) &&
-            (luminance_max == rhs.luminance_max) &&
-            (luminance_min == rhs.luminance_min));
-  }
 };
 
 // High dynamic range (HDR) metadata common for HDR10 and WebM/VP9-based HDR
 // formats. This struct replicates the HDRMetadata struct defined in
 // https://cs.chromium.org/chromium/src/media/base/hdr_metadata.h
 struct HdrMetadata {
-  HdrMasteringMetadata mastering_metadata;
-  // Max content light level (CLL), i.e. maximum brightness level present in the
-  // stream, in nits. 1 nit = 1 candela/m2.
-  uint32_t max_content_light_level = 0;
-  // Max frame-average light level (FALL), i.e. maximum average brightness of
-  // the brightest frame in the stream, in nits.
-  uint32_t max_frame_average_light_level = 0;
-
   HdrMetadata();
 
   bool operator==(const HdrMetadata& rhs) const {
@@ -80,6 +83,21 @@
         (max_frame_average_light_level == rhs.max_frame_average_light_level) &&
         (mastering_metadata == rhs.mastering_metadata));
   }
+
+  bool Validate() const {
+    return max_content_light_level >= 0 && max_content_light_level <= 20000 &&
+           max_frame_average_light_level >= 0 &&
+           max_frame_average_light_level <= 20000 &&
+           mastering_metadata.Validate();
+  }
+
+  HdrMasteringMetadata mastering_metadata;
+  // Max content light level (CLL), i.e. maximum brightness level present in the
+  // stream, in nits. 1 nit = 1 candela/m2. Valid range [0, 20000].
+  int max_content_light_level = 0;
+  // Max frame-average light level (FALL), i.e. maximum average brightness of
+  // the brightest frame in the stream, in nits. Valid range [0, 20000].
+  int max_frame_average_light_level = 0;
 };
 
 }  // namespace webrtc
diff --git a/api/video/i010_buffer.cc b/api/video/i010_buffer.cc
index adb5a5e..7286676 100644
--- a/api/video/i010_buffer.cc
+++ b/api/video/i010_buffer.cc
@@ -9,14 +9,12 @@
  */
 #include "api/video/i010_buffer.h"
 
-#include <algorithm>
 #include <utility>
 
 #include "api/video/i420_buffer.h"
 #include "rtc_base/checks.h"
-#include "rtc_base/refcountedobject.h"
+#include "rtc_base/ref_counted_object.h"
 #include "third_party/libyuv/include/libyuv/convert.h"
-#include "third_party/libyuv/include/libyuv/planar_functions.h"
 #include "third_party/libyuv/include/libyuv/scale.h"
 
 // Aligning pointer to 64 bytes for improved performance, e.g. use SIMD.
@@ -234,4 +232,35 @@
   CropAndScaleFrom(src, 0, 0, src.width(), src.height());
 }
 
+void I010Buffer::PasteFrom(const I010BufferInterface& picture,
+                           int offset_col,
+                           int offset_row) {
+  RTC_CHECK_LE(picture.width() + offset_col, width());
+  RTC_CHECK_LE(picture.height() + offset_row, height());
+  RTC_CHECK_GE(offset_col, 0);
+  RTC_CHECK_GE(offset_row, 0);
+
+  // Pasted picture has to be aligned so subsumpled UV plane isn't corrupted.
+  RTC_CHECK(offset_col % 2 == 0);
+  RTC_CHECK(offset_row % 2 == 0);
+  RTC_CHECK(picture.width() % 2 == 0 ||
+            picture.width() + offset_col == width());
+  RTC_CHECK(picture.height() % 2 == 0 ||
+            picture.height() + offset_row == height());
+
+  libyuv::CopyPlane_16(picture.DataY(), picture.StrideY(),
+                       MutableDataY() + StrideY() * offset_row + offset_col,
+                       StrideY(), picture.width(), picture.height());
+
+  libyuv::CopyPlane_16(
+      picture.DataU(), picture.StrideU(),
+      MutableDataU() + StrideU() * offset_row / 2 + offset_col / 2, StrideU(),
+      picture.width() / 2, picture.height() / 2);
+
+  libyuv::CopyPlane_16(
+      picture.DataV(), picture.StrideV(),
+      MutableDataV() + StrideV() * offset_row / 2 + offset_col / 2, StrideV(),
+      picture.width() / 2, picture.height() / 2);
+}
+
 }  // namespace webrtc
diff --git a/api/video/i010_buffer.h b/api/video/i010_buffer.h
index 1208b31..4b35ca3 100644
--- a/api/video/i010_buffer.h
+++ b/api/video/i010_buffer.h
@@ -11,8 +11,10 @@
 #ifndef API_VIDEO_I010_BUFFER_H_
 #define API_VIDEO_I010_BUFFER_H_
 
+#include <stdint.h>
 #include <memory>
 
+#include "api/scoped_refptr.h"
 #include "api/video/video_frame_buffer.h"
 #include "api/video/video_rotation.h"
 #include "rtc_base/memory/aligned_malloc.h"
@@ -63,6 +65,12 @@
   // Scale all of |src| to the size of |this| buffer, with no cropping.
   void ScaleFrom(const I010BufferInterface& src);
 
+  // Pastes whole picture to canvas at (offset_row, offset_col).
+  // Offsets and picture dimensions must be even.
+  void PasteFrom(const I010BufferInterface& picture,
+                 int offset_col,
+                 int offset_row);
+
  protected:
   I010Buffer(int width, int height, int stride_y, int stride_u, int stride_v);
   ~I010Buffer() override;
diff --git a/api/video/i420_buffer.cc b/api/video/i420_buffer.cc
index 8d239f3..46de581 100644
--- a/api/video/i420_buffer.cc
+++ b/api/video/i420_buffer.cc
@@ -10,12 +10,11 @@
 #include "api/video/i420_buffer.h"
 
 #include <string.h>
-
 #include <algorithm>
 #include <utility>
 
 #include "rtc_base/checks.h"
-#include "rtc_base/keep_ref_until_done.h"
+#include "rtc_base/ref_counted_object.h"
 #include "third_party/libyuv/include/libyuv/convert.h"
 #include "third_party/libyuv/include/libyuv/planar_functions.h"
 #include "third_party/libyuv/include/libyuv/scale.h"
@@ -227,4 +226,35 @@
   CropAndScaleFrom(src, 0, 0, src.width(), src.height());
 }
 
+void I420Buffer::PasteFrom(const I420BufferInterface& picture,
+                           int offset_col,
+                           int offset_row) {
+  RTC_CHECK_LE(picture.width() + offset_col, width());
+  RTC_CHECK_LE(picture.height() + offset_row, height());
+  RTC_CHECK_GE(offset_col, 0);
+  RTC_CHECK_GE(offset_row, 0);
+
+  // Pasted picture has to be aligned so subsumpled UV plane isn't corrupted.
+  RTC_CHECK(offset_col % 2 == 0);
+  RTC_CHECK(offset_row % 2 == 0);
+  RTC_CHECK(picture.width() % 2 == 0 ||
+            picture.width() + offset_col == width());
+  RTC_CHECK(picture.height() % 2 == 0 ||
+            picture.height() + offset_row == height());
+
+  libyuv::CopyPlane(picture.DataY(), picture.StrideY(),
+                    MutableDataY() + StrideY() * offset_row + offset_col,
+                    StrideY(), picture.width(), picture.height());
+
+  libyuv::CopyPlane(
+      picture.DataU(), picture.StrideU(),
+      MutableDataU() + StrideU() * offset_row / 2 + offset_col / 2, StrideU(),
+      picture.width() / 2, picture.height() / 2);
+
+  libyuv::CopyPlane(
+      picture.DataV(), picture.StrideV(),
+      MutableDataV() + StrideV() * offset_row / 2 + offset_col / 2, StrideV(),
+      picture.width() / 2, picture.height() / 2);
+}
+
 }  // namespace webrtc
diff --git a/api/video/i420_buffer.h b/api/video/i420_buffer.h
index 631e394..b76a507 100644
--- a/api/video/i420_buffer.h
+++ b/api/video/i420_buffer.h
@@ -14,10 +14,10 @@
 #include <stdint.h>
 #include <memory>
 
+#include "api/scoped_refptr.h"
 #include "api/video/video_frame_buffer.h"
 #include "api/video/video_rotation.h"
 #include "rtc_base/memory/aligned_malloc.h"
-#include "rtc_base/scoped_ref_ptr.h"
 #include "rtc_base/system/rtc_export.h"
 
 namespace webrtc {
@@ -97,6 +97,12 @@
   // Scale all of |src| to the size of |this| buffer, with no cropping.
   void ScaleFrom(const I420BufferInterface& src);
 
+  // Pastes whole picture to canvas at (offset_row, offset_col).
+  // Offsets and picture dimensions must be even.
+  void PasteFrom(const I420BufferInterface& picture,
+                 int offset_col,
+                 int offset_row);
+
  protected:
   I420Buffer(int width, int height);
   I420Buffer(int width, int height, int stride_y, int stride_u, int stride_v);
diff --git a/api/video/video_bitrate_allocation.h b/api/video/video_bitrate_allocation.h
index d1771b4..ef64226 100644
--- a/api/video/video_bitrate_allocation.h
+++ b/api/video/video_bitrate_allocation.h
@@ -18,14 +18,10 @@
 #include <vector>
 
 #include "absl/types/optional.h"
+#include "api/video/video_codec_constants.h"
 
 namespace webrtc {
 
-// TODO(sprang): Move back to common_types when include of this is removed.
-enum : int { kMaxSimulcastStreams = 4 };
-enum : int { kMaxSpatialLayers = 5 };
-enum : int { kMaxTemporalStreams = 4 };
-
 // Class that describes how video bitrate, in bps, is allocated across temporal
 // and spatial layers. Not that bitrates are NOT cumulative. Depending on if
 // layers are dependent or not, it is up to the user to aggregate.
diff --git a/api/video/video_codec_constants.h b/api/video/video_codec_constants.h
new file mode 100644
index 0000000..a3f7cd2
--- /dev/null
+++ b/api/video/video_codec_constants.h
@@ -0,0 +1,22 @@
+/*
+ *  Copyright (c) 2019 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef API_VIDEO_VIDEO_CODEC_CONSTANTS_H_
+#define API_VIDEO_VIDEO_CODEC_CONSTANTS_H_
+
+namespace webrtc {
+
+enum : int { kMaxSimulcastStreams = 4 };
+enum : int { kMaxSpatialLayers = 5 };
+enum : int { kMaxTemporalStreams = 4 };
+
+}  // namespace webrtc
+
+#endif  // API_VIDEO_VIDEO_CODEC_CONSTANTS_H_
diff --git a/api/video/video_codec_type.h b/api/video/video_codec_type.h
index 447723c..2e406c0 100644
--- a/api/video/video_codec_type.h
+++ b/api/video/video_codec_type.h
@@ -21,7 +21,6 @@
   kVideoCodecVP8,
   kVideoCodecVP9,
   kVideoCodecH264,
-  kVideoCodecI420,
   kVideoCodecMultiplex,
 };
 
diff --git a/api/video/video_frame.cc b/api/video/video_frame.cc
index eaae33b..7a71f43 100644
--- a/api/video/video_frame.cc
+++ b/api/video/video_frame.cc
@@ -10,18 +10,63 @@
 
 #include "api/video/video_frame.h"
 
+#include <algorithm>
+
 #include "rtc_base/checks.h"
-#include "rtc_base/timeutils.h"
+#include "rtc_base/time_utils.h"
 
 namespace webrtc {
 
+void VideoFrame::UpdateRect::Union(const UpdateRect& other) {
+  if (other.IsEmpty())
+    return;
+  if (IsEmpty()) {
+    *this = other;
+    return;
+  }
+  int right = std::max(offset_x + width, other.offset_x + other.width);
+  int bottom = std::max(offset_y + height, other.offset_y + other.height);
+  offset_x = std::min(offset_x, other.offset_x);
+  offset_y = std::min(offset_y, other.offset_y);
+  width = right - offset_x;
+  height = bottom - offset_y;
+  RTC_DCHECK_GT(width, 0);
+  RTC_DCHECK_GT(height, 0);
+}
+
+void VideoFrame::UpdateRect::Intersect(const UpdateRect& other) {
+  if (other.IsEmpty() || IsEmpty()) {
+    MakeEmptyUpdate();
+    return;
+  }
+
+  int right = std::min(offset_x + width, other.offset_x + other.width);
+  int bottom = std::min(offset_y + height, other.offset_y + other.height);
+  offset_x = std::max(offset_x, other.offset_x);
+  offset_y = std::max(offset_y, other.offset_y);
+  width = right - offset_x;
+  height = bottom - offset_y;
+  if (width <= 0 || height <= 0) {
+    MakeEmptyUpdate();
+  }
+}
+
+void VideoFrame::UpdateRect::MakeEmptyUpdate() {
+  width = height = offset_x = offset_y = 0;
+}
+
+bool VideoFrame::UpdateRect::IsEmpty() const {
+  return width == 0 && height == 0;
+}
+
 VideoFrame::Builder::Builder() = default;
 
 VideoFrame::Builder::~Builder() = default;
 
 VideoFrame VideoFrame::Builder::build() {
-  return VideoFrame(video_frame_buffer_, timestamp_us_, timestamp_rtp_,
-                    ntp_time_ms_, rotation_, color_space_);
+  RTC_CHECK(video_frame_buffer_ != nullptr);
+  return VideoFrame(id_, video_frame_buffer_, timestamp_us_, timestamp_rtp_,
+                    ntp_time_ms_, rotation_, color_space_, update_rect_);
 }
 
 VideoFrame::Builder& VideoFrame::Builder::set_video_frame_buffer(
@@ -59,7 +104,7 @@
 }
 
 VideoFrame::Builder& VideoFrame::Builder::set_color_space(
-    const ColorSpace& color_space) {
+    const absl::optional<ColorSpace>& color_space) {
   color_space_ = color_space;
   return *this;
 }
@@ -71,6 +116,17 @@
   return *this;
 }
 
+VideoFrame::Builder& VideoFrame::Builder::set_id(uint16_t id) {
+  id_ = id;
+  return *this;
+}
+
+VideoFrame::Builder& VideoFrame::Builder::set_update_rect(
+    const VideoFrame::UpdateRect& update_rect) {
+  update_rect_ = update_rect;
+  return *this;
+}
+
 VideoFrame::VideoFrame(const rtc::scoped_refptr<VideoFrameBuffer>& buffer,
                        webrtc::VideoRotation rotation,
                        int64_t timestamp_us)
@@ -78,7 +134,8 @@
       timestamp_rtp_(0),
       ntp_time_ms_(0),
       timestamp_us_(timestamp_us),
-      rotation_(rotation) {}
+      rotation_(rotation),
+      update_rect_{0, 0, buffer->width(), buffer->height()} {}
 
 VideoFrame::VideoFrame(const rtc::scoped_refptr<VideoFrameBuffer>& buffer,
                        uint32_t timestamp_rtp,
@@ -88,22 +145,33 @@
       timestamp_rtp_(timestamp_rtp),
       ntp_time_ms_(0),
       timestamp_us_(render_time_ms * rtc::kNumMicrosecsPerMillisec),
-      rotation_(rotation) {
+      rotation_(rotation),
+      update_rect_{0, 0, buffer->width(), buffer->height()} {
   RTC_DCHECK(buffer);
 }
 
-VideoFrame::VideoFrame(const rtc::scoped_refptr<VideoFrameBuffer>& buffer,
+VideoFrame::VideoFrame(uint16_t id,
+                       const rtc::scoped_refptr<VideoFrameBuffer>& buffer,
                        int64_t timestamp_us,
                        uint32_t timestamp_rtp,
                        int64_t ntp_time_ms,
                        VideoRotation rotation,
-                       const absl::optional<ColorSpace>& color_space)
-    : video_frame_buffer_(buffer),
+                       const absl::optional<ColorSpace>& color_space,
+                       const absl::optional<UpdateRect>& update_rect)
+    : id_(id),
+      video_frame_buffer_(buffer),
       timestamp_rtp_(timestamp_rtp),
       ntp_time_ms_(ntp_time_ms),
       timestamp_us_(timestamp_us),
       rotation_(rotation),
-      color_space_(color_space) {}
+      color_space_(color_space),
+      update_rect_(update_rect.value_or(UpdateRect{
+          0, 0, video_frame_buffer_->width(), video_frame_buffer_->height()})) {
+  RTC_DCHECK_GE(update_rect_.offset_x, 0);
+  RTC_DCHECK_GE(update_rect_.offset_y, 0);
+  RTC_DCHECK_LE(update_rect_.offset_x + update_rect_.width, width());
+  RTC_DCHECK_LE(update_rect_.offset_y + update_rect_.height, height());
+}
 
 VideoFrame::~VideoFrame() = default;
 
diff --git a/api/video/video_frame.h b/api/video/video_frame.h
index 2c5d081..c7dd02a 100644
--- a/api/video/video_frame.h
+++ b/api/video/video_frame.h
@@ -14,17 +14,36 @@
 #include <stdint.h>
 
 #include "absl/types/optional.h"
+#include "api/scoped_refptr.h"
 #include "api/video/color_space.h"
 #include "api/video/hdr_metadata.h"
 #include "api/video/video_frame_buffer.h"
 #include "api/video/video_rotation.h"
-#include "rtc_base/scoped_ref_ptr.h"
+#include "rtc_base/checks.h"
 #include "rtc_base/system/rtc_export.h"
 
 namespace webrtc {
 
 class RTC_EXPORT VideoFrame {
  public:
+  struct UpdateRect {
+    int offset_x;
+    int offset_y;
+    int width;
+    int height;
+
+    // Makes this UpdateRect a bounding box of this and other rect.
+    void Union(const UpdateRect& other);
+
+    // Makes this UpdateRect an intersection of this and other rect.
+    void Intersect(const UpdateRect& other);
+
+    // Sets everything to 0, making this UpdateRect a zero-size (empty) update.
+    void MakeEmptyUpdate();
+
+    bool IsEmpty() const;
+  };
+
   // Preferred way of building VideoFrame objects.
   class Builder {
    public:
@@ -39,16 +58,20 @@
     Builder& set_timestamp_rtp(uint32_t timestamp_rtp);
     Builder& set_ntp_time_ms(int64_t ntp_time_ms);
     Builder& set_rotation(VideoRotation rotation);
-    Builder& set_color_space(const ColorSpace& color_space);
+    Builder& set_color_space(const absl::optional<ColorSpace>& color_space);
     Builder& set_color_space(const ColorSpace* color_space);
+    Builder& set_id(uint16_t id);
+    Builder& set_update_rect(const UpdateRect& update_rect);
 
    private:
+    uint16_t id_ = 0;
     rtc::scoped_refptr<webrtc::VideoFrameBuffer> video_frame_buffer_;
     int64_t timestamp_us_ = 0;
     uint32_t timestamp_rtp_ = 0;
     int64_t ntp_time_ms_ = 0;
     VideoRotation rotation_ = kVideoRotation_0;
     absl::optional<ColorSpace> color_space_;
+    absl::optional<UpdateRect> update_rect_;
   };
 
   // To be deprecated. Migrate all use to Builder.
@@ -75,6 +98,15 @@
   // Get frame size in pixels.
   uint32_t size() const;
 
+  // Get frame ID. Returns 0 if ID is not set. Not guarantee to be transferred
+  // from the sender to the receiver, but preserved on single side. The id
+  // should be propagated between all frame modifications during its lifetime
+  // from capturing to sending as encoded image. It is intended to be unique
+  // over a time window of a few minutes for peer connection, to which
+  // corresponding video stream belongs to.
+  uint16_t id() const { return id_; }
+  void set_id(uint16_t id) { id_ = id; }
+
   // System monotonic clock, same timebase as rtc::TimeMicros().
   int64_t timestamp_us() const { return timestamp_us_; }
   void set_timestamp_us(int64_t timestamp_us) { timestamp_us_ = timestamp_us; }
@@ -115,8 +147,9 @@
   void set_rotation(VideoRotation rotation) { rotation_ = rotation; }
 
   // Get color space when available.
-  const ColorSpace* color_space() const {
-    return color_space_ ? &*color_space_ : nullptr;
+  const absl::optional<ColorSpace>& color_space() const { return color_space_; }
+  void set_color_space(const absl::optional<ColorSpace>& color_space) {
+    color_space_ = color_space;
   }
 
   // Get render time in milliseconds.
@@ -133,14 +166,29 @@
     return video_frame_buffer()->type() == VideoFrameBuffer::Type::kNative;
   }
 
+  // Always initialized to whole frame update, can be set by Builder or manually
+  // by |set_update_rect|.
+  UpdateRect update_rect() const { return update_rect_; }
+  // Rectangle must be within the frame dimensions.
+  void set_update_rect(const VideoFrame::UpdateRect& update_rect) {
+    RTC_DCHECK_GE(update_rect.offset_x, 0);
+    RTC_DCHECK_GE(update_rect.offset_y, 0);
+    RTC_DCHECK_LE(update_rect.offset_x + update_rect.width, width());
+    RTC_DCHECK_LE(update_rect.offset_y + update_rect.height, height());
+    update_rect_ = update_rect;
+  }
+
  private:
-  VideoFrame(const rtc::scoped_refptr<VideoFrameBuffer>& buffer,
+  VideoFrame(uint16_t id,
+             const rtc::scoped_refptr<VideoFrameBuffer>& buffer,
              int64_t timestamp_us,
              uint32_t timestamp_rtp,
              int64_t ntp_time_ms,
              VideoRotation rotation,
-             const absl::optional<ColorSpace>& color_space);
+             const absl::optional<ColorSpace>& color_space,
+             const absl::optional<UpdateRect>& update_rect);
 
+  uint16_t id_;
   // An opaque reference counted handle that stores the pixel data.
   rtc::scoped_refptr<webrtc::VideoFrameBuffer> video_frame_buffer_;
   uint32_t timestamp_rtp_;
@@ -148,6 +196,9 @@
   int64_t timestamp_us_;
   VideoRotation rotation_;
   absl::optional<ColorSpace> color_space_;
+  // Updated since the last frame area. Unless set explicitly, will always be
+  // a full frame rectangle.
+  UpdateRect update_rect_;
 };
 
 }  // namespace webrtc
diff --git a/api/video/video_frame_buffer.h b/api/video/video_frame_buffer.h
index 1e8169a..7fb603e 100644
--- a/api/video/video_frame_buffer.h
+++ b/api/video/video_frame_buffer.h
@@ -13,8 +13,8 @@
 
 #include <stdint.h>
 
-#include "rtc_base/refcount.h"
-#include "rtc_base/scoped_ref_ptr.h"
+#include "api/scoped_refptr.h"
+#include "rtc_base/ref_count.h"
 
 namespace webrtc {
 
diff --git a/api/video/video_source_interface.h b/api/video/video_source_interface.h
index 2bf7370..9d1641c 100644
--- a/api/video/video_source_interface.h
+++ b/api/video/video_source_interface.h
@@ -47,15 +47,13 @@
 template <typename VideoFrameT>
 class VideoSourceInterface {
  public:
+  virtual ~VideoSourceInterface() = default;
+
   virtual void AddOrUpdateSink(VideoSinkInterface<VideoFrameT>* sink,
                                const VideoSinkWants& wants) = 0;
   // RemoveSink must guarantee that at the time the method returns,
   // there is no current and no future calls to VideoSinkInterface::OnFrame.
   virtual void RemoveSink(VideoSinkInterface<VideoFrameT>* sink) = 0;
-
- protected:
-  // Non-public, since one shouldn't own sources via this interface.
-  virtual ~VideoSourceInterface() {}
 };
 
 }  // namespace rtc
diff --git a/api/video/video_stream_encoder_create.cc b/api/video/video_stream_encoder_create.cc
index 3147d34..875edd9 100644
--- a/api/video/video_stream_encoder_create.cc
+++ b/api/video/video_stream_encoder_create.cc
@@ -11,17 +11,30 @@
 #include "api/video/video_stream_encoder_create.h"
 
 #include "absl/memory/memory.h"
+#include "api/task_queue/global_task_queue_factory.h"
+#include "video/overuse_frame_detector.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));
+    const VideoStreamEncoderSettings& settings) {
+  return CreateVideoStreamEncoder(Clock::GetRealTimeClock(),
+                                  &GlobalTaskQueueFactory(), number_of_cores,
+                                  encoder_stats_observer, settings);
 }
+
+std::unique_ptr<VideoStreamEncoderInterface> CreateVideoStreamEncoder(
+    Clock* clock,
+    TaskQueueFactory* task_queue_factory,
+    uint32_t number_of_cores,
+    VideoStreamEncoderObserver* encoder_stats_observer,
+    const VideoStreamEncoderSettings& settings) {
+  return absl::make_unique<VideoStreamEncoder>(
+      clock, number_of_cores, encoder_stats_observer, settings,
+      absl::make_unique<OveruseFrameDetector>(encoder_stats_observer),
+      task_queue_factory);
+}
+
 }  // namespace webrtc
diff --git a/api/video/video_stream_encoder_create.h b/api/video/video_stream_encoder_create.h
index 9117273..4241626 100644
--- a/api/video/video_stream_encoder_create.h
+++ b/api/video/video_stream_encoder_create.h
@@ -11,31 +11,31 @@
 #ifndef API_VIDEO_VIDEO_STREAM_ENCODER_CREATE_H_
 #define API_VIDEO_VIDEO_STREAM_ENCODER_CREATE_H_
 
-#include <map>
+#include <stdint.h>
 #include <memory>
-#include <utility>
 
+#include "api/task_queue/task_queue_factory.h"
+#include "api/video/video_frame.h"
+#include "api/video/video_sink_interface.h"
 #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 {
+// TODO(srte): Find a way to avoid this forward declaration.
+class Clock;
 
 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);
+    const VideoStreamEncoderSettings& settings);
 
-inline std::unique_ptr<VideoStreamEncoderInterface> CreateVideoStreamEncoder(
+std::unique_ptr<VideoStreamEncoderInterface> CreateVideoStreamEncoder(
+    Clock* clock,
+    TaskQueueFactory* task_queue_factory,
     uint32_t number_of_cores,
     VideoStreamEncoderObserver* encoder_stats_observer,
-    const VideoStreamEncoderSettings& settings) {
-  return CreateVideoStreamEncoder(number_of_cores, encoder_stats_observer,
-                                  settings, nullptr);
-}
-
+    const VideoStreamEncoderSettings& settings);
 }  // 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 2f95e58..7181143 100644
--- a/api/video/video_stream_encoder_interface.h
+++ b/api/video/video_stream_encoder_interface.h
@@ -13,7 +13,8 @@
 
 #include <vector>
 
-#include "api/rtpparameters.h"  // For DegradationPreference.
+#include "api/rtp_parameters.h"  // For DegradationPreference.
+#include "api/video/video_bitrate_allocator.h"
 #include "api/video/video_sink_interface.h"
 #include "api/video/video_source_interface.h"
 #include "api/video_codecs/video_encoder.h"
@@ -21,9 +22,6 @@
 
 namespace webrtc {
 
-// TODO(nisse): Move full declaration to api/.
-class VideoBitrateAllocationObserver;
-
 // This interface represents a class responsible for creating and driving the
 // encoder(s) for a single video stream. It is also responsible for adaptation
 // decisions related to video quality, requesting reduced frame rate or
@@ -44,6 +42,7 @@
    public:
     virtual void OnEncoderConfigurationChanged(
         std::vector<VideoStream> streams,
+        VideoEncoderConfig::ContentType content_type,
         int min_transmit_bitrate_bps) = 0;
   };
 
diff --git a/api/video/video_timing.cc b/api/video/video_timing.cc
index 40de011..df1bc48 100644
--- a/api/video/video_timing.cc
+++ b/api/video/video_timing.cc
@@ -10,10 +10,21 @@
 
 #include "api/video/video_timing.h"
 
+#include "api/array_view.h"
+#include "rtc_base/logging.h"
+#include "rtc_base/numerics/safe_conversions.h"
 #include "rtc_base/strings/string_builder.h"
 
 namespace webrtc {
 
+uint16_t VideoSendTiming::GetDeltaCappedMs(int64_t base_ms, int64_t time_ms) {
+  if (time_ms < base_ms) {
+    RTC_DLOG(LS_ERROR) << "Delta " << (time_ms - base_ms)
+                       << "ms expected to be positive";
+  }
+  return rtc::saturated_cast<uint16_t>(time_ms - base_ms);
+}
+
 TimingFrameInfo::TimingFrameInfo()
     : rtp_timestamp(0),
       capture_time_ms(-1),
diff --git a/api/video/video_timing.h b/api/video/video_timing.h
index e787a45..745afbc 100644
--- a/api/video/video_timing.h
+++ b/api/video/video_timing.h
@@ -16,9 +16,6 @@
 #include <limits>
 #include <string>
 
-#include "rtc_base/checks.h"
-#include "rtc_base/numerics/safe_conversions.h"
-
 namespace webrtc {
 
 // Video timing timestamps in ms counted from capture_time_ms of a frame.
@@ -46,10 +43,7 @@
   // Used to fill this data structure as per
   // https://webrtc.org/experiments/rtp-hdrext/video-timing/ extension stores
   // 16-bit deltas of timestamps from packet capture time.
-  static uint16_t GetDeltaCappedMs(int64_t base_ms, int64_t time_ms) {
-    RTC_DCHECK_GE(time_ms, base_ms);
-    return rtc::saturated_cast<uint16_t>(time_ms - base_ms);
-  }
+  static uint16_t GetDeltaCappedMs(int64_t base_ms, int64_t time_ms);
 
   uint16_t encode_start_delta_ms;
   uint16_t encode_finish_delta_ms;
diff --git a/api/video_track_source_proxy.h b/api/video_track_source_proxy.h
new file mode 100644
index 0000000..eb11bef
--- /dev/null
+++ b/api/video_track_source_proxy.h
@@ -0,0 +1,43 @@
+/*
+ *  Copyright 2012 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_TRACK_SOURCE_PROXY_H_
+#define API_VIDEO_TRACK_SOURCE_PROXY_H_
+
+#include "api/media_stream_interface.h"
+#include "api/proxy.h"
+
+namespace webrtc {
+
+// Makes sure the real VideoTrackSourceInterface implementation is destroyed on
+// the signaling thread and marshals all method calls to the signaling thread.
+// TODO(deadbeef): Move this to .cc file and out of api/. What threads methods
+// are called on is an implementation detail.
+BEGIN_PROXY_MAP(VideoTrackSource)
+PROXY_SIGNALING_THREAD_DESTRUCTOR()
+PROXY_CONSTMETHOD0(SourceState, state)
+PROXY_CONSTMETHOD0(bool, remote)
+PROXY_CONSTMETHOD0(bool, is_screencast)
+PROXY_CONSTMETHOD0(absl::optional<bool>, needs_denoising)
+PROXY_METHOD1(bool, GetStats, Stats*)
+PROXY_WORKER_METHOD2(void,
+                     AddOrUpdateSink,
+                     rtc::VideoSinkInterface<VideoFrame>*,
+                     const rtc::VideoSinkWants&)
+PROXY_WORKER_METHOD1(void, RemoveSink, rtc::VideoSinkInterface<VideoFrame>*)
+PROXY_WORKER_METHOD1(void, SetLatency, double)
+PROXY_WORKER_CONSTMETHOD0(double, GetLatency)
+PROXY_METHOD1(void, RegisterObserver, ObserverInterface*)
+PROXY_METHOD1(void, UnregisterObserver, ObserverInterface*)
+END_PROXY_MAP()
+
+}  // namespace webrtc
+
+#endif  // API_VIDEO_TRACK_SOURCE_PROXY_H_
diff --git a/audio/BUILD.gn b/audio/BUILD.gn
index c045af6..3a1d123 100644
--- a/audio/BUILD.gn
+++ b/audio/BUILD.gn
@@ -37,15 +37,11 @@
     "transport_feedback_packet_loss_tracker.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 = [
     "../api:array_view",
     "../api:call_api",
     "../api:libjingle_peerconnection_api",
+    "../api:scoped_refptr",
     "../api:transport_api",
     "../api/audio:aec3_factory",
     "../api/audio:audio_frame_api",
@@ -61,7 +57,6 @@
     "../logging:rtc_stream_config",
     "../modules/audio_coding",
     "../modules/audio_coding:audio_encoder_cng",
-    "../modules/audio_coding:audio_format_conversion",
     "../modules/audio_coding:audio_network_adaptor_config",
     "../modules/audio_device",
     "../modules/audio_processing",
@@ -79,7 +74,7 @@
     "../rtc_base:rtc_base_approved",
     "../rtc_base:rtc_task_queue",
     "../rtc_base:safe_minmax",
-    "../rtc_base:stringutils",
+    "../rtc_base/experiments:audio_allocation_settings",
     "../system_wrappers",
     "../system_wrappers:field_trial",
     "../system_wrappers:metrics",
@@ -104,12 +99,8 @@
       "../system_wrappers:system_wrappers",
       "../test:test_common",
       "../test:test_support",
+      "//third_party/abseil-cpp/absl/memory",
     ]
-
-    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_tests") {
@@ -148,6 +139,7 @@
       "../logging:rtc_event_log_api",
       "../modules/audio_device:mock_audio_device",
       "../rtc_base:rtc_base_tests_utils",
+      "../test:field_trial",
 
       # For TestAudioDeviceModule
       "../modules/audio_device:audio_device_impl",
@@ -163,6 +155,7 @@
       "../rtc_base:rtc_base_approved",
       "../rtc_base:rtc_task_queue",
       "../rtc_base:safe_compare",
+      "../rtc_base:timeutils",
       "../system_wrappers:system_wrappers",
       "../test:audio_codec_mocks",
       "../test:rtp_test_utils",
@@ -172,11 +165,6 @@
       "//testing/gtest",
       "//third_party/abseil-cpp/absl/memory",
     ]
-
-    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" ]
-    }
   }
 
   if (rtc_enable_protobuf) {
@@ -206,11 +194,6 @@
         "../resources/voice_engine/audio_tiny16.wav",
         "../resources/voice_engine/audio_tiny48.wav",
       ]
-
-      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" ]
-      }
     }
 
     group("low_bandwidth_audio_perf_test") {
@@ -280,10 +263,5 @@
     data = [
       "//resources/voice_engine/audio_dtx16.wav",
     ]
-
-    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" ]
-    }
   }
 }
diff --git a/audio/audio_level.h b/audio/audio_level.h
index 3bbe5fd..bb04cc0 100644
--- a/audio/audio_level.h
+++ b/audio/audio_level.h
@@ -11,7 +11,7 @@
 #ifndef AUDIO_AUDIO_LEVEL_H_
 #define AUDIO_AUDIO_LEVEL_H_
 
-#include "rtc_base/criticalsection.h"
+#include "rtc_base/critical_section.h"
 #include "rtc_base/thread_annotations.h"
 
 namespace webrtc {
diff --git a/audio/audio_receive_stream.cc b/audio/audio_receive_stream.cc
index 8d4afe0..b7b68d0 100644
--- a/audio/audio_receive_stream.cc
+++ b/audio/audio_receive_stream.cc
@@ -17,7 +17,7 @@
 #include "api/array_view.h"
 #include "api/audio_codecs/audio_format.h"
 #include "api/call/audio_sink.h"
-#include "api/rtpparameters.h"
+#include "api/rtp_parameters.h"
 #include "audio/audio_send_stream.h"
 #include "audio/audio_state.h"
 #include "audio/channel_receive.h"
@@ -27,7 +27,7 @@
 #include "rtc_base/checks.h"
 #include "rtc_base/logging.h"
 #include "rtc_base/strings/string_builder.h"
-#include "rtc_base/timeutils.h"
+#include "rtc_base/time_utils.h"
 
 namespace webrtc {
 
@@ -67,6 +67,7 @@
 namespace internal {
 namespace {
 std::unique_ptr<voe::ChannelReceiveInterface> CreateChannelReceive(
+    Clock* clock,
     webrtc::AudioState* audio_state,
     ProcessThread* module_process_thread,
     const webrtc::AudioReceiveStream::Config& config,
@@ -75,33 +76,37 @@
   internal::AudioState* internal_audio_state =
       static_cast<internal::AudioState*>(audio_state);
   return voe::CreateChannelReceive(
-      module_process_thread, internal_audio_state->audio_device_module(),
+      clock, module_process_thread, internal_audio_state->audio_device_module(),
       config.media_transport, config.rtcp_send_transport, event_log,
       config.rtp.remote_ssrc, config.jitter_buffer_max_packets,
       config.jitter_buffer_fast_accelerate, config.jitter_buffer_min_delay_ms,
-      config.decoder_factory, config.codec_pair_id, config.frame_decryptor,
-      config.crypto_options);
+      config.jitter_buffer_enable_rtx_handling, config.decoder_factory,
+      config.codec_pair_id, config.frame_decryptor, config.crypto_options);
 }
 }  // namespace
 
 AudioReceiveStream::AudioReceiveStream(
+    Clock* clock,
     RtpStreamReceiverControllerInterface* receiver_controller,
     PacketRouter* packet_router,
     ProcessThread* module_process_thread,
     const webrtc::AudioReceiveStream::Config& config,
     const rtc::scoped_refptr<webrtc::AudioState>& audio_state,
     webrtc::RtcEventLog* event_log)
-    : AudioReceiveStream(receiver_controller,
+    : AudioReceiveStream(clock,
+                         receiver_controller,
                          packet_router,
                          config,
                          audio_state,
                          event_log,
-                         CreateChannelReceive(audio_state.get(),
+                         CreateChannelReceive(clock,
+                                              audio_state.get(),
                                               module_process_thread,
                                               config,
                                               event_log)) {}
 
 AudioReceiveStream::AudioReceiveStream(
+    Clock* clock,
     RtpStreamReceiverControllerInterface* receiver_controller,
     PacketRouter* packet_router,
     const webrtc::AudioReceiveStream::Config& config,
@@ -175,8 +180,8 @@
       channel_receive_->GetRTCPStatistics();
   // TODO(solenberg): Don't return here if we can't get the codec - return the
   //                  stats we *can* get.
-  webrtc::CodecInst codec_inst = {0};
-  if (!channel_receive_->GetRecCodec(&codec_inst)) {
+  auto receive_codec = channel_receive_->GetReceiveCodec();
+  if (!receive_codec) {
     return stats;
   }
 
@@ -185,13 +190,12 @@
   stats.packets_lost = call_stats.cumulativeLost;
   stats.fraction_lost = Q8ToFloat(call_stats.fractionLost);
   stats.capture_start_ntp_time_ms = call_stats.capture_start_ntp_time_ms_;
-  if (codec_inst.pltype != -1) {
-    stats.codec_name = codec_inst.plname;
-    stats.codec_payload_type = codec_inst.pltype;
-  }
+  stats.codec_name = receive_codec->second.name;
+  stats.codec_payload_type = receive_codec->first;
   stats.ext_seqnum = call_stats.extendedMax;
-  if (codec_inst.plfreq / 1000 > 0) {
-    stats.jitter_ms = call_stats.jitterSamples / (codec_inst.plfreq / 1000);
+  int clockrate_khz = receive_codec->second.clockrate_hz / 1000;
+  if (clockrate_khz > 0) {
+    stats.jitter_ms = call_stats.jitterSamples / clockrate_khz;
   }
   stats.delay_estimate_ms = channel_receive_->GetDelayEstimate();
   stats.audio_level = channel_receive_->GetSpeechOutputLevelFullRange();
@@ -208,6 +212,7 @@
   stats.jitter_buffer_delay_seconds =
       static_cast<double>(ns.jitterBufferDelayMs) /
       static_cast<double>(rtc::kNumMillisecsPerSec);
+  stats.jitter_buffer_emitted_count = ns.jitterBufferEmittedCount;
   stats.expand_rate = Q14ToFloat(ns.currentExpandRate);
   stats.speech_expand_rate = Q14ToFloat(ns.currentSpeechExpandRate);
   stats.secondary_decoded_rate = Q14ToFloat(ns.currentSecondaryDecodedRate);
@@ -216,6 +221,9 @@
   stats.preemptive_expand_rate = Q14ToFloat(ns.currentPreemptiveRate);
   stats.jitter_buffer_flushes = ns.packetBufferFlushes;
   stats.delayed_packet_outage_samples = ns.delayedPacketOutageSamples;
+  stats.relative_packet_arrival_delay_seconds =
+      static_cast<double>(ns.relativePacketArrivalDelayMs) /
+      static_cast<double>(rtc::kNumMillisecsPerSec);
 
   auto ds = channel_receive_->GetDecodingCallStatistics();
   stats.decoding_calls_to_silence_generator = ds.calls_to_silence_generator;
@@ -239,6 +247,16 @@
   channel_receive_->SetChannelOutputVolumeScaling(gain);
 }
 
+bool AudioReceiveStream::SetBaseMinimumPlayoutDelayMs(int delay_ms) {
+  RTC_DCHECK_RUN_ON(&worker_thread_checker_);
+  return channel_receive_->SetBaseMinimumPlayoutDelayMs(delay_ms);
+}
+
+int AudioReceiveStream::GetBaseMinimumPlayoutDelayMs() const {
+  RTC_DCHECK_RUN_ON(&worker_thread_checker_);
+  return channel_receive_->GetBaseMinimumPlayoutDelayMs();
+}
+
 std::vector<RtpSource> AudioReceiveStream::GetSources() const {
   RTC_DCHECK_RUN_ON(&worker_thread_checker_);
   return channel_receive_->GetSources();
diff --git a/audio/audio_receive_stream.h b/audio/audio_receive_stream.h
index 86bcb1c..1745c0f 100644
--- a/audio/audio_receive_stream.h
+++ b/audio/audio_receive_stream.h
@@ -19,8 +19,9 @@
 #include "audio/audio_state.h"
 #include "call/audio_receive_stream.h"
 #include "call/syncable.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 #include "rtc_base/thread_checker.h"
+#include "system_wrappers/include/clock.h"
 
 namespace webrtc {
 class PacketRouter;
@@ -41,7 +42,8 @@
                                  public AudioMixer::Source,
                                  public Syncable {
  public:
-  AudioReceiveStream(RtpStreamReceiverControllerInterface* receiver_controller,
+  AudioReceiveStream(Clock* clock,
+                     RtpStreamReceiverControllerInterface* receiver_controller,
                      PacketRouter* packet_router,
                      ProcessThread* module_process_thread,
                      const webrtc::AudioReceiveStream::Config& config,
@@ -49,6 +51,7 @@
                      webrtc::RtcEventLog* event_log);
   // For unit tests, which need to supply a mock channel receive.
   AudioReceiveStream(
+      Clock* clock,
       RtpStreamReceiverControllerInterface* receiver_controller,
       PacketRouter* packet_router,
       const webrtc::AudioReceiveStream::Config& config,
@@ -64,6 +67,8 @@
   webrtc::AudioReceiveStream::Stats GetStats() const override;
   void SetSink(AudioSinkInterface* sink) override;
   void SetGain(float gain) override;
+  bool SetBaseMinimumPlayoutDelayMs(int delay_ms) override;
+  int GetBaseMinimumPlayoutDelayMs() const override;
   std::vector<webrtc::RtpSource> GetSources() const override;
 
   // TODO(nisse): We don't formally implement RtpPacketSinkInterface, and this
diff --git a/audio/audio_receive_stream_unittest.cc b/audio/audio_receive_stream_unittest.cc
index 7422810..4594e56 100644
--- a/audio/audio_receive_stream_unittest.cc
+++ b/audio/audio_receive_stream_unittest.cc
@@ -10,6 +10,7 @@
 
 #include <map>
 #include <string>
+#include <utility>
 #include <vector>
 
 #include "api/test/mock_audio_mixer.h"
@@ -24,6 +25,7 @@
 #include "modules/bitrate_controller/include/mock/mock_bitrate_controller.h"
 #include "modules/pacing/packet_router.h"
 #include "modules/rtp_rtcp/source/byte_io.h"
+#include "rtc_base/time_utils.h"
 #include "test/gtest.h"
 #include "test/mock_audio_decoder_factory.h"
 #include "test/mock_transport.h"
@@ -63,10 +65,11 @@
 
 const CallReceiveStatistics kCallStats = {345, 678, 901, 234,
                                           -12, 567, 890, 123};
-const CodecInst kCodecInst = {123, "codec_name_recv", 96000, -187, 0, -103};
+const std::pair<int, SdpAudioFormat> kReceiveCodec =
+    {123, {"codec_name_recv", 96000, 0}};
 const NetworkStatistics kNetworkStats = {
-    123, 456, false, 789012, 3456, 123, 456, 0,  {}, 789, 12,
-    345, 678, 901,   0,      -1,   -1,  -1,  -1, -1, 0};
+    123, 456, false, 789012, 3456, 123, 456, 789, 0,  {}, 789,
+    12,  345, 678,   901,    0,    -1,  -1,  -1,  -1, -1, 0};
 const AudioDecodingCallStats kAudioDecodeStats = MakeAudioDecodeStatsForTest();
 
 struct ConfigHelper {
@@ -112,8 +115,8 @@
   std::unique_ptr<internal::AudioReceiveStream> CreateAudioReceiveStream() {
     return std::unique_ptr<internal::AudioReceiveStream>(
         new internal::AudioReceiveStream(
-            &rtp_stream_receiver_controller_, &packet_router_, stream_config_,
-            audio_state_, &event_log_,
+            Clock::GetRealTimeClock(), &rtp_stream_receiver_controller_,
+            &packet_router_, stream_config_, audio_state_, &event_log_,
             std::unique_ptr<voe::ChannelReceiveInterface>(channel_receive_)));
   }
 
@@ -140,8 +143,8 @@
         .WillOnce(Return(kNetworkStats));
     EXPECT_CALL(*channel_receive_, GetDecodingCallStatistics())
         .WillOnce(Return(kAudioDecodeStats));
-    EXPECT_CALL(*channel_receive_, GetRecCodec(_))
-        .WillOnce(DoAll(SetArgPointee<0>(kCodecInst), Return(true)));
+    EXPECT_CALL(*channel_receive_, GetReceiveCodec())
+        .WillOnce(Return(kReceiveCodec));
   }
 
  private:
@@ -267,10 +270,11 @@
             stats.packets_rcvd);
   EXPECT_EQ(kCallStats.cumulativeLost, stats.packets_lost);
   EXPECT_EQ(Q8ToFloat(kCallStats.fractionLost), stats.fraction_lost);
-  EXPECT_EQ(std::string(kCodecInst.plname), stats.codec_name);
+  EXPECT_EQ(kReceiveCodec.second.name, stats.codec_name);
   EXPECT_EQ(kCallStats.extendedMax, stats.ext_seqnum);
-  EXPECT_EQ(kCallStats.jitterSamples / (kCodecInst.plfreq / 1000),
-            stats.jitter_ms);
+  EXPECT_EQ(
+      kCallStats.jitterSamples / (kReceiveCodec.second.clockrate_hz / 1000),
+      stats.jitter_ms);
   EXPECT_EQ(kNetworkStats.currentBufferSize, stats.jitter_buffer_ms);
   EXPECT_EQ(kNetworkStats.preferredBufferSize,
             stats.jitter_buffer_preferred_ms);
@@ -285,6 +289,8 @@
   EXPECT_EQ(static_cast<double>(kNetworkStats.jitterBufferDelayMs) /
                 static_cast<double>(rtc::kNumMillisecsPerSec),
             stats.jitter_buffer_delay_seconds);
+  EXPECT_EQ(kNetworkStats.jitterBufferEmittedCount,
+            stats.jitter_buffer_emitted_count);
   EXPECT_EQ(Q14ToFloat(kNetworkStats.currentExpandRate), stats.expand_rate);
   EXPECT_EQ(Q14ToFloat(kNetworkStats.currentSpeechExpandRate),
             stats.speech_expand_rate);
diff --git a/audio/audio_send_stream.cc b/audio/audio_send_stream.cc
index 75e6efb..bb79149 100644
--- a/audio/audio_send_stream.cc
+++ b/audio/audio_send_stream.cc
@@ -19,7 +19,7 @@
 #include "api/audio_codecs/audio_encoder_factory.h"
 #include "api/audio_codecs/audio_format.h"
 #include "api/call/transport.h"
-#include "api/crypto/frameencryptorinterface.h"
+#include "api/crypto/frame_encryptor_interface.h"
 #include "audio/audio_state.h"
 #include "audio/channel_send.h"
 #include "audio/conversion.h"
@@ -37,7 +37,6 @@
 #include "rtc_base/logging.h"
 #include "rtc_base/strings/audio_format_to_string.h"
 #include "rtc_base/task_queue.h"
-#include "rtc_base/timeutils.h"
 #include "system_wrappers/include/field_trial.h"
 
 namespace webrtc {
@@ -48,14 +47,6 @@
 constexpr size_t kPacketLossRateMinNumAckedPackets = 50;
 constexpr size_t kRecoverablePacketLossRateMinNumAckedPairs = 40;
 
-void CallEncoder(const std::unique_ptr<voe::ChannelSendInterface>& channel_send,
-                 rtc::FunctionView<void(AudioEncoder*)> lambda) {
-  channel_send->ModifyEncoder([&](std::unique_ptr<AudioEncoder>* encoder_ptr) {
-    RTC_DCHECK(encoder_ptr);
-    lambda(encoder_ptr->get());
-  });
-}
-
 void UpdateEventLogStreamConfig(RtcEventLog* event_log,
                                 const AudioSendStream::Config& config,
                                 const AudioSendStream::Config* old_config) {
@@ -91,6 +82,7 @@
 }  // namespace
 
 AudioSendStream::AudioSendStream(
+    Clock* clock,
     const webrtc::AudioSendStream::Config& config,
     const rtc::scoped_refptr<webrtc::AudioState>& audio_state,
     rtc::TaskQueue* worker_queue,
@@ -100,7 +92,8 @@
     RtcEventLog* event_log,
     RtcpRttStats* rtcp_rtt_stats,
     const absl::optional<RtpState>& suspended_rtp_state)
-    : AudioSendStream(config,
+    : AudioSendStream(clock,
+                      config,
                       audio_state,
                       worker_queue,
                       rtp_transport,
@@ -108,9 +101,11 @@
                       event_log,
                       rtcp_rtt_stats,
                       suspended_rtp_state,
-                      voe::CreateChannelSend(worker_queue,
+                      voe::CreateChannelSend(clock,
+                                             worker_queue,
                                              module_process_thread,
                                              config.media_transport,
+                                             /*overhead_observer=*/this,
                                              config.send_transport,
                                              rtcp_rtt_stats,
                                              event_log,
@@ -120,6 +115,7 @@
                                              config.rtcp_report_interval_ms)) {}
 
 AudioSendStream::AudioSendStream(
+    Clock* clock,
     const webrtc::AudioSendStream::Config& config,
     const rtc::scoped_refptr<webrtc::AudioState>& audio_state,
     rtc::TaskQueue* worker_queue,
@@ -129,7 +125,8 @@
     RtcpRttStats* rtcp_rtt_stats,
     const absl::optional<RtpState>& suspended_rtp_state,
     std::unique_ptr<voe::ChannelSendInterface> channel_send)
-    : worker_queue_(worker_queue),
+    : clock_(clock),
+      worker_queue_(worker_queue),
       config_(Config(/*send_transport=*/nullptr,
                      /*media_transport=*/nullptr)),
       audio_state_(audio_state),
@@ -152,7 +149,15 @@
   // should be no rtp_transport, and below check should be strengthened to XOR
   // (either rtp_transport or media_transport but not both).
   RTC_DCHECK(rtp_transport || config.media_transport);
-
+  if (config.media_transport) {
+    // TODO(sukhanov): Currently media transport audio overhead is considered
+    // constant, we will not get overhead_observer calls when using
+    // media_transport. In the future when we introduce RTP media transport we
+    // should make audio overhead interface consistent and work for both RTP and
+    // non-RTP implementations.
+    audio_overhead_per_packet_bytes_ =
+        config.media_transport->GetAudioPacketOverhead();
+  }
   rtp_rtcp_module_ = channel_send_->GetRtpRtcp();
   RTC_DCHECK(rtp_rtcp_module_);
 
@@ -197,11 +202,19 @@
       ids.transport_sequence_number = extension.id;
     } else if (extension.uri == RtpExtension::kMidUri) {
       ids.mid = extension.id;
+    } else if (extension.uri == RtpExtension::kRidUri) {
+      ids.rid = extension.id;
+    } else if (extension.uri == RtpExtension::kRepairedRidUri) {
+      ids.repaired_rid = extension.id;
     }
   }
   return ids;
 }
 
+int AudioSendStream::TransportSeqNumId(const AudioSendStream::Config& config) {
+  return FindExtensionIds(config.rtp.extensions).transport_sequence_number;
+}
+
 void AudioSendStream::ConfigureStream(
     webrtc::internal::AudioSendStream* stream,
     const webrtc::AudioSendStream::Config& new_config,
@@ -247,18 +260,16 @@
   }
   bool transport_seq_num_id_changed =
       new_ids.transport_sequence_number != old_ids.transport_sequence_number;
-  if (first_time ||
-      (transport_seq_num_id_changed &&
-       !webrtc::field_trial::IsEnabled("WebRTC-Audio-ForceNoTWCC"))) {
+  if (first_time || (transport_seq_num_id_changed &&
+                     !stream->allocation_settings_.ForceNoAudioFeedback())) {
     if (!first_time) {
       channel_send->ResetSenderCongestionControlObjects();
     }
 
     RtcpBandwidthObserver* bandwidth_observer = nullptr;
-    bool has_transport_sequence_number =
-        new_ids.transport_sequence_number != 0 &&
-        !webrtc::field_trial::IsEnabled("WebRTC-Audio-ForceNoTWCC");
-    if (has_transport_sequence_number) {
+
+    if (stream->allocation_settings_.ShouldSendTransportSequenceNumber(
+            new_ids.transport_sequence_number)) {
       channel_send->EnableSendTransportSequenceNumber(
           new_ids.transport_sequence_number);
       // Probing in application limited region is only used in combination with
@@ -281,6 +292,13 @@
     channel_send->SetMid(new_config.rtp.mid, new_ids.mid);
   }
 
+  // RID RTP header extension
+  if ((first_time || new_ids.rid != old_ids.rid ||
+       new_ids.repaired_rid != old_ids.repaired_rid ||
+       new_config.rtp.rid != old_config.rtp.rid)) {
+    channel_send->SetRid(new_config.rtp.rid, new_ids.rid, new_ids.repaired_rid);
+  }
+
   if (!ReconfigureSendCodec(stream, new_config)) {
     RTC_LOG(LS_ERROR) << "Failed to set up send codec state.";
   }
@@ -297,20 +315,13 @@
     return;
   }
 
-  bool has_transport_sequence_number =
-      FindExtensionIds(config_.rtp.extensions).transport_sequence_number != 0 &&
-      !webrtc::field_trial::IsEnabled("WebRTC-Audio-ForceNoTWCC");
-  if (config_.min_bitrate_bps != -1 && config_.max_bitrate_bps != -1 &&
-      !config_.has_dscp &&
-      (has_transport_sequence_number ||
-       !webrtc::field_trial::IsEnabled("WebRTC-Audio-SendSideBwe") ||
-       webrtc::field_trial::IsEnabled("WebRTC-Audio-ABWENoTWCC"))) {
-    // Audio BWE is enabled.
+  if (allocation_settings_.IncludeAudioInAllocationOnStart(
+          config_.min_bitrate_bps, config_.max_bitrate_bps, config_.has_dscp,
+          TransportSeqNumId(config_))) {
     rtp_transport_->packet_sender()->SetAccountForAudioPackets(true);
     rtp_rtcp_module_->SetAsPartOfAllocation(true);
     ConfigureBitrateObserver(config_.min_bitrate_bps, config_.max_bitrate_bps,
-                             config_.bitrate_priority,
-                             has_transport_sequence_number);
+                             config_.bitrate_priority);
   } else {
     rtp_rtcp_module_->SetAsPartOfAllocation(false);
   }
@@ -448,7 +459,7 @@
     // TODO(eladalon): This function call could potentially reset the window,
     // setting both PLR and RPLR to unknown. Consider (during upcoming
     // refactoring) passing an indication of such an event.
-    packet_loss_tracker_.OnPacketAdded(seq_num, rtc::TimeMillis());
+    packet_loss_tracker_.OnPacketAdded(seq_num, clock_->TimeInMilliseconds());
   }
 }
 
@@ -474,9 +485,36 @@
   }
 }
 
-void AudioSendStream::SetTransportOverhead(int transport_overhead_per_packet) {
+void AudioSendStream::SetTransportOverhead(
+    int transport_overhead_per_packet_bytes) {
   RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
-  channel_send_->SetTransportOverhead(transport_overhead_per_packet);
+  rtc::CritScope cs(&overhead_per_packet_lock_);
+  transport_overhead_per_packet_bytes_ = transport_overhead_per_packet_bytes;
+  UpdateOverheadForEncoder();
+}
+
+void AudioSendStream::OnOverheadChanged(
+    size_t overhead_bytes_per_packet_bytes) {
+  rtc::CritScope cs(&overhead_per_packet_lock_);
+  audio_overhead_per_packet_bytes_ = overhead_bytes_per_packet_bytes;
+  UpdateOverheadForEncoder();
+}
+
+void AudioSendStream::UpdateOverheadForEncoder() {
+  const size_t overhead_per_packet_bytes = GetPerPacketOverheadBytes();
+  channel_send_->CallEncoder([&](AudioEncoder* encoder) {
+    encoder->OnReceivedOverhead(overhead_per_packet_bytes);
+  });
+}
+
+size_t AudioSendStream::TestOnlyGetPerPacketOverheadBytes() const {
+  rtc::CritScope cs(&overhead_per_packet_lock_);
+  return GetPerPacketOverheadBytes();
+}
+
+size_t AudioSendStream::GetPerPacketOverheadBytes() const {
+  return transport_overhead_per_packet_bytes_ +
+         audio_overhead_per_packet_bytes_;
 }
 
 RtpState AudioSendStream::GetRtpState() const {
@@ -529,16 +567,11 @@
     return false;
   }
 
-  // If other side does not support audio TWCC and WebRTC-Audio-ABWENoTWCC is
-  // not enabled, do not update target audio bitrate if we are in
-  // WebRTC-Audio-SendSideBwe-For-Video experiment
-  const bool do_not_update_target_bitrate =
-      !webrtc::field_trial::IsEnabled("WebRTC-Audio-ABWENoTWCC") &&
-      webrtc::field_trial::IsEnabled("WebRTC-Audio-SendSideBwe-For-Video") &&
-      !FindExtensionIds(new_config.rtp.extensions).transport_sequence_number;
   // If a bitrate has been specified for the codec, use it over the
   // codec's default.
-  if (!do_not_update_target_bitrate && spec.target_bitrate_bps) {
+  if (stream->allocation_settings_.UpdateAudioTargetBitrate(
+          TransportSeqNumId(new_config)) &&
+      spec.target_bitrate_bps) {
     encoder->OnReceivedTargetAudioBitrate(*spec.target_bitrate_bps);
   }
 
@@ -567,10 +600,18 @@
         new_config.send_codec_spec->format.clockrate_hz);
   }
 
+  // Set currently known overhead (used in ANA, opus only).
+  // If overhead changes later, it will be updated in UpdateOverheadForEncoder.
+  {
+    rtc::CritScope cs(&stream->overhead_per_packet_lock_);
+    encoder->OnReceivedOverhead(stream->GetPerPacketOverheadBytes());
+  }
+
   stream->StoreEncoderProperties(encoder->SampleRateHz(),
                                  encoder->NumChannels());
   stream->channel_send_->SetEncoder(new_config.send_codec_spec->payload_type,
                                     std::move(encoder));
+
   return true;
 }
 
@@ -601,22 +642,16 @@
     return SetupSendCodec(stream, new_config);
   }
 
-  // If other side does not support audio TWCC and WebRTC-Audio-ABWENoTWCC is
-  // not enabled, do not update target audio bitrate if we are in
-  // WebRTC-Audio-SendSideBwe-For-Video experiment
-  const bool do_not_update_target_bitrate =
-      !webrtc::field_trial::IsEnabled("WebRTC-Audio-ABWENoTWCC") &&
-      webrtc::field_trial::IsEnabled("WebRTC-Audio-SendSideBwe-For-Video") &&
-      !FindExtensionIds(new_config.rtp.extensions).transport_sequence_number;
-
   const absl::optional<int>& new_target_bitrate_bps =
       new_config.send_codec_spec->target_bitrate_bps;
   // If a bitrate has been specified for the codec, use it over the
   // codec's default.
-  if (!do_not_update_target_bitrate && new_target_bitrate_bps &&
+  if (stream->allocation_settings_.UpdateAudioTargetBitrate(
+          TransportSeqNumId(new_config)) &&
+      new_target_bitrate_bps &&
       new_target_bitrate_bps !=
           old_config.send_codec_spec->target_bitrate_bps) {
-    CallEncoder(stream->channel_send_, [&](AudioEncoder* encoder) {
+    stream->channel_send_->CallEncoder([&](AudioEncoder* encoder) {
       encoder->OnReceivedTargetAudioBitrate(*new_target_bitrate_bps);
     });
   }
@@ -624,6 +659,12 @@
   ReconfigureANA(stream, new_config);
   ReconfigureCNG(stream, new_config);
 
+  // Set currently known overhead (used in ANA, opus only).
+  {
+    rtc::CritScope cs(&stream->overhead_per_packet_lock_);
+    stream->UpdateOverheadForEncoder();
+  }
+
   return true;
 }
 
@@ -634,7 +675,7 @@
     return;
   }
   if (new_config.audio_network_adaptor_config) {
-    CallEncoder(stream->channel_send_, [&](AudioEncoder* encoder) {
+    stream->channel_send_->CallEncoder([&](AudioEncoder* encoder) {
       if (encoder->EnableAudioNetworkAdaptor(
               *new_config.audio_network_adaptor_config, stream->event_log_)) {
         RTC_DLOG(LS_INFO) << "Audio network adaptor enabled on SSRC "
@@ -644,9 +685,8 @@
       }
     });
   } else {
-    CallEncoder(stream->channel_send_, [&](AudioEncoder* encoder) {
-      encoder->DisableAudioNetworkAdaptor();
-    });
+    stream->channel_send_->CallEncoder(
+        [&](AudioEncoder* encoder) { encoder->DisableAudioNetworkAdaptor(); });
     RTC_DLOG(LS_INFO) << "Audio network adaptor disabled on SSRC "
                       << new_config.rtp.ssrc;
   }
@@ -701,26 +741,21 @@
   // allow us to configure the bitrate observer if the new config has bitrate
   // limits set, but would only have us call RemoveBitrateObserver if we were
   // previously configured with bitrate limits.
-  int new_transport_seq_num_id =
-      FindExtensionIds(new_config.rtp.extensions).transport_sequence_number;
   if (stream->config_.min_bitrate_bps == new_config.min_bitrate_bps &&
       stream->config_.max_bitrate_bps == new_config.max_bitrate_bps &&
       stream->config_.bitrate_priority == new_config.bitrate_priority &&
-      (FindExtensionIds(stream->config_.rtp.extensions)
-               .transport_sequence_number == new_transport_seq_num_id ||
-       !webrtc::field_trial::IsEnabled("WebRTC-Audio-SendSideBwe"))) {
+      (TransportSeqNumId(stream->config_) == TransportSeqNumId(new_config) ||
+       stream->allocation_settings_.IgnoreSeqNumIdChange())) {
     return;
   }
 
-  bool has_transport_sequence_number = new_transport_seq_num_id != 0;
-  if (new_config.min_bitrate_bps != -1 && new_config.max_bitrate_bps != -1 &&
-      !new_config.has_dscp &&
-      (has_transport_sequence_number ||
-       !webrtc::field_trial::IsEnabled("WebRTC-Audio-SendSideBwe"))) {
+  if (stream->allocation_settings_.IncludeAudioInAllocationOnReconfigure(
+          new_config.min_bitrate_bps, new_config.max_bitrate_bps,
+          new_config.has_dscp, TransportSeqNumId(new_config))) {
     stream->rtp_transport_->packet_sender()->SetAccountForAudioPackets(true);
-    stream->ConfigureBitrateObserver(
-        new_config.min_bitrate_bps, new_config.max_bitrate_bps,
-        new_config.bitrate_priority, has_transport_sequence_number);
+    stream->ConfigureBitrateObserver(new_config.min_bitrate_bps,
+                                     new_config.max_bitrate_bps,
+                                     new_config.bitrate_priority);
     stream->rtp_rtcp_module_->SetAsPartOfAllocation(true);
   } else {
     stream->rtp_transport_->packet_sender()->SetAccountForAudioPackets(false);
@@ -731,8 +766,7 @@
 
 void AudioSendStream::ConfigureBitrateObserver(int min_bitrate_bps,
                                                int max_bitrate_bps,
-                                               double bitrate_priority,
-                                               bool has_packet_feedback) {
+                                               double bitrate_priority) {
   RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
   RTC_DCHECK_GE(max_bitrate_bps, min_bitrate_bps);
   rtc::Event thread_sync_event;
@@ -746,8 +780,9 @@
     bitrate_allocator_->AddObserver(
         this, MediaStreamAllocationConfig{
                   static_cast<uint32_t>(min_bitrate_bps),
-                  static_cast<uint32_t>(max_bitrate_bps), 0, true,
-                  config_.track_id, bitrate_priority, has_packet_feedback});
+                  static_cast<uint32_t>(max_bitrate_bps), 0,
+                  allocation_settings_.DefaultPriorityBitrate().bps(), true,
+                  config_.track_id, bitrate_priority});
     thread_sync_event.Set();
   });
   thread_sync_event.Wait(rtc::Event::kForever);
@@ -765,14 +800,8 @@
 
 void AudioSendStream::RegisterCngPayloadType(int payload_type,
                                              int clockrate_hz) {
-  const CodecInst codec = {payload_type, "CN", clockrate_hz, 0, 1, 0};
-  if (rtp_rtcp_module_->RegisterSendPayload(codec) != 0) {
-    rtp_rtcp_module_->DeRegisterSendPayload(codec.pltype);
-    if (rtp_rtcp_module_->RegisterSendPayload(codec) != 0) {
-      RTC_DLOG(LS_ERROR) << "RegisterCngPayloadType() failed to register CN to "
-                            "RTP/RTCP module";
-    }
-  }
+  rtp_rtcp_module_->RegisterAudioSendPayload(payload_type, "CN", clockrate_hz,
+                                             1, 0);
 }
 }  // namespace internal
 }  // namespace webrtc
diff --git a/audio/audio_send_stream.h b/audio/audio_send_stream.h
index bf94901..c227e61 100644
--- a/audio/audio_send_stream.h
+++ b/audio/audio_send_stream.h
@@ -20,7 +20,8 @@
 #include "call/audio_state.h"
 #include "call/bitrate_allocator.h"
 #include "modules/rtp_rtcp/include/rtp_rtcp.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
+#include "rtc_base/experiments/audio_allocation_settings.h"
 #include "rtc_base/race_checker.h"
 #include "rtc_base/thread_checker.h"
 
@@ -35,9 +36,11 @@
 
 class AudioSendStream final : public webrtc::AudioSendStream,
                               public webrtc::BitrateAllocatorObserver,
-                              public webrtc::PacketFeedbackObserver {
+                              public webrtc::PacketFeedbackObserver,
+                              public webrtc::OverheadObserver {
  public:
-  AudioSendStream(const webrtc::AudioSendStream::Config& config,
+  AudioSendStream(Clock* clock,
+                  const webrtc::AudioSendStream::Config& config,
                   const rtc::scoped_refptr<webrtc::AudioState>& audio_state,
                   rtc::TaskQueue* worker_queue,
                   ProcessThread* module_process_thread,
@@ -47,7 +50,8 @@
                   RtcpRttStats* rtcp_rtt_stats,
                   const absl::optional<RtpState>& suspended_rtp_state);
   // For unit tests, which need to supply a mock ChannelSend.
-  AudioSendStream(const webrtc::AudioSendStream::Config& config,
+  AudioSendStream(Clock* clock,
+                  const webrtc::AudioSendStream::Config& config,
                   const rtc::scoped_refptr<webrtc::AudioState>& audio_state,
                   rtc::TaskQueue* worker_queue,
                   RtpTransportControllerSendInterface* rtp_transport,
@@ -84,11 +88,19 @@
   void OnPacketFeedbackVector(
       const std::vector<PacketFeedback>& packet_feedback_vector) override;
 
-  void SetTransportOverhead(int transport_overhead_per_packet);
+  void SetTransportOverhead(int transport_overhead_per_packet_bytes);
+
+  // OverheadObserver override reports audio packetization overhead from
+  // RTP/RTCP module or Media Transport.
+  void OnOverheadChanged(size_t overhead_bytes_per_packet_bytes) override;
 
   RtpState GetRtpState() const;
   const voe::ChannelSendInterface* GetChannel() const;
 
+  // Returns combined per-packet overhead.
+  size_t TestOnlyGetPerPacketOverheadBytes() const
+      RTC_LOCKS_EXCLUDED(overhead_per_packet_lock_);
+
  private:
   class TimedTransport;
 
@@ -112,16 +124,26 @@
 
   void ConfigureBitrateObserver(int min_bitrate_bps,
                                 int max_bitrate_bps,
-                                double bitrate_priority,
-                                bool has_packet_feedback);
+                                double bitrate_priority);
   void RemoveBitrateObserver();
 
+  // Sets per-packet overhead on encoded (for ANA) based on current known values
+  // of transport and packetization overheads.
+  void UpdateOverheadForEncoder()
+      RTC_EXCLUSIVE_LOCKS_REQUIRED(overhead_per_packet_lock_);
+
+  // Returns combined per-packet overhead.
+  size_t GetPerPacketOverheadBytes() const
+      RTC_EXCLUSIVE_LOCKS_REQUIRED(overhead_per_packet_lock_);
+
   void RegisterCngPayloadType(int payload_type, int clockrate_hz);
+  Clock* clock_;
 
   rtc::ThreadChecker worker_thread_checker_;
   rtc::ThreadChecker pacer_thread_checker_;
   rtc::RaceChecker audio_capture_race_checker_;
   rtc::TaskQueue* worker_queue_;
+  const AudioAllocationSettings allocation_settings_;
   webrtc::AudioSendStream::Config config_;
   rtc::scoped_refptr<webrtc::AudioState> audio_state_;
   const std::unique_ptr<voe::ChannelSendInterface> channel_send_;
@@ -148,9 +170,22 @@
     int audio_level = 0;
     int transport_sequence_number = 0;
     int mid = 0;
+    int rid = 0;
+    int repaired_rid = 0;
   };
   static ExtensionIds FindExtensionIds(
       const std::vector<RtpExtension>& extensions);
+  static int TransportSeqNumId(const Config& config);
+
+  rtc::CriticalSection overhead_per_packet_lock_;
+
+  // Current transport overhead (ICE, TURN, etc.)
+  size_t transport_overhead_per_packet_bytes_
+      RTC_GUARDED_BY(overhead_per_packet_lock_) = 0;
+
+  // Current audio packetization overhead (RTP or Media Transport).
+  size_t audio_overhead_per_packet_bytes_
+      RTC_GUARDED_BY(overhead_per_packet_lock_) = 0;
 
   RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(AudioSendStream);
 };
diff --git a/audio/audio_send_stream_tests.cc b/audio/audio_send_stream_tests.cc
index 7deeff3..8a83554 100644
--- a/audio/audio_send_stream_tests.cc
+++ b/audio/audio_send_stream_tests.cc
@@ -8,7 +8,12 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
+#include <string>
+#include <utility>
+#include <vector>
+
 #include "test/call_test.h"
+#include "test/field_trial.h"
 #include "test/gtest.h"
 #include "test/rtcp_packet_parser.h"
 
@@ -16,6 +21,11 @@
 namespace test {
 namespace {
 
+enum : int {  // The first valid value is 1.
+  kAudioLevelExtensionId = 1,
+  kTransportSequenceNumberExtensionId,
+};
+
 class AudioSendTest : public SendTest {
  public:
   AudioSendTest() : SendTest(CallTest::kDefaultTimeoutMs) {}
@@ -101,8 +111,8 @@
   class AudioLevelObserver : public AudioSendTest {
    public:
     AudioLevelObserver() : AudioSendTest() {
-      EXPECT_TRUE(parser_->RegisterRtpHeaderExtension(
-          kRtpExtensionAudioLevel, test::kAudioLevelExtensionId));
+      EXPECT_TRUE(parser_->RegisterRtpHeaderExtension(kRtpExtensionAudioLevel,
+                                                      kAudioLevelExtensionId));
     }
 
     Action OnSendRtp(const uint8_t* packet, size_t length) override {
@@ -125,8 +135,8 @@
         AudioSendStream::Config* send_config,
         std::vector<AudioReceiveStream::Config>* receive_configs) override {
       send_config->rtp.extensions.clear();
-      send_config->rtp.extensions.push_back(RtpExtension(
-          RtpExtension::kAudioLevelUri, test::kAudioLevelExtensionId));
+      send_config->rtp.extensions.push_back(
+          RtpExtension(RtpExtension::kAudioLevelUri, kAudioLevelExtensionId));
     }
 
     void PerformTest() override {
@@ -137,42 +147,54 @@
   RunBaseTest(&test);
 }
 
-TEST_F(AudioSendStreamCallTest, SupportsTransportWideSequenceNumbers) {
-  static const uint8_t kExtensionId = test::kTransportSequenceNumberExtensionId;
-  class TransportWideSequenceNumberObserver : public AudioSendTest {
-   public:
-    TransportWideSequenceNumberObserver() : AudioSendTest() {
-      EXPECT_TRUE(parser_->RegisterRtpHeaderExtension(
-          kRtpExtensionTransportSequenceNumber, kExtensionId));
-    }
+class TransportWideSequenceNumberObserver : public AudioSendTest {
+ public:
+  explicit TransportWideSequenceNumberObserver(bool expect_sequence_number)
+      : AudioSendTest(), expect_sequence_number_(expect_sequence_number) {
+    EXPECT_TRUE(parser_->RegisterRtpHeaderExtension(
+        kRtpExtensionTransportSequenceNumber,
+        kTransportSequenceNumberExtensionId));
+  }
 
-   private:
-    Action OnSendRtp(const uint8_t* packet, size_t length) override {
-      RTPHeader header;
-      EXPECT_TRUE(parser_->Parse(packet, length, &header));
+ private:
+  Action OnSendRtp(const uint8_t* packet, size_t length) override {
+    RTPHeader header;
+    EXPECT_TRUE(parser_->Parse(packet, length, &header));
 
-      EXPECT_TRUE(header.extension.hasTransportSequenceNumber);
-      EXPECT_FALSE(header.extension.hasTransmissionTimeOffset);
-      EXPECT_FALSE(header.extension.hasAbsoluteSendTime);
+    EXPECT_EQ(header.extension.hasTransportSequenceNumber,
+              expect_sequence_number_);
+    EXPECT_FALSE(header.extension.hasTransmissionTimeOffset);
+    EXPECT_FALSE(header.extension.hasAbsoluteSendTime);
 
-      observation_complete_.Set();
+    observation_complete_.Set();
 
-      return SEND_PACKET;
-    }
+    return SEND_PACKET;
+  }
 
-    void ModifyAudioConfigs(
-        AudioSendStream::Config* send_config,
-        std::vector<AudioReceiveStream::Config>* receive_configs) override {
-      send_config->rtp.extensions.clear();
-      send_config->rtp.extensions.push_back(RtpExtension(
-          RtpExtension::kTransportSequenceNumberUri, kExtensionId));
-    }
+  void ModifyAudioConfigs(
+      AudioSendStream::Config* send_config,
+      std::vector<AudioReceiveStream::Config>* receive_configs) override {
+    send_config->rtp.extensions.clear();
+    send_config->rtp.extensions.push_back(
+        RtpExtension(RtpExtension::kTransportSequenceNumberUri,
+                     kTransportSequenceNumberExtensionId));
+  }
 
-    void PerformTest() override {
-      EXPECT_TRUE(Wait()) << "Timed out while waiting for a single RTP packet.";
-    }
-  } test;
+  void PerformTest() override {
+    EXPECT_TRUE(Wait()) << "Timed out while waiting for a single RTP packet.";
+  }
+  const bool expect_sequence_number_;
+};
 
+TEST_F(AudioSendStreamCallTest, SendsTransportWideSequenceNumbersInFieldTrial) {
+  ScopedFieldTrials field_trials("WebRTC-Audio-SendSideBwe/Enabled/");
+  TransportWideSequenceNumberObserver test(/*expect_sequence_number=*/true);
+  RunBaseTest(&test);
+}
+
+TEST_F(AudioSendStreamCallTest,
+       DoesNotSendTransportWideSequenceNumbersPerDefault) {
+  TransportWideSequenceNumberObserver test(/*expect_sequence_number=*/false);
   RunBaseTest(&test);
 }
 
diff --git a/audio/audio_send_stream_unittest.cc b/audio/audio_send_stream_unittest.cc
index e400ada..ddd8137 100644
--- a/audio/audio_send_stream_unittest.cc
+++ b/audio/audio_send_stream_unittest.cc
@@ -28,6 +28,8 @@
 #include "modules/rtp_rtcp/mocks/mock_rtcp_rtt_stats.h"
 #include "modules/rtp_rtcp/mocks/mock_rtp_rtcp.h"
 #include "rtc_base/task_queue.h"
+#include "system_wrappers/include/clock.h"
+#include "test/field_trial.h"
 #include "test/gtest.h"
 #include "test/mock_audio_encoder.h"
 #include "test/mock_audio_encoder_factory.h"
@@ -61,7 +63,6 @@
 const int kTelephoneEventPayloadFrequency = 65432;
 const int kTelephoneEventCode = 45;
 const int kTelephoneEventDuration = 6789;
-const CodecInst kIsacCodec = {103, "isac", 16000, 320, 1, 32000};
 constexpr int kIsacPayloadType = 103;
 const SdpAudioFormat kIsacFormat = {"isac", 16000, 1};
 const SdpAudioFormat kOpusFormat = {"opus", 48000, 2};
@@ -73,12 +74,10 @@
 
 class MockLimitObserver : public BitrateAllocator::LimitObserver {
  public:
-  MOCK_METHOD5(OnAllocationLimitsChanged,
+  MOCK_METHOD3(OnAllocationLimitsChanged,
                void(uint32_t min_send_bitrate_bps,
                     uint32_t max_padding_bitrate_bps,
-                    uint32_t total_bitrate_bps,
-                    uint32_t allocated_without_feedback_bps,
-                    bool has_packet_feedback));
+                    uint32_t total_bitrate_bps));
 };
 
 std::unique_ptr<MockAudioEncoder> SetupAudioEncoderMock(
@@ -127,9 +126,10 @@
 
 struct ConfigHelper {
   ConfigHelper(bool audio_bwe_enabled, bool expect_set_encoder_call)
-      : stream_config_(/*send_transport=*/nullptr, /*media_transport=*/nullptr),
+      : clock_(1000000),
+        stream_config_(/*send_transport=*/nullptr, /*media_transport=*/nullptr),
         audio_processing_(new rtc::RefCountedObject<MockAudioProcessing>()),
-        bitrate_allocator_(&limit_observer_),
+        bitrate_allocator_(&clock_, &limit_observer_),
         worker_queue_("ConfigHelper_worker_queue"),
         audio_encoder_(nullptr) {
     using testing::Invoke;
@@ -163,8 +163,9 @@
   std::unique_ptr<internal::AudioSendStream> CreateAudioSendStream() {
     return std::unique_ptr<internal::AudioSendStream>(
         new internal::AudioSendStream(
-            stream_config_, audio_state_, &worker_queue_, &rtp_transport_,
-            &bitrate_allocator_, &event_log_, &rtcp_rtt_stats_, absl::nullopt,
+            Clock::GetRealTimeClock(), stream_config_, audio_state_,
+            &worker_queue_, &rtp_transport_, &bitrate_allocator_, &event_log_,
+            &rtcp_rtt_stats_, absl::nullopt,
             std::unique_ptr<voe::ChannelSendInterface>(channel_send_)));
   }
 
@@ -211,6 +212,7 @@
           .Times(1);
     }
     EXPECT_CALL(*channel_send_, ResetSenderCongestionControlObjects()).Times(1);
+    EXPECT_CALL(*channel_send_, SetRid(std::string(), 0, 0)).Times(1);
   }
 
   void SetupMockForSetupSendCodec(bool expect_set_encoder_call) {
@@ -224,15 +226,14 @@
     }
   }
 
-  void SetupMockForModifyEncoder() {
+  void SetupMockForCallEncoder() {
     // Let ModifyEncoder to invoke mock audio encoder.
-    EXPECT_CALL(*channel_send_, ModifyEncoder(_))
-        .WillRepeatedly(Invoke(
-            [this](rtc::FunctionView<void(std::unique_ptr<AudioEncoder>*)>
-                       modifier) {
+    EXPECT_CALL(*channel_send_, CallEncoder(_))
+        .WillRepeatedly(
+            [this](rtc::FunctionView<void(AudioEncoder*)> modifier) {
               if (this->audio_encoder_)
-                modifier(&this->audio_encoder_);
-            }));
+                modifier(this->audio_encoder_.get());
+            });
   }
 
   void SetupMockForSendTelephoneEvent() {
@@ -285,6 +286,7 @@
   }
 
  private:
+  SimulatedClock clock_;
   rtc::scoped_refptr<AudioState> audio_state_;
   AudioSendStream::Config stream_config_;
   testing::StrictMock<MockChannelSend>* channel_send_ = nullptr;
@@ -356,6 +358,7 @@
 }
 
 TEST(AudioSendStreamTest, AudioBweCorrectObjectsOnChannelProxy) {
+  ScopedFieldTrials field_trials("WebRTC-Audio-SendSideBwe/Enabled/");
   ConfigHelper helper(true, true);
   auto send_stream = helper.CreateAudioSendStream();
 }
@@ -375,11 +378,11 @@
   EXPECT_EQ(kCallStats.packetsSent, stats.packets_sent);
   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(kIsacFormat.name, stats.codec_name);
   EXPECT_EQ(static_cast<int32_t>(kReportBlock.extended_highest_sequence_number),
             stats.ext_seqnum);
   EXPECT_EQ(static_cast<int32_t>(kReportBlock.interarrival_jitter /
-                                 (kIsacCodec.plfreq / 1000)),
+                                 (kIsacFormat.clockrate_hz / 1000)),
             stats.jitter_ms);
   EXPECT_EQ(kCallStats.rttMs, stats.rtt_ms);
   EXPECT_EQ(0, stats.audio_level);
@@ -428,7 +431,7 @@
   auto stream_config = helper.config();
   stream_config.audio_network_adaptor_config = kAnaReconfigString;
 
-  helper.SetupMockForModifyEncoder();
+  helper.SetupMockForCallEncoder();
   send_stream->Reconfigure(stream_config);
 }
 
@@ -507,6 +510,7 @@
 }
 
 TEST(AudioSendStreamTest, ReconfigureTransportCcResetsFirst) {
+  ScopedFieldTrials field_trials("WebRTC-Audio-SendSideBwe/Enabled/");
   ConfigHelper helper(false, true);
   auto send_stream = helper.CreateAudioSendStream();
   auto new_config = helper.config();
@@ -522,9 +526,61 @@
                                             helper.transport(), Ne(nullptr)))
         .Times(1);
   }
+
+  // CallEncoder will be called to re-set overhead.
+  EXPECT_CALL(*helper.channel_send(), CallEncoder(testing::_)).Times(1);
+
   send_stream->Reconfigure(new_config);
 }
 
+TEST(AudioSendStreamTest, OnTransportOverheadChanged) {
+  ConfigHelper helper(false, true);
+  auto send_stream = helper.CreateAudioSendStream();
+  auto new_config = helper.config();
+
+  // CallEncoder will be called on overhead change.
+  EXPECT_CALL(*helper.channel_send(), CallEncoder(testing::_)).Times(1);
+
+  const size_t transport_overhead_per_packet_bytes = 333;
+  send_stream->SetTransportOverhead(transport_overhead_per_packet_bytes);
+
+  EXPECT_EQ(transport_overhead_per_packet_bytes,
+            send_stream->TestOnlyGetPerPacketOverheadBytes());
+}
+
+TEST(AudioSendStreamTest, OnAudioOverheadChanged) {
+  ConfigHelper helper(false, true);
+  auto send_stream = helper.CreateAudioSendStream();
+  auto new_config = helper.config();
+
+  // CallEncoder will be called on overhead change.
+  EXPECT_CALL(*helper.channel_send(), CallEncoder(testing::_)).Times(1);
+
+  const size_t audio_overhead_per_packet_bytes = 555;
+  send_stream->OnOverheadChanged(audio_overhead_per_packet_bytes);
+  EXPECT_EQ(audio_overhead_per_packet_bytes,
+            send_stream->TestOnlyGetPerPacketOverheadBytes());
+}
+
+TEST(AudioSendStreamTest, OnAudioAndTransportOverheadChanged) {
+  ConfigHelper helper(false, true);
+  auto send_stream = helper.CreateAudioSendStream();
+  auto new_config = helper.config();
+
+  // CallEncoder will be called when each of overhead changes.
+  EXPECT_CALL(*helper.channel_send(), CallEncoder(testing::_)).Times(2);
+
+  const size_t transport_overhead_per_packet_bytes = 333;
+  send_stream->SetTransportOverhead(transport_overhead_per_packet_bytes);
+
+  const size_t audio_overhead_per_packet_bytes = 555;
+  send_stream->OnOverheadChanged(audio_overhead_per_packet_bytes);
+
+  EXPECT_EQ(
+      transport_overhead_per_packet_bytes + audio_overhead_per_packet_bytes,
+      send_stream->TestOnlyGetPerPacketOverheadBytes());
+}
+
 // Validates that reconfiguring the AudioSendStream with a Frame encryptor
 // correctly reconfigures on the object without crashing.
 TEST(AudioSendStreamTest, ReconfigureWithFrameEncryptor) {
diff --git a/audio/audio_state.cc b/audio/audio_state.cc
index 7d473ae..334eaed 100644
--- a/audio/audio_state.cc
+++ b/audio/audio_state.cc
@@ -17,9 +17,9 @@
 #include "absl/memory/memory.h"
 #include "audio/audio_receive_stream.h"
 #include "modules/audio_device/include/audio_device.h"
-#include "rtc_base/atomicops.h"
 #include "rtc_base/checks.h"
 #include "rtc_base/logging.h"
+#include "rtc_base/ref_counted_object.h"
 #include "rtc_base/thread.h"
 
 namespace webrtc {
@@ -168,20 +168,6 @@
   audio_transport_.SetStereoChannelSwapping(enable);
 }
 
-// Reference count; implementation copied from rtc::RefCountedObject.
-void AudioState::AddRef() const {
-  rtc::AtomicOps::Increment(&ref_count_);
-}
-
-// Reference count; implementation copied from rtc::RefCountedObject.
-rtc::RefCountReleaseStatus AudioState::Release() const {
-  if (rtc::AtomicOps::Decrement(&ref_count_) == 0) {
-    delete this;
-    return rtc::RefCountReleaseStatus::kDroppedLastRef;
-  }
-  return rtc::RefCountReleaseStatus::kOtherRefsRemained;
-}
-
 void AudioState::UpdateAudioTransportWithSendingStreams() {
   RTC_DCHECK(thread_checker_.CalledOnValidThread());
   std::vector<webrtc::AudioSendStream*> sending_streams;
@@ -199,6 +185,6 @@
 
 rtc::scoped_refptr<AudioState> AudioState::Create(
     const AudioState::Config& config) {
-  return rtc::scoped_refptr<AudioState>(new internal::AudioState(config));
+  return new rtc::RefCountedObject<internal::AudioState>(config);
 }
 }  // namespace webrtc
diff --git a/audio/audio_state.h b/audio/audio_state.h
index 9e302c4..60250da 100644
--- a/audio/audio_state.h
+++ b/audio/audio_state.h
@@ -18,9 +18,9 @@
 #include "audio/audio_transport_impl.h"
 #include "audio/null_audio_poller.h"
 #include "call/audio_state.h"
-#include "rtc_base/constructormagic.h"
-#include "rtc_base/criticalsection.h"
-#include "rtc_base/refcount.h"
+#include "rtc_base/constructor_magic.h"
+#include "rtc_base/critical_section.h"
+#include "rtc_base/ref_count.h"
 #include "rtc_base/thread_checker.h"
 
 namespace webrtc {
@@ -30,7 +30,7 @@
 
 namespace internal {
 
-class AudioState final : public webrtc::AudioState {
+class AudioState : public webrtc::AudioState {
  public:
   explicit AudioState(const AudioState::Config& config);
   ~AudioState() override;
@@ -60,10 +60,6 @@
   void RemoveSendingStream(webrtc::AudioSendStream* stream);
 
  private:
-  // rtc::RefCountInterface implementation.
-  void AddRef() const override;
-  rtc::RefCountReleaseStatus Release() const override;
-
   void UpdateAudioTransportWithSendingStreams();
 
   rtc::ThreadChecker thread_checker_;
@@ -72,10 +68,6 @@
   bool recording_enabled_ = true;
   bool playout_enabled_ = true;
 
-  // Reference count; implementation copied from rtc::RefCountedObject.
-  // TODO(nisse): Use RefCountedObject or RefCountedBase instead.
-  mutable volatile int ref_count_ = 0;
-
   // Transports mixed audio from the mixer to the audio device and
   // recorded audio to the sending streams.
   AudioTransportImpl audio_transport_;
diff --git a/audio/audio_state_unittest.cc b/audio/audio_state_unittest.cc
index dc622df..75bf4e1 100644
--- a/audio/audio_state_unittest.cc
+++ b/audio/audio_state_unittest.cc
@@ -16,7 +16,7 @@
 #include "modules/audio_device/include/mock_audio_device.h"
 #include "modules/audio_mixer/audio_mixer_impl.h"
 #include "modules/audio_processing/include/mock_audio_processing.h"
-#include "rtc_base/refcountedobject.h"
+#include "rtc_base/ref_counted_object.h"
 #include "test/gtest.h"
 
 namespace webrtc {
@@ -98,14 +98,14 @@
 
 TEST(AudioStateTest, ConstructDestruct) {
   ConfigHelper helper;
-  std::unique_ptr<internal::AudioState> audio_state(
-      new internal::AudioState(helper.config()));
+  rtc::scoped_refptr<internal::AudioState> audio_state(
+      new rtc::RefCountedObject<internal::AudioState>(helper.config()));
 }
 
 TEST(AudioStateTest, RecordedAudioArrivesAtSingleStream) {
   ConfigHelper helper;
-  std::unique_ptr<internal::AudioState> audio_state(
-      new internal::AudioState(helper.config()));
+  rtc::scoped_refptr<internal::AudioState> audio_state(
+      new rtc::RefCountedObject<internal::AudioState>(helper.config()));
 
   MockAudioSendStream stream;
   audio_state->AddSendingStream(&stream, 8000, 2);
@@ -142,8 +142,8 @@
 
 TEST(AudioStateTest, RecordedAudioArrivesAtMultipleStreams) {
   ConfigHelper helper;
-  std::unique_ptr<internal::AudioState> audio_state(
-      new internal::AudioState(helper.config()));
+  rtc::scoped_refptr<internal::AudioState> audio_state(
+      new rtc::RefCountedObject<internal::AudioState>(helper.config()));
 
   MockAudioSendStream stream_1;
   MockAudioSendStream stream_2;
@@ -196,8 +196,9 @@
   constexpr size_t kNumChannels = 2;
 
   ConfigHelper helper;
-  std::unique_ptr<internal::AudioState> audio_state(
-      new internal::AudioState(helper.config()));
+  rtc::scoped_refptr<internal::AudioState> audio_state(
+      new rtc::RefCountedObject<internal::AudioState>(helper.config()));
+
   audio_state->SetStereoChannelSwapping(true);
 
   MockAudioSendStream stream;
@@ -227,8 +228,8 @@
   constexpr size_t kNumChannels = 1;
 
   ConfigHelper helper;
-  std::unique_ptr<internal::AudioState> audio_state(
-      new internal::AudioState(helper.config()));
+  rtc::scoped_refptr<internal::AudioState> audio_state(
+      new rtc::RefCountedObject<internal::AudioState>(helper.config()));
 
   // Push a silent buffer -> Level stats should be zeros except for duration.
   {
diff --git a/audio/audio_transport_impl.cc b/audio/audio_transport_impl.cc
index 539456e..cdbdacd 100644
--- a/audio/audio_transport_impl.cc
+++ b/audio/audio_transport_impl.cc
@@ -133,9 +133,9 @@
 
   // Typing detection (utilizes the APM/VAD decision). We let the VAD determine
   // if we're using this feature or not.
-  // TODO(solenberg): is_enabled() takes a lock. Work around that.
+  // TODO(solenberg): GetConfig() takes a lock. Work around that.
   bool typing_detected = false;
-  if (audio_processing_->voice_detection()->is_enabled()) {
+  if (audio_processing_->GetConfig().voice_detection.enabled) {
     if (audio_frame->vad_activity_ != AudioFrame::kVadUnknown) {
       bool vad_active = audio_frame->vad_activity_ == AudioFrame::kVadActive;
       typing_detected = typing_detection_.Process(key_pressed, vad_active);
@@ -214,7 +214,6 @@
                                         int64_t* ntp_time_ms) {
   RTC_DCHECK_EQ(bits_per_sample, 16);
   RTC_DCHECK_GE(number_of_channels, 1);
-  RTC_DCHECK_LE(number_of_channels, 2);
   RTC_DCHECK_GE(sample_rate, AudioProcessing::NativeRate::kSampleRate8kHz);
 
   // 100 = 1 second / data duration (10 ms).
diff --git a/audio/audio_transport_impl.h b/audio/audio_transport_impl.h
index 3a3155c..4c244a1 100644
--- a/audio/audio_transport_impl.h
+++ b/audio/audio_transport_impl.h
@@ -14,14 +14,14 @@
 #include <vector>
 
 #include "api/audio/audio_mixer.h"
+#include "api/scoped_refptr.h"
 #include "audio/audio_level.h"
 #include "common_audio/resampler/include/push_resampler.h"
 #include "modules/audio_device/include/audio_device.h"
 #include "modules/audio_processing/include/audio_processing.h"
 #include "modules/audio_processing/typing_detection.h"
-#include "rtc_base/constructormagic.h"
-#include "rtc_base/criticalsection.h"
-#include "rtc_base/scoped_ref_ptr.h"
+#include "rtc_base/constructor_magic.h"
+#include "rtc_base/critical_section.h"
 #include "rtc_base/thread_annotations.h"
 
 namespace webrtc {
diff --git a/audio/channel_receive.cc b/audio/channel_receive.cc
index 483147f..79523c8 100644
--- a/audio/channel_receive.cc
+++ b/audio/channel_receive.cc
@@ -33,16 +33,17 @@
 #include "modules/rtp_rtcp/source/contributing_sources.h"
 #include "modules/rtp_rtcp/source/rtp_header_extensions.h"
 #include "modules/rtp_rtcp/source/rtp_packet_received.h"
+#include "modules/rtp_rtcp/source/rtp_rtcp_config.h"
 #include "modules/utility/include/process_thread.h"
 #include "rtc_base/checks.h"
-#include "rtc_base/criticalsection.h"
+#include "rtc_base/critical_section.h"
 #include "rtc_base/format_macros.h"
 #include "rtc_base/location.h"
 #include "rtc_base/logging.h"
 #include "rtc_base/numerics/safe_minmax.h"
 #include "rtc_base/race_checker.h"
 #include "rtc_base/thread_checker.h"
-#include "rtc_base/timeutils.h"
+#include "rtc_base/time_utils.h"
 #include "system_wrappers/include/metrics.h"
 
 namespace webrtc {
@@ -51,50 +52,32 @@
 namespace {
 
 constexpr double kAudioSampleDurationSeconds = 0.01;
-constexpr int64_t kMaxRetransmissionWindowMs = 1000;
-constexpr int64_t kMinRetransmissionWindowMs = 30;
 
 // Video Sync.
 constexpr int kVoiceEngineMinMinPlayoutDelayMs = 0;
 constexpr int kVoiceEngineMaxMinPlayoutDelayMs = 10000;
 
-webrtc::FrameType WebrtcFrameTypeForMediaTransportFrameType(
-    MediaTransportEncodedAudioFrame::FrameType frame_type) {
-  switch (frame_type) {
-    case MediaTransportEncodedAudioFrame::FrameType::kSpeech:
-      return kAudioFrameSpeech;
-      break;
-
-    case MediaTransportEncodedAudioFrame::FrameType::
-        kDiscountinuousTransmission:
-      return kAudioFrameCN;
-      break;
-  }
-}
-
-WebRtcRTPHeader CreateWebrtcRTPHeaderForMediaTransportFrame(
+RTPHeader CreateRTPHeaderForMediaTransportFrame(
     const MediaTransportEncodedAudioFrame& frame,
     uint64_t channel_id) {
-  webrtc::WebRtcRTPHeader webrtc_header = {};
-  webrtc_header.header.payloadType = frame.payload_type();
-  webrtc_header.header.payload_type_frequency = frame.sampling_rate_hz();
-  webrtc_header.header.timestamp = frame.starting_sample_index();
-  webrtc_header.header.sequenceNumber = frame.sequence_number();
+  webrtc::RTPHeader rtp_header;
+  rtp_header.payloadType = frame.payload_type();
+  rtp_header.payload_type_frequency = frame.sampling_rate_hz();
+  rtp_header.timestamp = frame.starting_sample_index();
+  rtp_header.sequenceNumber = frame.sequence_number();
 
-  webrtc_header.frameType =
-      WebrtcFrameTypeForMediaTransportFrameType(frame.frame_type());
-
-  webrtc_header.header.ssrc = static_cast<uint32_t>(channel_id);
+  rtp_header.ssrc = static_cast<uint32_t>(channel_id);
 
   // The rest are initialized by the RTPHeader constructor.
-  return webrtc_header;
+  return rtp_header;
 }
 
 class ChannelReceive : public ChannelReceiveInterface,
                        public MediaTransportAudioSinkInterface {
  public:
   // Used for receive streams.
-  ChannelReceive(ProcessThread* module_process_thread,
+  ChannelReceive(Clock* clock,
+                 ProcessThread* module_process_thread,
                  AudioDeviceModule* audio_device_module,
                  MediaTransportInterface* media_transport,
                  Transport* rtcp_send_transport,
@@ -103,6 +86,7 @@
                  size_t jitter_buffer_max_packets,
                  bool jitter_buffer_fast_playout,
                  int jitter_buffer_min_delay_ms,
+                 bool jitter_buffer_enable_rtx_handling,
                  rtc::scoped_refptr<AudioDecoderFactory> decoder_factory,
                  absl::optional<AudioCodecPairId> codec_pair_id,
                  rtc::scoped_refptr<FrameDecryptorInterface> frame_decryptor,
@@ -119,7 +103,8 @@
   void StopPlayout() override;
 
   // Codecs
-  bool GetRecCodec(CodecInst* codec) const override;
+  absl::optional<std::pair<int, SdpAudioFormat>>
+      GetReceiveCodec() const override;
 
   bool ReceivedRTCPPacket(const uint8_t* data, size_t length) override;
 
@@ -143,6 +128,10 @@
   void SetMinimumPlayoutDelay(int delayMs) override;
   uint32_t GetPlayoutTimestamp() const override;
 
+  // Audio quality.
+  bool SetBaseMinimumPlayoutDelayMs(int delay_ms) override;
+  int GetBaseMinimumPlayoutDelayMs() const override;
+
   // Produces the transport-related timestamps; current_delay_ms is left unset.
   absl::optional<Syncable::Info> GetSyncInfo() const override;
 
@@ -184,7 +173,7 @@
 
   int32_t OnReceivedPayloadData(const uint8_t* payloadData,
                                 size_t payloadSize,
-                                const WebRtcRTPHeader* rtpHeader);
+                                const RTPHeader& rtpHeader);
 
   bool Playing() const {
     rtc::CritScope lock(&playing_lock_);
@@ -272,10 +261,9 @@
   webrtc::CryptoOptions crypto_options_;
 };
 
-int32_t ChannelReceive::OnReceivedPayloadData(
-    const uint8_t* payloadData,
-    size_t payloadSize,
-    const WebRtcRTPHeader* rtpHeader) {
+int32_t ChannelReceive::OnReceivedPayloadData(const uint8_t* payloadData,
+                                              size_t payloadSize,
+                                              const RTPHeader& rtp_header) {
   // We should not be receiving any RTP packets if media_transport is set.
   RTC_CHECK(!media_transport_);
 
@@ -286,7 +274,7 @@
   }
 
   // Push the incoming payload (parsed and ready for decoding) into the ACM
-  if (audio_coding_->IncomingPacket(payloadData, payloadSize, *rtpHeader) !=
+  if (audio_coding_->IncomingPacket(payloadData, payloadSize, rtp_header) !=
       0) {
     RTC_DLOG(LS_ERROR) << "ChannelReceive::OnReceivedPayloadData() unable to "
                           "push data to the ACM";
@@ -319,8 +307,7 @@
   // Send encoded audio frame to Decoder / NetEq.
   if (audio_coding_->IncomingPacket(
           frame.encoded_data().data(), frame.encoded_data().size(),
-          CreateWebrtcRTPHeaderForMediaTransportFrame(frame, channel_id)) !=
-      0) {
+          CreateRTPHeaderForMediaTransportFrame(frame, channel_id)) != 0) {
     RTC_DLOG(LS_ERROR) << "ChannelReceive::OnData: unable to "
                           "push data to the ACM";
   }
@@ -442,6 +429,7 @@
 }
 
 ChannelReceive::ChannelReceive(
+    Clock* clock,
     ProcessThread* module_process_thread,
     AudioDeviceModule* audio_device_module,
     MediaTransportInterface* media_transport,
@@ -451,16 +439,16 @@
     size_t jitter_buffer_max_packets,
     bool jitter_buffer_fast_playout,
     int jitter_buffer_min_delay_ms,
+    bool jitter_buffer_enable_rtx_handling,
     rtc::scoped_refptr<AudioDecoderFactory> decoder_factory,
     absl::optional<AudioCodecPairId> codec_pair_id,
     rtc::scoped_refptr<FrameDecryptorInterface> frame_decryptor,
     const webrtc::CryptoOptions& crypto_options)
     : event_log_(rtc_event_log),
-      rtp_receive_statistics_(
-          ReceiveStatistics::Create(Clock::GetRealTimeClock())),
+      rtp_receive_statistics_(ReceiveStatistics::Create(clock)),
       remote_ssrc_(remote_ssrc),
       _outputAudioLevel(),
-      ntp_estimator_(Clock::GetRealTimeClock()),
+      ntp_estimator_(clock),
       playout_timestamp_rtp_(0),
       playout_delay_ms_(0),
       rtp_ts_wraparound_handler_(new rtc::TimestampWrapAroundHandler()),
@@ -485,12 +473,15 @@
   acm_config.neteq_config.enable_fast_accelerate = jitter_buffer_fast_playout;
   acm_config.neteq_config.min_delay_ms = jitter_buffer_min_delay_ms;
   acm_config.neteq_config.enable_muted_state = true;
+  acm_config.neteq_config.enable_rtx_handling =
+      jitter_buffer_enable_rtx_handling;
   audio_coding_.reset(AudioCodingModule::Create(acm_config));
 
   _outputAudioLevel.Clear();
 
   rtp_receive_statistics_->EnableRetransmitDetection(remote_ssrc_, true);
   RtpRtcp::Configuration configuration;
+  configuration.clock = clock;
   configuration.audio = true;
   configuration.receiver_only = true;
   configuration.outgoing_transport = rtcp_send_transport;
@@ -552,9 +543,10 @@
   _outputAudioLevel.Clear();
 }
 
-bool ChannelReceive::GetRecCodec(CodecInst* codec) const {
+absl::optional<std::pair<int, SdpAudioFormat>>
+    ChannelReceive::GetReceiveCodec() const {
   RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
-  return (audio_coding_->ReceiveCodec(codec) == 0);
+  return audio_coding_->ReceiveCodec();
 }
 
 std::vector<webrtc::RtpSource> ChannelReceive::GetSources() const {
@@ -628,8 +620,6 @@
   const uint8_t* payload = packet + header.headerLength;
   assert(packet_length >= header.headerLength);
   size_t payload_length = packet_length - header.headerLength;
-  WebRtcRTPHeader webrtc_rtp_header = {};
-  webrtc_rtp_header.header = header;
 
   size_t payload_data_length = payload_length - header.paddingLength;
 
@@ -668,11 +658,9 @@
   }
 
   if (payload_data_length == 0) {
-    webrtc_rtp_header.frameType = kEmptyFrame;
-    return OnReceivedPayloadData(nullptr, 0, &webrtc_rtp_header);
+    return OnReceivedPayloadData(nullptr, 0, header);
   }
-  return OnReceivedPayloadData(payload, payload_data_length,
-                               &webrtc_rtp_header);
+  return OnReceivedPayloadData(payload, payload_data_length, header);
 }
 
 // May be called on either worker thread or network thread.
@@ -690,13 +678,6 @@
     return true;
   }
 
-  int64_t nack_window_ms = rtt;
-  if (nack_window_ms < kMinRetransmissionWindowMs) {
-    nack_window_ms = kMinRetransmissionWindowMs;
-  } else if (nack_window_ms > kMaxRetransmissionWindowMs) {
-    nack_window_ms = kMaxRetransmissionWindowMs;
-  }
-
   uint32_t ntp_secs = 0;
   uint32_t ntp_frac = 0;
   uint32_t rtp_timestamp = 0;
@@ -802,11 +783,14 @@
 void ChannelReceive::SetNACKStatus(bool enable, int max_packets) {
   RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
   // None of these functions can fail.
-  rtp_receive_statistics_->SetMaxReorderingThreshold(max_packets);
-  if (enable)
+  if (enable) {
+    rtp_receive_statistics_->SetMaxReorderingThreshold(max_packets);
     audio_coding_->EnableNack(max_packets);
-  else
+  } else {
+    rtp_receive_statistics_->SetMaxReorderingThreshold(
+        kDefaultMaxReorderingThreshold);
     audio_coding_->DisableNack();
+  }
 }
 
 // Called when we are missing one or more packets.
@@ -848,12 +832,8 @@
   RTC_DCHECK(module_process_thread_checker_.CalledOnValidThread());
   // Limit to range accepted by both VoE and ACM, so we're at least getting as
   // close as possible, instead of failing.
-  delay_ms = rtc::SafeClamp(delay_ms, 0, 10000);
-  if ((delay_ms < kVoiceEngineMinMinPlayoutDelayMs) ||
-      (delay_ms > kVoiceEngineMaxMinPlayoutDelayMs)) {
-    RTC_DLOG(LS_ERROR) << "SetMinimumPlayoutDelay() invalid min delay";
-    return;
-  }
+  delay_ms = rtc::SafeClamp(delay_ms, kVoiceEngineMinMinPlayoutDelayMs,
+                            kVoiceEngineMaxMinPlayoutDelayMs);
   if (audio_coding_->SetMinimumPlayoutDelay(delay_ms) != 0) {
     RTC_DLOG(LS_ERROR)
         << "SetMinimumPlayoutDelay() failed to set min playout delay";
@@ -868,6 +848,14 @@
   }
 }
 
+bool ChannelReceive::SetBaseMinimumPlayoutDelayMs(int delay_ms) {
+  return audio_coding_->SetBaseMinimumPlayoutDelayMs(delay_ms);
+}
+
+int ChannelReceive::GetBaseMinimumPlayoutDelayMs() const {
+  return audio_coding_->GetBaseMinimumPlayoutDelayMs();
+}
+
 absl::optional<Syncable::Info> ChannelReceive::GetSyncInfo() const {
   RTC_DCHECK(module_process_thread_checker_.CalledOnValidThread());
   Syncable::Info info;
@@ -920,13 +908,13 @@
 }
 
 int ChannelReceive::GetRtpTimestampRateHz() const {
-  const auto format = audio_coding_->ReceiveFormat();
+  const auto decoder = audio_coding_->ReceiveCodec();
   // Default to the playout frequency if we've not gotten any packets yet.
   // TODO(ossu): Zero clockrate can only happen if we've added an external
   // decoder for a format we don't support internally. Remove once that way of
   // adding decoders is gone!
-  return (format && format->clockrate_hz != 0)
-             ? format->clockrate_hz
+  return (decoder && decoder->second.clockrate_hz != 0)
+             ? decoder->second.clockrate_hz
              : audio_coding_->PlayoutFrequency();
 }
 
@@ -973,6 +961,7 @@
 }  // namespace
 
 std::unique_ptr<ChannelReceiveInterface> CreateChannelReceive(
+    Clock* clock,
     ProcessThread* module_process_thread,
     AudioDeviceModule* audio_device_module,
     MediaTransportInterface* media_transport,
@@ -982,16 +971,17 @@
     size_t jitter_buffer_max_packets,
     bool jitter_buffer_fast_playout,
     int jitter_buffer_min_delay_ms,
+    bool jitter_buffer_enable_rtx_handling,
     rtc::scoped_refptr<AudioDecoderFactory> decoder_factory,
     absl::optional<AudioCodecPairId> codec_pair_id,
     rtc::scoped_refptr<FrameDecryptorInterface> frame_decryptor,
     const webrtc::CryptoOptions& crypto_options) {
   return absl::make_unique<ChannelReceive>(
-      module_process_thread, audio_device_module, media_transport,
+      clock, module_process_thread, audio_device_module, media_transport,
       rtcp_send_transport, rtc_event_log, remote_ssrc,
       jitter_buffer_max_packets, jitter_buffer_fast_playout,
-      jitter_buffer_min_delay_ms, decoder_factory, codec_pair_id,
-      frame_decryptor, crypto_options);
+      jitter_buffer_min_delay_ms, jitter_buffer_enable_rtx_handling,
+      decoder_factory, codec_pair_id, frame_decryptor, crypto_options);
 }
 
 }  // namespace voe
diff --git a/audio/channel_receive.h b/audio/channel_receive.h
index 9027623..b3e4f9c 100644
--- a/audio/channel_receive.h
+++ b/audio/channel_receive.h
@@ -13,6 +13,7 @@
 
 #include <map>
 #include <memory>
+#include <utility>
 #include <vector>
 
 #include "absl/types/optional.h"
@@ -20,9 +21,9 @@
 #include "api/audio_codecs/audio_decoder_factory.h"
 #include "api/call/audio_sink.h"
 #include "api/call/transport.h"
-#include "api/crypto/cryptooptions.h"
+#include "api/crypto/crypto_options.h"
 #include "api/media_transport_interface.h"
-#include "api/rtpreceiverinterface.h"
+#include "api/rtp_receiver_interface.h"
 #include "call/rtp_packet_sink_interface.h"
 #include "call/syncable.h"
 #include "modules/audio_coding/include/audio_coding_module.h"
@@ -79,7 +80,9 @@
   virtual void StartPlayout() = 0;
   virtual void StopPlayout() = 0;
 
-  virtual bool GetRecCodec(CodecInst* codec) const = 0;
+  // Payload type and format of last received RTP packet, if any.
+  virtual absl::optional<std::pair<int, SdpAudioFormat>>
+      GetReceiveCodec() const = 0;
 
   virtual bool ReceivedRTCPPacket(const uint8_t* data, size_t length) = 0;
 
@@ -99,6 +102,12 @@
   virtual void SetMinimumPlayoutDelay(int delay_ms) = 0;
   virtual uint32_t GetPlayoutTimestamp() const = 0;
 
+  // Audio quality.
+  // Base minimum delay sets lower bound on minimum delay value which
+  // determines minimum delay until audio playout.
+  virtual bool SetBaseMinimumPlayoutDelayMs(int delay_ms) = 0;
+  virtual int GetBaseMinimumPlayoutDelayMs() const = 0;
+
   // Produces the transport-related timestamps; current_delay_ms is left unset.
   virtual absl::optional<Syncable::Info> GetSyncInfo() const = 0;
 
@@ -127,6 +136,7 @@
 };
 
 std::unique_ptr<ChannelReceiveInterface> CreateChannelReceive(
+    Clock* clock,
     ProcessThread* module_process_thread,
     AudioDeviceModule* audio_device_module,
     MediaTransportInterface* media_transport,
@@ -136,6 +146,7 @@
     size_t jitter_buffer_max_packets,
     bool jitter_buffer_fast_playout,
     int jitter_buffer_min_delay_ms,
+    bool jitter_buffer_enable_rtx_handling,
     rtc::scoped_refptr<AudioDecoderFactory> decoder_factory,
     absl::optional<AudioCodecPairId> codec_pair_id,
     rtc::scoped_refptr<FrameDecryptorInterface> frame_decryptor,
diff --git a/audio/channel_send.cc b/audio/channel_send.cc
index c458fe4..0c8be1f 100644
--- a/audio/channel_send.cc
+++ b/audio/channel_send.cc
@@ -20,7 +20,7 @@
 #include "absl/memory/memory.h"
 #include "api/array_view.h"
 #include "api/call/transport.h"
-#include "api/crypto/frameencryptorinterface.h"
+#include "api/crypto/frame_encryptor_interface.h"
 #include "audio/utility/audio_frame_operations.h"
 #include "call/rtp_transport_controller_send_interface.h"
 #include "logging/rtc_event_log/events/rtc_event_audio_playout.h"
@@ -31,7 +31,7 @@
 #include "modules/pacing/packet_router.h"
 #include "modules/utility/include/process_thread.h"
 #include "rtc_base/checks.h"
-#include "rtc_base/criticalsection.h"
+#include "rtc_base/critical_section.h"
 #include "rtc_base/event.h"
 #include "rtc_base/format_macros.h"
 #include "rtc_base/location.h"
@@ -41,7 +41,8 @@
 #include "rtc_base/rate_limiter.h"
 #include "rtc_base/task_queue.h"
 #include "rtc_base/thread_checker.h"
-#include "rtc_base/timeutils.h"
+#include "rtc_base/time_utils.h"
+#include "system_wrappers/include/clock.h"
 #include "system_wrappers/include/field_trial.h"
 #include "system_wrappers/include/metrics.h"
 
@@ -78,8 +79,6 @@
 
 class ChannelSend
     : public ChannelSendInterface,
-      public Transport,
-      public OverheadObserver,
       public AudioPacketizationCallback,  // receive encoded packets from the
                                           // ACM
       public TargetTransferRateObserver {
@@ -88,9 +87,11 @@
   // declaration.
   friend class VoERtcpObserver;
 
-  ChannelSend(rtc::TaskQueue* encoder_queue,
+  ChannelSend(Clock* clock,
+              rtc::TaskQueue* encoder_queue,
               ProcessThread* module_process_thread,
               MediaTransportInterface* media_transport,
+              OverheadObserver* overhead_observer,
               Transport* rtp_transport,
               RtcpRttStats* rtcp_rtt_stats,
               RtcEventLog* rtc_event_log,
@@ -106,6 +107,7 @@
                   std::unique_ptr<AudioEncoder> encoder) override;
   void ModifyEncoder(rtc::FunctionView<void(std::unique_ptr<AudioEncoder>*)>
                          modifier) override;
+  void CallEncoder(rtc::FunctionView<void(AudioEncoder*)> modifier) override;
 
   // API methods
   void StartSend() override;
@@ -134,6 +136,9 @@
 
   // RTP+RTCP
   void SetLocalSSRC(uint32_t ssrc) override;
+  void SetRid(const std::string& rid,
+              int extension_id,
+              int repaired_extension_id) override;
   void SetMid(const std::string& mid, int extension_id) override;
   void SetExtmapAllowMixed(bool extmap_allow_mixed) override;
   void SetSendAudioLevelIndicationStatus(bool enable, int id) override;
@@ -158,8 +163,6 @@
   // packet.
   void ProcessAndEncodeAudio(std::unique_ptr<AudioFrame> audio_frame) override;
 
-  void SetTransportOverhead(size_t transport_overhead_per_packet) override;
-
   // The existence of this function alongside OnUplinkPacketLossRate is
   // a compromise. We want the encoder to be agnostic of the PLR source, but
   // we also don't want it to receive conflicting information from TWCC and
@@ -186,23 +189,11 @@
                    size_t payloadSize,
                    const RTPFragmentationHeader* fragmentation) override;
 
-  // From Transport (called by the RTP/RTCP module)
-  bool SendRtp(const uint8_t* data,
-               size_t len,
-               const PacketOptions& packet_options) override;
-  bool SendRtcp(const uint8_t* data, size_t len) override;
-
-  // From OverheadObserver in the RTP/RTCP module
-  void OnOverheadChanged(size_t overhead_bytes_per_packet) override;
-
   void OnUplinkPacketLossRate(float packet_loss_rate);
   bool InputMute() const;
 
   int SetSendRtpHeaderExtension(bool enable, RTPExtensionType type, int id);
 
-  void UpdateOverheadForEncoder()
-      RTC_EXCLUSIVE_LOCKS_REQUIRED(overhead_per_packet_lock_);
-
   int32_t SendRtpAudio(FrameType frameType,
                        uint8_t payloadType,
                        uint32_t timeStamp,
@@ -238,7 +229,6 @@
   // audio thread to another, but access is still sequential.
   rtc::RaceChecker audio_thread_race_checker_;
 
-  rtc::CriticalSection _callbackCritSect;
   rtc::CriticalSection volume_settings_critsect_;
 
   bool sending_ RTC_GUARDED_BY(&worker_thread_checker_) = false;
@@ -250,11 +240,8 @@
   std::unique_ptr<AudioCodingModule> audio_coding_;
   uint32_t _timeStamp RTC_GUARDED_BY(encoder_queue_);
 
-  uint16_t send_sequence_number_;
-
   // uses
   ProcessThread* const _moduleProcessThreadPtr;
-  Transport* const _transportPtr;  // WebRtc socket or external transport
   RmsLevel rms_level_ RTC_GUARDED_BY(encoder_queue_);
   bool input_mute_ RTC_GUARDED_BY(volume_settings_critsect_);
   bool previous_frame_muted_ RTC_GUARDED_BY(encoder_queue_);
@@ -262,10 +249,7 @@
   // TODO(henrika): can today be accessed on the main thread and on the
   // task queue; hence potential race.
   bool _includeAudioLevelIndication;
-  size_t transport_overhead_per_packet_
-      RTC_GUARDED_BY(overhead_per_packet_lock_);
-  size_t rtp_overhead_per_packet_ RTC_GUARDED_BY(overhead_per_packet_lock_);
-  rtc::CriticalSection overhead_per_packet_lock_;
+
   // RtcpBandwidthObserver
   const std::unique_ptr<VoERtcpObserver> rtcp_observer_;
 
@@ -416,7 +400,7 @@
  public:
   explicit VoERtcpObserver(ChannelSend* owner)
       : owner_(owner), bandwidth_observer_(nullptr) {}
-  virtual ~VoERtcpObserver() {}
+  ~VoERtcpObserver() override {}
 
   void SetBandwidthObserver(RtcpBandwidthObserver* bandwidth_observer) {
     rtc::CritScope lock(&crit_);
@@ -515,6 +499,12 @@
   rtc::ArrayView<const uint8_t> payload(payloadData, payloadSize);
 
   if (media_transport() != nullptr) {
+    if (frameType == kEmptyFrame) {
+      // TODO(bugs.webrtc.org/9719): Media transport Send doesn't support
+      // sending empty frames.
+      return 0;
+    }
+
     return SendMediaTransportAudio(frameType, payloadType, timeStamp, payload,
                                    fragmentation);
   } else {
@@ -606,7 +596,7 @@
     sampling_rate_hz = media_transport_sampling_frequency_;
     channel_id = media_transport_channel_id_;
   }
-  const MediaTransportEncodedAudioFrame frame(
+  MediaTransportEncodedAudioFrame frame(
       /*sampling_rate_hz=*/sampling_rate_hz,
 
       // TODO(nisse): Timestamp and sample index are the same for all supported
@@ -641,48 +631,11 @@
   return 0;
 }
 
-bool ChannelSend::SendRtp(const uint8_t* data,
-                          size_t len,
-                          const PacketOptions& options) {
-  // We should not be sending RTP packets if media transport is available.
-  RTC_CHECK(!media_transport());
-
-  rtc::CritScope cs(&_callbackCritSect);
-
-  if (_transportPtr == NULL) {
-    RTC_DLOG(LS_ERROR)
-        << "ChannelSend::SendPacket() failed to send RTP packet due to"
-        << " invalid transport object";
-    return false;
-  }
-
-  if (!_transportPtr->SendRtp(data, len, options)) {
-    RTC_DLOG(LS_ERROR) << "ChannelSend::SendPacket() RTP transmission failed";
-    return false;
-  }
-  return true;
-}
-
-bool ChannelSend::SendRtcp(const uint8_t* data, size_t len) {
-  rtc::CritScope cs(&_callbackCritSect);
-  if (_transportPtr == NULL) {
-    RTC_DLOG(LS_ERROR)
-        << "ChannelSend::SendRtcp() failed to send RTCP packet due to"
-        << " invalid transport object";
-    return false;
-  }
-
-  int n = _transportPtr->SendRtcp(data, len);
-  if (n < 0) {
-    RTC_DLOG(LS_ERROR) << "ChannelSend::SendRtcp() transmission failed";
-    return false;
-  }
-  return true;
-}
-
-ChannelSend::ChannelSend(rtc::TaskQueue* encoder_queue,
+ChannelSend::ChannelSend(Clock* clock,
+                         rtc::TaskQueue* encoder_queue,
                          ProcessThread* module_process_thread,
                          MediaTransportInterface* media_transport,
+                         OverheadObserver* overhead_observer,
                          Transport* rtp_transport,
                          RtcpRttStats* rtcp_rtt_stats,
                          RtcEventLog* rtc_event_log,
@@ -693,20 +646,16 @@
     : event_log_(rtc_event_log),
       _timeStamp(0),  // This is just an offset, RTP module will add it's own
                       // random offset
-      send_sequence_number_(0),
       _moduleProcessThreadPtr(module_process_thread),
-      _transportPtr(rtp_transport),
       input_mute_(false),
       previous_frame_muted_(false),
       _includeAudioLevelIndication(false),
-      transport_overhead_per_packet_(0),
-      rtp_overhead_per_packet_(0),
       rtcp_observer_(new VoERtcpObserver(this)),
       feedback_observer_proxy_(new TransportFeedbackProxy()),
       seq_num_allocator_proxy_(new TransportSequenceNumberProxy()),
       rtp_packet_sender_proxy_(new RtpPacketSenderProxy()),
-      retransmission_rate_limiter_(new RateLimiter(Clock::GetRealTimeClock(),
-                                                   kMaxRetransmissionWindowMs)),
+      retransmission_rate_limiter_(
+          new RateLimiter(clock, kMaxRetransmissionWindowMs)),
       use_twcc_plr_for_ana_(
           webrtc::field_trial::FindFullName("UseTwccPlrForAna") == "Enabled"),
       encoder_queue_(encoder_queue),
@@ -726,13 +675,19 @@
   // RTPMediaTransport. In this case it means that overhead and bandwidth
   // observers should not be called when using media transport.
   if (!media_transport_) {
-    configuration.overhead_observer = this;
+    // TODO(sukhanov): Overhead observer is only needed for RTP path, because in
+    // media transport audio overhead is currently considered constant (see
+    // getter MediaTransportInterface::GetAudioPacketOverhead).  In the future
+    // when we introduce RTP media transport we should make audio overhead
+    // interface consistent and work for both RTP and non-RTP implementations.
+    configuration.overhead_observer = overhead_observer;
     configuration.bandwidth_callback = rtcp_observer_.get();
     configuration.transport_feedback_callback = feedback_observer_proxy_.get();
   }
 
+  configuration.clock = clock;
   configuration.audio = true;
-  configuration.outgoing_transport = this;
+  configuration.outgoing_transport = rtp_transport;
 
   configuration.paced_sender = rtp_packet_sender_proxy_.get();
   configuration.transport_sequence_number_allocator =
@@ -753,7 +708,6 @@
   if (media_transport_) {
     RTC_DLOG(LS_INFO) << "Setting media_transport_ rate observers.";
     media_transport_->AddTargetTransferRateObserver(this);
-    OnOverheadChanged(media_transport_->GetAudioPacketOverhead());
   } else {
     RTC_DLOG(LS_INFO) << "Not setting media_transport_ rate observers.";
   }
@@ -780,7 +734,6 @@
   }
 
   StopSend();
-
   int error = audio_coding_->RegisterTransportCallback(NULL);
   RTC_DCHECK_EQ(0, error);
 
@@ -793,11 +746,6 @@
   RTC_DCHECK(!sending_);
   sending_ = true;
 
-  // Resume the previous sequence number which was reset by StopSend(). This
-  // needs to be done before |sending| is set to true on the RTP/RTCP module.
-  if (send_sequence_number_) {
-    _rtpRtcpModule->SetSequenceNumber(send_sequence_number_);
-  }
   _rtpRtcpModule->SetSendingMediaStatus(true);
   int ret = _rtpRtcpModule->SetSendingStatus(true);
   RTC_DCHECK_EQ(0, ret);
@@ -833,14 +781,6 @@
   }
   flush.Wait(rtc::Event::kForever);
 
-  // Store the sequence number to be able to pick up the same sequence for
-  // the next StartSend(). This is needed for restarting device, otherwise
-  // it might cause libSRTP to complain about packets being replayed.
-  // TODO(xians): Remove this workaround after RtpRtcpModule's refactoring
-  // CL is landed. See issue
-  // https://code.google.com/p/webrtc/issues/detail?id=2111 .
-  send_sequence_number_ = _rtpRtcpModule->SequenceNumber();
-
   // Reset sending SSRC and sequence number and triggers direct transmission
   // of RTCP BYE
   if (_rtpRtcpModule->SetSendingStatus(false) == -1) {
@@ -854,33 +794,14 @@
   RTC_DCHECK_RUN_ON(&worker_thread_checker_);
   RTC_DCHECK_GE(payload_type, 0);
   RTC_DCHECK_LE(payload_type, 127);
-  // TODO(ossu): Make CodecInsts up, for now: one for the RTP/RTCP module and
-  // one for for us to keep track of sample rate and number of channels, etc.
 
   // The RTP/RTCP module needs to know the RTP timestamp rate (i.e. clockrate)
   // as well as some other things, so we collect this info and send it along.
-  CodecInst rtp_codec;
-  rtp_codec.pltype = payload_type;
-  strncpy(rtp_codec.plname, "audio", sizeof(rtp_codec.plname));
-  rtp_codec.plname[sizeof(rtp_codec.plname) - 1] = 0;
-  // Seems unclear if it should be clock rate or sample rate. CodecInst
-  // supposedly carries the sample rate, but only clock rate seems sensible to
-  // send to the RTP/RTCP module.
-  rtp_codec.plfreq = encoder->RtpTimestampRateHz();
-  rtp_codec.pacsize = rtc::CheckedDivExact(
-      static_cast<int>(encoder->Max10MsFramesInAPacket() * rtp_codec.plfreq),
-      100);
-  rtp_codec.channels = encoder->NumChannels();
-  rtp_codec.rate = 0;
-
-  if (_rtpRtcpModule->RegisterSendPayload(rtp_codec) != 0) {
-    _rtpRtcpModule->DeRegisterSendPayload(payload_type);
-    if (_rtpRtcpModule->RegisterSendPayload(rtp_codec) != 0) {
-      RTC_DLOG(LS_ERROR)
-          << "SetEncoder() failed to register codec to RTP/RTCP module";
-      return false;
-    }
-  }
+  _rtpRtcpModule->RegisterAudioSendPayload(payload_type,
+                                           "audio",
+                                           encoder->RtpTimestampRateHz(),
+                                           encoder->NumChannels(),
+                                           0);
 
   if (media_transport_) {
     rtc::CritScope cs(&media_transport_lock_);
@@ -895,10 +816,22 @@
 
 void ChannelSend::ModifyEncoder(
     rtc::FunctionView<void(std::unique_ptr<AudioEncoder>*)> modifier) {
-  RTC_DCHECK_RUN_ON(&worker_thread_checker_);
+  // This method can be called on the worker thread, module process thread
+  // or network thread. Audio coding is thread safe, so we do not need to
+  // enforce the calling thread.
   audio_coding_->ModifyEncoder(modifier);
 }
 
+void ChannelSend::CallEncoder(rtc::FunctionView<void(AudioEncoder*)> modifier) {
+  ModifyEncoder([modifier](std::unique_ptr<AudioEncoder>* encoder_ptr) {
+    if (*encoder_ptr) {
+      modifier(encoder_ptr->get());
+    } else {
+      RTC_DLOG(LS_WARNING) << "Trying to call unset encoder.";
+    }
+  });
+}
+
 void ChannelSend::OnBitrateAllocation(BitrateAllocationUpdate update) {
   // This method can be called on the worker thread, module process thread
   // or on a TaskQueue via VideoSendStreamImpl::OnEncoderConfigurationChanged.
@@ -908,10 +841,8 @@
   //            module_process_thread_checker_.CalledOnValidThread());
   rtc::CritScope lock(&bitrate_crit_section_);
 
-  audio_coding_->ModifyEncoder([&](std::unique_ptr<AudioEncoder>* encoder) {
-    if (*encoder) {
-      (*encoder)->OnReceivedUplinkAllocation(update);
-    }
+  CallEncoder([&](AudioEncoder* encoder) {
+    encoder->OnReceivedUplinkAllocation(update);
   });
   retransmission_rate_limiter_->SetMaxRate(update.target_bitrate.bps());
   configured_bitrate_bps_ = update.target_bitrate.bps();
@@ -926,31 +857,25 @@
   RTC_DCHECK_RUN_ON(&worker_thread_checker_);
   if (!use_twcc_plr_for_ana_)
     return;
-  audio_coding_->ModifyEncoder([&](std::unique_ptr<AudioEncoder>* encoder) {
-    if (*encoder) {
-      (*encoder)->OnReceivedUplinkPacketLossFraction(packet_loss_rate);
-    }
+  CallEncoder([&](AudioEncoder* encoder) {
+    encoder->OnReceivedUplinkPacketLossFraction(packet_loss_rate);
   });
 }
 
 void ChannelSend::OnRecoverableUplinkPacketLossRate(
     float recoverable_packet_loss_rate) {
   RTC_DCHECK_RUN_ON(&worker_thread_checker_);
-  audio_coding_->ModifyEncoder([&](std::unique_ptr<AudioEncoder>* encoder) {
-    if (*encoder) {
-      (*encoder)->OnReceivedUplinkRecoverablePacketLossFraction(
-          recoverable_packet_loss_rate);
-    }
+  CallEncoder([&](AudioEncoder* encoder) {
+    encoder->OnReceivedUplinkRecoverablePacketLossFraction(
+        recoverable_packet_loss_rate);
   });
 }
 
 void ChannelSend::OnUplinkPacketLossRate(float packet_loss_rate) {
   if (use_twcc_plr_for_ana_)
     return;
-  audio_coding_->ModifyEncoder([&](std::unique_ptr<AudioEncoder>* encoder) {
-    if (*encoder) {
-      (*encoder)->OnReceivedUplinkPacketLossFraction(packet_loss_rate);
-    }
+  CallEncoder([&](AudioEncoder* encoder) {
+    encoder->OnReceivedUplinkPacketLossFraction(packet_loss_rate);
   });
 }
 
@@ -1017,19 +942,8 @@
   RTC_DCHECK_RUN_ON(&worker_thread_checker_);
   RTC_DCHECK_LE(0, payload_type);
   RTC_DCHECK_GE(127, payload_type);
-  CodecInst codec = {0};
-  codec.pltype = payload_type;
-  codec.plfreq = payload_frequency;
-  memcpy(codec.plname, "telephone-event", 16);
-  if (_rtpRtcpModule->RegisterSendPayload(codec) != 0) {
-    _rtpRtcpModule->DeRegisterSendPayload(codec.pltype);
-    if (_rtpRtcpModule->RegisterSendPayload(codec) != 0) {
-      RTC_DLOG(LS_ERROR)
-          << "SetSendTelephoneEventPayloadType() failed to register "
-             "send payload type";
-      return false;
-    }
-  }
+  _rtpRtcpModule->RegisterAudioSendPayload(payload_type, "telephone-event",
+                                           payload_frequency, 0, 0);
   return true;
 }
 
@@ -1044,6 +958,23 @@
   _rtpRtcpModule->SetSSRC(ssrc);
 }
 
+void ChannelSend::SetRid(const std::string& rid,
+                         int extension_id,
+                         int repaired_extension_id) {
+  RTC_DCHECK_RUN_ON(&worker_thread_checker_);
+  if (extension_id != 0) {
+    int ret = SetSendRtpHeaderExtension(!rid.empty(), kRtpExtensionRtpStreamId,
+                                        extension_id);
+    RTC_DCHECK_EQ(0, ret);
+  }
+  if (repaired_extension_id != 0) {
+    int ret = SetSendRtpHeaderExtension(!rid.empty(), kRtpExtensionRtpStreamId,
+                                        repaired_extension_id);
+    RTC_DCHECK_EQ(0, ret);
+  }
+  _rtpRtcpModule->SetRid(rid);
+}
+
 void ChannelSend::SetMid(const std::string& mid, int extension_id) {
   RTC_DCHECK_RUN_ON(&worker_thread_checker_);
   int ret = SetSendRtpHeaderExtension(true, kRtpExtensionMid, extension_id);
@@ -1220,30 +1151,6 @@
   _timeStamp += static_cast<uint32_t>(audio_input->samples_per_channel_);
 }
 
-void ChannelSend::UpdateOverheadForEncoder() {
-  size_t overhead_per_packet =
-      transport_overhead_per_packet_ + rtp_overhead_per_packet_;
-  audio_coding_->ModifyEncoder([&](std::unique_ptr<AudioEncoder>* encoder) {
-    if (*encoder) {
-      (*encoder)->OnReceivedOverhead(overhead_per_packet);
-    }
-  });
-}
-
-void ChannelSend::SetTransportOverhead(size_t transport_overhead_per_packet) {
-  RTC_DCHECK_RUN_ON(&worker_thread_checker_);
-  rtc::CritScope cs(&overhead_per_packet_lock_);
-  transport_overhead_per_packet_ = transport_overhead_per_packet;
-  UpdateOverheadForEncoder();
-}
-
-// TODO(solenberg): Make AudioSendStream an OverheadObserver instead.
-void ChannelSend::OnOverheadChanged(size_t overhead_bytes_per_packet) {
-  rtc::CritScope cs(&overhead_per_packet_lock_);
-  rtp_overhead_per_packet_ = overhead_bytes_per_packet;
-  UpdateOverheadForEncoder();
-}
-
 ANAStats ChannelSend::GetANAStatistics() const {
   RTC_DCHECK_RUN_ON(&worker_thread_checker_);
   return audio_coding_->GetANAStats();
@@ -1310,7 +1217,7 @@
   RTC_DCHECK_RUN_ON(&worker_thread_checker_);
   rtc::CritScope cs(&encoder_queue_lock_);
   if (encoder_queue_is_active_) {
-    encoder_queue_->PostTask([this, frame_encryptor]() {
+    encoder_queue_->PostTask([this, frame_encryptor]() mutable {
       this->frame_encryptor_ = std::move(frame_encryptor);
     });
   } else {
@@ -1318,6 +1225,9 @@
   }
 }
 
+// TODO(sukhanov): Consider moving TargetTransferRate observer to
+// AudioSendStream. Since AudioSendStream owns encoder and configures ANA, it
+// makes sense to consolidate all rate (and overhead) calculation there.
 void ChannelSend::OnTargetTransferRate(TargetTransferRate rate) {
   RTC_DCHECK(media_transport_);
   OnReceivedRtt(rate.network_estimate.round_trip_time.ms());
@@ -1325,20 +1235,18 @@
 
 void ChannelSend::OnReceivedRtt(int64_t rtt_ms) {
   // Invoke audio encoders OnReceivedRtt().
-  audio_coding_->ModifyEncoder(
-      [rtt_ms](std::unique_ptr<AudioEncoder>* encoder) {
-        if (*encoder) {
-          (*encoder)->OnReceivedRtt(rtt_ms);
-        }
-      });
+  CallEncoder(
+      [rtt_ms](AudioEncoder* encoder) { encoder->OnReceivedRtt(rtt_ms); });
 }
 
 }  // namespace
 
 std::unique_ptr<ChannelSendInterface> CreateChannelSend(
+    Clock* clock,
     rtc::TaskQueue* encoder_queue,
     ProcessThread* module_process_thread,
     MediaTransportInterface* media_transport,
+    OverheadObserver* overhead_observer,
     Transport* rtp_transport,
     RtcpRttStats* rtcp_rtt_stats,
     RtcEventLog* rtc_event_log,
@@ -1347,9 +1255,10 @@
     bool extmap_allow_mixed,
     int rtcp_report_interval_ms) {
   return absl::make_unique<ChannelSend>(
-      encoder_queue, module_process_thread, media_transport, rtp_transport,
-      rtcp_rtt_stats, rtc_event_log, frame_encryptor, crypto_options,
-      extmap_allow_mixed, rtcp_report_interval_ms);
+      clock, encoder_queue, module_process_thread, media_transport,
+      overhead_observer, rtp_transport, rtcp_rtt_stats, rtc_event_log,
+      frame_encryptor, crypto_options, extmap_allow_mixed,
+      rtcp_report_interval_ms);
 }
 
 }  // namespace voe
diff --git a/audio/channel_send.h b/audio/channel_send.h
index 083e9a6..4ab53c0 100644
--- a/audio/channel_send.h
+++ b/audio/channel_send.h
@@ -17,7 +17,7 @@
 
 #include "api/audio/audio_frame.h"
 #include "api/audio_codecs/audio_encoder.h"
-#include "api/crypto/cryptooptions.h"
+#include "api/crypto/crypto_options.h"
 #include "api/media_transport_interface.h"
 #include "modules/rtp_rtcp/include/rtp_rtcp.h"
 #include "rtc_base/function_view.h"
@@ -63,8 +63,13 @@
                           std::unique_ptr<AudioEncoder> encoder) = 0;
   virtual void ModifyEncoder(
       rtc::FunctionView<void(std::unique_ptr<AudioEncoder>*)> modifier) = 0;
+  virtual void CallEncoder(rtc::FunctionView<void(AudioEncoder*)> modifier) = 0;
 
   virtual void SetLocalSSRC(uint32_t ssrc) = 0;
+  // Use 0 to indicate that the extension should not be registered.
+  virtual void SetRid(const std::string& rid,
+                      int extension_id,
+                      int repaired_extension_id) = 0;
   virtual void SetMid(const std::string& mid, int extension_id) = 0;
   virtual void SetRTCP_CNAME(absl::string_view c_name) = 0;
   virtual void SetExtmapAllowMixed(bool extmap_allow_mixed) = 0;
@@ -85,7 +90,6 @@
 
   virtual void ProcessAndEncodeAudio(
       std::unique_ptr<AudioFrame> audio_frame) = 0;
-  virtual void SetTransportOverhead(size_t transport_overhead_per_packet) = 0;
   virtual RtpRtcp* GetRtpRtcp() const = 0;
 
   virtual void OnTwccBasedUplinkPacketLossRate(float packet_loss_rate) = 0;
@@ -111,9 +115,11 @@
 };
 
 std::unique_ptr<ChannelSendInterface> CreateChannelSend(
+    Clock* clock,
     rtc::TaskQueue* encoder_queue,
     ProcessThread* module_process_thread,
     MediaTransportInterface* media_transport,
+    OverheadObserver* overhead_observer,
     Transport* rtp_transport,
     RtcpRttStats* rtcp_rtt_stats,
     RtcEventLog* rtc_event_log,
diff --git a/audio/mock_voe_channel_proxy.h b/audio/mock_voe_channel_proxy.h
index eee25c5..a03ce7e 100644
--- a/audio/mock_voe_channel_proxy.h
+++ b/audio/mock_voe_channel_proxy.h
@@ -14,6 +14,7 @@
 #include <map>
 #include <memory>
 #include <string>
+#include <utility>
 #include <vector>
 
 #include "api/test/mock_frame_encryptor.h"
@@ -52,7 +53,10 @@
   MOCK_CONST_METHOD0(GetPlayoutTimestamp, uint32_t());
   MOCK_CONST_METHOD0(GetSyncInfo, absl::optional<Syncable::Info>());
   MOCK_METHOD1(SetMinimumPlayoutDelay, void(int delay_ms));
-  MOCK_CONST_METHOD1(GetRecCodec, bool(CodecInst* codec_inst));
+  MOCK_METHOD1(SetBaseMinimumPlayoutDelayMs, bool(int delay_ms));
+  MOCK_CONST_METHOD0(GetBaseMinimumPlayoutDelayMs, int());
+  MOCK_CONST_METHOD0(GetReceiveCodec,
+                     absl::optional<std::pair<int, SdpAudioFormat>>());
   MOCK_METHOD1(SetReceiveCodecs,
                void(const std::map<int, SdpAudioFormat>& codecs));
   MOCK_CONST_METHOD0(GetSources, std::vector<RtpSource>());
@@ -72,6 +76,12 @@
   MOCK_METHOD1(
       ModifyEncoder,
       void(rtc::FunctionView<void(std::unique_ptr<AudioEncoder>*)> modifier));
+  MOCK_METHOD1(CallEncoder,
+               void(rtc::FunctionView<void(AudioEncoder*)> modifier));
+  MOCK_METHOD3(SetRid,
+               void(const std::string& rid,
+                    int extension_id,
+                    int repaired_extension_id));
   MOCK_METHOD2(SetMid, void(const std::string& mid, int extension_id));
   MOCK_METHOD1(SetLocalSSRC, void(uint32_t ssrc));
   MOCK_METHOD1(SetRTCP_CNAME, void(absl::string_view c_name));
diff --git a/audio/null_audio_poller.cc b/audio/null_audio_poller.cc
index d2b1199..063a367 100644
--- a/audio/null_audio_poller.cc
+++ b/audio/null_audio_poller.cc
@@ -15,7 +15,7 @@
 #include "rtc_base/checks.h"
 #include "rtc_base/location.h"
 #include "rtc_base/thread.h"
-#include "rtc_base/timeutils.h"
+#include "rtc_base/time_utils.h"
 
 namespace webrtc {
 namespace internal {
diff --git a/audio/null_audio_poller.h b/audio/null_audio_poller.h
index f91eb7d..9a81426 100644
--- a/audio/null_audio_poller.h
+++ b/audio/null_audio_poller.h
@@ -14,8 +14,8 @@
 #include <stdint.h>
 
 #include "modules/audio_device/include/audio_device_defines.h"
-#include "rtc_base/messagehandler.h"
-#include "rtc_base/messagequeue.h"
+#include "rtc_base/message_handler.h"
+#include "rtc_base/message_queue.h"
 #include "rtc_base/thread_checker.h"
 
 namespace webrtc {
diff --git a/audio/remix_resample.cc b/audio/remix_resample.cc
index cc59e2a..e77c386 100644
--- a/audio/remix_resample.cc
+++ b/audio/remix_resample.cc
@@ -80,7 +80,7 @@
     // The audio in dst_frame really is mono at this point; MonoToStereo will
     // set this back to stereo.
     dst_frame->num_channels_ = 1;
-    AudioFrameOperations::MonoToStereo(dst_frame);
+    AudioFrameOperations::UpmixChannels(2, dst_frame);
   }
 }
 
diff --git a/audio/transport_feedback_packet_loss_tracker_unittest.cc b/audio/transport_feedback_packet_loss_tracker_unittest.cc
index f522635..cc90651 100644
--- a/audio/transport_feedback_packet_loss_tracker_unittest.cc
+++ b/audio/transport_feedback_packet_loss_tracker_unittest.cc
@@ -561,8 +561,8 @@
 // to weed out potential bugs with wrap-around handling.
 constexpr uint16_t kBases[] = {0x0000, 0x3456, 0xc032, 0xfffe};
 
-INSTANTIATE_TEST_CASE_P(_,
-                        TransportFeedbackPacketLossTrackerTest,
-                        testing::ValuesIn(kBases));
+INSTANTIATE_TEST_SUITE_P(_,
+                         TransportFeedbackPacketLossTrackerTest,
+                         testing::ValuesIn(kBases));
 
 }  // namespace webrtc
diff --git a/audio/utility/BUILD.gn b/audio/utility/BUILD.gn
index 11a65bd..f60b512 100644
--- a/audio/utility/BUILD.gn
+++ b/audio/utility/BUILD.gn
@@ -22,7 +22,9 @@
 
   deps = [
     "../../api/audio:audio_frame_api",
+    "../../common_audio",
     "../../rtc_base:checks",
+    "../../rtc_base:deprecation",
     "../../rtc_base:rtc_base_approved",
   ]
 }
@@ -40,9 +42,5 @@
       "../../test:test_support",
       "//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" ]
-    }
   }
 }
diff --git a/audio/utility/audio_frame_operations.cc b/audio/utility/audio_frame_operations.cc
index 1a8232b..d3180a7 100644
--- a/audio/utility/audio_frame_operations.cc
+++ b/audio/utility/audio_frame_operations.cc
@@ -13,7 +13,9 @@
 #include <string.h>
 #include <algorithm>
 #include <cstdint>
+#include <utility>
 
+#include "common_audio/include/audio_util.h"
 #include "rtc_base/checks.h"
 #include "rtc_base/numerics/safe_conversions.h"
 
@@ -69,60 +71,20 @@
   }
 }
 
-void AudioFrameOperations::MonoToStereo(const int16_t* src_audio,
-                                        size_t samples_per_channel,
-                                        int16_t* dst_audio) {
-  for (size_t i = 0; i < samples_per_channel; i++) {
-    dst_audio[2 * i] = src_audio[i];
-    dst_audio[2 * i + 1] = src_audio[i];
-  }
-}
-
 int AudioFrameOperations::MonoToStereo(AudioFrame* frame) {
   if (frame->num_channels_ != 1) {
     return -1;
   }
-  if ((frame->samples_per_channel_ * 2) >= AudioFrame::kMaxDataSizeSamples) {
-    // Not enough memory to expand from mono to stereo.
-    return -1;
-  }
-
-  if (!frame->muted()) {
-    // TODO(yujo): this operation can be done in place.
-    int16_t data_copy[AudioFrame::kMaxDataSizeSamples];
-    memcpy(data_copy, frame->data(),
-           sizeof(int16_t) * frame->samples_per_channel_);
-    MonoToStereo(data_copy, frame->samples_per_channel_, frame->mutable_data());
-  }
-  frame->num_channels_ = 2;
-
+  UpmixChannels(2, frame);
   return 0;
 }
 
-void AudioFrameOperations::StereoToMono(const int16_t* src_audio,
-                                        size_t samples_per_channel,
-                                        int16_t* dst_audio) {
-  for (size_t i = 0; i < samples_per_channel; i++) {
-    dst_audio[i] =
-        (static_cast<int32_t>(src_audio[2 * i]) + src_audio[2 * i + 1]) >> 1;
-  }
-}
-
 int AudioFrameOperations::StereoToMono(AudioFrame* frame) {
   if (frame->num_channels_ != 2) {
     return -1;
   }
-
-  RTC_DCHECK_LE(frame->samples_per_channel_ * 2,
-                AudioFrame::kMaxDataSizeSamples);
-
-  if (!frame->muted()) {
-    StereoToMono(frame->data(), frame->samples_per_channel_,
-                 frame->mutable_data());
-  }
-  frame->num_channels_ = 1;
-
-  return 0;
+  DownmixChannels(1, frame);
+  return frame->num_channels_ == 1 ? 0 : -1;
 }
 
 void AudioFrameOperations::QuadToStereo(const int16_t* src_audio,
@@ -154,65 +116,66 @@
   return 0;
 }
 
-void AudioFrameOperations::QuadToMono(const int16_t* src_audio,
-                                      size_t samples_per_channel,
-                                      int16_t* dst_audio) {
-  for (size_t i = 0; i < samples_per_channel; i++) {
-    dst_audio[i] =
-        (static_cast<int32_t>(src_audio[4 * i]) + src_audio[4 * i + 1] +
-         src_audio[4 * i + 2] + src_audio[4 * i + 3]) >>
-        2;
-  }
-}
-
-int AudioFrameOperations::QuadToMono(AudioFrame* frame) {
-  if (frame->num_channels_ != 4) {
-    return -1;
-  }
-
-  RTC_DCHECK_LE(frame->samples_per_channel_ * 4,
-                AudioFrame::kMaxDataSizeSamples);
-
-  if (!frame->muted()) {
-    QuadToMono(frame->data(), frame->samples_per_channel_,
-               frame->mutable_data());
-  }
-  frame->num_channels_ = 1;
-
-  return 0;
-}
-
 void AudioFrameOperations::DownmixChannels(const int16_t* src_audio,
                                            size_t src_channels,
                                            size_t samples_per_channel,
                                            size_t dst_channels,
                                            int16_t* dst_audio) {
-  if (src_channels == 2 && dst_channels == 1) {
-    StereoToMono(src_audio, samples_per_channel, dst_audio);
+  if (src_channels > 1 && dst_channels == 1) {
+    DownmixInterleavedToMono(src_audio, samples_per_channel, src_channels,
+                             dst_audio);
     return;
   } else if (src_channels == 4 && dst_channels == 2) {
     QuadToStereo(src_audio, samples_per_channel, dst_audio);
     return;
-  } else if (src_channels == 4 && dst_channels == 1) {
-    QuadToMono(src_audio, samples_per_channel, dst_audio);
-    return;
   }
 
   RTC_NOTREACHED() << "src_channels: " << src_channels
                    << ", dst_channels: " << dst_channels;
 }
 
-int AudioFrameOperations::DownmixChannels(size_t dst_channels,
-                                          AudioFrame* frame) {
-  if (frame->num_channels_ == 2 && dst_channels == 1) {
-    return StereoToMono(frame);
+void AudioFrameOperations::DownmixChannels(size_t dst_channels,
+                                           AudioFrame* frame) {
+  RTC_DCHECK_LE(frame->samples_per_channel_ * frame->num_channels_,
+                AudioFrame::kMaxDataSizeSamples);
+  if (frame->num_channels_ > 1 && dst_channels == 1) {
+    if (!frame->muted()) {
+      DownmixInterleavedToMono(frame->data(), frame->samples_per_channel_,
+                               frame->num_channels_, frame->mutable_data());
+    }
+    frame->num_channels_ = 1;
   } else if (frame->num_channels_ == 4 && dst_channels == 2) {
-    return QuadToStereo(frame);
-  } else if (frame->num_channels_ == 4 && dst_channels == 1) {
-    return QuadToMono(frame);
+    int err = QuadToStereo(frame);
+    RTC_DCHECK_EQ(err, 0);
+  } else {
+    RTC_NOTREACHED() << "src_channels: " << frame->num_channels_
+                     << ", dst_channels: " << dst_channels;
+  }
+}
+
+void AudioFrameOperations::UpmixChannels(size_t target_number_of_channels,
+                                         AudioFrame* frame) {
+  RTC_DCHECK_EQ(frame->num_channels_, 1);
+  RTC_DCHECK_LE(frame->samples_per_channel_ * target_number_of_channels,
+                AudioFrame::kMaxDataSizeSamples);
+
+  if (frame->num_channels_ != 1 ||
+      frame->samples_per_channel_ * target_number_of_channels >
+          AudioFrame::kMaxDataSizeSamples) {
+    return;
   }
 
-  return -1;
+  if (!frame->muted()) {
+    // Up-mixing done in place. Going backwards through the frame ensure nothing
+    // is irrevocably overwritten.
+    for (int i = frame->samples_per_channel_ - 1; i >= 0; i--) {
+      for (size_t j = 0; j < target_number_of_channels; ++j) {
+        frame->mutable_data()[target_number_of_channels * i + j] =
+            frame->data()[i];
+      }
+    }
+  }
+  frame->num_channels_ = target_number_of_channels;
 }
 
 void AudioFrameOperations::SwapStereoChannels(AudioFrame* frame) {
@@ -223,9 +186,7 @@
 
   int16_t* frame_data = frame->mutable_data();
   for (size_t i = 0; i < frame->samples_per_channel_ * 2; i += 2) {
-    int16_t temp_data = frame_data[i];
-    frame_data[i] = frame_data[i + 1];
-    frame_data[i + 1] = temp_data;
+    std::swap(frame_data[i], frame_data[i + 1]);
   }
 }
 
diff --git a/audio/utility/audio_frame_operations.h b/audio/utility/audio_frame_operations.h
index c1445b6..65c310c 100644
--- a/audio/utility/audio_frame_operations.h
+++ b/audio/utility/audio_frame_operations.h
@@ -15,6 +15,7 @@
 #include <stdint.h>
 
 #include "api/audio/audio_frame.h"
+#include "rtc_base/deprecation.h"
 
 namespace webrtc {
 
@@ -32,28 +33,15 @@
   // |result_frame| is empty.
   static void Add(const AudioFrame& frame_to_add, AudioFrame* result_frame);
 
-  // Upmixes mono |src_audio| to stereo |dst_audio|. This is an out-of-place
-  // operation, meaning src_audio and dst_audio must point to different
-  // buffers. It is the caller's responsibility to ensure that |dst_audio| is
-  // sufficiently large.
-  static void MonoToStereo(const int16_t* src_audio,
-                           size_t samples_per_channel,
-                           int16_t* dst_audio);
-
   // |frame.num_channels_| will be updated. This version checks for sufficient
-  // buffer size and that |num_channels_| is mono.
-  static int MonoToStereo(AudioFrame* frame);
-
-  // Downmixes stereo |src_audio| to mono |dst_audio|. This is an in-place
-  // operation, meaning |src_audio| and |dst_audio| may point to the same
-  // buffer.
-  static void StereoToMono(const int16_t* src_audio,
-                           size_t samples_per_channel,
-                           int16_t* dst_audio);
+  // buffer size and that |num_channels_| is mono. Use UpmixChannels
+  // instead. TODO(bugs.webrtc.org/8649): remove.
+  RTC_DEPRECATED static int MonoToStereo(AudioFrame* frame);
 
   // |frame.num_channels_| will be updated. This version checks that
-  // |num_channels_| is stereo.
-  static int StereoToMono(AudioFrame* frame);
+  // |num_channels_| is stereo. Use DownmixChannels
+  // instead. TODO(bugs.webrtc.org/8649): remove.
+  RTC_DEPRECATED static int StereoToMono(AudioFrame* frame);
 
   // Downmixes 4 channels |src_audio| to stereo |dst_audio|. This is an in-place
   // operation, meaning |src_audio| and |dst_audio| may point to the same
@@ -66,17 +54,6 @@
   // |num_channels_| is 4 channels.
   static int QuadToStereo(AudioFrame* frame);
 
-  // Downmixes 4 channels |src_audio| to mono |dst_audio|. This is an in-place
-  // operation, meaning |src_audio| and |dst_audio| may point to the same
-  // buffer.
-  static void QuadToMono(const int16_t* src_audio,
-                         size_t samples_per_channel,
-                         int16_t* dst_audio);
-
-  // |frame.num_channels_| will be updated. This version checks that
-  // |num_channels_| is 4 channels.
-  static int QuadToMono(AudioFrame* frame);
-
   // Downmixes |src_channels| |src_audio| to |dst_channels| |dst_audio|.
   // This is an in-place operation, meaning |src_audio| and |dst_audio|
   // may point to the same buffer. Supported channel combinations are
@@ -88,10 +65,16 @@
                               int16_t* dst_audio);
 
   // |frame.num_channels_| will be updated. This version checks that
+  // |num_channels_| and |dst_channels| are valid and performs relevant downmix.
+  // Supported channel combinations are N channels to Mono, and Quad to Stereo.
+  static void DownmixChannels(size_t dst_channels, AudioFrame* frame);
+
+  // |frame.num_channels_| will be updated. This version checks that
   // |num_channels_| and |dst_channels| are valid and performs relevant
-  // downmix.  Supported channel combinations are Stereo to Mono, Quad to Mono,
-  // and Quad to Stereo.
-  static int DownmixChannels(size_t dst_channels, AudioFrame* frame);
+  // downmix. Supported channel combinations are Mono to N
+  // channels. The single channel is replicated.
+  static void UpmixChannels(size_t target_number_of_channels,
+                            AudioFrame* frame);
 
   // Swap the left and right channels of |frame|. Fails silently if |frame| is
   // not stereo.
diff --git a/audio/utility/audio_frame_operations_unittest.cc b/audio/utility/audio_frame_operations_unittest.cc
index 76f1dcd..dd41d1a 100644
--- a/audio/utility/audio_frame_operations_unittest.cc
+++ b/audio/utility/audio_frame_operations_unittest.cc
@@ -103,19 +103,21 @@
   }
 }
 
+#if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
 TEST_F(AudioFrameOperationsTest, MonoToStereoFailsWithBadParameters) {
-  EXPECT_EQ(-1, AudioFrameOperations::MonoToStereo(&frame_));
-
+  EXPECT_DEATH(AudioFrameOperations::UpmixChannels(2, &frame_), "");
   frame_.samples_per_channel_ = AudioFrame::kMaxDataSizeSamples;
   frame_.num_channels_ = 1;
-  EXPECT_EQ(-1, AudioFrameOperations::MonoToStereo(&frame_));
+  EXPECT_DEATH(AudioFrameOperations::UpmixChannels(2, &frame_), "");
 }
+#endif
 
 TEST_F(AudioFrameOperationsTest, MonoToStereoSucceeds) {
   frame_.num_channels_ = 1;
   SetFrameData(1, &frame_);
 
-  EXPECT_EQ(0, AudioFrameOperations::MonoToStereo(&frame_));
+  AudioFrameOperations::UpmixChannels(2, &frame_);
+  EXPECT_EQ(2u, frame_.num_channels_);
 
   AudioFrame stereo_frame;
   stereo_frame.samples_per_channel_ = 320;
@@ -127,36 +129,22 @@
 TEST_F(AudioFrameOperationsTest, MonoToStereoMuted) {
   frame_.num_channels_ = 1;
   ASSERT_TRUE(frame_.muted());
-  EXPECT_EQ(0, AudioFrameOperations::MonoToStereo(&frame_));
+  AudioFrameOperations::UpmixChannels(2, &frame_);
+  EXPECT_EQ(2u, frame_.num_channels_);
   EXPECT_TRUE(frame_.muted());
 }
 
-TEST_F(AudioFrameOperationsTest, MonoToStereoBufferSucceeds) {
-  AudioFrame target_frame;
-  frame_.num_channels_ = 1;
-  SetFrameData(4, &frame_);
-
-  target_frame.num_channels_ = 2;
-  target_frame.samples_per_channel_ = frame_.samples_per_channel_;
-
-  AudioFrameOperations::MonoToStereo(frame_.data(), frame_.samples_per_channel_,
-                                     target_frame.mutable_data());
-
-  AudioFrame stereo_frame;
-  stereo_frame.samples_per_channel_ = 320;
-  stereo_frame.num_channels_ = 2;
-  SetFrameData(4, 4, &stereo_frame);
-  VerifyFramesAreEqual(stereo_frame, target_frame);
-}
-
+#if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
 TEST_F(AudioFrameOperationsTest, StereoToMonoFailsWithBadParameters) {
   frame_.num_channels_ = 1;
-  EXPECT_EQ(-1, AudioFrameOperations::StereoToMono(&frame_));
+  EXPECT_DEATH(AudioFrameOperations::DownmixChannels(1, &frame_), "");
 }
+#endif
 
 TEST_F(AudioFrameOperationsTest, StereoToMonoSucceeds) {
   SetFrameData(4, 2, &frame_);
-  EXPECT_EQ(0, AudioFrameOperations::StereoToMono(&frame_));
+  AudioFrameOperations::DownmixChannels(1, &frame_);
+  EXPECT_EQ(1u, frame_.num_channels_);
 
   AudioFrame mono_frame;
   mono_frame.samples_per_channel_ = 320;
@@ -167,7 +155,8 @@
 
 TEST_F(AudioFrameOperationsTest, StereoToMonoMuted) {
   ASSERT_TRUE(frame_.muted());
-  EXPECT_EQ(0, AudioFrameOperations::StereoToMono(&frame_));
+  AudioFrameOperations::DownmixChannels(1, &frame_);
+  EXPECT_EQ(1u, frame_.num_channels_);
   EXPECT_TRUE(frame_.muted());
 }
 
@@ -178,8 +167,9 @@
   target_frame.num_channels_ = 1;
   target_frame.samples_per_channel_ = frame_.samples_per_channel_;
 
-  AudioFrameOperations::StereoToMono(frame_.data(), frame_.samples_per_channel_,
-                                     target_frame.mutable_data());
+  AudioFrameOperations::DownmixChannels(frame_.data(), 2,
+                                        frame_.samples_per_channel_, 1,
+                                        target_frame.mutable_data());
 
   AudioFrame mono_frame;
   mono_frame.samples_per_channel_ = 320;
@@ -190,8 +180,8 @@
 
 TEST_F(AudioFrameOperationsTest, StereoToMonoDoesNotWrapAround) {
   SetFrameData(-32768, -32768, &frame_);
-  EXPECT_EQ(0, AudioFrameOperations::StereoToMono(&frame_));
-
+  AudioFrameOperations::DownmixChannels(1, &frame_);
+  EXPECT_EQ(1u, frame_.num_channels_);
   AudioFrame mono_frame;
   mono_frame.samples_per_channel_ = 320;
   mono_frame.num_channels_ = 1;
@@ -199,18 +189,12 @@
   VerifyFramesAreEqual(mono_frame, frame_);
 }
 
-TEST_F(AudioFrameOperationsTest, QuadToMonoFailsWithBadParameters) {
-  frame_.num_channels_ = 1;
-  EXPECT_EQ(-1, AudioFrameOperations::QuadToMono(&frame_));
-  frame_.num_channels_ = 2;
-  EXPECT_EQ(-1, AudioFrameOperations::QuadToMono(&frame_));
-}
-
 TEST_F(AudioFrameOperationsTest, QuadToMonoSucceeds) {
   frame_.num_channels_ = 4;
   SetFrameData(4, 2, 6, 8, &frame_);
 
-  EXPECT_EQ(0, AudioFrameOperations::QuadToMono(&frame_));
+  AudioFrameOperations::DownmixChannels(1, &frame_);
+  EXPECT_EQ(1u, frame_.num_channels_);
 
   AudioFrame mono_frame;
   mono_frame.samples_per_channel_ = 320;
@@ -222,7 +206,8 @@
 TEST_F(AudioFrameOperationsTest, QuadToMonoMuted) {
   frame_.num_channels_ = 4;
   ASSERT_TRUE(frame_.muted());
-  EXPECT_EQ(0, AudioFrameOperations::QuadToMono(&frame_));
+  AudioFrameOperations::DownmixChannels(1, &frame_);
+  EXPECT_EQ(1u, frame_.num_channels_);
   EXPECT_TRUE(frame_.muted());
 }
 
@@ -234,8 +219,9 @@
   target_frame.num_channels_ = 1;
   target_frame.samples_per_channel_ = frame_.samples_per_channel_;
 
-  AudioFrameOperations::QuadToMono(frame_.data(), frame_.samples_per_channel_,
-                                   target_frame.mutable_data());
+  AudioFrameOperations::DownmixChannels(frame_.data(), 4,
+                                        frame_.samples_per_channel_, 1,
+                                        target_frame.mutable_data());
   AudioFrame mono_frame;
   mono_frame.samples_per_channel_ = 320;
   mono_frame.num_channels_ = 1;
@@ -246,7 +232,8 @@
 TEST_F(AudioFrameOperationsTest, QuadToMonoDoesNotWrapAround) {
   frame_.num_channels_ = 4;
   SetFrameData(-32768, -32768, -32768, -32768, &frame_);
-  EXPECT_EQ(0, AudioFrameOperations::QuadToMono(&frame_));
+  AudioFrameOperations::DownmixChannels(1, &frame_);
+  EXPECT_EQ(1u, frame_.num_channels_);
 
   AudioFrame mono_frame;
   mono_frame.samples_per_channel_ = 320;
diff --git a/common_audio/BUILD.gn b/common_audio/BUILD.gn
index 74b0c60..f7ffa00 100644
--- a/common_audio/BUILD.gn
+++ b/common_audio/BUILD.gn
@@ -58,7 +58,7 @@
     "../system_wrappers:cpu_features_api",
     "third_party/fft4g:fft4g",
     "//third_party/abseil-cpp/absl/container:inlined_vector",
-    "//third_party/abseil-cpp/absl/memory:memory",
+    "//third_party/abseil-cpp/absl/memory",
     "//third_party/abseil-cpp/absl/types:optional",
   ]
 
diff --git a/common_audio/audio_converter.cc b/common_audio/audio_converter.cc
index 0f97abb..c560346 100644
--- a/common_audio/audio_converter.cc
+++ b/common_audio/audio_converter.cc
@@ -31,7 +31,7 @@
                 size_t dst_channels,
                 size_t dst_frames)
       : AudioConverter(src_channels, src_frames, dst_channels, dst_frames) {}
-  ~CopyConverter() override{};
+  ~CopyConverter() override {}
 
   void Convert(const float* const* src,
                size_t src_size,
@@ -52,7 +52,7 @@
                  size_t dst_channels,
                  size_t dst_frames)
       : AudioConverter(src_channels, src_frames, dst_channels, dst_frames) {}
-  ~UpmixConverter() override{};
+  ~UpmixConverter() override {}
 
   void Convert(const float* const* src,
                size_t src_size,
@@ -74,7 +74,7 @@
                    size_t dst_channels,
                    size_t dst_frames)
       : AudioConverter(src_channels, src_frames, dst_channels, dst_frames) {}
-  ~DownmixConverter() override{};
+  ~DownmixConverter() override {}
 
   void Convert(const float* const* src,
                size_t src_size,
@@ -103,7 +103,7 @@
       resamplers_.push_back(std::unique_ptr<PushSincResampler>(
           new PushSincResampler(src_frames, dst_frames)));
   }
-  ~ResampleConverter() override{};
+  ~ResampleConverter() override {}
 
   void Convert(const float* const* src,
                size_t src_size,
@@ -132,7 +132,7 @@
           std::unique_ptr<ChannelBuffer<float>>(new ChannelBuffer<float>(
               (*it)->dst_frames(), (*it)->dst_channels())));
   }
-  ~CompositionConverter() override{};
+  ~CompositionConverter() override {}
 
   void Convert(const float* const* src,
                size_t src_size,
diff --git a/common_audio/audio_converter.h b/common_audio/audio_converter.h
index 24a5e72..73ad1ef 100644
--- a/common_audio/audio_converter.h
+++ b/common_audio/audio_converter.h
@@ -14,7 +14,7 @@
 #include <stddef.h>
 #include <memory>
 
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
diff --git a/common_audio/real_fourier_unittest.cc b/common_audio/real_fourier_unittest.cc
index 1324887..eac4fce 100644
--- a/common_audio/real_fourier_unittest.cc
+++ b/common_audio/real_fourier_unittest.cc
@@ -68,7 +68,7 @@
 };
 
 using FftTypes = ::testing::Types<RealFourierOoura>;
-TYPED_TEST_CASE(RealFourierTest, FftTypes);
+TYPED_TEST_SUITE(RealFourierTest, FftTypes);
 
 TYPED_TEST(RealFourierTest, SimpleForwardTransform) {
   this->real_buffer_[0] = 1.0f;
diff --git a/common_audio/resampler/push_sinc_resampler.h b/common_audio/resampler/push_sinc_resampler.h
index db9cdc1..b002ff7 100644
--- a/common_audio/resampler/push_sinc_resampler.h
+++ b/common_audio/resampler/push_sinc_resampler.h
@@ -16,7 +16,7 @@
 #include <memory>
 
 #include "common_audio/resampler/sinc_resampler.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
diff --git a/common_audio/resampler/push_sinc_resampler_unittest.cc b/common_audio/resampler/push_sinc_resampler_unittest.cc
index 2f53a74..ee111c4 100644
--- a/common_audio/resampler/push_sinc_resampler_unittest.cc
+++ b/common_audio/resampler/push_sinc_resampler_unittest.cc
@@ -16,7 +16,7 @@
 #include "common_audio/include/audio_util.h"
 #include "common_audio/resampler/push_sinc_resampler.h"
 #include "common_audio/resampler/sinusoidal_linear_chirp_source.h"
-#include "rtc_base/timeutils.h"
+#include "rtc_base/time_utils.h"
 #include "test/gmock.h"
 #include "test/gtest.h"
 
@@ -255,7 +255,7 @@
 
 // Thresholds chosen arbitrarily based on what each resampling reported during
 // testing.  All thresholds are in dbFS, http://en.wikipedia.org/wiki/DBFS.
-INSTANTIATE_TEST_CASE_P(
+INSTANTIATE_TEST_SUITE_P(
     PushSincResamplerTest,
     PushSincResamplerTest,
     ::testing::Values(
diff --git a/common_audio/resampler/sinc_resampler.h b/common_audio/resampler/sinc_resampler.h
index 0be4318..ffd70d9 100644
--- a/common_audio/resampler/sinc_resampler.h
+++ b/common_audio/resampler/sinc_resampler.h
@@ -17,7 +17,7 @@
 #include <stddef.h>
 #include <memory>
 
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 #include "rtc_base/gtest_prod_util.h"
 #include "rtc_base/memory/aligned_malloc.h"
 #include "rtc_base/system/arch.h"
diff --git a/common_audio/resampler/sinc_resampler_unittest.cc b/common_audio/resampler/sinc_resampler_unittest.cc
index eb5424d..3aedacc 100644
--- a/common_audio/resampler/sinc_resampler_unittest.cc
+++ b/common_audio/resampler/sinc_resampler_unittest.cc
@@ -24,7 +24,7 @@
 #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 "rtc_base/time_utils.h"
 #include "system_wrappers/include/cpu_features_wrapper.h"
 #include "test/gmock.h"
 #include "test/gtest.h"
@@ -340,7 +340,7 @@
 
 // Thresholds chosen arbitrarily based on what each resampling reported during
 // testing.  All thresholds are in dbFS, http://en.wikipedia.org/wiki/DBFS.
-INSTANTIATE_TEST_CASE_P(
+INSTANTIATE_TEST_SUITE_P(
     SincResamplerTest,
     SincResamplerTest,
     testing::Values(
diff --git a/common_audio/resampler/sinusoidal_linear_chirp_source.h b/common_audio/resampler/sinusoidal_linear_chirp_source.h
index 71dcff5..81f6a24 100644
--- a/common_audio/resampler/sinusoidal_linear_chirp_source.h
+++ b/common_audio/resampler/sinusoidal_linear_chirp_source.h
@@ -15,7 +15,7 @@
 #define COMMON_AUDIO_RESAMPLER_SINUSOIDAL_LINEAR_CHIRP_SOURCE_H_
 
 #include "common_audio/resampler/sinc_resampler.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
diff --git a/common_audio/smoothing_filter.cc b/common_audio/smoothing_filter.cc
index 0d5aaa4..e5ce987 100644
--- a/common_audio/smoothing_filter.cc
+++ b/common_audio/smoothing_filter.cc
@@ -13,7 +13,7 @@
 #include <cmath>
 
 #include "rtc_base/checks.h"
-#include "rtc_base/timeutils.h"
+#include "rtc_base/time_utils.h"
 
 namespace webrtc {
 
diff --git a/common_audio/smoothing_filter.h b/common_audio/smoothing_filter.h
index c467d85..e5f561e 100644
--- a/common_audio/smoothing_filter.h
+++ b/common_audio/smoothing_filter.h
@@ -14,7 +14,7 @@
 #include <stdint.h>
 
 #include "absl/types/optional.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
diff --git a/common_audio/smoothing_filter_unittest.cc b/common_audio/smoothing_filter_unittest.cc
index abe4272..5f6711e 100644
--- a/common_audio/smoothing_filter_unittest.cc
+++ b/common_audio/smoothing_filter_unittest.cc
@@ -12,7 +12,7 @@
 #include <memory>
 
 #include "common_audio/smoothing_filter.h"
-#include "rtc_base/fakeclock.h"
+#include "rtc_base/fake_clock.h"
 #include "test/gtest.h"
 
 namespace webrtc {
diff --git a/common_audio/sparse_fir_filter.h b/common_audio/sparse_fir_filter.h
index 22bcdff..5197a8e 100644
--- a/common_audio/sparse_fir_filter.h
+++ b/common_audio/sparse_fir_filter.h
@@ -14,7 +14,7 @@
 #include <cstring>
 #include <vector>
 
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
diff --git a/common_audio/wav_file.h b/common_audio/wav_file.h
index cbce59d..7e790e0 100644
--- a/common_audio/wav_file.h
+++ b/common_audio/wav_file.h
@@ -17,7 +17,7 @@
 #include <cstddef>
 #include <string>
 
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 #include "rtc_base/platform_file.h"
 
 namespace webrtc {
diff --git a/common_audio/wav_file_unittest.cc b/common_audio/wav_file_unittest.cc
index d40229a..b7e5d3f 100644
--- a/common_audio/wav_file_unittest.cc
+++ b/common_audio/wav_file_unittest.cc
@@ -17,7 +17,7 @@
 #include "common_audio/wav_file.h"
 #include "common_audio/wav_header.h"
 #include "test/gtest.h"
-#include "test/testsupport/fileutils.h"
+#include "test/testsupport/file_utils.h"
 
 // WavWriterTest.CPPFileDescriptor and WavWriterTest.CPP flaky on Mac.
 // See webrtc:9247.
diff --git a/common_audio/window_generator.h b/common_audio/window_generator.h
index ad3b445..0cbe24a 100644
--- a/common_audio/window_generator.h
+++ b/common_audio/window_generator.h
@@ -13,7 +13,7 @@
 
 #include <stddef.h>
 
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
diff --git a/common_types.h b/common_types.h
index 848b899..2b877d6 100644
--- a/common_types.h
+++ b/common_types.h
@@ -14,12 +14,8 @@
 #include <stddef.h>  // For size_t
 #include <cstdint>
 
-#include "absl/strings/match.h"
-// TODO(sprang): Remove this include when all usage includes it directly.
-#include "api/video/video_bitrate_allocation.h"
 // TODO(bugs.webrtc.org/7660): Delete include once downstream code is updated.
 #include "api/video/video_codec_type.h"
-#include "rtc_base/checks.h"
 
 #if defined(_MSC_VER)
 // Disable "new behavior: elements of array will be default initialized"
@@ -27,8 +23,6 @@
 #pragma warning(disable : 4351)
 #endif
 
-#define RTP_PAYLOAD_NAME_SIZE 32u
-
 namespace webrtc {
 
 enum FrameType {
@@ -158,29 +152,6 @@
   virtual void OnOverheadChanged(size_t overhead_bytes_per_packet) = 0;
 };
 
-// ==================================================================
-// Voice specific types
-// ==================================================================
-
-// Each codec supported can be described by this structure.
-struct CodecInst {
-  int pltype;
-  char plname[RTP_PAYLOAD_NAME_SIZE];
-  int plfreq;
-  int pacsize;
-  size_t channels;
-  int rate;  // bits/sec unlike {start,min,max}Bitrate elsewhere in this file!
-
-  bool operator==(const CodecInst& other) const {
-    return pltype == other.pltype &&
-           absl::EqualsIgnoreCase(plname, other.plname) &&
-           plfreq == other.plfreq && pacsize == other.pacsize &&
-           channels == other.channels && rate == other.rate;
-  }
-
-  bool operator!=(const CodecInst& other) const { return !(*this == other); }
-};
-
 // RTP
 enum { kRtpCsrcSize = 15 };  // RFC 3550 page 13
 
diff --git a/cras-config/aec_config.cc b/cras-config/aec_config.cc
index d0cf19b..d8fb369 100644
--- a/cras-config/aec_config.cc
+++ b/cras-config/aec_config.cc
@@ -24,8 +24,6 @@
 	if (ini == NULL)
 		return;
 
-	config->buffering.use_new_render_buffering =
-		AEC_GET_INT(ini, BUFFERING, USE_NEW_RENDER_BUFFERING);
 	config->buffering.excess_render_detection_interval_blocks =
 		AEC_GET_INT(ini, BUFFERING,
 			EXCESS_RENDER_DETECTION_INTERVAL_BLOCKS);
@@ -38,18 +36,10 @@
 		AEC_GET_INT(ini, DELAY, DOWN_SAMPLING_FACTOR);
 	config->delay.num_filters =
 		AEC_GET_INT(ini, DELAY, NUM_FILTERS);
-	config->delay.api_call_jitter_blocks =
-		AEC_GET_INT(ini, DELAY, API_CALL_JITTER_BLOCKS);
-	config->delay.min_echo_path_delay_blocks =
-		AEC_GET_INT(ini, DELAY, MIN_ECHO_PATH_DELAY_BLOCKS);
-	config->delay.delay_headroom_blocks =
-		AEC_GET_INT(ini, DELAY, DELAY_HEADROOM_BLOCKS);
-	config->delay.hysteresis_limit_1_blocks =
-		AEC_GET_INT(ini, DELAY, HYSTERESIS_LIMIT_1_BLOCKS);
-	config->delay.hysteresis_limit_2_blocks =
-		AEC_GET_INT(ini, DELAY, HYSTERESIS_LIMIT_2_BLOCKS);
-	config->delay.skew_hysteresis_blocks =
-		AEC_GET_INT(ini, DELAY, SKEW_HYSTERESIS_BLOCKS);
+	config->delay.delay_headroom_samples =
+		AEC_GET_INT(ini, DELAY, DELAY_HEADROOM_SAMPLES);
+	config->delay.hysteresis_limit_blocks =
+		AEC_GET_INT(ini, DELAY, HYSTERESIS_LIMIT_BLOCKS);
 	config->delay.fixed_capture_delay_samples =
 		AEC_GET_INT(ini, DELAY, FIXED_CAPTURE_DELAY_SAMPLES);
 	config->delay.delay_estimate_smoothing =
@@ -121,12 +111,8 @@
 	config->erle.num_sections =
 		AEC_GET_INT(ini, ERLE, NUM_SECTIONS);
 
-	config->ep_strength.lf =
-		AEC_GET_FLOAT(ini, EP_STRENGTH, LF);
-	config->ep_strength.mf =
-		AEC_GET_FLOAT(ini, EP_STRENGTH, MF);
-	config->ep_strength.hf =
-		AEC_GET_FLOAT(ini, EP_STRENGTH, HF);
+	config->ep_strength.default_gain =
+		AEC_GET_FLOAT(ini, EP_STRENGTH, DEFAULT_GAIN);
 	config->ep_strength.default_len =
 		AEC_GET_FLOAT(ini, EP_STRENGTH, DEFAULT_LEN);
 	config->ep_strength.reverb_based_on_render =
@@ -161,14 +147,6 @@
 	config->render_levels.poor_excitation_render_limit_ds8 =
 		AEC_GET_FLOAT(ini, RENDER_LEVELS, POOR_EXCITATION_RENDER_LIMIT_DS8);
 
-	config->echo_removal_control.gain_rampup.initial_gain =
-		AEC_GET_FLOAT(ini, ECHO_REMOVAL_CTL, INITIAL_GAIN);
-	config->echo_removal_control.gain_rampup.first_non_zero_gain =
-		AEC_GET_FLOAT(ini, ECHO_REMOVAL_CTL, FIRST_NON_ZERO_GAIN);
-	config->echo_removal_control.gain_rampup.non_zero_gain_blocks =
-		AEC_GET_INT(ini, ECHO_REMOVAL_CTL, NON_ZERO_GAIN_BLOCKS);
-	config->echo_removal_control.gain_rampup.full_gain_blocks =
-		AEC_GET_INT(ini, ECHO_REMOVAL_CTL, FULL_GAIN_BLOCKS);
 	config->echo_removal_control.has_clock_drift =
 		AEC_GET_INT(ini, ECHO_REMOVAL_CTL, HAS_CLOCK_DRIFT);
 	config->echo_removal_control.linear_and_stable_echo_path =
@@ -288,8 +266,6 @@
 
 	syslog(LOG_ERR, "---- aec config dump ----");
 	syslog(LOG_ERR, "Buffering:");
-	syslog(LOG_ERR, "    use_new_render_buffering %d",
-			config.buffering.use_new_render_buffering);
 	syslog(LOG_ERR, "    excess_render_detection_interval_blocks %zu",
 			config.buffering.excess_render_detection_interval_blocks);
 	syslog(LOG_ERR, "    max_allowed_excess_render_blocks %zu",
@@ -300,15 +276,9 @@
 			config.delay.default_delay,
 			config.delay.down_sampling_factor,
 			config.delay.num_filters);
-	syslog(LOG_ERR, "    api_call_jitter_blocks %zu, min_echo_path_delay_blocks %zu",
-			config.delay.api_call_jitter_blocks,
-			config.delay.min_echo_path_delay_blocks);
-	syslog(LOG_ERR, "    delay_headroom_blocks %zu, hysteresis_limit_1_blocks %zu",
-			config.delay.delay_headroom_blocks,
-			config.delay.hysteresis_limit_1_blocks);
-	syslog(LOG_ERR, "    hysteresis_limit_2_blocks %zu, skew_hysteresis_blocks %zu",
-			config.delay.hysteresis_limit_2_blocks,
-			config.delay.skew_hysteresis_blocks);
+	syslog(LOG_ERR, "    delay_headroom_samples %zu, hysteresis_limit_blocks %zu",
+			config.delay.delay_headroom_samples,
+			config.delay.hysteresis_limit_blocks);
 	syslog(LOG_ERR, "    fixed_capture_delay_samples %zu",
 			config.delay.fixed_capture_delay_samples);
 	syslog(LOG_ERR, "    delay_estimate_smoothing %f",
@@ -359,10 +329,8 @@
 	syslog(LOG_ERR, "Erle: min %f max_l %f max_h %f onset_detection %d",
 			config.erle.min, config.erle.max_l,
 			config.erle.max_h, config.erle.onset_detection);
-	syslog(LOG_ERR, "Ep strength: lf %f mf %f hf %f default_len %f",
-			config.ep_strength.lf,
-			config.ep_strength.mf,
-			config.ep_strength.hf,
+	syslog(LOG_ERR, "Ep strength: default_gain %f default_len %f",
+			config.ep_strength.default_gain,
 			config.ep_strength.default_len);
 	syslog(LOG_ERR, "    echo_can_saturate %d, bounded_erl %d,"
 			"    ep_strength.reverb_based_on_render %d",
@@ -394,12 +362,6 @@
 			config.render_levels.poor_excitation_render_limit_ds8);
 	syslog(LOG_ERR, "Echo removal control:");
 	syslog(LOG_ERR, "    gain rampup:");
-	syslog(LOG_ERR, "        initial_gain %f, first_non_zero_gain %f",
-			config.echo_removal_control.gain_rampup.initial_gain,
-			config.echo_removal_control.gain_rampup.first_non_zero_gain);
-	syslog(LOG_ERR, "        non_zero_gain_blocks %d, full_gain_blocks %d",
-			config.echo_removal_control.gain_rampup.non_zero_gain_blocks,
-			config.echo_removal_control.gain_rampup.full_gain_blocks);
 	syslog(LOG_ERR, "    has_clock_drift %d",
 			config.echo_removal_control.has_clock_drift);
 	syslog(LOG_ERR, "    linear_and_stable_echo_path %d",
diff --git a/cras-config/aec_config.h b/cras-config/aec_config.h
index 33185b3..3b6fd5d 100644
--- a/cras-config/aec_config.h
+++ b/cras-config/aec_config.h
@@ -10,8 +10,6 @@
 
 #include "api/audio/echo_canceller3_config.h"
 
-#define AEC_BUFFERING_USE_NEW_RENDER_BUFFERING "buffering:use_new_render_buffering"
-#define AEC_BUFFERING_USE_NEW_RENDER_BUFFERING_VALUE 1
 #define AEC_BUFFERING_EXCESS_RENDER_DETECTION_INTERVAL_BLOCKS \
 	"buffering:excess_render_detection_interval_blocks"
 #define AEC_BUFFERING_EXCESS_RENDER_DETECTION_INTERVAL_BLOCKS_VALUE 250
@@ -25,18 +23,10 @@
 #define AEC_DELAY_DOWN_SAMPLING_FACTOR_VALUE 4
 #define AEC_DELAY_NUM_FILTERS "delay:num_filters"
 #define AEC_DELAY_NUM_FILTERS_VALUE 5
-#define AEC_DELAY_API_CALL_JITTER_BLOCKS "delay:api_call_jitter_blocks"
-#define AEC_DELAY_API_CALL_JITTER_BLOCKS_VALUE 26
-#define AEC_DELAY_MIN_ECHO_PATH_DELAY_BLOCKS "delay:min_echo_path_delay_blocks"
-#define AEC_DELAY_MIN_ECHO_PATH_DELAY_BLOCKS_VALUE 0
-#define AEC_DELAY_DELAY_HEADROOM_BLOCKS "delay:delay_headroom_blocks"
-#define AEC_DELAY_DELAY_HEADROOM_BLOCKS_VALUE 2
-#define AEC_DELAY_HYSTERESIS_LIMIT_1_BLOCKS "delay:hysteresis_limit_1_blocks"
-#define AEC_DELAY_HYSTERESIS_LIMIT_1_BLOCKS_VALUE 1
-#define AEC_DELAY_HYSTERESIS_LIMIT_2_BLOCKS "delay:hysteresis_limit_2_blocks"
-#define AEC_DELAY_HYSTERESIS_LIMIT_2_BLOCKS_VALUE 1
-#define AEC_DELAY_SKEW_HYSTERESIS_BLOCKS "delay:skew_hysteresis_blocks"
-#define AEC_DELAY_SKEW_HYSTERESIS_BLOCKS_VALUE 3
+#define AEC_DELAY_DELAY_HEADROOM_SAMPLES "delay:delay_headroom_samples"
+#define AEC_DELAY_DELAY_HEADROOM_SAMPLES_VALUE 32
+#define AEC_DELAY_HYSTERESIS_LIMIT_BLOCKS "delay:hysteresis_limit_blocks"
+#define AEC_DELAY_HYSTERESIS_LIMIT_BLOCKS_VALUE 1
 #define AEC_DELAY_FIXED_CAPTURE_DELAY_SAMPLES \
 	"delay:fixed_capture_delay_samples"
 #define AEC_DELAY_FIXED_CAPTURE_DELAY_SAMPLES_VALUE 0
@@ -124,12 +114,8 @@
 #define AEC_ERLE_NUM_SECTIONS_VALUE 1
 
 // EpStrength
-#define AEC_EP_STRENGTH_LF "ep_strength:lf"
-#define AEC_EP_STRENGTH_LF_VALUE 1.f
-#define AEC_EP_STRENGTH_MF "ep_strength:mf"
-#define AEC_EP_STRENGTH_MF_VALUE 1.f
-#define AEC_EP_STRENGTH_HF "ep_strength:hf"
-#define AEC_EP_STRENGTH_HF_VALUE 1.f
+#define AEC_EP_STRENGTH_DEFAULT_GAIN "ep_strength:default_gain"
+#define AEC_EP_STRENGTH_DEFAULT_GAIN_VALUE 1.f
 #define AEC_EP_STRENGTH_DEFAULT_LEN "ep_strength:default_len"
 #define AEC_EP_STRENGTH_DEFAULT_LEN_VALUE 0.83f
 #define AEC_EP_STRENGTH_REVERB_BASED_ON_RENDER \
@@ -175,17 +161,6 @@
 #define AEC_RENDER_LEVELS_POOR_EXCITATION_RENDER_LIMIT_DS8_VALUE 20.f
 
 // Echo removal controls
-#define AEC_ECHO_REMOVAL_CTL_INITIAL_GAIN "echo_removal_control:initial_gain"
-#define AEC_ECHO_REMOVAL_CTL_INITIAL_GAIN_VALUE 0.0f
-#define AEC_ECHO_REMOVAL_CTL_FIRST_NON_ZERO_GAIN \
-	"echo_removal_control:first_non_zero_gain"
-#define AEC_ECHO_REMOVAL_CTL_FIRST_NON_ZERO_GAIN_VALUE 0.001f
-#define AEC_ECHO_REMOVAL_CTL_NON_ZERO_GAIN_BLOCKS \
-	"echo_removal_control:non_zero_gain_blocks"
-#define AEC_ECHO_REMOVAL_CTL_NON_ZERO_GAIN_BLOCKS_VALUE 187
-#define AEC_ECHO_REMOVAL_CTL_FULL_GAIN_BLOCKS \
-	"echo_removal_control:full_gain_blocks"
-#define AEC_ECHO_REMOVAL_CTL_FULL_GAIN_BLOCKS_VALUE 312
 #define AEC_ECHO_REMOVAL_CTL_HAS_CLOCK_DRIFT \
 	"echo_removal_control:has_clock_drift"
 #define AEC_ECHO_REMOVAL_CTL_HAS_CLOCK_DRIFT_VALUE 0
diff --git a/modules/audio_coding/BUILD.gn b/modules/audio_coding/BUILD.gn
index df4ba23..5a47245 100644
--- a/modules/audio_coding/BUILD.gn
+++ b/modules/audio_coding/BUILD.gn
@@ -8,59 +8,12 @@
 
 import("../../webrtc.gni")
 import("audio_coding.gni")
-if (!build_with_mozilla) {
+if (rtc_enable_protobuf) {
   import("//third_party/protobuf/proto_library.gni")
 }
 
 visibility = [ ":*" ]
 
-rtc_static_library("audio_format_conversion") {
-  visibility += webrtc_default_visibility
-  sources = [
-    "codecs/audio_format_conversion.cc",
-    "codecs/audio_format_conversion.h",
-  ]
-  deps = [
-    "../..:webrtc_common",
-    "../../api:array_view",
-    "../../api/audio_codecs:audio_codecs_api",
-    "../../rtc_base:checks",
-    "../../rtc_base:rtc_base_approved",
-    "../../rtc_base:sanitizer",
-    "//third_party/abseil-cpp/absl/strings",
-    "//third_party/abseil-cpp/absl/types:optional",
-  ]
-}
-
-rtc_static_library("rent_a_codec") {
-  # Client code SHOULD NOT USE THIS TARGET, but for now it needs to be public
-  # because there exists client code that uses it.
-  # TODO(bugs.webrtc.org/9808): Move to private visibility as soon as that
-  # client code gets updated.
-  visibility += [ "*" ]
-
-  sources = [
-    "acm2/acm_codec_database.cc",
-    "acm2/acm_codec_database.h",
-    "acm2/rent_a_codec.cc",
-    "acm2/rent_a_codec.h",
-  ]
-  deps = [
-    ":audio_coding_module_typedefs",
-    ":neteq_decoder_enum",
-    "../..:webrtc_common",
-    "../../api:array_view",
-    "../../api/audio_codecs:audio_codecs_api",
-    "../../rtc_base:checks",
-    "../../rtc_base:protobuf_utils",
-    "../../rtc_base:rtc_base_approved",
-    "../../system_wrappers",
-    "//third_party/abseil-cpp/absl/strings",
-    "//third_party/abseil-cpp/absl/types:optional",
-  ]
-  defines = audio_codec_defines
-}
-
 rtc_source_set("audio_coding_module_typedefs") {
   sources = [
     "include/audio_coding_module_typedefs.h",
@@ -89,8 +42,6 @@
   deps = [
     ":audio_coding_module_typedefs",
     ":neteq",
-    ":neteq_decoder_enum",
-    ":rent_a_codec",
     "..:module_api",
     "..:module_api_public",
     "../..:webrtc_common",
@@ -440,6 +391,7 @@
   deps = [
     ":isac_bwinfo",
     "../..:webrtc_common",
+    "../../api:scoped_refptr",
     "../../api/audio_codecs:audio_codecs_api",
     "../../rtc_base:checks",
     "../../rtc_base:rtc_base_approved",
@@ -815,6 +767,7 @@
     "../../api/audio_codecs/opus:audio_encoder_opus_config",
     "../../common_audio",
     "../../rtc_base:checks",
+    "../../rtc_base:protobuf_utils",
     "../../rtc_base:rtc_base_approved",
     "../../rtc_base:rtc_numerics",
     "../../rtc_base:safe_minmax",
@@ -825,7 +778,6 @@
   ]
   public_deps = [
     ":webrtc_opus_c",
-    "../../rtc_base:protobuf_utils",
   ]
 
   defines = audio_codec_defines
@@ -948,23 +900,6 @@
       ":ana_debug_dump_proto",
     ]
   }
-
-  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("neteq_decoder_enum") {
-  sources = [
-    "neteq/neteq_decoder_enum.cc",
-    "neteq/neteq_decoder_enum.h",
-  ]
-  deps = [
-    "../../api/audio_codecs:audio_codecs_api",
-    "../../rtc_base:rtc_base_approved",
-    "//third_party/abseil-cpp/absl/types:optional",
-  ]
 }
 
 rtc_static_library("neteq") {
@@ -1003,6 +938,8 @@
     "neteq/expand.h",
     "neteq/expand_uma_logger.cc",
     "neteq/expand_uma_logger.h",
+    "neteq/histogram.cc",
+    "neteq/histogram.h",
     "neteq/include/neteq.h",
     "neteq/merge.cc",
     "neteq/merge.h",
@@ -1039,13 +976,13 @@
 
   deps = [
     ":audio_coding_module_typedefs",
-    ":neteq_decoder_enum",
     ":webrtc_cng",
     "..:module_api",
     "..:module_api_public",
     "../..:webrtc_common",
     "../../api:array_view",
     "../../api:libjingle_peerconnection_api",
+    "../../api:scoped_refptr",
     "../../api/audio:audio_frame_api",
     "../../api/audio_codecs:audio_codecs_api",
     "../../common_audio",
@@ -1059,6 +996,7 @@
     "../../rtc_base/system:fallthrough",
     "../../system_wrappers:field_trial",
     "../../system_wrappers:metrics",
+    "//third_party/abseil-cpp/absl/memory",
     "//third_party/abseil-cpp/absl/strings",
     "//third_party/abseil-cpp/absl/types:optional",
   ]
@@ -1092,10 +1030,10 @@
     "../../api:neteq_simulator_api",
     "../../api/audio:audio_frame_api",
     "../../api/audio_codecs:audio_codecs_api",
-    "../../api/audio_codecs:builtin_audio_decoder_factory",
     "../../rtc_base:checks",
     "../../rtc_base:rtc_base_approved",
     "../rtp_rtcp",
+    "../rtp_rtcp:rtp_rtcp_format",
     "//third_party/abseil-cpp/absl/types:optional",
   ]
   defines = audio_codec_defines
@@ -1120,11 +1058,6 @@
     "neteq/tools/rtp_generator.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 = [
     ":pcm16b",
     "../..:webrtc_common",
@@ -1170,11 +1103,6 @@
     "neteq/tools/neteq_stats_plotter.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 = [
     "..:module_api",
     "../..:webrtc_common",
@@ -1220,11 +1148,6 @@
       "neteq/tools/rtc_event_log_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_tools_minimal",
       "../../logging:rtc_event_log_parser",
@@ -1232,6 +1155,7 @@
       "../../rtc_base:rtc_base_approved",
       "../rtp_rtcp",
       "../rtp_rtcp:rtp_rtcp_format",
+      "//third_party/abseil-cpp/absl/memory",
       "//third_party/abseil-cpp/absl/types:optional",
     ]
     public_deps = [
@@ -1343,14 +1267,11 @@
       "test/opus_test.cc",
       "test/opus_test.h",
       "test/target_delay_unittest.cc",
-      "test/utility.cc",
-      "test/utility.h",
     ]
     deps = [
       ":audio_coding",
       ":audio_coding_module_typedefs",
       ":audio_encoder_cng",
-      ":audio_format_conversion",
       ":pcm16b_c",
       ":red",
       ":webrtc_opus_c",
@@ -1379,14 +1300,11 @@
       "../../system_wrappers",
       "../../test:fileutils",
       "../../test:test_support",
+      "//third_party/abseil-cpp/absl/memory",
       "//third_party/abseil-cpp/absl/strings",
       "//third_party/abseil-cpp/absl/types:optional",
     ]
     defines = audio_coding_defines
-    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_perf_tests") {
@@ -1402,7 +1320,6 @@
       ":neteq_test_tools",
       "../..:webrtc_common",
       "../../api/audio_codecs/opus:audio_encoder_opus",
-      "../../rtc_base:protobuf_utils",
       "../../rtc_base:rtc_base_approved",
       "../../system_wrappers",
       "../../system_wrappers:field_trial",
@@ -1410,11 +1327,6 @@
       "../../test:perf_test",
       "../../test:test_support",
     ]
-
-    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("acm_receive_test") {
@@ -1427,9 +1339,9 @@
     defines = audio_coding_defines
 
     deps = audio_coding_deps + [
+             "../../api:scoped_refptr",
              "..:module_api",
              ":audio_coding",
-             ":audio_format_conversion",
              "../../api/audio_codecs:audio_codecs_api",
              "../../api/audio_codecs:builtin_audio_decoder_factory",
              ":neteq_tools",
@@ -1453,7 +1365,6 @@
              "../../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",
@@ -1495,7 +1406,6 @@
              "../../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",
@@ -1528,22 +1438,20 @@
       deps = [
         "../../rtc_base:checks",
         "../../test:fileutils",
+        "//third_party/abseil-cpp/absl/types:optional",
       ]
       sources = [
         "neteq/tools/neteq_test_factory.cc",
         "neteq/tools/neteq_test_factory.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",
         ":neteq_test_tools",
         "../..:webrtc_common",
+        "../../api/audio_codecs:builtin_audio_decoder_factory",
         "../../rtc_base:rtc_base_approved",
+        "../../test:audio_codec_mocks",
         "../../test:test_support",
         "//third_party/abseil-cpp/absl/memory",
       ]
@@ -1594,11 +1502,6 @@
       "codecs/tools/audio_codec_speed_test.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" ]
-    }
-
     data = audio_codec_speed_tests_resources
 
     if (is_android) {
@@ -1626,17 +1529,10 @@
   rtc_source_set("neteq_test_support") {
     testonly = true
     sources = [
-      "neteq/tools/neteq_external_decoder_test.cc",
-      "neteq/tools/neteq_external_decoder_test.h",
       "neteq/tools/neteq_performance_test.cc",
       "neteq/tools/neteq_performance_test.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",
       ":neteq_test_tools",
@@ -1661,11 +1557,6 @@
       "neteq/tools/neteq_quality_test.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",
       ":neteq_test_tools",
@@ -2033,6 +1924,7 @@
       "neteq/dtmf_buffer_unittest.cc",
       "neteq/dtmf_tone_generator_unittest.cc",
       "neteq/expand_unittest.cc",
+      "neteq/histogram_unittest.cc",
       "neteq/merge_unittest.cc",
       "neteq/mock/mock_buffer_level_filter.h",
       "neteq/mock/mock_decoder_database.h",
@@ -2041,13 +1933,12 @@
       "neteq/mock/mock_dtmf_buffer.h",
       "neteq/mock/mock_dtmf_tone_generator.h",
       "neteq/mock/mock_expand.h",
-      "neteq/mock/mock_external_decoder_pcm16b.h",
+      "neteq/mock/mock_histogram.h",
       "neteq/mock/mock_packet_buffer.h",
       "neteq/mock/mock_red_payload_splitter.h",
       "neteq/mock/mock_statistics_calculator.h",
       "neteq/nack_tracker_unittest.cc",
       "neteq/neteq_decoder_plc_unittest.cc",
-      "neteq/neteq_external_decoder_unittest.cc",
       "neteq/neteq_impl_unittest.cc",
       "neteq/neteq_network_stats_unittest.cc",
       "neteq/neteq_stereo_unittest.cc",
@@ -2072,7 +1963,6 @@
       ":audio_coding",
       ":audio_coding_module_typedefs",
       ":audio_encoder_cng",
-      ":audio_format_conversion",
       ":audio_network_adaptor",
       ":g711",
       ":ilbc",
@@ -2086,10 +1976,10 @@
       ":neteq_test_tools",
       ":pcm16b",
       ":red",
-      ":rent_a_codec",
       ":webrtc_cng",
       ":webrtc_opus",
       "..:module_api",
+      "..:module_api_public",
       "../..:webrtc_common",
       "../../api/audio:audio_frame_api",
       "../../api/audio_codecs:audio_codecs_api",
@@ -2105,11 +1995,11 @@
       "../../logging:rtc_event_log_api",
       "../../modules/rtp_rtcp:rtp_rtcp_format",
       "../../rtc_base:checks",
-      "../../rtc_base:protobuf_utils",
       "../../rtc_base:rtc_base",
       "../../rtc_base:rtc_base_approved",
       "../../rtc_base:rtc_base_tests_utils",
       "../../rtc_base:sanitizer",
+      "../../rtc_base:timeutils",
       "../../rtc_base/system:arch",
       "../../system_wrappers",
       "../../system_wrappers:cpu_features_api",
@@ -2135,11 +2025,6 @@
         ":neteq_unittest_proto",
       ]
     }
-
-    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" ]
-    }
   }
 }
 
diff --git a/modules/audio_coding/acm2/acm_codec_database.cc b/modules/audio_coding/acm2/acm_codec_database.cc
deleted file mode 100644
index cada80c..0000000
--- a/modules/audio_coding/acm2/acm_codec_database.cc
+++ /dev/null
@@ -1,336 +0,0 @@
-/*
- *  Copyright (c) 2012 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 generates databases with information about all supported audio
- * codecs.
- */
-
-// TODO(tlegrand): Change constant input pointers in all functions to constant
-// references, where appropriate.
-#include "modules/audio_coding/acm2/acm_codec_database.h"
-
-#include "absl/strings/match.h"
-#include "api/array_view.h"
-#include "modules/audio_coding/acm2/rent_a_codec.h"
-
-#if ((defined WEBRTC_CODEC_ISAC) && (defined WEBRTC_CODEC_ISACFX))
-#error iSAC and iSACFX codecs cannot be enabled at the same time
-#endif
-
-namespace webrtc {
-
-namespace acm2 {
-
-namespace {
-
-// Checks if the bitrate is valid for iSAC.
-bool IsISACRateValid(int rate) {
-  return (rate == -1) || ((rate <= 56000) && (rate >= 10000));
-}
-
-// Checks if the bitrate is valid for iLBC.
-bool IsILBCRateValid(int rate, int frame_size_samples) {
-  if (((frame_size_samples == 240) || (frame_size_samples == 480)) &&
-      (rate == 13300)) {
-    return true;
-  } else if (((frame_size_samples == 160) || (frame_size_samples == 320)) &&
-             (rate == 15200)) {
-    return true;
-  } else {
-    return false;
-  }
-}
-
-// Checks if the bitrate is valid for Opus.
-bool IsOpusRateValid(int rate) {
-  return (rate >= 6000) && (rate <= 510000);
-}
-
-}  // namespace
-
-// Not yet used payload-types.
-// 83,  82,  81, 80, 79,  78,  77,  76,  75,  74,  73,  72,  71,  70,  69, 68,
-// 67, 66, 65
-
-const CodecInst ACMCodecDB::database_[] = {
-#if (defined(WEBRTC_CODEC_ISAC) || defined(WEBRTC_CODEC_ISACFX))
-    {103, "ISAC", 16000, 480, 1, 32000},
-#if (defined(WEBRTC_CODEC_ISAC))
-    {104, "ISAC", 32000, 960, 1, 56000},
-#endif
-#endif
-    // Mono
-    {107, "L16", 8000, 80, 1, 128000},
-    {108, "L16", 16000, 160, 1, 256000},
-    {109, "L16", 32000, 320, 1, 512000},
-    // Stereo
-    {111, "L16", 8000, 80, 2, 128000},
-    {112, "L16", 16000, 160, 2, 256000},
-    {113, "L16", 32000, 320, 2, 512000},
-    // G.711, PCM mu-law and A-law.
-    // Mono
-    {0, "PCMU", 8000, 160, 1, 64000},
-    {8, "PCMA", 8000, 160, 1, 64000},
-    // Stereo
-    {110, "PCMU", 8000, 160, 2, 64000},
-    {118, "PCMA", 8000, 160, 2, 64000},
-#ifdef WEBRTC_CODEC_ILBC
-    {102, "ILBC", 8000, 240, 1, 13300},
-#endif
-    // Mono
-    {9, "G722", 16000, 320, 1, 64000},
-    // Stereo
-    {119, "G722", 16000, 320, 2, 64000},
-#ifdef WEBRTC_CODEC_OPUS
-    // Opus internally supports 48, 24, 16, 12, 8 kHz.
-    // Mono and stereo.
-    {120, "opus", 48000, 960, 2, 64000},
-#endif
-    // Comfort noise for four different sampling frequencies.
-    {13, "CN", 8000, 240, 1, 0},
-    {98, "CN", 16000, 480, 1, 0},
-    {99, "CN", 32000, 960, 1, 0},
-#ifdef ENABLE_48000_HZ
-    {100, "CN", 48000, 1440, 1, 0},
-#endif
-    {106, "telephone-event", 8000, 240, 1, 0},
-    {114, "telephone-event", 16000, 240, 1, 0},
-    {115, "telephone-event", 32000, 240, 1, 0},
-    {116, "telephone-event", 48000, 240, 1, 0},
-#ifdef WEBRTC_CODEC_RED
-    {127, "red", 8000, 0, 1, 0},
-#endif
-    // To prevent compile errors due to trailing commas.
-    {-1, "Null", -1, -1, 0, -1}};
-
-// Create database with all codec settings at compile time.
-// Each entry needs the following parameters in the given order:
-// Number of allowed packet sizes, a vector with the allowed packet sizes,
-// Basic block samples, max number of channels that are supported.
-const ACMCodecDB::CodecSettings ACMCodecDB::codec_settings_[] = {
-#if (defined(WEBRTC_CODEC_ISAC) || defined(WEBRTC_CODEC_ISACFX))
-    {2, {480, 960}, 0, 1},
-#if (defined(WEBRTC_CODEC_ISAC))
-    {1, {960}, 0, 1},
-#endif
-#endif
-    // Mono
-    {4, {80, 160, 240, 320}, 0, 2},
-    {4, {160, 320, 480, 640}, 0, 2},
-    {2, {320, 640}, 0, 2},
-    // Stereo
-    {4, {80, 160, 240, 320}, 0, 2},
-    {4, {160, 320, 480, 640}, 0, 2},
-    {2, {320, 640}, 0, 2},
-    // G.711, PCM mu-law and A-law.
-    // Mono
-    {6, {80, 160, 240, 320, 400, 480}, 0, 2},
-    {6, {80, 160, 240, 320, 400, 480}, 0, 2},
-    // Stereo
-    {6, {80, 160, 240, 320, 400, 480}, 0, 2},
-    {6, {80, 160, 240, 320, 400, 480}, 0, 2},
-#ifdef WEBRTC_CODEC_ILBC
-    {4, {160, 240, 320, 480}, 0, 1},
-#endif
-    // Mono
-    {6, {160, 320, 480, 640, 800, 960}, 0, 2},
-    // Stereo
-    {6, {160, 320, 480, 640, 800, 960}, 0, 2},
-#ifdef WEBRTC_CODEC_OPUS
-// Opus supports frames shorter than 10ms,
-// but it doesn't help us to use them.
-// Mono and stereo.
-#if WEBRTC_OPUS_SUPPORT_120MS_PTIME
-    {5, {480, 960, 1920, 2880, 5760}, 0, 2},
-#else
-    {4, {480, 960, 1920, 2880}, 0, 2},
-#endif
-#endif
-    // Comfort noise for three different sampling frequencies.
-    {1, {240}, 240, 1},
-    {1, {480}, 480, 1},
-    {1, {960}, 960, 1},
-// TODO(solenberg): What is this flag? It is never set in the build files.
-#ifdef ENABLE_48000_HZ
-    {1, {1440}, 1440, 1},
-#endif
-    {1, {240}, 240, 1},
-    {1, {240}, 240, 1},
-    {1, {240}, 240, 1},
-    {1, {240}, 240, 1},
-#ifdef WEBRTC_CODEC_RED
-    {1, {0}, 0, 1},
-#endif
-    // To prevent compile errors due to trailing commas.
-    {-1, {-1}, -1, 0}};
-
-// Create a database of all NetEQ decoders at compile time.
-const NetEqDecoder ACMCodecDB::neteq_decoders_[] = {
-#if (defined(WEBRTC_CODEC_ISAC) || defined(WEBRTC_CODEC_ISACFX))
-    NetEqDecoder::kDecoderISAC,
-#if (defined(WEBRTC_CODEC_ISAC))
-    NetEqDecoder::kDecoderISACswb,
-#endif
-#endif
-    // Mono
-    NetEqDecoder::kDecoderPCM16B, NetEqDecoder::kDecoderPCM16Bwb,
-    NetEqDecoder::kDecoderPCM16Bswb32kHz,
-    // Stereo
-    NetEqDecoder::kDecoderPCM16B_2ch, NetEqDecoder::kDecoderPCM16Bwb_2ch,
-    NetEqDecoder::kDecoderPCM16Bswb32kHz_2ch,
-    // G.711, PCM mu-las and A-law.
-    // Mono
-    NetEqDecoder::kDecoderPCMu, NetEqDecoder::kDecoderPCMa,
-    // Stereo
-    NetEqDecoder::kDecoderPCMu_2ch, NetEqDecoder::kDecoderPCMa_2ch,
-#ifdef WEBRTC_CODEC_ILBC
-    NetEqDecoder::kDecoderILBC,
-#endif
-    // Mono
-    NetEqDecoder::kDecoderG722,
-    // Stereo
-    NetEqDecoder::kDecoderG722_2ch,
-#ifdef WEBRTC_CODEC_OPUS
-    // Mono and stereo.
-    NetEqDecoder::kDecoderOpus,
-#endif
-    // Comfort noise for three different sampling frequencies.
-    NetEqDecoder::kDecoderCNGnb, NetEqDecoder::kDecoderCNGwb,
-    NetEqDecoder::kDecoderCNGswb32kHz,
-#ifdef ENABLE_48000_HZ
-    NetEqDecoder::kDecoderCNGswb48kHz,
-#endif
-    NetEqDecoder::kDecoderAVT, NetEqDecoder::kDecoderAVT16kHz,
-    NetEqDecoder::kDecoderAVT32kHz, NetEqDecoder::kDecoderAVT48kHz,
-#ifdef WEBRTC_CODEC_RED
-    NetEqDecoder::kDecoderRED,
-#endif
-};
-
-// Enumerator for error codes when asking for codec database id.
-enum {
-  kInvalidCodec = -10,
-  kInvalidPayloadtype = -30,
-  kInvalidPacketSize = -40,
-  kInvalidRate = -50
-};
-
-// Gets the codec id number from the database. If there is some mismatch in
-// the codec settings, the function will return an error code.
-// NOTE! The first mismatch found will generate the return value.
-int ACMCodecDB::CodecNumber(const CodecInst& codec_inst) {
-  // Look for a matching codec in the database.
-  int codec_id = CodecId(codec_inst);
-
-  // Checks if we found a matching codec.
-  if (codec_id == -1) {
-    return kInvalidCodec;
-  }
-
-  // Checks the validity of payload type
-  if (!RentACodec::IsPayloadTypeValid(codec_inst.pltype)) {
-    return kInvalidPayloadtype;
-  }
-
-  // Comfort Noise is special case, packet-size & rate is not checked.
-  if (absl::EqualsIgnoreCase(database_[codec_id].plname, "CN")) {
-    return codec_id;
-  }
-
-  // RED is special case, packet-size & rate is not checked.
-  if (absl::EqualsIgnoreCase(database_[codec_id].plname, "red")) {
-    return codec_id;
-  }
-
-  // Checks the validity of packet size.
-  if (codec_settings_[codec_id].num_packet_sizes > 0) {
-    bool packet_size_ok = false;
-    int i;
-    int packet_size_samples;
-    for (i = 0; i < codec_settings_[codec_id].num_packet_sizes; i++) {
-      packet_size_samples = codec_settings_[codec_id].packet_sizes_samples[i];
-      if (codec_inst.pacsize == packet_size_samples) {
-        packet_size_ok = true;
-        break;
-      }
-    }
-
-    if (!packet_size_ok) {
-      return kInvalidPacketSize;
-    }
-  }
-
-  if (codec_inst.pacsize < 1) {
-    return kInvalidPacketSize;
-  }
-
-  // Check the validity of rate. Codecs with multiple rates have their own
-  // function for this.
-  if (absl::EqualsIgnoreCase("isac", codec_inst.plname)) {
-    return IsISACRateValid(codec_inst.rate) ? codec_id : kInvalidRate;
-  } else if (absl::EqualsIgnoreCase("ilbc", codec_inst.plname)) {
-    return IsILBCRateValid(codec_inst.rate, codec_inst.pacsize) ? codec_id
-                                                                : kInvalidRate;
-  } else if (absl::EqualsIgnoreCase("opus", codec_inst.plname)) {
-    return IsOpusRateValid(codec_inst.rate) ? codec_id : kInvalidRate;
-  }
-
-  return database_[codec_id].rate == codec_inst.rate ? codec_id : kInvalidRate;
-}
-
-// Looks for a matching payload name, frequency, and channels in the
-// codec list. Need to check all three since some codecs have several codec
-// entries with different frequencies and/or channels.
-// Does not check other codec settings, such as payload type and packet size.
-// Returns the id of the codec, or -1 if no match is found.
-int ACMCodecDB::CodecId(const CodecInst& codec_inst) {
-  return (CodecId(codec_inst.plname, codec_inst.plfreq, codec_inst.channels));
-}
-
-int ACMCodecDB::CodecId(const char* payload_name,
-                        int frequency,
-                        size_t channels) {
-  for (const CodecInst& ci : database_) {
-    bool name_match = false;
-    bool frequency_match = false;
-    bool channels_match = false;
-
-    // Payload name, sampling frequency and number of channels need to match.
-    // NOTE! If |frequency| is -1, the frequency is not applicable, and is
-    // always treated as true, like for RED.
-    name_match = absl::EqualsIgnoreCase(ci.plname, payload_name);
-    frequency_match = (frequency == ci.plfreq) || (frequency == -1);
-    // The number of channels must match for all codecs but Opus.
-    if (!absl::EqualsIgnoreCase(payload_name, "opus")) {
-      channels_match = (channels == ci.channels);
-    } else {
-      // For opus we just check that number of channels is valid.
-      channels_match = (channels == 1 || channels == 2);
-    }
-
-    if (name_match && frequency_match && channels_match) {
-      // We have found a matching codec in the list.
-      return &ci - database_;
-    }
-  }
-
-  // We didn't find a matching codec.
-  return -1;
-}
-// Gets codec id number from database for the receiver.
-int ACMCodecDB::ReceiverCodecNumber(const CodecInst& codec_inst) {
-  // Look for a matching codec in the database.
-  return CodecId(codec_inst);
-}
-
-}  // namespace acm2
-
-}  // namespace webrtc
diff --git a/modules/audio_coding/acm2/acm_codec_database.h b/modules/audio_coding/acm2/acm_codec_database.h
deleted file mode 100644
index ee6bb46..0000000
--- a/modules/audio_coding/acm2/acm_codec_database.h
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- *  Copyright (c) 2012 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 generates databases with information about all supported audio
- * codecs.
- */
-
-#ifndef MODULES_AUDIO_CODING_ACM2_ACM_CODEC_DATABASE_H_
-#define MODULES_AUDIO_CODING_ACM2_ACM_CODEC_DATABASE_H_
-
-#include "common_types.h"  // NOLINT(build/include)
-#include "modules/audio_coding/acm2/rent_a_codec.h"
-
-namespace webrtc {
-
-namespace acm2 {
-
-// TODO(tlegrand): replace class ACMCodecDB with a namespace.
-class ACMCodecDB {
- public:
-  // kMaxNumCodecs - Maximum number of codecs that can be activated in one
-  //                 build.
-  // kMaxNumPacketSize - Maximum number of allowed packet sizes for one codec.
-  // These might need to be increased if adding a new codec to the database
-  static const int kMaxNumCodecs = 50;
-  static const int kMaxNumPacketSize = 6;
-
-  // Codec specific settings
-  //
-  // num_packet_sizes     - number of allowed packet sizes.
-  // packet_sizes_samples - list of the allowed packet sizes.
-  // basic_block_samples  - assigned a value different from 0 if the codec
-  //                        requires to be fed with a specific number of samples
-  //                        that can be different from packet size.
-  // channel_support      - number of channels supported to encode;
-  //                        1 = mono, 2 = stereo, etc.
-  struct CodecSettings {
-    int num_packet_sizes;
-    int packet_sizes_samples[kMaxNumPacketSize];
-    int basic_block_samples;
-    size_t channel_support;
-  };
-
-  // Returns codec id from database, given the information received in the input
-  // [codec_inst].
-  // Input:
-  //   [codec_inst] - Information about the codec for which we require the
-  //                  database id.
-  // Return:
-  //   codec id if successful, otherwise < 0.
-  static int CodecNumber(const CodecInst& codec_inst);
-  static int CodecId(const CodecInst& codec_inst);
-  static int CodecId(const char* payload_name, int frequency, size_t channels);
-  static int ReceiverCodecNumber(const CodecInst& codec_inst);
-
-  // Databases with information about the supported codecs
-  // database_ - stored information about all codecs: payload type, name,
-  //             sampling frequency, packet size in samples, default channel
-  //             support, and default rate.
-  // codec_settings_ - stored codec settings: number of allowed packet sizes,
-  //                   a vector with the allowed packet sizes, basic block
-  //                   samples, and max number of channels that are supported.
-  // neteq_decoders_ - list of supported decoders in NetEQ.
-  static const CodecInst database_[kMaxNumCodecs];
-  static const CodecSettings codec_settings_[kMaxNumCodecs];
-  static const NetEqDecoder neteq_decoders_[kMaxNumCodecs];
-};
-
-}  // namespace acm2
-
-}  // namespace webrtc
-
-#endif  // MODULES_AUDIO_CODING_ACM2_ACM_CODEC_DATABASE_H_
diff --git a/modules/audio_coding/acm2/acm_receive_test.cc b/modules/audio_coding/acm2/acm_receive_test.cc
index c149ec1..078c991 100644
--- a/modules/audio_coding/acm2/acm_receive_test.cc
+++ b/modules/audio_coding/acm2/acm_receive_test.cc
@@ -14,9 +14,7 @@
 
 #include <memory>
 
-#include "absl/strings/match.h"
 #include "api/audio_codecs/builtin_audio_decoder_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/audio_sink.h"
 #include "modules/audio_coding/neteq/tools/packet.h"
@@ -28,89 +26,6 @@
 namespace test {
 
 namespace {
-// Returns true if the codec should be registered, otherwise false. Changes
-// the number of channels for the Opus codec to always be 1.
-bool ModifyAndUseThisCodec(CodecInst* codec_param) {
-  if (absl::EqualsIgnoreCase(codec_param->plname, "CN") &&
-      codec_param->plfreq == 48000)
-    return false;  // Skip 48 kHz comfort noise.
-
-  if (absl::EqualsIgnoreCase(codec_param->plname, "telephone-event"))
-    return false;  // Skip DTFM.
-
-  return true;
-}
-
-// Remaps payload types from ACM's default to those used in the resource file
-// neteq_universal_new.rtp. Returns true if the codec should be registered,
-// otherwise false. The payload types are set as follows (all are mono codecs):
-// PCMu = 0;
-// PCMa = 8;
-// Comfort noise 8 kHz = 13
-// Comfort noise 16 kHz = 98
-// Comfort noise 32 kHz = 99
-// iLBC = 102
-// iSAC wideband = 103
-// iSAC super-wideband = 104
-// AVT/DTMF = 106
-// RED = 117
-// PCM16b 8 kHz = 93
-// PCM16b 16 kHz = 94
-// PCM16b 32 kHz = 95
-// G.722 = 94
-bool RemapPltypeAndUseThisCodec(const char* plname,
-                                int plfreq,
-                                size_t channels,
-                                int* pltype) {
-  if (channels != 1)
-    return false;  // Don't use non-mono codecs.
-
-  // Re-map pltypes to those used in the NetEq test files.
-  if (absl::EqualsIgnoreCase(plname, "PCMU") && plfreq == 8000) {
-    *pltype = 0;
-  } else if (absl::EqualsIgnoreCase(plname, "PCMA") && plfreq == 8000) {
-    *pltype = 8;
-  } else if (absl::EqualsIgnoreCase(plname, "CN") && plfreq == 8000) {
-    *pltype = 13;
-  } else if (absl::EqualsIgnoreCase(plname, "CN") && plfreq == 16000) {
-    *pltype = 98;
-  } else if (absl::EqualsIgnoreCase(plname, "CN") && plfreq == 32000) {
-    *pltype = 99;
-  } else if (absl::EqualsIgnoreCase(plname, "ILBC")) {
-    *pltype = 102;
-  } else if (absl::EqualsIgnoreCase(plname, "ISAC") && plfreq == 16000) {
-    *pltype = 103;
-  } else if (absl::EqualsIgnoreCase(plname, "ISAC") && plfreq == 32000) {
-    *pltype = 104;
-  } else if (absl::EqualsIgnoreCase(plname, "telephone-event") &&
-             plfreq == 8000) {
-    *pltype = 106;
-  } else if (absl::EqualsIgnoreCase(plname, "telephone-event") &&
-             plfreq == 16000) {
-    *pltype = 114;
-  } else if (absl::EqualsIgnoreCase(plname, "telephone-event") &&
-             plfreq == 32000) {
-    *pltype = 115;
-  } else if (absl::EqualsIgnoreCase(plname, "telephone-event") &&
-             plfreq == 48000) {
-    *pltype = 116;
-  } else if (absl::EqualsIgnoreCase(plname, "red")) {
-    *pltype = 117;
-  } else if (absl::EqualsIgnoreCase(plname, "L16") && plfreq == 8000) {
-    *pltype = 93;
-  } else if (absl::EqualsIgnoreCase(plname, "L16") && plfreq == 16000) {
-    *pltype = 94;
-  } else if (absl::EqualsIgnoreCase(plname, "L16") && plfreq == 32000) {
-    *pltype = 95;
-  } else if (absl::EqualsIgnoreCase(plname, "G722")) {
-    *pltype = 9;
-  } else {
-    // Don't use any other codecs.
-    return false;
-  }
-  return true;
-}
-
 AudioCodingModule::Config MakeAcmConfig(
     Clock* clock,
     rtc::scoped_refptr<AudioDecoderFactory> decoder_factory) {
@@ -119,7 +34,6 @@
   config.decoder_factory = std::move(decoder_factory);
   return config;
 }
-
 }  // namespace
 
 AcmReceiveTestOldApi::AcmReceiveTestOldApi(
@@ -139,36 +53,43 @@
 AcmReceiveTestOldApi::~AcmReceiveTestOldApi() = default;
 
 void AcmReceiveTestOldApi::RegisterDefaultCodecs() {
-  CodecInst my_codec_param;
-  for (int n = 0; n < acm_->NumberOfCodecs(); n++) {
-    ASSERT_EQ(0, acm_->Codec(n, &my_codec_param)) << "Failed to get codec.";
-    if (ModifyAndUseThisCodec(&my_codec_param)) {
-      ASSERT_EQ(true,
-                acm_->RegisterReceiveCodec(my_codec_param.pltype,
-                                           CodecInstToSdp(my_codec_param)))
-          << "Couldn't register receive codec.\n";
-    }
-  }
+  acm_->SetReceiveCodecs({{103, {"ISAC", 16000, 1}},
+                          {104, {"ISAC", 32000, 1}},
+                          {107, {"L16", 8000, 1}},
+                          {108, {"L16", 16000, 1}},
+                          {109, {"L16", 32000, 1}},
+                          {111, {"L16", 8000, 2}},
+                          {112, {"L16", 16000, 2}},
+                          {113, {"L16", 32000, 2}},
+                          {0, {"PCMU", 8000, 1}},
+                          {110, {"PCMU", 8000, 2}},
+                          {8, {"PCMA", 8000, 1}},
+                          {118, {"PCMA", 8000, 2}},
+                          {102, {"ILBC", 8000, 1}},
+                          {9, {"G722", 8000, 1}},
+                          {119, {"G722", 8000, 2}},
+                          {120, {"OPUS", 48000, 2, {{"stereo", "1"}}}},
+                          {13, {"CN", 8000, 1}},
+                          {98, {"CN", 16000, 1}},
+                          {99, {"CN", 32000, 1}}});
 }
 
+// Remaps payload types from ACM's default to those used in the resource file
+// neteq_universal_new.rtp.
 void AcmReceiveTestOldApi::RegisterNetEqTestCodecs() {
-  CodecInst my_codec_param;
-  for (int n = 0; n < acm_->NumberOfCodecs(); n++) {
-    ASSERT_EQ(0, acm_->Codec(n, &my_codec_param)) << "Failed to get codec.";
-    if (!ModifyAndUseThisCodec(&my_codec_param)) {
-      // Skip this codec.
-      continue;
-    }
-
-    if (RemapPltypeAndUseThisCodec(my_codec_param.plname, my_codec_param.plfreq,
-                                   my_codec_param.channels,
-                                   &my_codec_param.pltype)) {
-      ASSERT_EQ(true,
-                acm_->RegisterReceiveCodec(my_codec_param.pltype,
-                                           CodecInstToSdp(my_codec_param)))
-          << "Couldn't register receive codec.\n";
-    }
-  }
+  acm_->SetReceiveCodecs({{103, {"ISAC", 16000, 1}},
+                          {104, {"ISAC", 32000, 1}},
+                          {93, {"L16", 8000, 1}},
+                          {94, {"L16", 16000, 1}},
+                          {95, {"L16", 32000, 1}},
+                          {0, {"PCMU", 8000, 1}},
+                          {8, {"PCMA", 8000, 1}},
+                          {102, {"ILBC", 8000, 1}},
+                          {9, {"G722", 8000, 1}},
+                          {120, {"OPUS", 48000, 2}},
+                          {13, {"CN", 8000, 1}},
+                          {98, {"CN", 16000, 1}},
+                          {99, {"CN", 32000, 1}}});
 }
 
 void AcmReceiveTestOldApi::Run() {
@@ -199,18 +120,15 @@
       AfterGetAudio();
     }
 
-    // Insert packet after converting from RTPHeader to WebRtcRTPHeader.
-    WebRtcRTPHeader header;
-    header.header = packet->header();
-    header.frameType = kAudioFrameSpeech;
-    EXPECT_EQ(0,
-              acm_->IncomingPacket(
-                  packet->payload(),
-                  static_cast<int32_t>(packet->payload_length_bytes()), header))
+    EXPECT_EQ(0, acm_->IncomingPacket(
+                     packet->payload(),
+                     static_cast<int32_t>(packet->payload_length_bytes()),
+                     packet->header()))
         << "Failure when inserting packet:" << std::endl
-        << "  PT = " << static_cast<int>(header.header.payloadType) << std::endl
-        << "  TS = " << header.header.timestamp << std::endl
-        << "  SN = " << header.header.sequenceNumber;
+        << "  PT = " << static_cast<int>(packet->header().payloadType)
+        << std::endl
+        << "  TS = " << packet->header().timestamp << std::endl
+        << "  SN = " << packet->header().sequenceNumber;
   }
 }
 
diff --git a/modules/audio_coding/acm2/acm_receive_test.h b/modules/audio_coding/acm2/acm_receive_test.h
index 83ffcb3..9d004c6 100644
--- a/modules/audio_coding/acm2/acm_receive_test.h
+++ b/modules/audio_coding/acm2/acm_receive_test.h
@@ -16,14 +16,13 @@
 #include <string>
 
 #include "api/audio_codecs/audio_decoder_factory.h"
-#include "rtc_base/constructormagic.h"
-#include "rtc_base/scoped_ref_ptr.h"
+#include "api/scoped_refptr.h"
+#include "rtc_base/constructor_magic.h"
 #include "system_wrappers/include/clock.h"
 
 namespace webrtc {
 class AudioCodingModule;
 class AudioDecoder;
-struct CodecInst;
 
 namespace test {
 class AudioSink;
@@ -34,7 +33,8 @@
   enum NumOutputChannels : size_t {
     kArbitraryChannels = 0,
     kMonoOutput = 1,
-    kStereoOutput = 2
+    kStereoOutput = 2,
+    kQuadOutput = 4
   };
 
   AcmReceiveTestOldApi(PacketSource* packet_source,
diff --git a/modules/audio_coding/acm2/acm_receiver.cc b/modules/audio_coding/acm2/acm_receiver.cc
index d3af7c0..da7d621 100644
--- a/modules/audio_coding/acm2/acm_receiver.cc
+++ b/modules/audio_coding/acm2/acm_receiver.cc
@@ -20,9 +20,7 @@
 #include "api/audio_codecs/audio_decoder.h"
 #include "modules/audio_coding/acm2/acm_resampler.h"
 #include "modules/audio_coding/acm2/call_statistics.h"
-#include "modules/audio_coding/acm2/rent_a_codec.h"
 #include "modules/audio_coding/neteq/include/neteq.h"
-#include "modules/audio_coding/neteq/neteq_decoder_enum.h"
 #include "modules/include/module_common_types.h"
 #include "rtc_base/checks.h"
 #include "rtc_base/logging.h"
@@ -60,56 +58,66 @@
   return -1;
 }
 
+bool AcmReceiver::SetBaseMinimumDelayMs(int delay_ms) {
+  return neteq_->SetBaseMinimumDelayMs(delay_ms);
+}
+
+int AcmReceiver::GetBaseMinimumDelayMs() const {
+  return neteq_->GetBaseMinimumDelayMs();
+}
+
 absl::optional<int> AcmReceiver::last_packet_sample_rate_hz() const {
   rtc::CritScope lock(&crit_sect_);
-  return last_packet_sample_rate_hz_;
+  if (!last_decoder_) {
+    return absl::nullopt;
+  }
+  return last_decoder_->second.clockrate_hz;
 }
 
 int AcmReceiver::last_output_sample_rate_hz() const {
   return neteq_->last_output_sample_rate_hz();
 }
 
-int AcmReceiver::InsertPacket(const WebRtcRTPHeader& rtp_header,
+int AcmReceiver::InsertPacket(const RTPHeader& rtp_header,
                               rtc::ArrayView<const uint8_t> incoming_payload) {
-  uint32_t receive_timestamp = 0;
-  const RTPHeader* header = &rtp_header.header;  // Just a shorthand.
-
   if (incoming_payload.empty()) {
-    neteq_->InsertEmptyPacket(rtp_header.header);
+    neteq_->InsertEmptyPacket(rtp_header);
     return 0;
   }
 
+  int payload_type = rtp_header.payloadType;
+  auto format = neteq_->GetDecoderFormat(payload_type);
+  if (format && absl::EqualsIgnoreCase(format->name, "red")) {
+    // This is a RED packet. Get the format of the audio codec.
+    payload_type = incoming_payload[0] & 0x7f;
+    format = neteq_->GetDecoderFormat(payload_type);
+  }
+  if (!format) {
+    RTC_LOG_F(LS_ERROR) << "Payload-type "
+                        << payload_type
+                        << " is not registered.";
+    return -1;
+  }
+
   {
     rtc::CritScope lock(&crit_sect_);
-
-    const absl::optional<CodecInst> ci =
-        RtpHeaderToDecoder(*header, incoming_payload[0]);
-    if (!ci) {
-      RTC_LOG_F(LS_ERROR) << "Payload-type "
-                          << static_cast<int>(header->payloadType)
-                          << " is not registered.";
-      return -1;
-    }
-    receive_timestamp = NowInTimestamp(ci->plfreq);
-
-    if (absl::EqualsIgnoreCase(ci->plname, "cn")) {
-      if (last_audio_decoder_ && last_audio_decoder_->channels > 1) {
+    if (absl::EqualsIgnoreCase(format->name, "cn")) {
+      if (last_decoder_ && last_decoder_->second.num_channels > 1) {
         // This is a CNG and the audio codec is not mono, so skip pushing in
         // packets into NetEq.
         return 0;
       }
     } else {
-      last_audio_decoder_ = ci;
-      last_audio_format_ = neteq_->GetDecoderFormat(ci->pltype);
-      RTC_DCHECK(last_audio_format_);
-      last_packet_sample_rate_hz_ = ci->plfreq;
+      RTC_DCHECK(format);
+      last_decoder_ = std::make_pair(payload_type, *format);
     }
   }  // |crit_sect_| is released.
 
-  if (neteq_->InsertPacket(rtp_header.header, incoming_payload,
-                           receive_timestamp) < 0) {
+  uint32_t receive_timestamp = NowInTimestamp(format->clockrate_hz);
+  if (neteq_->InsertPacket(rtp_header, incoming_payload, receive_timestamp) <
+      0) {
     RTC_LOG(LERROR) << "AcmReceiver::InsertPacket "
-                    << static_cast<int>(header->payloadType)
+                    << static_cast<int>(rtp_header.payloadType)
                     << " Failed to insert packet";
     return -1;
   }
@@ -186,85 +194,6 @@
   neteq_->SetCodecs(codecs);
 }
 
-int32_t AcmReceiver::AddCodec(int acm_codec_id,
-                              uint8_t payload_type,
-                              size_t channels,
-                              int /*sample_rate_hz*/,
-                              AudioDecoder* audio_decoder,
-                              const std::string& name) {
-  // TODO(kwiberg): This function has been ignoring the |sample_rate_hz|
-  // argument for a long time. Arguably, it should simply be removed.
-
-  const auto neteq_decoder = [acm_codec_id, channels]() -> NetEqDecoder {
-    if (acm_codec_id == -1)
-      return NetEqDecoder::kDecoderArbitrary;  // External decoder.
-    const absl::optional<RentACodec::CodecId> cid =
-        RentACodec::CodecIdFromIndex(acm_codec_id);
-    RTC_DCHECK(cid) << "Invalid codec index: " << acm_codec_id;
-    const absl::optional<NetEqDecoder> ned =
-        RentACodec::NetEqDecoderFromCodecId(*cid, channels);
-    RTC_DCHECK(ned) << "Invalid codec ID: " << static_cast<int>(*cid);
-    return *ned;
-  }();
-  const absl::optional<SdpAudioFormat> new_format =
-      NetEqDecoderToSdpAudioFormat(neteq_decoder);
-
-  rtc::CritScope lock(&crit_sect_);
-
-  const auto old_format = neteq_->GetDecoderFormat(payload_type);
-  if (old_format && new_format && *old_format == *new_format) {
-    // Re-registering the same codec. Do nothing and return.
-    return 0;
-  }
-
-  if (neteq_->RemovePayloadType(payload_type) != NetEq::kOK) {
-    RTC_LOG(LERROR) << "Cannot remove payload "
-                    << static_cast<int>(payload_type);
-    return -1;
-  }
-
-  int ret_val;
-  if (!audio_decoder) {
-    ret_val = neteq_->RegisterPayloadType(neteq_decoder, name, payload_type);
-  } else {
-    ret_val = neteq_->RegisterExternalDecoder(audio_decoder, neteq_decoder,
-                                              name, payload_type);
-  }
-  if (ret_val != NetEq::kOK) {
-    RTC_LOG(LERROR) << "AcmReceiver::AddCodec " << acm_codec_id
-                    << static_cast<int>(payload_type)
-                    << " channels: " << channels;
-    return -1;
-  }
-  return 0;
-}
-
-bool AcmReceiver::AddCodec(int rtp_payload_type,
-                           const SdpAudioFormat& audio_format) {
-  const auto old_format = neteq_->GetDecoderFormat(rtp_payload_type);
-  if (old_format && *old_format == audio_format) {
-    // Re-registering the same codec. Do nothing and return.
-    return true;
-  }
-
-  if (neteq_->RemovePayloadType(rtp_payload_type) != NetEq::kOK) {
-    RTC_LOG(LERROR)
-        << "AcmReceiver::AddCodec: Could not remove existing decoder"
-           " for payload type "
-        << rtp_payload_type;
-    return false;
-  }
-
-  const bool success =
-      neteq_->RegisterPayloadType(rtp_payload_type, audio_format);
-  if (!success) {
-    RTC_LOG(LERROR) << "AcmReceiver::AddCodec failed for payload type "
-                    << rtp_payload_type << ", decoder format "
-                    << rtc::ToString(audio_format);
-  }
-  return success;
-}
-
 void AcmReceiver::FlushBuffers() {
   neteq_->FlushBuffers();
 }
@@ -272,24 +201,7 @@
 void AcmReceiver::RemoveAllCodecs() {
   rtc::CritScope lock(&crit_sect_);
   neteq_->RemoveAllPayloadTypes();
-  last_audio_decoder_ = absl::nullopt;
-  last_audio_format_ = absl::nullopt;
-  last_packet_sample_rate_hz_ = absl::nullopt;
-}
-
-int AcmReceiver::RemoveCodec(uint8_t payload_type) {
-  rtc::CritScope lock(&crit_sect_);
-  if (neteq_->RemovePayloadType(payload_type) != NetEq::kOK) {
-    RTC_LOG(LERROR) << "AcmReceiver::RemoveCodec "
-                    << static_cast<int>(payload_type);
-    return -1;
-  }
-  if (last_audio_decoder_ && payload_type == last_audio_decoder_->pltype) {
-    last_audio_decoder_ = absl::nullopt;
-    last_audio_format_ = absl::nullopt;
-    last_packet_sample_rate_hz_ = absl::nullopt;
-  }
-  return 0;
+  last_decoder_ = absl::nullopt;
 }
 
 absl::optional<uint32_t> AcmReceiver::GetPlayoutTimestamp() {
@@ -304,18 +216,14 @@
   return neteq_->TargetDelayMs();
 }
 
-int AcmReceiver::LastAudioCodec(CodecInst* codec) const {
+absl::optional<std::pair<int, SdpAudioFormat>>
+    AcmReceiver::LastDecoder() const {
   rtc::CritScope lock(&crit_sect_);
-  if (!last_audio_decoder_) {
-    return -1;
+  if (!last_decoder_) {
+    return absl::nullopt;
   }
-  *codec = *last_audio_decoder_;
-  return 0;
-}
-
-absl::optional<SdpAudioFormat> AcmReceiver::LastAudioFormat() const {
-  rtc::CritScope lock(&crit_sect_);
-  return last_audio_format_;
+  RTC_DCHECK_NE(-1, last_decoder_->first);  // Payload type should be valid.
+  return last_decoder_;
 }
 
 void AcmReceiver::GetNetworkStatistics(NetworkStatistics* acm_stat) {
@@ -345,8 +253,12 @@
   acm_stat->concealedSamples = neteq_lifetime_stat.concealed_samples;
   acm_stat->concealmentEvents = neteq_lifetime_stat.concealment_events;
   acm_stat->jitterBufferDelayMs = neteq_lifetime_stat.jitter_buffer_delay_ms;
+  acm_stat->jitterBufferEmittedCount =
+      neteq_lifetime_stat.jitter_buffer_emitted_count;
   acm_stat->delayedPacketOutageSamples =
       neteq_lifetime_stat.delayed_packet_outage_samples;
+  acm_stat->relativePacketArrivalDelayMs =
+      neteq_lifetime_stat.relative_packet_arrival_delay_ms;
 
   NetEqOperationsAndState neteq_operations_and_state =
       neteq_->GetOperationsAndState();
@@ -354,26 +266,6 @@
       neteq_operations_and_state.packet_buffer_flushes;
 }
 
-int AcmReceiver::DecoderByPayloadType(uint8_t payload_type,
-                                      CodecInst* codec) const {
-  rtc::CritScope lock(&crit_sect_);
-  const absl::optional<CodecInst> ci = neteq_->GetDecoder(payload_type);
-  if (ci) {
-    *codec = *ci;
-    return 0;
-  } else {
-    RTC_LOG(LERROR) << "AcmReceiver::DecoderByPayloadType "
-                    << static_cast<int>(payload_type);
-    return -1;
-  }
-}
-
-absl::optional<SdpAudioFormat> AcmReceiver::DecoderByPayloadType(
-    int payload_type) const {
-  rtc::CritScope lock(&crit_sect_);
-  return neteq_->GetDecoderFormat(payload_type);
-}
-
 int AcmReceiver::EnableNack(size_t max_nack_list_size) {
   neteq_->EnableNack(max_nack_list_size);
   return 0;
@@ -393,19 +285,6 @@
   // TODO(turajs): Should NetEq Buffer be flushed?
 }
 
-const absl::optional<CodecInst> AcmReceiver::RtpHeaderToDecoder(
-    const RTPHeader& rtp_header,
-    uint8_t first_payload_byte) const {
-  const absl::optional<CodecInst> ci =
-      neteq_->GetDecoder(rtp_header.payloadType);
-  if (ci && absl::EqualsIgnoreCase(ci->plname, "red")) {
-    // This is a RED packet. Get the payload of the audio codec.
-    return neteq_->GetDecoder(first_payload_byte & 0x7f);
-  } else {
-    return ci;
-  }
-}
-
 uint32_t AcmReceiver::NowInTimestamp(int decoder_sampling_rate) const {
   // Down-cast the time to (32-6)-bit since we only care about
   // the least significant bits. (32-6) bits cover 2^(32-6) = 67108864 ms.
diff --git a/modules/audio_coding/acm2/acm_receiver.h b/modules/audio_coding/acm2/acm_receiver.h
index 8e7d839..1f449a3 100644
--- a/modules/audio_coding/acm2/acm_receiver.h
+++ b/modules/audio_coding/acm2/acm_receiver.h
@@ -15,6 +15,7 @@
 #include <map>
 #include <memory>
 #include <string>
+#include <utility>
 #include <vector>
 
 #include "absl/types/optional.h"
@@ -24,16 +25,14 @@
 #include "modules/audio_coding/acm2/acm_resampler.h"
 #include "modules/audio_coding/acm2/call_statistics.h"
 #include "modules/audio_coding/include/audio_coding_module.h"
-#include "rtc_base/criticalsection.h"
+#include "rtc_base/critical_section.h"
 #include "rtc_base/thread_annotations.h"
 
 namespace webrtc {
 
 class Clock;
-struct CodecInst;
 class NetEq;
 struct RTPHeader;
-struct WebRtcRTPHeader;
 
 namespace acm2 {
 
@@ -58,7 +57,7 @@
   // Return value             : 0 if OK.
   //                           <0 if NetEq returned an error.
   //
-  int InsertPacket(const WebRtcRTPHeader& rtp_header,
+  int InsertPacket(const RTPHeader& rtp_header,
                    rtc::ArrayView<const uint8_t> incoming_payload);
 
   //
@@ -85,43 +84,6 @@
   void SetCodecs(const std::map<int, SdpAudioFormat>& codecs);
 
   //
-  // Adds a new codec to the NetEq codec database.
-  //
-  // Input:
-  //   - acm_codec_id        : ACM codec ID; -1 means external decoder.
-  //   - payload_type        : payload type.
-  //   - sample_rate_hz      : sample rate.
-  //   - audio_decoder       : pointer to a decoder object. If it's null, then
-  //                           NetEq will internally create a decoder object
-  //                           based on the value of |acm_codec_id| (which
-  //                           mustn't be -1). Otherwise, NetEq will use the
-  //                           given decoder for the given payload type. NetEq
-  //                           won't take ownership of the decoder; it's up to
-  //                           the caller to delete it when it's no longer
-  //                           needed.
-  //
-  //                           Providing an existing decoder object here is
-  //                           necessary for external decoders, but may also be
-  //                           used for built-in decoders if NetEq doesn't have
-  //                           all the info it needs to construct them properly
-  //                           (e.g. iSAC, where the decoder needs to be paired
-  //                           with an encoder).
-  //
-  // Return value             : 0 if OK.
-  //                           <0 if NetEq returned an error.
-  //
-  int AddCodec(int acm_codec_id,
-               uint8_t payload_type,
-               size_t channels,
-               int sample_rate_hz,
-               AudioDecoder* audio_decoder,
-               const std::string& name);
-
-  // Adds a new decoder to the NetEq codec database. Returns true iff
-  // successful.
-  bool AddCodec(int rtp_payload_type, const SdpAudioFormat& audio_format);
-
-  //
   // Sets a minimum delay for packet buffer. The given delay is maintained,
   // unless channel condition dictates a higher delay.
   //
@@ -145,6 +107,16 @@
   //
   int SetMaximumDelay(int delay_ms);
 
+  // Sets a base minimum delay in milliseconds for the packet buffer.
+  // Base minimum delay sets lower bound minimum delay value which
+  // is set via SetMinimumDelay.
+  //
+  // Returns true if value was successfully set, false overwise.
+  bool SetBaseMinimumDelayMs(int delay_ms);
+
+  // Returns current value of base minimum delay in milliseconds.
+  int GetBaseMinimumDelayMs() const;
+
   //
   // Resets the initial delay to zero.
   //
@@ -173,17 +145,6 @@
   void FlushBuffers();
 
   //
-  // Removes a payload-type from the NetEq codec database.
-  //
-  // Input:
-  //   - payload_type         : the payload-type to be removed.
-  //
-  // Return value             : 0 if OK.
-  //                           -1 if an error occurred.
-  //
-  int RemoveCodec(uint8_t payload_type);
-
-  //
   // Remove all registered codecs.
   //
   void RemoveAllCodecs();
@@ -204,30 +165,10 @@
   int TargetDelayMs() const;
 
   //
-  // Get the audio codec associated with the last non-CNG/non-DTMF received
-  // payload. If no non-CNG/non-DTMF packet is received -1 is returned,
-  // otherwise return 0.
+  // Get payload type and format of the last non-CNG/non-DTMF received payload.
+  // If no non-CNG/non-DTMF packet is received absl::nullopt is returned.
   //
-  int LastAudioCodec(CodecInst* codec) const;
-
-  absl::optional<SdpAudioFormat> LastAudioFormat() const;
-
-  //
-  // Get a decoder given its registered payload-type.
-  //
-  // Input:
-  //    -payload_type         : the payload-type of the codec to be retrieved.
-  //
-  // Output:
-  //    -codec                : codec associated with the given payload-type.
-  //
-  // Return value             : 0 if succeeded.
-  //                           -1 if failed, e.g. given payload-type is not
-  //                              registered.
-  //
-  int DecoderByPayloadType(uint8_t payload_type,
-                           CodecInst* codec) const;
-  absl::optional<SdpAudioFormat> DecoderByPayloadType(int payload_type) const;
+  absl::optional<std::pair<int, SdpAudioFormat>> LastDecoder() const;
 
   //
   // Enable NACK and set the maximum size of the NACK list. If NACK is already
@@ -260,32 +201,17 @@
   void GetDecodingCallStatistics(AudioDecodingCallStats* stats) const;
 
  private:
-  struct Decoder {
-    int acm_codec_id;
-    uint8_t payload_type;
-    // This field is meaningful for codecs where both mono and
-    // stereo versions are registered under the same ID.
-    size_t channels;
-    int sample_rate_hz;
-  };
-
-  const absl::optional<CodecInst> RtpHeaderToDecoder(
-      const RTPHeader& rtp_header,
-      uint8_t first_payload_byte) const
-      RTC_EXCLUSIVE_LOCKS_REQUIRED(crit_sect_);
-
   uint32_t NowInTimestamp(int decoder_sampling_rate) const;
 
   rtc::CriticalSection crit_sect_;
-  absl::optional<CodecInst> last_audio_decoder_ RTC_GUARDED_BY(crit_sect_);
-  absl::optional<SdpAudioFormat> last_audio_format_ RTC_GUARDED_BY(crit_sect_);
+  absl::optional<std::pair<int, SdpAudioFormat>> last_decoder_
+      RTC_GUARDED_BY(crit_sect_);
   ACMResampler resampler_ RTC_GUARDED_BY(crit_sect_);
   std::unique_ptr<int16_t[]> last_audio_buffer_ RTC_GUARDED_BY(crit_sect_);
   CallStatistics call_stats_ RTC_GUARDED_BY(crit_sect_);
   const std::unique_ptr<NetEq> neteq_;  // NetEq is thread-safe; no lock needed.
-  const Clock* const clock_;
+  Clock* const clock_;
   bool resampled_last_output_frame_ RTC_GUARDED_BY(crit_sect_);
-  absl::optional<int> last_packet_sample_rate_hz_ RTC_GUARDED_BY(crit_sect_);
 };
 
 }  // namespace acm2
diff --git a/modules/audio_coding/acm2/acm_receiver_unittest.cc b/modules/audio_coding/acm2/acm_receiver_unittest.cc
index 46384fe..e5a7684 100644
--- a/modules/audio_coding/acm2/acm_receiver_unittest.cc
+++ b/modules/audio_coding/acm2/acm_receiver_unittest.cc
@@ -15,7 +15,6 @@
 
 #include "api/audio_codecs/builtin_audio_decoder_factory.h"
 #include "api/audio_codecs/builtin_audio_encoder_factory.h"
-#include "modules/audio_coding/acm2/rent_a_codec.h"
 #include "modules/audio_coding/codecs/cng/audio_encoder_cng.h"
 #include "modules/audio_coding/include/audio_coding_module.h"
 #include "modules/audio_coding/neteq/tools/rtp_generator.h"
@@ -24,7 +23,7 @@
 #include "rtc_base/numerics/safe_conversions.h"
 #include "system_wrappers/include/clock.h"
 #include "test/gtest.h"
-#include "test/testsupport/fileutils.h"
+#include "test/testsupport/file_utils.h"
 
 namespace webrtc {
 
@@ -51,13 +50,12 @@
     acm_->InitializeReceiver();
     acm_->RegisterTransportCallback(this);
 
-    rtp_header_.header.sequenceNumber = 0;
-    rtp_header_.header.timestamp = 0;
-    rtp_header_.header.markerBit = false;
-    rtp_header_.header.ssrc = 0x12345678;  // Arbitrary.
-    rtp_header_.header.numCSRCs = 0;
-    rtp_header_.header.payloadType = 0;
-    rtp_header_.frameType = kAudioFrameSpeech;
+    rtp_header_.sequenceNumber = 0;
+    rtp_header_.timestamp = 0;
+    rtp_header_.markerBit = false;
+    rtp_header_.ssrc = 0x12345678;  // Arbitrary.
+    rtp_header_.numCSRCs = 0;
+    rtp_header_.payloadType = 0;
   }
 
   void TearDown() override {}
@@ -105,14 +103,6 @@
     return num_10ms_frames;
   }
 
-  template <size_t N>
-  void AddSetOfCodecs(rtc::ArrayView<SdpAudioFormat> formats) {
-    static int payload_type = 0;
-    for (const auto& format : formats) {
-      EXPECT_TRUE(receiver_->AddCodec(payload_type++, format));
-    }
-  }
-
   int SendData(FrameType frame_type,
                uint8_t payload_type,
                uint32_t timestamp,
@@ -122,9 +112,8 @@
     if (frame_type == kEmptyFrame)
       return 0;
 
-    rtp_header_.header.payloadType = payload_type;
-    rtp_header_.frameType = frame_type;
-    rtp_header_.header.timestamp = timestamp;
+    rtp_header_.payloadType = payload_type;
+    rtp_header_.timestamp = timestamp;
 
     int ret_val = receiver_->InsertPacket(
         rtp_header_,
@@ -133,7 +122,7 @@
       assert(false);
       return -1;
     }
-    rtp_header_.header.sequenceNumber++;
+    rtp_header_.sequenceNumber++;
     packet_sent_ = true;
     last_frame_type_ = frame_type;
     return 0;
@@ -146,7 +135,7 @@
   AudioCodingModule::Config config_;
   std::unique_ptr<AcmReceiver> receiver_;
   std::unique_ptr<AudioCodingModule> acm_;
-  WebRtcRTPHeader rtp_header_;
+  RTPHeader rtp_header_;
   uint32_t timestamp_;
   bool packet_sent_;  // Set when SendData is called reset when inserting audio.
   uint32_t last_packet_send_timestamp_;
@@ -154,111 +143,26 @@
 };
 
 #if defined(WEBRTC_ANDROID)
-#define MAYBE_AddCodecGetCodec DISABLED_AddCodecGetCodec
-#else
-#define MAYBE_AddCodecGetCodec AddCodecGetCodec
-#endif
-TEST_F(AcmReceiverTestOldApi, MAYBE_AddCodecGetCodec) {
-  const std::vector<AudioCodecSpec> codecs =
-      decoder_factory_->GetSupportedDecoders();
-
-  // Add codec.
-  for (size_t n = 0; n < codecs.size(); ++n) {
-    if (n & 0x1) {  // Just add codecs with odd index.
-      const int payload_type = rtc::checked_cast<int>(n);
-      EXPECT_TRUE(receiver_->AddCodec(payload_type, codecs[n].format));
-    }
-  }
-  // Get codec and compare.
-  for (size_t n = 0; n < codecs.size(); ++n) {
-    const int payload_type = rtc::checked_cast<int>(n);
-    if (n & 0x1) {
-      // Codecs with odd index should match the reference.
-      EXPECT_EQ(absl::make_optional(codecs[n].format),
-                receiver_->DecoderByPayloadType(payload_type));
-    } else {
-      // Codecs with even index are not registered.
-      EXPECT_EQ(absl::nullopt, receiver_->DecoderByPayloadType(payload_type));
-    }
-  }
-}
-
-#if defined(WEBRTC_ANDROID)
-#define MAYBE_AddCodecChangePayloadType DISABLED_AddCodecChangePayloadType
-#else
-#define MAYBE_AddCodecChangePayloadType AddCodecChangePayloadType
-#endif
-TEST_F(AcmReceiverTestOldApi, MAYBE_AddCodecChangePayloadType) {
-  const SdpAudioFormat format("giraffe", 8000, 1);
-
-  // Register the same codec with different payloads.
-  EXPECT_EQ(true, receiver_->AddCodec(17, format));
-  EXPECT_EQ(true, receiver_->AddCodec(18, format));
-
-  // Both payload types should exist.
-  EXPECT_EQ(absl::make_optional(format), receiver_->DecoderByPayloadType(17));
-  EXPECT_EQ(absl::make_optional(format), receiver_->DecoderByPayloadType(18));
-}
-
-#if defined(WEBRTC_ANDROID)
-#define MAYBE_AddCodecChangeCodecId DISABLED_AddCodecChangeCodecId
-#else
-#define MAYBE_AddCodecChangeCodecId AddCodecChangeCodecId
-#endif
-TEST_F(AcmReceiverTestOldApi, AddCodecChangeCodecId) {
-  const SdpAudioFormat format1("giraffe", 8000, 1);
-  const SdpAudioFormat format2("gnu", 16000, 1);
-
-  // Register the same payload type with different codec ID.
-  EXPECT_EQ(true, receiver_->AddCodec(17, format1));
-  EXPECT_EQ(true, receiver_->AddCodec(17, format2));
-
-  // Make sure that the last codec is used.
-  EXPECT_EQ(absl::make_optional(format2), receiver_->DecoderByPayloadType(17));
-}
-
-#if defined(WEBRTC_ANDROID)
-#define MAYBE_AddCodecRemoveCodec DISABLED_AddCodecRemoveCodec
-#else
-#define MAYBE_AddCodecRemoveCodec AddCodecRemoveCodec
-#endif
-TEST_F(AcmReceiverTestOldApi, MAYBE_AddCodecRemoveCodec) {
-  EXPECT_EQ(true, receiver_->AddCodec(17, SdpAudioFormat("giraffe", 8000, 1)));
-
-  // Remove non-existing codec should not fail. ACM1 legacy.
-  EXPECT_EQ(0, receiver_->RemoveCodec(18));
-
-  // Remove an existing codec.
-  EXPECT_EQ(0, receiver_->RemoveCodec(17));
-
-  // Ask for the removed codec, must fail.
-  EXPECT_EQ(absl::nullopt, receiver_->DecoderByPayloadType(17));
-}
-
-#if defined(WEBRTC_ANDROID)
 #define MAYBE_SampleRate DISABLED_SampleRate
 #else
 #define MAYBE_SampleRate SampleRate
 #endif
 TEST_F(AcmReceiverTestOldApi, MAYBE_SampleRate) {
-  const std::vector<SdpAudioFormat> codecs = {{"ISAC", 16000, 1},
-                                              {"ISAC", 32000, 1}};
-  for (size_t i = 0; i < codecs.size(); ++i) {
-    const int payload_type = rtc::checked_cast<int>(i);
-    EXPECT_EQ(true, receiver_->AddCodec(payload_type, codecs[i]));
-  }
+  const std::map<int, SdpAudioFormat> codecs = {{0, {"ISAC", 16000, 1}},
+                                                {1, {"ISAC", 32000, 1}}};
+  receiver_->SetCodecs(codecs);
 
   constexpr int kOutSampleRateHz = 8000;  // Different than codec sample rate.
   for (size_t i = 0; i < codecs.size(); ++i) {
     const int payload_type = rtc::checked_cast<int>(i);
     const int num_10ms_frames =
-        InsertOnePacketOfSilence(SetEncoder(payload_type, codecs[i]));
+        InsertOnePacketOfSilence(SetEncoder(payload_type, codecs.at(i)));
     for (int k = 0; k < num_10ms_frames; ++k) {
       AudioFrame frame;
       bool muted;
       EXPECT_EQ(0, receiver_->GetAudio(kOutSampleRateHz, &frame, &muted));
     }
-    EXPECT_EQ(encoder_factory_->QueryAudioEncoder(codecs[i])->sample_rate_hz,
+    EXPECT_EQ(encoder_factory_->QueryAudioEncoder(codecs.at(i))->sample_rate_hz,
               receiver_->last_output_sample_rate_hz());
   }
 }
@@ -278,7 +182,7 @@
     EXPECT_TRUE(config_.neteq_config.for_test_no_time_stretching);
 
     constexpr int payload_type = 17;
-    EXPECT_TRUE(receiver_->AddCodec(payload_type, codec));
+    receiver_->SetCodecs({{payload_type, codec}});
 
     const AudioCodecInfo info = SetEncoder(payload_type, codec);
     const int output_sample_rate_hz = info.sample_rate_hz;
@@ -356,7 +260,7 @@
   constexpr int payload_type = 34;
   const SdpAudioFormat codec = {"L16", 16000, 1};
   const AudioCodecInfo info = SetEncoder(payload_type, codec);
-  EXPECT_TRUE(receiver_->AddCodec(payload_type, codec));
+  receiver_->SetCodecs({{payload_type, codec}});
   constexpr int kNumPackets = 5;
   AudioFrame frame;
   for (int n = 0; n < kNumPackets; ++n) {
@@ -387,7 +291,7 @@
   const SdpAudioFormat codec = {"L16", 16000, 1};
   const AudioCodecInfo info = SetEncoder(payload_type, codec);
   encoder_factory_->QueryAudioEncoder(codec).value();
-  EXPECT_TRUE(receiver_->AddCodec(payload_type, codec));
+  receiver_->SetCodecs({{payload_type, codec}});
   const int kNumPackets = 5;
   AudioFrame frame;
   for (int n = 0; n < kNumPackets; ++n) {
@@ -407,43 +311,43 @@
 #endif
 #if defined(WEBRTC_CODEC_ISAC)
 TEST_F(AcmReceiverTestOldApi, MAYBE_LastAudioCodec) {
-  const std::vector<SdpAudioFormat> codecs = {{"ISAC", 16000, 1},
-                                              {"PCMA", 8000, 1},
-                                              {"ISAC", 32000, 1},
-                                              {"L16", 32000, 1}};
-  for (size_t i = 0; i < codecs.size(); ++i) {
-    const int payload_type = rtc::checked_cast<int>(i);
-    EXPECT_TRUE(receiver_->AddCodec(payload_type, codecs[i]));
-  }
-
-  const std::map<int, int> cng_payload_types = {
-      {8000, 100}, {16000, 101}, {32000, 102}};
-  for (const auto& x : cng_payload_types) {
-    const int sample_rate_hz = x.first;
-    const int payload_type = x.second;
-    EXPECT_TRUE(receiver_->AddCodec(payload_type, {"CN", sample_rate_hz, 1}));
+  const std::map<int, SdpAudioFormat> codecs = {{0, {"ISAC", 16000, 1}},
+                                                {1, {"PCMA", 8000, 1}},
+                                                {2, {"ISAC", 32000, 1}},
+                                                {3, {"L16", 32000, 1}}};
+  const std::map<int, int> cng_payload_types = {{8000, 100},
+                                                {16000, 101},
+                                                {32000, 102}};
+  {
+    std::map<int, SdpAudioFormat> receive_codecs = codecs;
+    for (const auto& cng_type : cng_payload_types) {
+      receive_codecs.emplace(
+          std::make_pair(cng_type.second, SdpAudioFormat("CN", cng_type.first, 1)));
+    }
+    receiver_->SetCodecs(receive_codecs);
   }
 
   // No audio payload is received.
-  EXPECT_EQ(absl::nullopt, receiver_->LastAudioFormat());
+  EXPECT_EQ(absl::nullopt, receiver_->LastDecoder());
 
   // Start with sending DTX.
   packet_sent_ = false;
   InsertOnePacketOfSilence(
-      SetEncoder(0, codecs[0], cng_payload_types));  // Enough to test
+      SetEncoder(0, codecs.at(0), cng_payload_types));  // Enough to test
                                                      // with one codec.
   ASSERT_TRUE(packet_sent_);
   EXPECT_EQ(kAudioFrameCN, last_frame_type_);
 
   // Has received, only, DTX. Last Audio codec is undefined.
-  EXPECT_EQ(absl::nullopt, receiver_->LastAudioFormat());
-  EXPECT_FALSE(receiver_->last_packet_sample_rate_hz());
+  EXPECT_EQ(absl::nullopt, receiver_->LastDecoder());
+  EXPECT_EQ(absl::nullopt, receiver_->last_packet_sample_rate_hz());
 
   for (size_t i = 0; i < codecs.size(); ++i) {
     // Set DTX off to send audio payload.
     packet_sent_ = false;
     const int payload_type = rtc::checked_cast<int>(i);
-    const AudioCodecInfo info_without_cng = SetEncoder(payload_type, codecs[i]);
+    const AudioCodecInfo info_without_cng =
+        SetEncoder(payload_type, codecs.at(i));
     InsertOnePacketOfSilence(info_without_cng);
 
     // Sanity check if Actually an audio payload received, and it should be
@@ -456,7 +360,7 @@
     // Set VAD on to send DTX. Then check if the "Last Audio codec" returns
     // the expected codec. Encode repeatedly until a DTX is sent.
     const AudioCodecInfo info_with_cng =
-        SetEncoder(payload_type, codecs[i], cng_payload_types);
+        SetEncoder(payload_type, codecs.at(i), cng_payload_types);
     while (last_frame_type_ != kAudioFrameCN) {
       packet_sent_ = false;
       InsertOnePacketOfSilence(info_with_cng);
@@ -464,7 +368,7 @@
     }
     EXPECT_EQ(info_with_cng.sample_rate_hz,
               receiver_->last_packet_sample_rate_hz());
-    EXPECT_EQ(codecs[i], receiver_->LastAudioFormat());
+    EXPECT_EQ(codecs.at(i), receiver_->LastDecoder()->second);
   }
 }
 #endif
diff --git a/modules/audio_coding/acm2/acm_send_test.cc b/modules/audio_coding/acm2/acm_send_test.cc
index c5e010c..b6110b6 100644
--- a/modules/audio_coding/acm2/acm_send_test.cc
+++ b/modules/audio_coding/acm2/acm_send_test.cc
@@ -14,15 +14,15 @@
 #include <stdio.h>
 #include <string.h>
 
+#include "absl/strings/match.h"
 #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 "rtc_base/string_encode.h"
 #include "test/gtest.h"
 
 namespace webrtc {
@@ -59,23 +59,28 @@
 AcmSendTestOldApi::~AcmSendTestOldApi() = default;
 
 bool AcmSendTestOldApi::RegisterCodec(const char* payload_name,
-                                      int sampling_freq_hz,
-                                      int channels,
+                                      int clockrate_hz,
+                                      int num_channels,
                                       int payload_type,
                                       int frame_size_samples) {
-  CodecInst codec;
-  RTC_CHECK_EQ(0, AudioCodingModule::Codec(payload_name, &codec,
-                                           sampling_freq_hz, channels));
-  codec.pltype = payload_type;
-  codec.pacsize = frame_size_samples;
-  auto factory = CreateBuiltinAudioEncoderFactory();
-  SdpAudioFormat format = CodecInstToSdp(codec);
+  SdpAudioFormat format(payload_name, clockrate_hz, num_channels);
+  if (absl::EqualsIgnoreCase(payload_name, "g722")) {
+    RTC_CHECK_EQ(16000, clockrate_hz);
+    format.clockrate_hz = 8000;
+  } else if (absl::EqualsIgnoreCase(payload_name, "opus")) {
+    RTC_CHECK(num_channels == 1 || num_channels == 2);
+    if (num_channels == 2) {
+      format.parameters["stereo"] = "1";
+    }
+    format.num_channels = 2;
+  }
   format.parameters["ptime"] = rtc::ToString(rtc::CheckedDivExact(
-      frame_size_samples, rtc::CheckedDivExact(sampling_freq_hz, 1000)));
+      frame_size_samples, rtc::CheckedDivExact(clockrate_hz, 1000)));
+  auto factory = CreateBuiltinAudioEncoderFactory();
   acm_->SetEncoder(
       factory->MakeAudioEncoder(payload_type, format, absl::nullopt));
   codec_registered_ = true;
-  input_frame_.num_channels_ = channels;
+  input_frame_.num_channels_ = num_channels;
   assert(input_block_size_samples_ * input_frame_.num_channels_ <=
          AudioFrame::kMaxDataSizeSamples);
   return codec_registered_;
@@ -101,13 +106,9 @@
   // Insert audio and process until one packet is produced.
   while (clock_.TimeInMilliseconds() < test_duration_ms_) {
     clock_.AdvanceTimeMilliseconds(kBlockSizeMs);
-    RTC_CHECK(audio_source_->Read(input_block_size_samples_,
-                                  input_frame_.mutable_data()));
-    if (input_frame_.num_channels_ > 1) {
-      InputAudioFile::DuplicateInterleaved(
-          input_frame_.data(), input_block_size_samples_,
-          input_frame_.num_channels_, input_frame_.mutable_data());
-    }
+    RTC_CHECK(audio_source_->Read(
+        input_block_size_samples_ * input_frame_.num_channels_,
+        input_frame_.mutable_data()));
     data_to_send_ = false;
     RTC_CHECK_GE(acm_->Add10MsData(input_frame_), 0);
     input_frame_.timestamp_ += static_cast<uint32_t>(input_block_size_samples_);
diff --git a/modules/audio_coding/acm2/acm_send_test.h b/modules/audio_coding/acm2/acm_send_test.h
index 3479de0..24d230b 100644
--- a/modules/audio_coding/acm2/acm_send_test.h
+++ b/modules/audio_coding/acm2/acm_send_test.h
@@ -17,7 +17,7 @@
 #include "api/audio/audio_frame.h"
 #include "modules/audio_coding/include/audio_coding_module.h"
 #include "modules/audio_coding/neteq/tools/packet_source.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 #include "system_wrappers/include/clock.h"
 
 namespace webrtc {
diff --git a/modules/audio_coding/acm2/audio_coding_module.cc b/modules/audio_coding/acm2/audio_coding_module.cc
index c0aab3a..1547b37 100644
--- a/modules/audio_coding/acm2/audio_coding_module.cc
+++ b/modules/audio_coding/acm2/audio_coding_module.cc
@@ -18,12 +18,11 @@
 #include "api/array_view.h"
 #include "modules/audio_coding/acm2/acm_receiver.h"
 #include "modules/audio_coding/acm2/acm_resampler.h"
-#include "modules/audio_coding/acm2/rent_a_codec.h"
 #include "modules/include/module_common_types.h"
 #include "modules/include/module_common_types_public.h"
 #include "rtc_base/buffer.h"
 #include "rtc_base/checks.h"
-#include "rtc_base/criticalsection.h"
+#include "rtc_base/critical_section.h"
 #include "rtc_base/logging.h"
 #include "rtc_base/numerics/safe_conversions.h"
 #include "rtc_base/thread_annotations.h"
@@ -45,9 +44,6 @@
   void ModifyEncoder(rtc::FunctionView<void(std::unique_ptr<AudioEncoder>*)>
                          modifier) override;
 
-  // Get current send codec.
-  absl::optional<CodecInst> SendCodec() 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.
@@ -90,24 +86,13 @@
 
   void SetReceiveCodecs(const std::map<int, SdpAudioFormat>& codecs) override;
 
-  bool RegisterReceiveCodec(int rtp_payload_type,
-                            const SdpAudioFormat& audio_format) override;
-
-  int RegisterExternalReceiveCodec(int rtp_payload_type,
-                                   AudioDecoder* external_decoder,
-                                   int sample_rate_hz,
-                                   int num_channels,
-                                   const std::string& name) override;
-
   // Get current received codec.
-  int ReceiveCodec(CodecInst* current_codec) const override;
-
-  absl::optional<SdpAudioFormat> ReceiveFormat() const override;
+  absl::optional<std::pair<int, SdpAudioFormat>> ReceiveCodec() const override;
 
   // Incoming packet from network parsed and ready for decode.
   int IncomingPacket(const uint8_t* incoming_payload,
                      const size_t payload_length,
-                     const WebRtcRTPHeader& rtp_info) override;
+                     const RTPHeader& rtp_info) override;
 
   // Minimum playout delay.
   int SetMinimumPlayoutDelay(int time_ms) override;
@@ -115,6 +100,10 @@
   // Maximum playout delay.
   int SetMaximumPlayoutDelay(int time_ms) override;
 
+  bool SetBaseMinimumPlayoutDelayMs(int delay_ms) override;
+
+  int GetBaseMinimumPlayoutDelayMs() const override;
+
   absl::optional<uint32_t> PlayoutTimestamp() override;
 
   int FilteredCurrentDelayMs() const override;
@@ -141,8 +130,6 @@
 
   int DisableOpusDtx() override;
 
-  int UnregisterReceiveCodec(uint8_t payload_type) override;
-
   int EnableNack(size_t max_nack_list_size) override;
 
   void DisableNack() override;
@@ -317,42 +304,6 @@
   }
 }
 
-// Wraps a raw AudioEncoder pointer. The idea is that you can put one of these
-// in a unique_ptr, to protect the contained raw pointer from being deleted
-// when the unique_ptr expires. (This is of course a bad idea in general, but
-// backwards compatibility.)
-class RawAudioEncoderWrapper final : public AudioEncoder {
- public:
-  RawAudioEncoderWrapper(AudioEncoder* enc) : enc_(enc) {}
-  int SampleRateHz() const override { return enc_->SampleRateHz(); }
-  size_t NumChannels() const override { return enc_->NumChannels(); }
-  int RtpTimestampRateHz() const override { return enc_->RtpTimestampRateHz(); }
-  size_t Num10MsFramesInNextPacket() const override {
-    return enc_->Num10MsFramesInNextPacket();
-  }
-  size_t Max10MsFramesInAPacket() const override {
-    return enc_->Max10MsFramesInAPacket();
-  }
-  int GetTargetBitrate() const override { return enc_->GetTargetBitrate(); }
-  EncodedInfo EncodeImpl(uint32_t rtp_timestamp,
-                         rtc::ArrayView<const int16_t> audio,
-                         rtc::Buffer* encoded) override {
-    return enc_->Encode(rtp_timestamp, audio, encoded);
-  }
-  void Reset() override { return enc_->Reset(); }
-  bool SetFec(bool enable) override { return enc_->SetFec(enable); }
-  bool SetDtx(bool enable) override { return enc_->SetDtx(enable); }
-  bool SetApplication(Application application) override {
-    return enc_->SetApplication(application);
-  }
-  void SetMaxPlaybackRate(int frequency_hz) override {
-    return enc_->SetMaxPlaybackRate(frequency_hz);
-  }
-
- private:
-  AudioEncoder* enc_;
-};
-
 void AudioCodingModuleImpl::ChangeLogger::MaybeLog(int value) {
   if (value != last_value_ || first_time_) {
     first_time_ = false;
@@ -480,26 +431,6 @@
   modifier(&encoder_stack_);
 }
 
-// Get current send codec.
-absl::optional<CodecInst> AudioCodingModuleImpl::SendCodec() const {
-  rtc::CritScope lock(&acm_crit_sect_);
-  if (encoder_stack_) {
-    CodecInst ci;
-    ci.channels = encoder_stack_->NumChannels();
-    ci.plfreq = encoder_stack_->SampleRateHz();
-    ci.pacsize = rtc::CheckedDivExact(
-        static_cast<int>(encoder_stack_->Max10MsFramesInAPacket() * ci.plfreq),
-        100);
-    ci.pltype = -1;  // Not valid.
-    ci.rate = -1;    // Not valid.
-    static const char kName[] = "external";
-    memcpy(ci.plname, kName, sizeof(kName));
-    return ci;
-  } else {
-    return absl::nullopt;
-  }
-}
-
 void AudioCodingModuleImpl::SetBitRate(int bitrate_bps) {
   rtc::CritScope lock(&acm_crit_sect_);
   if (encoder_stack_) {
@@ -546,7 +477,9 @@
     return -1;
   }
 
-  if (audio_frame.num_channels_ != 1 && audio_frame.num_channels_ != 2) {
+  if (audio_frame.num_channels_ != 1 && audio_frame.num_channels_ != 2 &&
+      audio_frame.num_channels_ != 4 && audio_frame.num_channels_ != 6 &&
+      audio_frame.num_channels_ != 8) {
     RTC_LOG(LS_ERROR) << "Cannot Add 10 ms audio, invalid number of channels.";
     return -1;
   }
@@ -721,9 +654,6 @@
   // start-up.
   if (receiver_initialized_)
     receiver_.RemoveAllCodecs();
-  receiver_.ResetInitialDelay();
-  receiver_.SetMinimumDelay(0);
-  receiver_.SetMaximumDelay(0);
   receiver_.FlushBuffers();
 
   receiver_initialized_ = true;
@@ -748,60 +678,16 @@
   receiver_.SetCodecs(codecs);
 }
 
-bool AudioCodingModuleImpl::RegisterReceiveCodec(
-    int rtp_payload_type,
-    const SdpAudioFormat& audio_format) {
+absl::optional<std::pair<int, SdpAudioFormat>>
+    AudioCodingModuleImpl::ReceiveCodec() const {
   rtc::CritScope lock(&acm_crit_sect_);
-  RTC_DCHECK(receiver_initialized_);
-
-  if (!acm2::RentACodec::IsPayloadTypeValid(rtp_payload_type)) {
-    RTC_LOG_F(LS_ERROR) << "Invalid payload-type " << rtp_payload_type
-                        << " for decoder.";
-    return false;
-  }
-
-  return receiver_.AddCodec(rtp_payload_type, audio_format);
-}
-
-int AudioCodingModuleImpl::RegisterExternalReceiveCodec(
-    int rtp_payload_type,
-    AudioDecoder* external_decoder,
-    int sample_rate_hz,
-    int num_channels,
-    const std::string& name) {
-  rtc::CritScope lock(&acm_crit_sect_);
-  RTC_DCHECK(receiver_initialized_);
-  if (num_channels > 2 || num_channels < 0) {
-    RTC_LOG_F(LS_ERROR) << "Unsupported number of channels: " << num_channels;
-    return -1;
-  }
-
-  // Check if the payload-type is valid.
-  if (!acm2::RentACodec::IsPayloadTypeValid(rtp_payload_type)) {
-    RTC_LOG_F(LS_ERROR) << "Invalid payload-type " << rtp_payload_type
-                        << " for external decoder.";
-    return -1;
-  }
-
-  return receiver_.AddCodec(-1 /* external */, rtp_payload_type, num_channels,
-                            sample_rate_hz, external_decoder, name);
-}
-
-// Get current received codec.
-int AudioCodingModuleImpl::ReceiveCodec(CodecInst* current_codec) const {
-  rtc::CritScope lock(&acm_crit_sect_);
-  return receiver_.LastAudioCodec(current_codec);
-}
-
-absl::optional<SdpAudioFormat> AudioCodingModuleImpl::ReceiveFormat() const {
-  rtc::CritScope lock(&acm_crit_sect_);
-  return receiver_.LastAudioFormat();
+  return receiver_.LastDecoder();
 }
 
 // Incoming packet from network parsed and ready for decode.
 int AudioCodingModuleImpl::IncomingPacket(const uint8_t* incoming_payload,
                                           const size_t payload_length,
-                                          const WebRtcRTPHeader& rtp_header) {
+                                          const RTPHeader& rtp_header) {
   RTC_DCHECK_EQ(payload_length == 0, incoming_payload == nullptr);
   return receiver_.InsertPacket(
       rtp_header,
@@ -825,6 +711,15 @@
   return receiver_.SetMaximumDelay(time_ms);
 }
 
+bool AudioCodingModuleImpl::SetBaseMinimumPlayoutDelayMs(int delay_ms) {
+  // All necessary validation happens on NetEq level.
+  return receiver_.SetBaseMinimumDelayMs(delay_ms);
+}
+
+int AudioCodingModuleImpl::GetBaseMinimumPlayoutDelayMs() const {
+  return receiver_.GetBaseMinimumDelayMs();
+}
+
 // Get 10 milliseconds of raw audio data to play out.
 // Automatic resample to the requested frequency.
 int AudioCodingModuleImpl::PlayoutData10Ms(int desired_freq_hz,
@@ -902,10 +797,6 @@
   return true;
 }
 
-int AudioCodingModuleImpl::UnregisterReceiveCodec(uint8_t payload_type) {
-  return receiver_.RemoveCodec(payload_type);
-}
-
 int AudioCodingModuleImpl::EnableNack(size_t max_nack_list_size) {
   return receiver_.EnableNack(max_nack_list_size);
 }
@@ -951,52 +842,4 @@
   return new AudioCodingModuleImpl(config);
 }
 
-int AudioCodingModule::NumberOfCodecs() {
-  return static_cast<int>(acm2::RentACodec::NumberOfCodecs());
-}
-
-int AudioCodingModule::Codec(int list_id, CodecInst* codec) {
-  auto codec_id = acm2::RentACodec::CodecIdFromIndex(list_id);
-  if (!codec_id)
-    return -1;
-  auto ci = acm2::RentACodec::CodecInstById(*codec_id);
-  if (!ci)
-    return -1;
-  *codec = *ci;
-  return 0;
-}
-
-int AudioCodingModule::Codec(const char* payload_name,
-                             CodecInst* codec,
-                             int sampling_freq_hz,
-                             size_t channels) {
-  absl::optional<CodecInst> ci = acm2::RentACodec::CodecInstByParams(
-      payload_name, sampling_freq_hz, channels);
-  if (ci) {
-    *codec = *ci;
-    return 0;
-  } else {
-    // We couldn't find a matching codec, so set the parameters to unacceptable
-    // values and return.
-    codec->plname[0] = '\0';
-    codec->pltype = -1;
-    codec->pacsize = 0;
-    codec->rate = 0;
-    codec->plfreq = 0;
-    return -1;
-  }
-}
-
-int AudioCodingModule::Codec(const char* payload_name,
-                             int sampling_freq_hz,
-                             size_t channels) {
-  absl::optional<acm2::RentACodec::CodecId> ci =
-      acm2::RentACodec::CodecIdByParams(payload_name, sampling_freq_hz,
-                                        channels);
-  if (!ci)
-    return -1;
-  absl::optional<int> i = acm2::RentACodec::CodecIndexFromId(*ci);
-  return i ? *i : -1;
-}
-
 }  // 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 4e262f7..4ee9add 100644
--- a/modules/audio_coding/acm2/audio_coding_module_unittest.cc
+++ b/modules/audio_coding/acm2/audio_coding_module_unittest.cc
@@ -13,17 +13,20 @@
 #include <memory>
 #include <vector>
 
+#include "absl/memory/memory.h"
 #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 "api/audio_codecs/opus/audio_decoder_opus.h"
 #include "api/audio_codecs/opus/audio_encoder_opus.h"
 #include "modules/audio_coding/acm2/acm_receive_test.h"
 #include "modules/audio_coding/acm2/acm_send_test.h"
-#include "modules/audio_coding/codecs/audio_format_conversion.h"
 #include "modules/audio_coding/codecs/cng/audio_encoder_cng.h"
 #include "modules/audio_coding/codecs/g711/audio_decoder_pcm.h"
 #include "modules/audio_coding/codecs/g711/audio_encoder_pcm.h"
 #include "modules/audio_coding/codecs/isac/main/include/audio_encoder_isac.h"
+#include "modules/audio_coding/codecs/opus/audio_decoder_opus.h"
+#include "modules/audio_coding/codecs/opus/audio_encoder_opus.h"
 #include "modules/audio_coding/include/audio_coding_module.h"
 #include "modules/audio_coding/include/audio_coding_module_typedefs.h"
 #include "modules/audio_coding/neteq/tools/audio_checksum.h"
@@ -34,20 +37,21 @@
 #include "modules/audio_coding/neteq/tools/output_wav_file.h"
 #include "modules/audio_coding/neteq/tools/packet.h"
 #include "modules/audio_coding/neteq/tools/rtp_file_source.h"
-#include "rtc_base/criticalsection.h"
+#include "rtc_base/critical_section.h"
 #include "rtc_base/event.h"
-#include "rtc_base/messagedigest.h"
+#include "rtc_base/message_digest.h"
 #include "rtc_base/numerics/safe_conversions.h"
 #include "rtc_base/platform_thread.h"
-#include "rtc_base/refcountedobject.h"
+#include "rtc_base/ref_counted_object.h"
 #include "rtc_base/system/arch.h"
 #include "rtc_base/thread_annotations.h"
 #include "system_wrappers/include/clock.h"
 #include "system_wrappers/include/sleep.h"
+#include "test/audio_decoder_proxy_factory.h"
 #include "test/gtest.h"
 #include "test/mock_audio_decoder.h"
 #include "test/mock_audio_encoder.h"
-#include "test/testsupport/fileutils.h"
+#include "test/testsupport/file_utils.h"
 
 using ::testing::AtLeast;
 using ::testing::Invoke;
@@ -71,21 +75,20 @@
 
   virtual ~RtpUtility() {}
 
-  void Populate(WebRtcRTPHeader* rtp_header) {
-    rtp_header->header.sequenceNumber = 0xABCD;
-    rtp_header->header.timestamp = 0xABCDEF01;
-    rtp_header->header.payloadType = payload_type_;
-    rtp_header->header.markerBit = false;
-    rtp_header->header.ssrc = 0x1234;
-    rtp_header->header.numCSRCs = 0;
-    rtp_header->frameType = kAudioFrameSpeech;
+  void Populate(RTPHeader* rtp_header) {
+    rtp_header->sequenceNumber = 0xABCD;
+    rtp_header->timestamp = 0xABCDEF01;
+    rtp_header->payloadType = payload_type_;
+    rtp_header->markerBit = false;
+    rtp_header->ssrc = 0x1234;
+    rtp_header->numCSRCs = 0;
 
-    rtp_header->header.payload_type_frequency = kSampleRateHz;
+    rtp_header->payload_type_frequency = kSampleRateHz;
   }
 
-  void Forward(WebRtcRTPHeader* rtp_header) {
-    ++rtp_header->header.sequenceNumber;
-    rtp_header->header.timestamp += samples_per_packet_;
+  void Forward(RTPHeader* rtp_header) {
+    ++rtp_header->sequenceNumber;
+    rtp_header->timestamp += samples_per_packet_;
   }
 
  private:
@@ -190,12 +193,11 @@
   // Set up L16 codec.
   virtual void SetUpL16Codec() {
     audio_format_ = SdpAudioFormat("L16", kSampleRateHz, 1);
-    ASSERT_EQ(0, AudioCodingModule::Codec("L16", &codec_, kSampleRateHz, 1));
-    codec_.pltype = kPayloadType;
+    pac_size_ = 160;
   }
 
   virtual void RegisterCodec() {
-    EXPECT_EQ(true, acm_->RegisterReceiveCodec(kPayloadType, *audio_format_));
+    acm_->SetReceiveCodecs({{kPayloadType, *audio_format_}});
     acm_->SetEncoder(CreateBuiltinAudioEncoderFactory()->MakeAudioEncoder(
         kPayloadType, *audio_format_, absl::nullopt));
   }
@@ -226,7 +228,7 @@
 
   virtual void VerifyEncoding() {
     int last_length = packet_cb_.last_payload_len_bytes();
-    EXPECT_TRUE(last_length == 2 * codec_.pacsize || last_length == 0)
+    EXPECT_TRUE(last_length == 2 * pac_size_ || last_length == 0)
         << "Last encoded packet was " << last_length << " bytes.";
   }
 
@@ -238,13 +240,11 @@
   std::unique_ptr<RtpUtility> rtp_utility_;
   std::unique_ptr<AudioCodingModule> acm_;
   PacketizationCallbackStubOldApi packet_cb_;
-  WebRtcRTPHeader rtp_header_;
+  RTPHeader rtp_header_;
   AudioFrame input_frame_;
 
-  // These two have to be kept in sync for now. In the future, we'll be able to
-  // eliminate the CodecInst and keep only the SdpAudioFormat.
   absl::optional<SdpAudioFormat> audio_format_;
-  CodecInst codec_;
+  int pac_size_ = -1;
 
   Clock* clock_;
 };
@@ -343,7 +343,7 @@
 // Also checks that the frame type is kAudioFrameSpeech.
 TEST_F(AudioCodingModuleTestOldApi, TransportCallbackIsInvokedForEachPacket) {
   const int k10MsBlocksPerPacket = 3;
-  codec_.pacsize = k10MsBlocksPerPacket * kSampleRateHz / 100;
+  pac_size_ = k10MsBlocksPerPacket * kSampleRateHz / 100;
   audio_format_->parameters["ptime"] = "30";
   RegisterCodec();
   const int kLoops = 10;
@@ -363,7 +363,7 @@
 TEST_F(AudioCodingModuleTestOldApi, TimestampSeriesContinuesWhenCodecChanges) {
   RegisterCodec();  // This registers the default codec.
   uint32_t expected_ts = input_frame_.timestamp_;
-  int blocks_per_packet = codec_.pacsize / (kSampleRateHz / 100);
+  int blocks_per_packet = pac_size_ / (kSampleRateHz / 100);
   // Encode 5 packets of the first codec type.
   const int kNumPackets1 = 5;
   for (int j = 0; j < kNumPackets1; ++j) {
@@ -373,14 +373,14 @@
     }
     EXPECT_EQ(j + 1, packet_cb_.num_calls());
     EXPECT_EQ(expected_ts, packet_cb_.last_timestamp());
-    expected_ts += codec_.pacsize;
+    expected_ts += pac_size_;
   }
 
   // Change codec.
-  ASSERT_EQ(0, AudioCodingModule::Codec("ISAC", &codec_, kSampleRateHz, 1));
   audio_format_ = SdpAudioFormat("ISAC", kSampleRateHz, 1);
+  pac_size_ = 480;
   RegisterCodec();
-  blocks_per_packet = codec_.pacsize / (kSampleRateHz / 100);
+  blocks_per_packet = pac_size_ / (kSampleRateHz / 100);
   // Encode another 5 packets.
   const int kNumPackets2 = 5;
   for (int j = 0; j < kNumPackets2; ++j) {
@@ -390,7 +390,7 @@
     }
     EXPECT_EQ(kNumPackets1 + j + 1, packet_cb_.num_calls());
     EXPECT_EQ(expected_ts, packet_cb_.last_timestamp());
-    expected_ts += codec_.pacsize;
+    expected_ts += pac_size_;
   }
 }
 #endif
@@ -404,9 +404,8 @@
     : public AudioCodingModuleTestOldApi {
  protected:
   void RegisterCngCodec(int rtp_payload_type) {
-    EXPECT_EQ(true,
-              acm_->RegisterReceiveCodec(
-                  rtp_payload_type, SdpAudioFormat("cn", kSampleRateHz, 1)));
+    acm_->SetReceiveCodecs({{kPayloadType, *audio_format_},
+                            {rtp_payload_type, {"cn", kSampleRateHz, 1}}});
     acm_->ModifyEncoder([&](std::unique_ptr<AudioEncoder>* enc) {
       AudioEncoderCngConfig config;
       config.speech_encoder = std::move(*enc);
@@ -461,7 +460,7 @@
 TEST_F(AudioCodingModuleTestWithComfortNoiseOldApi,
        TransportCallbackTestForComfortNoiseRegisterCngLast) {
   const int k10MsBlocksPerPacket = 3;
-  codec_.pacsize = k10MsBlocksPerPacket * kSampleRateHz / 100;
+  pac_size_ = k10MsBlocksPerPacket * kSampleRateHz / 100;
   audio_format_->parameters["ptime"] = "30";
   RegisterCodec();
   const int kCngPayloadType = 105;
@@ -650,12 +649,11 @@
   void RegisterCodec() override {
     static_assert(kSampleRateHz == 16000, "test designed for iSAC 16 kHz");
     audio_format_ = SdpAudioFormat("isac", kSampleRateHz, 1);
-    AudioCodingModule::Codec("ISAC", &codec_, kSampleRateHz, 1);
-    codec_.pltype = kPayloadType;
+    pac_size_ = 480;
 
     // Register iSAC codec in ACM, effectively unregistering the PCM16B codec
     // registered in AudioCodingModuleTestOldApi::SetUp();
-    EXPECT_EQ(true, acm_->RegisterReceiveCodec(kPayloadType, *audio_format_));
+    acm_->SetReceiveCodecs({{kPayloadType, *audio_format_}});
     acm_->SetEncoder(CreateBuiltinAudioEncoderFactory()->MakeAudioEncoder(
         kPayloadType, *audio_format_, absl::nullopt));
   }
@@ -755,15 +753,11 @@
   }
 
   void RegisterCodec() override {
-    static_assert(kSampleRateHz == 16000, "test designed for iSAC 16 kHz");
-    AudioCodingModule::Codec("ISAC", &codec_, kSampleRateHz, 1);
-    codec_.pltype = kPayloadType;
-
     // Register iSAC codec in ACM, effectively unregistering the PCM16B codec
     // registered in AudioCodingModuleTestOldApi::SetUp();
     // Only register the decoder for now. The encoder is registered later.
-    ASSERT_EQ(true, acm_->RegisterReceiveCodec(codec_.pltype,
-                                               CodecInstToSdp(codec_)));
+    static_assert(kSampleRateHz == 16000, "test designed for iSAC 16 kHz");
+    acm_->SetReceiveCodecs({{kPayloadType, {"ISAC", kSampleRateHz, 1}}});
   }
 
   void StartThreads() {
@@ -801,16 +795,15 @@
       ++receive_packet_count_;
 
       // Encode new frame.
-      uint32_t input_timestamp = rtp_header_.header.timestamp;
+      uint32_t input_timestamp = rtp_header_.timestamp;
       while (info.encoded_bytes == 0) {
         info = isac_encoder_->Encode(input_timestamp,
                                      audio_loop_.GetNextBlock(), &encoded);
         input_timestamp += 160;  // 10 ms at 16 kHz.
       }
-      EXPECT_EQ(rtp_header_.header.timestamp + kPacketSizeSamples,
-                input_timestamp);
-      EXPECT_EQ(rtp_header_.header.timestamp, info.encoded_timestamp);
-      EXPECT_EQ(rtp_header_.header.payloadType, info.payload_type);
+      EXPECT_EQ(rtp_header_.timestamp + kPacketSizeSamples, input_timestamp);
+      EXPECT_EQ(rtp_header_.timestamp, info.encoded_timestamp);
+      EXPECT_EQ(rtp_header_.payloadType, info.payload_type);
     }
     // Now we're not holding the crit sect when calling ACM.
 
@@ -946,7 +939,7 @@
             ->test_case_name() +
         "_" + ::testing::UnitTest::GetInstance()->current_test_info()->name() +
         "_output.wav";
-    test::OutputWavFile output_file(output_file_name, output_freq_hz);
+    test::OutputWavFile output_file(output_file_name, output_freq_hz, 1);
     test::AudioSinkFork output(&checksum, &output_file);
 
     test::AcmReceiveTestOldApi test(
@@ -968,35 +961,35 @@
 #if (defined(WEBRTC_CODEC_ISAC) || defined(WEBRTC_CODEC_ISACFX)) && \
     defined(WEBRTC_CODEC_ILBC)
 TEST_F(AcmReceiverBitExactnessOldApi, 8kHzOutput) {
-  Run(8000, PlatformChecksum("7294941b62293e143d6d6c84955923fd",
-                             "f26b8c9aa8257c7185925fa5b102f46a",
-                             "65e5ef5c3de9c2abf3c8d0989772e9fc",
+  Run(8000, PlatformChecksum("bcfbe2e89b4317b22e29557168edf187",
+                             "af15addb648cf7f032d6415672365fb3",
+                             "54a0008eb79537dee1d8fdaa5bc29f4b",
                              "4598140b5e4f7ee66c5adad609e65a3e",
-                             "04a1d3e735730b6d7dbd5df10f717d27"));
+                             "3155d7f2593a3276986f36221a61783c"));
 }
 
 TEST_F(AcmReceiverBitExactnessOldApi, 16kHzOutput) {
-  Run(16000, PlatformChecksum("de8143dd3cc23241f1e1d5cf14e04b8a",
-                              "eada3f321120d8d5afffbe4170a55d2f",
-                              "135d8c3c7b92aa13d45cad7c91068e3e",
+  Run(16000, PlatformChecksum("1737deef193e6c90e139ce82b7361ae4",
+                              "9e2a9f7728c71d6559ce3a32d2b10a5d",
+                              "114958862099142ac78b12100c21cb8d",
                               "f2aad418af974a3b1694d5ae5cc2c3c7",
-                              "728b69068332efade35b1a9c32029e1b"));
+                              "af2889a5ca84fb40c9aa209b9318ee7a"));
 }
 
 TEST_F(AcmReceiverBitExactnessOldApi, 32kHzOutput) {
-  Run(32000, PlatformChecksum("521d336237bdcc9ab44050e9da8917fc",
-                              "73d44a7bedb6dfa7c70cf997223d8c10",
-                              "f3ee2f14b03fb8e98f526f82583f84d9",
+  Run(32000, PlatformChecksum("1bf40ff024c6aa5b832d1d242c29cb3b",
+                              "3c9690cd136e9ecd1b26a22f70fe1d5c",
+                              "a1a3a01d8e25fcd11f1cedcd02e968b8",
                               "100869c8dcde51346c2073e52a272d98",
-                              "5f338b4bc38707d0a14d75a357e1546e"));
+                              "33695077e9ec6bca80819ce2ba263a78"));
 }
 
 TEST_F(AcmReceiverBitExactnessOldApi, 48kHzOutput) {
-  Run(48000, PlatformChecksum("5955e31373828969de7fb308fb58a84e",
-                              "83c0eca235b1a806426ff6ca8655cdf7",
-                              "1126a8c03d1ebc6aa7348b9c541e2082",
+  Run(48000, PlatformChecksum("bf92db1e502deff5adf6fd2e6ab9a2e5",
+                              "c37b110ab50d87620972daee5d1eaf31",
+                              "5d55b68be7bcf39b60fcc74519363fb4",
                               "bd44bf97e7899186532f91235cef444d",
-                              "9d092dbc96e7ef6870b78c1056e87315"));
+                              "32eec738698ffe62b9777d6a349cd596"));
 }
 
 TEST_F(AcmReceiverBitExactnessOldApi, 48kHzOutputExternalDecoder) {
@@ -1079,13 +1072,23 @@
   rtc::scoped_refptr<rtc::RefCountedObject<ADFactory>> factory(
       new rtc::RefCountedObject<ADFactory>);
   Run(48000,
-      PlatformChecksum("5955e31373828969de7fb308fb58a84e",
-                       "83c0eca235b1a806426ff6ca8655cdf7",
-                       "1126a8c03d1ebc6aa7348b9c541e2082",
+      PlatformChecksum("bf92db1e502deff5adf6fd2e6ab9a2e5",
+                       "c37b110ab50d87620972daee5d1eaf31",
+                       "5d55b68be7bcf39b60fcc74519363fb4",
                        "bd44bf97e7899186532f91235cef444d",
-                       "9d092dbc96e7ef6870b78c1056e87315"),
+                       "32eec738698ffe62b9777d6a349cd596"),
       factory, [](AudioCodingModule* acm) {
-        acm->RegisterReceiveCodec(0, {"MockPCMu", 8000, 1});
+        acm->SetReceiveCodecs({{0, {"MockPCMu", 8000, 1}},
+                               {103, {"ISAC", 16000, 1}},
+                               {104, {"ISAC", 32000, 1}},
+                               {93, {"L16", 8000, 1}},
+                               {94, {"L16", 16000, 1}},
+                               {95, {"L16", 32000, 1}},
+                               {8, {"PCMA", 8000, 1}},
+                               {102, {"ILBC", 8000, 1}},
+                               {13, {"CN", 8000, 1}},
+                               {98, {"CN", 16000, 1}},
+                               {99, {"CN", 32000, 1}}});
       });
 }
 #endif
@@ -1117,15 +1120,12 @@
 
   // Sets up the test::AcmSendTest object. Returns true on success, otherwise
   // false.
-  bool SetUpSender() {
-    const std::string input_file_name =
-        webrtc::test::ResourcePath("audio_coding/testfile32kHz", "pcm");
+  bool SetUpSender(std::string input_file_name, int source_rate) {
     // Note that |audio_source_| will loop forever. The test duration is set
     // explicitly by |kTestDurationMs|.
     audio_source_.reset(new test::InputAudioFile(input_file_name));
-    static const int kSourceRateHz = 32000;
-    send_test_.reset(new test::AcmSendTestOldApi(
-        audio_source_.get(), kSourceRateHz, kTestDurationMs));
+    send_test_.reset(new test::AcmSendTestOldApi(audio_source_.get(),
+                                                 source_rate, kTestDurationMs));
     return send_test_.get() != NULL;
   }
 
@@ -1158,7 +1158,11 @@
   void Run(const std::string& audio_checksum_ref,
            const std::string& payload_checksum_ref,
            int expected_packets,
-           test::AcmReceiveTestOldApi::NumOutputChannels expected_channels) {
+           test::AcmReceiveTestOldApi::NumOutputChannels expected_channels,
+           rtc::scoped_refptr<AudioDecoderFactory> decoder_factory = nullptr) {
+    if (!decoder_factory) {
+      decoder_factory = CreateBuiltinAudioDecoderFactory();
+    }
     // Set up the receiver used to decode the packets and verify the decoded
     // output.
     test::AudioChecksum audio_checksum;
@@ -1170,12 +1174,12 @@
         "_" + ::testing::UnitTest::GetInstance()->current_test_info()->name() +
         "_output.wav";
     const int kOutputFreqHz = 8000;
-    test::OutputWavFile output_file(output_file_name, kOutputFreqHz);
+    test::OutputWavFile output_file(output_file_name, kOutputFreqHz,
+                                    expected_channels);
     // Have the output audio sent both to file and to the checksum calculator.
     test::AudioSinkFork output(&audio_checksum, &output_file);
     test::AcmReceiveTestOldApi receive_test(this, &output, kOutputFreqHz,
-                                            expected_channels,
-                                            CreateBuiltinAudioDecoderFactory());
+                                            expected_channels, decoder_factory);
     ASSERT_NO_FATAL_FAILURE(receive_test.RegisterDefaultCodecs());
 
     // This is where the actual test is executed.
@@ -1251,7 +1255,8 @@
                  int payload_type,
                  int codec_frame_size_samples,
                  int codec_frame_size_rtp_timestamps) {
-    ASSERT_TRUE(SetUpSender());
+    ASSERT_TRUE(SetUpSender(
+        channels == 1 ? kTestFileMono32kHz : kTestFileFakeStereo32kHz, 32000));
     ASSERT_TRUE(RegisterSendCodec(codec_name, codec_sample_rate_hz, channels,
                                   payload_type, codec_frame_size_samples,
                                   codec_frame_size_rtp_timestamps));
@@ -1260,7 +1265,7 @@
   void SetUpTestExternalEncoder(
       std::unique_ptr<AudioEncoder> external_speech_encoder,
       int payload_type) {
-    ASSERT_TRUE(SetUpSender());
+    ASSERT_TRUE(send_test_);
     RegisterExternalSendCodec(std::move(external_speech_encoder), payload_type);
   }
 
@@ -1272,6 +1277,14 @@
   uint16_t last_sequence_number_;
   uint32_t last_timestamp_;
   std::unique_ptr<rtc::MessageDigest> payload_checksum_;
+  const std::string kTestFileMono32kHz =
+      webrtc::test::ResourcePath("audio_coding/testfile32kHz", "pcm");
+  const std::string kTestFileFakeStereo32kHz =
+      webrtc::test::ResourcePath("audio_coding/testfile_fake_stereo_32kHz",
+                                 "pcm");
+  const std::string kTestFileQuad48kHz = webrtc::test::ResourcePath(
+      "audio_coding/speech_4_channels_48k_one_second",
+      "wav");
 };
 
 class AcmSenderBitExactnessNewApi : public AcmSenderBitExactnessOldApi {};
@@ -1471,7 +1484,7 @@
         "ab88b1a049c36bdfeb7e8b057ef6982a",
         "27fef7b799393347ec3b5694369a1c36",
         "27fef7b799393347ec3b5694369a1c36");
-};  // namespace
+}  // namespace
 
 TEST_F(AcmSenderBitExactnessOldApi, Opus_stereo_20ms) {
   ASSERT_NO_FATAL_FAILURE(SetUpTest("opus", 48000, 2, 120, 960, 960));
@@ -1482,17 +1495,59 @@
 TEST_F(AcmSenderBitExactnessNewApi, MAYBE_OpusFromFormat_stereo_20ms) {
   const auto config = AudioEncoderOpus::SdpToConfig(
       SdpAudioFormat("opus", 48000, 2, {{"stereo", "1"}}));
+  ASSERT_TRUE(SetUpSender(kTestFileFakeStereo32kHz, 32000));
   ASSERT_NO_FATAL_FAILURE(SetUpTestExternalEncoder(
       AudioEncoderOpus::MakeAudioEncoder(*config, 120), 120));
   Run(audio_checksum, payload_checksum, 50,
       test::AcmReceiveTestOldApi::kStereoOutput);
 }
 
+TEST_F(AcmSenderBitExactnessNewApi, OpusManyChannels) {
+  constexpr int kNumChannels = 4;
+  constexpr int kOpusPayloadType = 120;
+  constexpr int kBitrateBps = 128000;
+
+  // Read a 4 channel file at 48kHz.
+  ASSERT_TRUE(SetUpSender(kTestFileQuad48kHz, 48000));
+
+  // TODO(webrtc:8649): change to higher level
+  // AudioEncoderOpus::MakeAudioEncoder once a multistream encoder can be set up
+  // from SDP.
+  AudioEncoderOpusConfig config = *AudioEncoderOpus::SdpToConfig(
+      SdpAudioFormat("opus", 48000, 2, {{"stereo", "1"}}));
+  config.num_channels = kNumChannels;
+  config.bitrate_bps = kBitrateBps;
+
+  ASSERT_NO_FATAL_FAILURE(SetUpTestExternalEncoder(
+      absl::make_unique<AudioEncoderOpusImpl>(config, kOpusPayloadType),
+      kOpusPayloadType));
+
+  AudioDecoderOpusImpl opus_decoder(kNumChannels);
+
+  rtc::scoped_refptr<AudioDecoderFactory> decoder_factory =
+      new rtc::RefCountedObject<test::AudioDecoderProxyFactory>(&opus_decoder);
+
+  // Set up an EXTERNAL DECODER to parse 4 channels.
+  Run(AcmReceiverBitExactnessOldApi::PlatformChecksum(  // audio checksum
+          "b70470884d9a8613eff019b0d1c8876e|d0a73d377e0ca1be6b06e989e0ad2c35",
+          "d0a73d377e0ca1be6b06e989e0ad2c35",
+          "b45d2ce5fc4723e9eb41350af9c68f56", "android arm64 audio checksum",
+          "1c9a3c9dacdd4b8fc9ff608227e531f2"),
+      // payload_checksum,
+      AcmReceiverBitExactnessOldApi::PlatformChecksum(  // payload checksum
+          "c2e7d40f8269ef754bd86d6be9623fa7|76de0f4992e3937ca60d35bbb0d308d6",
+          "76de0f4992e3937ca60d35bbb0d308d6",
+          "2a310aca965c16c2dfd61a9f9fc0c877", "android arm64 payload checksum",
+          "2294f4b61fb8f174f5196776a0a49be7"),
+      50, test::AcmReceiveTestOldApi::kQuadOutput, decoder_factory);
+}
+
 TEST_F(AcmSenderBitExactnessNewApi, OpusFromFormat_stereo_20ms_voip) {
   auto config = AudioEncoderOpus::SdpToConfig(
       SdpAudioFormat("opus", 48000, 2, {{"stereo", "1"}}));
   // If not set, default will be kAudio in case of stereo.
   config->application = AudioEncoderOpusConfig::ApplicationMode::kVoip;
+  ASSERT_TRUE(SetUpSender(kTestFileFakeStereo32kHz, 32000));
   ASSERT_NO_FATAL_FAILURE(SetUpTestExternalEncoder(
       AudioEncoderOpus::MakeAudioEncoder(*config, 120), 120));
   // Checksum depends on libopus being compiled with or without SSE.
@@ -1746,11 +1801,11 @@
 }
 
 TEST_F(AcmSenderBitExactnessOldApi, External_Pcmu_20ms) {
-  CodecInst codec_inst;
-  codec_inst.channels = 1;
-  codec_inst.pacsize = 160;
-  codec_inst.pltype = 0;
-  AudioEncoderPcmU encoder(codec_inst);
+  AudioEncoderPcmU::Config config;
+  config.frame_size_ms = 20;
+  config.num_channels = 1;
+  config.payload_type = 0;
+  AudioEncoderPcmU encoder(config);
   auto mock_encoder = absl::make_unique<MockAudioEncoder>();
   // Set expectations on the mock encoder and also delegate the calls to the
   // real encoder.
@@ -1776,8 +1831,9 @@
           &encoder, static_cast<AudioEncoder::EncodedInfo (AudioEncoder::*)(
                         uint32_t, rtc::ArrayView<const int16_t>, rtc::Buffer*)>(
                         &AudioEncoderPcmU::Encode)));
+  ASSERT_TRUE(SetUpSender(kTestFileMono32kHz, 32000));
   ASSERT_NO_FATAL_FAILURE(
-      SetUpTestExternalEncoder(std::move(mock_encoder), codec_inst.pltype));
+      SetUpTestExternalEncoder(std::move(mock_encoder), config.payload_type));
   Run("81a9d4c0bb72e9becc43aef124c981e9", "8f9b8750bd80fe26b6cbf6659b89f0f9",
       50, test::AcmReceiveTestOldApi::kMonoOutput);
 }
diff --git a/modules/audio_coding/acm2/rent_a_codec.cc b/modules/audio_coding/acm2/rent_a_codec.cc
deleted file mode 100644
index bfddc42b..0000000
--- a/modules/audio_coding/acm2/rent_a_codec.cc
+++ /dev/null
@@ -1,72 +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 "modules/audio_coding/acm2/rent_a_codec.h"
-
-#include <memory>
-#include <utility>
-
-#include "rtc_base/logging.h"
-#include "modules/audio_coding/acm2/acm_codec_database.h"
-
-namespace webrtc {
-namespace acm2 {
-
-absl::optional<RentACodec::CodecId> RentACodec::CodecIdByParams(
-    const char* payload_name,
-    int sampling_freq_hz,
-    size_t channels) {
-  return CodecIdFromIndex(
-      ACMCodecDB::CodecId(payload_name, sampling_freq_hz, channels));
-}
-
-absl::optional<CodecInst> RentACodec::CodecInstById(CodecId codec_id) {
-  absl::optional<int> mi = CodecIndexFromId(codec_id);
-  return mi ? absl::optional<CodecInst>(ACMCodecDB::database_[*mi])
-            : absl::nullopt;
-}
-
-absl::optional<RentACodec::CodecId> RentACodec::CodecIdByInst(
-    const CodecInst& codec_inst) {
-  return CodecIdFromIndex(ACMCodecDB::CodecNumber(codec_inst));
-}
-
-absl::optional<CodecInst> RentACodec::CodecInstByParams(
-    const char* payload_name,
-    int sampling_freq_hz,
-    size_t channels) {
-  absl::optional<CodecId> codec_id =
-      CodecIdByParams(payload_name, sampling_freq_hz, channels);
-  if (!codec_id)
-    return absl::nullopt;
-  absl::optional<CodecInst> ci = CodecInstById(*codec_id);
-  RTC_DCHECK(ci);
-
-  // Keep the number of channels from the function call. For most codecs it
-  // will be the same value as in default codec settings, but not for all.
-  ci->channels = channels;
-
-  return ci;
-}
-
-absl::optional<NetEqDecoder> RentACodec::NetEqDecoderFromCodecId(
-    CodecId codec_id,
-    size_t num_channels) {
-  absl::optional<int> i = CodecIndexFromId(codec_id);
-  if (!i)
-    return absl::nullopt;
-  const NetEqDecoder ned = ACMCodecDB::neteq_decoders_[*i];
-  return (ned == NetEqDecoder::kDecoderOpus && num_channels == 2)
-             ? NetEqDecoder::kDecoderOpus_2ch
-             : ned;
-}
-
-}  // namespace acm2
-}  // namespace webrtc
diff --git a/modules/audio_coding/acm2/rent_a_codec.h b/modules/audio_coding/acm2/rent_a_codec.h
deleted file mode 100644
index 2cf1c6e..0000000
--- a/modules/audio_coding/acm2/rent_a_codec.h
+++ /dev/null
@@ -1,143 +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.
- */
-
-#ifndef MODULES_AUDIO_CODING_ACM2_RENT_A_CODEC_H_
-#define MODULES_AUDIO_CODING_ACM2_RENT_A_CODEC_H_
-
-#include <stddef.h>
-#include <map>
-#include <memory>
-
-#include "absl/types/optional.h"
-#include "api/array_view.h"
-#include "api/audio_codecs/audio_decoder.h"
-#include "api/audio_codecs/audio_encoder.h"
-#include "modules/audio_coding/include/audio_coding_module_typedefs.h"
-#include "modules/audio_coding/neteq/neteq_decoder_enum.h"
-#include "rtc_base/constructormagic.h"
-#include "rtc_base/scoped_ref_ptr.h"
-
-namespace webrtc {
-
-struct CodecInst;
-class LockedIsacBandwidthInfo;
-
-namespace acm2 {
-
-struct RentACodec {
-  enum class CodecId {
-#if defined(WEBRTC_CODEC_ISAC) || defined(WEBRTC_CODEC_ISACFX)
-    kISAC,
-#endif
-#ifdef WEBRTC_CODEC_ISAC
-    kISACSWB,
-#endif
-    // Mono
-    kPCM16B,
-    kPCM16Bwb,
-    kPCM16Bswb32kHz,
-    // Stereo
-    kPCM16B_2ch,
-    kPCM16Bwb_2ch,
-    kPCM16Bswb32kHz_2ch,
-    // Mono
-    kPCMU,
-    kPCMA,
-    // Stereo
-    kPCMU_2ch,
-    kPCMA_2ch,
-#ifdef WEBRTC_CODEC_ILBC
-    kILBC,
-#endif
-    kG722,      // Mono
-    kG722_2ch,  // Stereo
-#ifdef WEBRTC_CODEC_OPUS
-    kOpus,  // Mono and stereo
-#endif
-    kCNNB,
-    kCNWB,
-    kCNSWB,
-#ifdef ENABLE_48000_HZ
-    kCNFB,
-#endif
-    kAVT,
-    kAVT16kHz,
-    kAVT32kHz,
-    kAVT48kHz,
-#ifdef WEBRTC_CODEC_RED
-    kRED,
-#endif
-    kNumCodecs,  // Implementation detail. Don't use.
-
-// Set unsupported codecs to -1.
-#if !defined(WEBRTC_CODEC_ISAC) && !defined(WEBRTC_CODEC_ISACFX)
-    kISAC = -1,
-#endif
-#ifndef WEBRTC_CODEC_ISAC
-    kISACSWB = -1,
-#endif
-    // 48 kHz not supported, always set to -1.
-    kPCM16Bswb48kHz = -1,
-#ifndef WEBRTC_CODEC_ILBC
-    kILBC = -1,
-#endif
-#ifndef WEBRTC_CODEC_OPUS
-    kOpus = -1,  // Mono and stereo
-#endif
-#ifndef WEBRTC_CODEC_RED
-    kRED = -1,
-#endif
-#ifndef ENABLE_48000_HZ
-    kCNFB = -1,
-#endif
-
-    kNone = -1
-  };
-
-  static inline size_t NumberOfCodecs() {
-    return static_cast<size_t>(CodecId::kNumCodecs);
-  }
-
-  static inline absl::optional<int> CodecIndexFromId(CodecId codec_id) {
-    const int i = static_cast<int>(codec_id);
-    return i >= 0 && i < static_cast<int>(NumberOfCodecs())
-               ? absl::optional<int>(i)
-               : absl::nullopt;
-  }
-
-  static inline absl::optional<CodecId> CodecIdFromIndex(int codec_index) {
-    return static_cast<size_t>(codec_index) < NumberOfCodecs()
-               ? absl::optional<RentACodec::CodecId>(
-                     static_cast<RentACodec::CodecId>(codec_index))
-               : absl::nullopt;
-  }
-
-  static absl::optional<CodecId> CodecIdByParams(const char* payload_name,
-                                                 int sampling_freq_hz,
-                                                 size_t channels);
-  static absl::optional<CodecInst> CodecInstById(CodecId codec_id);
-  static absl::optional<CodecId> CodecIdByInst(const CodecInst& codec_inst);
-  static absl::optional<CodecInst> CodecInstByParams(const char* payload_name,
-                                                     int sampling_freq_hz,
-                                                     size_t channels);
-
-  static inline bool IsPayloadTypeValid(int payload_type) {
-    return payload_type >= 0 && payload_type <= 127;
-  }
-
-  static absl::optional<NetEqDecoder> NetEqDecoderFromCodecId(
-      CodecId codec_id,
-      size_t num_channels);
-};
-
-}  // namespace acm2
-}  // namespace webrtc
-
-#endif  // MODULES_AUDIO_CODING_ACM2_RENT_A_CODEC_H_
diff --git a/modules/audio_coding/audio_network_adaptor/audio_network_adaptor_impl.cc b/modules/audio_coding/audio_network_adaptor/audio_network_adaptor_impl.cc
index 9e47a06..ff6ac01 100644
--- a/modules/audio_coding/audio_network_adaptor/audio_network_adaptor_impl.cc
+++ b/modules/audio_coding/audio_network_adaptor/audio_network_adaptor_impl.cc
@@ -18,7 +18,7 @@
 #include "modules/audio_coding/audio_network_adaptor/debug_dump_writer.h"
 #include "modules/audio_coding/audio_network_adaptor/event_log_writer.h"
 #include "rtc_base/checks.h"
-#include "rtc_base/timeutils.h"
+#include "rtc_base/time_utils.h"
 #include "system_wrappers/include/field_trial.h"
 
 namespace webrtc {
@@ -29,7 +29,7 @@
 constexpr float kEventLogMinPacketLossChangeFraction = 0.5;
 }  // namespace
 
-AudioNetworkAdaptorImpl::Config::Config() : event_log(nullptr){};
+AudioNetworkAdaptorImpl::Config::Config() : event_log(nullptr) {}
 
 AudioNetworkAdaptorImpl::Config::~Config() = default;
 
diff --git a/modules/audio_coding/audio_network_adaptor/audio_network_adaptor_impl.h b/modules/audio_coding/audio_network_adaptor/audio_network_adaptor_impl.h
index 4c1c19b..fc2358b 100644
--- a/modules/audio_coding/audio_network_adaptor/audio_network_adaptor_impl.h
+++ b/modules/audio_coding/audio_network_adaptor/audio_network_adaptor_impl.h
@@ -20,7 +20,7 @@
 #include "modules/audio_coding/audio_network_adaptor/debug_dump_writer.h"
 #include "modules/audio_coding/audio_network_adaptor/include/audio_network_adaptor.h"
 #include "modules/audio_coding/audio_network_adaptor/include/audio_network_adaptor_config.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
diff --git a/modules/audio_coding/audio_network_adaptor/audio_network_adaptor_impl_unittest.cc b/modules/audio_coding/audio_network_adaptor/audio_network_adaptor_impl_unittest.cc
index be9550a..76531d0 100644
--- a/modules/audio_coding/audio_network_adaptor/audio_network_adaptor_impl_unittest.cc
+++ b/modules/audio_coding/audio_network_adaptor/audio_network_adaptor_impl_unittest.cc
@@ -18,7 +18,7 @@
 #include "modules/audio_coding/audio_network_adaptor/mock/mock_controller.h"
 #include "modules/audio_coding/audio_network_adaptor/mock/mock_controller_manager.h"
 #include "modules/audio_coding/audio_network_adaptor/mock/mock_debug_dump_writer.h"
-#include "rtc_base/fakeclock.h"
+#include "rtc_base/fake_clock.h"
 #include "test/field_trial.h"
 #include "test/gtest.h"
 
diff --git a/modules/audio_coding/audio_network_adaptor/bitrate_controller.h b/modules/audio_coding/audio_network_adaptor/bitrate_controller.h
index 6b6330b..41bfbd1 100644
--- a/modules/audio_coding/audio_network_adaptor/bitrate_controller.h
+++ b/modules/audio_coding/audio_network_adaptor/bitrate_controller.h
@@ -16,7 +16,7 @@
 #include "absl/types/optional.h"
 #include "modules/audio_coding/audio_network_adaptor/controller.h"
 #include "modules/audio_coding/audio_network_adaptor/include/audio_network_adaptor_config.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 namespace audio_network_adaptor {
diff --git a/modules/audio_coding/audio_network_adaptor/channel_controller.h b/modules/audio_coding/audio_network_adaptor/channel_controller.h
index 0d775b1..f211f40 100644
--- a/modules/audio_coding/audio_network_adaptor/channel_controller.h
+++ b/modules/audio_coding/audio_network_adaptor/channel_controller.h
@@ -16,7 +16,7 @@
 #include "absl/types/optional.h"
 #include "modules/audio_coding/audio_network_adaptor/controller.h"
 #include "modules/audio_coding/audio_network_adaptor/include/audio_network_adaptor_config.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
diff --git a/modules/audio_coding/audio_network_adaptor/controller_manager.cc b/modules/audio_coding/audio_network_adaptor/controller_manager.cc
index 32f9fcb..4c0e61c 100644
--- a/modules/audio_coding/audio_network_adaptor/controller_manager.cc
+++ b/modules/audio_coding/audio_network_adaptor/controller_manager.cc
@@ -11,6 +11,7 @@
 #include "modules/audio_coding/audio_network_adaptor/controller_manager.h"
 
 #include <cmath>
+#include <string>
 #include <utility>
 
 #include "modules/audio_coding/audio_network_adaptor/bitrate_controller.h"
@@ -22,7 +23,7 @@
 #include "modules/audio_coding/audio_network_adaptor/frame_length_controller.h"
 #include "modules/audio_coding/audio_network_adaptor/util/threshold_curve.h"
 #include "rtc_base/ignore_wundef.h"
-#include "rtc_base/timeutils.h"
+#include "rtc_base/time_utils.h"
 
 #if WEBRTC_ENABLE_PROTOBUF
 RTC_PUSH_IGNORING_WUNDEF()
@@ -147,13 +148,13 @@
   }
 
   FrameLengthController::Config ctor_config(
-      std::vector<int>(), initial_frame_length_ms, min_encoder_bitrate_bps,
+      std::set<int>(), initial_frame_length_ms, min_encoder_bitrate_bps,
       config.fl_increasing_packet_loss_fraction(),
       config.fl_decreasing_packet_loss_fraction(), fl_increase_overhead_offset,
       fl_decrease_overhead_offset, std::move(fl_changing_bandwidths_bps));
 
   for (auto frame_length : encoder_frame_lengths_ms)
-    ctor_config.encoder_frame_lengths_ms.push_back(frame_length);
+    ctor_config.encoder_frame_lengths_ms.insert(frame_length);
 
   return std::unique_ptr<FrameLengthController>(
       new FrameLengthController(ctor_config));
@@ -213,7 +214,7 @@
 ControllerManagerImpl::Config::~Config() = default;
 
 std::unique_ptr<ControllerManager> ControllerManagerImpl::Create(
-    const ProtoString& config_string,
+    const std::string& config_string,
     size_t num_encoder_channels,
     rtc::ArrayView<const int> encoder_frame_lengths_ms,
     int min_encoder_bitrate_bps,
@@ -229,7 +230,7 @@
 }
 
 std::unique_ptr<ControllerManager> ControllerManagerImpl::Create(
-    const ProtoString& config_string,
+    const std::string& config_string,
     size_t num_encoder_channels,
     rtc::ArrayView<const int> encoder_frame_lengths_ms,
     int min_encoder_bitrate_bps,
diff --git a/modules/audio_coding/audio_network_adaptor/controller_manager.h b/modules/audio_coding/audio_network_adaptor/controller_manager.h
index 1ff9bbf..f46450d 100644
--- a/modules/audio_coding/audio_network_adaptor/controller_manager.h
+++ b/modules/audio_coding/audio_network_adaptor/controller_manager.h
@@ -13,11 +13,11 @@
 
 #include <map>
 #include <memory>
+#include <string>
 #include <vector>
 
 #include "modules/audio_coding/audio_network_adaptor/controller.h"
-#include "rtc_base/constructormagic.h"
-#include "rtc_base/protobuf_utils.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
@@ -47,7 +47,7 @@
   };
 
   static std::unique_ptr<ControllerManager> Create(
-      const ProtoString& config_string,
+      const std::string& config_string,
       size_t num_encoder_channels,
       rtc::ArrayView<const int> encoder_frame_lengths_ms,
       int min_encoder_bitrate_bps,
@@ -58,7 +58,7 @@
       bool initial_dtx_enabled);
 
   static std::unique_ptr<ControllerManager> Create(
-      const ProtoString& config_string,
+      const std::string& config_string,
       size_t num_encoder_channels,
       rtc::ArrayView<const int> encoder_frame_lengths_ms,
       int min_encoder_bitrate_bps,
diff --git a/modules/audio_coding/audio_network_adaptor/controller_manager_unittest.cc b/modules/audio_coding/audio_network_adaptor/controller_manager_unittest.cc
index 061e4aa..ce47699 100644
--- a/modules/audio_coding/audio_network_adaptor/controller_manager_unittest.cc
+++ b/modules/audio_coding/audio_network_adaptor/controller_manager_unittest.cc
@@ -8,14 +8,14 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
+#include <string>
 #include <utility>
 
 #include "modules/audio_coding/audio_network_adaptor/controller_manager.h"
 #include "modules/audio_coding/audio_network_adaptor/mock/mock_controller.h"
 #include "modules/audio_coding/audio_network_adaptor/mock/mock_debug_dump_writer.h"
-#include "rtc_base/fakeclock.h"
+#include "rtc_base/fake_clock.h"
 #include "rtc_base/ignore_wundef.h"
-#include "rtc_base/protobuf_utils.h"
 #include "test/gtest.h"
 
 #if WEBRTC_ENABLE_PROTOBUF
@@ -266,7 +266,7 @@
 constexpr int kMinBitrateBps = 6000;
 
 ControllerManagerStates CreateControllerManager(
-    const ProtoString& config_string) {
+    const std::string& config_string) {
   ControllerManagerStates states;
   constexpr size_t kNumEncoderChannels = 2;
   const std::vector<int> encoder_frame_lengths_ms = {20, 60};
@@ -319,8 +319,8 @@
 }
 
 MATCHER_P(ControllerManagerEqual, value, "") {
-  ProtoString value_string;
-  ProtoString arg_string;
+  std::string value_string;
+  std::string arg_string;
   EXPECT_TRUE(arg.SerializeToString(&arg_string));
   EXPECT_TRUE(value.SerializeToString(&value_string));
   return arg_string == value_string;
@@ -339,7 +339,7 @@
   AddFrameLengthControllerConfig(&config);
   AddBitrateControllerConfig(&config);
 
-  ProtoString config_string;
+  std::string config_string;
   config.SerializeToString(&config_string);
 
   constexpr size_t kNumEncoderChannels = 2;
@@ -373,7 +373,7 @@
   AddFrameLengthControllerConfig(&config);
   AddBitrateControllerConfig(&config);
 
-  ProtoString config_string;
+  std::string config_string;
   config.SerializeToString(&config_string);
 
   auto states = CreateControllerManager(config_string);
@@ -395,7 +395,7 @@
   AddDtxControllerConfig(&config);
   AddBitrateControllerConfig(&config);
 
-  ProtoString config_string;
+  std::string config_string;
   config.SerializeToString(&config_string);
 
   auto states = CreateControllerManager(config_string);
@@ -426,7 +426,7 @@
 
   AddBitrateControllerConfig(&config);
 
-  ProtoString config_string;
+  std::string config_string;
   config.SerializeToString(&config_string);
 
   auto states = CreateControllerManager(config_string);
diff --git a/modules/audio_coding/audio_network_adaptor/debug_dump_writer.cc b/modules/audio_coding/audio_network_adaptor/debug_dump_writer.cc
index 8e04e8e..805df0a 100644
--- a/modules/audio_coding/audio_network_adaptor/debug_dump_writer.cc
+++ b/modules/audio_coding/audio_network_adaptor/debug_dump_writer.cc
@@ -10,11 +10,12 @@
 
 #include "modules/audio_coding/audio_network_adaptor/debug_dump_writer.h"
 
+#include <string>
+
 #include "absl/types/optional.h"
 #include "rtc_base/checks.h"
 #include "rtc_base/ignore_wundef.h"
 #include "rtc_base/numerics/safe_conversions.h"
-#include "rtc_base/protobuf_utils.h"
 #include "rtc_base/system/file_wrapper.h"
 
 #if WEBRTC_ENABLE_PROTOBUF
@@ -38,7 +39,7 @@
 
 void DumpEventToFile(const Event& event, FileWrapper* dump_file) {
   RTC_CHECK(dump_file->is_open());
-  ProtoString dump_data;
+  std::string dump_data;
   event.SerializeToString(&dump_data);
   int32_t size = rtc::checked_cast<int32_t>(event.ByteSizeLong());
   dump_file->Write(&size, sizeof(size));
@@ -67,14 +68,13 @@
 #endif
 
  private:
-  std::unique_ptr<FileWrapper> dump_file_;
+  FileWrapper dump_file_;
 };
 
-DebugDumpWriterImpl::DebugDumpWriterImpl(FILE* file_handle)
-    : dump_file_(FileWrapper::Create()) {
+DebugDumpWriterImpl::DebugDumpWriterImpl(FILE* file_handle) {
 #if WEBRTC_ENABLE_PROTOBUF
-  dump_file_->OpenFromFileHandle(file_handle);
-  RTC_CHECK(dump_file_->is_open());
+  dump_file_ = FileWrapper(file_handle);
+  RTC_CHECK(dump_file_.is_open());
 #else
   RTC_NOTREACHED();
 #endif
@@ -110,7 +110,7 @@
         *metrics.uplink_recoverable_packet_loss_fraction);
   }
 
-  DumpEventToFile(event, dump_file_.get());
+  DumpEventToFile(event, &dump_file_);
 #endif  // WEBRTC_ENABLE_PROTOBUF
 }
 
@@ -143,7 +143,7 @@
   if (config.num_channels)
     dump_config->set_num_channels(*config.num_channels);
 
-  DumpEventToFile(event, dump_file_.get());
+  DumpEventToFile(event, &dump_file_);
 #endif  // WEBRTC_ENABLE_PROTOBUF
 }
 
@@ -157,7 +157,7 @@
   event.set_type(Event::CONTROLLER_MANAGER_CONFIG);
   event.mutable_controller_manager_config()->CopyFrom(
       controller_manager_config);
-  DumpEventToFile(event, dump_file_.get());
+  DumpEventToFile(event, &dump_file_);
 }
 #endif  // WEBRTC_ENABLE_PROTOBUF
 
diff --git a/modules/audio_coding/audio_network_adaptor/debug_dump_writer.h b/modules/audio_coding/audio_network_adaptor/debug_dump_writer.h
index b464eb6..367f659 100644
--- a/modules/audio_coding/audio_network_adaptor/debug_dump_writer.h
+++ b/modules/audio_coding/audio_network_adaptor/debug_dump_writer.h
@@ -15,7 +15,7 @@
 
 #include "modules/audio_coding/audio_network_adaptor/controller.h"
 #include "modules/audio_coding/audio_network_adaptor/include/audio_network_adaptor.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 #include "rtc_base/ignore_wundef.h"
 #include "rtc_base/system/file_wrapper.h"
 #if WEBRTC_ENABLE_PROTOBUF
diff --git a/modules/audio_coding/audio_network_adaptor/dtx_controller.h b/modules/audio_coding/audio_network_adaptor/dtx_controller.h
index d3334ec..83fdf3d 100644
--- a/modules/audio_coding/audio_network_adaptor/dtx_controller.h
+++ b/modules/audio_coding/audio_network_adaptor/dtx_controller.h
@@ -14,7 +14,7 @@
 #include "absl/types/optional.h"
 #include "modules/audio_coding/audio_network_adaptor/controller.h"
 #include "modules/audio_coding/audio_network_adaptor/include/audio_network_adaptor_config.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
diff --git a/modules/audio_coding/audio_network_adaptor/event_log_writer.h b/modules/audio_coding/audio_network_adaptor/event_log_writer.h
index 72b5245..c5e57e6 100644
--- a/modules/audio_coding/audio_network_adaptor/event_log_writer.h
+++ b/modules/audio_coding/audio_network_adaptor/event_log_writer.h
@@ -12,7 +12,7 @@
 #define MODULES_AUDIO_CODING_AUDIO_NETWORK_ADAPTOR_EVENT_LOG_WRITER_H_
 
 #include "modules/audio_coding/audio_network_adaptor/include/audio_network_adaptor_config.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 class RtcEventLog;
diff --git a/modules/audio_coding/audio_network_adaptor/event_log_writer_unittest.cc b/modules/audio_coding/audio_network_adaptor/event_log_writer_unittest.cc
index 42189c3..b1e3313 100644
--- a/modules/audio_coding/audio_network_adaptor/event_log_writer_unittest.cc
+++ b/modules/audio_coding/audio_network_adaptor/event_log_writer_unittest.cc
@@ -13,6 +13,7 @@
 #include "logging/rtc_event_log/events/rtc_event_audio_network_adaptation.h"
 #include "logging/rtc_event_log/mock/mock_rtc_event_log.h"
 #include "modules/audio_coding/audio_network_adaptor/event_log_writer.h"
+#include "rtc_base/checks.h"
 #include "test/gtest.h"
 
 namespace webrtc {
diff --git a/modules/audio_coding/audio_network_adaptor/fec_controller_plr_based.h b/modules/audio_coding/audio_network_adaptor/fec_controller_plr_based.h
index b7d3d56..87afe2e 100644
--- a/modules/audio_coding/audio_network_adaptor/fec_controller_plr_based.h
+++ b/modules/audio_coding/audio_network_adaptor/fec_controller_plr_based.h
@@ -18,7 +18,7 @@
 #include "modules/audio_coding/audio_network_adaptor/controller.h"
 #include "modules/audio_coding/audio_network_adaptor/include/audio_network_adaptor_config.h"
 #include "modules/audio_coding/audio_network_adaptor/util/threshold_curve.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
diff --git a/modules/audio_coding/audio_network_adaptor/fec_controller_plr_based_unittest.cc b/modules/audio_coding/audio_network_adaptor/fec_controller_plr_based_unittest.cc
index de66717..d3f54ee 100644
--- a/modules/audio_coding/audio_network_adaptor/fec_controller_plr_based_unittest.cc
+++ b/modules/audio_coding/audio_network_adaptor/fec_controller_plr_based_unittest.cc
@@ -422,7 +422,7 @@
 
   // Test that FEC is turned on whenever we're on the curve or above it,
   // independent of the starting FEC state.
-  for (std::vector<NetworkState> states_list : {on, above}) {
+  for (const std::vector<NetworkState>& states_list : {on, above}) {
     for (NetworkState net_state : states_list) {
       for (bool initial_fec_enabled : {false, true}) {
         auto states =
diff --git a/modules/audio_coding/audio_network_adaptor/fec_controller_rplr_based.h b/modules/audio_coding/audio_network_adaptor/fec_controller_rplr_based.h
index 421cb70..c547bff 100644
--- a/modules/audio_coding/audio_network_adaptor/fec_controller_rplr_based.h
+++ b/modules/audio_coding/audio_network_adaptor/fec_controller_rplr_based.h
@@ -15,7 +15,7 @@
 #include "modules/audio_coding/audio_network_adaptor/controller.h"
 #include "modules/audio_coding/audio_network_adaptor/include/audio_network_adaptor_config.h"
 #include "modules/audio_coding/audio_network_adaptor/util/threshold_curve.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
diff --git a/modules/audio_coding/audio_network_adaptor/fec_controller_rplr_based_unittest.cc b/modules/audio_coding/audio_network_adaptor/fec_controller_rplr_based_unittest.cc
index 8e8704e..4438a23 100644
--- a/modules/audio_coding/audio_network_adaptor/fec_controller_rplr_based_unittest.cc
+++ b/modules/audio_coding/audio_network_adaptor/fec_controller_rplr_based_unittest.cc
@@ -462,7 +462,7 @@
 
   // Test that FEC is turned on whenever we're on the curve or above it,
   // independent of the starting FEC state.
-  for (std::vector<NetworkState> states_list : {on, above}) {
+  for (const std::vector<NetworkState>& states_list : {on, above}) {
     for (NetworkState net_state : states_list) {
       for (bool initial_fec_enabled : {false, true}) {
         FecControllerRplrBased controller(
diff --git a/modules/audio_coding/audio_network_adaptor/frame_length_controller.cc b/modules/audio_coding/audio_network_adaptor/frame_length_controller.cc
index b123c7c..3cb91fd 100644
--- a/modules/audio_coding/audio_network_adaptor/frame_length_controller.cc
+++ b/modules/audio_coding/audio_network_adaptor/frame_length_controller.cc
@@ -28,7 +28,7 @@
 }  // namespace
 
 FrameLengthController::Config::Config(
-    const std::vector<int>& encoder_frame_lengths_ms,
+    const std::set<int>& encoder_frame_lengths_ms,
     int initial_frame_length_ms,
     int min_encoder_bitrate_bps,
     float fl_increasing_packet_loss_fraction,
diff --git a/modules/audio_coding/audio_network_adaptor/frame_length_controller.h b/modules/audio_coding/audio_network_adaptor/frame_length_controller.h
index f0a5aab..e182247 100644
--- a/modules/audio_coding/audio_network_adaptor/frame_length_controller.h
+++ b/modules/audio_coding/audio_network_adaptor/frame_length_controller.h
@@ -13,12 +13,12 @@
 
 #include <stddef.h>
 #include <map>
-#include <vector>
+#include <set>
 
 #include "absl/types/optional.h"
 #include "modules/audio_coding/audio_network_adaptor/controller.h"
 #include "modules/audio_coding/audio_network_adaptor/include/audio_network_adaptor_config.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
@@ -33,7 +33,7 @@
       int from_frame_length_ms;
       int to_frame_length_ms;
     };
-    Config(const std::vector<int>& encoder_frame_lengths_ms,
+    Config(const std::set<int>& encoder_frame_lengths_ms,
            int initial_frame_length_ms,
            int min_encoder_bitrate_bps,
            float fl_increasing_packet_loss_fraction,
@@ -43,7 +43,7 @@
            std::map<FrameLengthChange, int> fl_changing_bandwidths_bps);
     Config(const Config& other);
     ~Config();
-    std::vector<int> encoder_frame_lengths_ms;
+    std::set<int> encoder_frame_lengths_ms;
     int initial_frame_length_ms;
     int min_encoder_bitrate_bps;
     // Uplink packet loss fraction below which frame length can increase.
@@ -74,7 +74,7 @@
 
   const Config config_;
 
-  std::vector<int>::const_iterator frame_length_ms_;
+  std::set<int>::const_iterator frame_length_ms_;
 
   absl::optional<int> uplink_bandwidth_bps_;
 
diff --git a/modules/audio_coding/audio_network_adaptor/frame_length_controller_unittest.cc b/modules/audio_coding/audio_network_adaptor/frame_length_controller_unittest.cc
index f97ad4f..8d6d815 100644
--- a/modules/audio_coding/audio_network_adaptor/frame_length_controller_unittest.cc
+++ b/modules/audio_coding/audio_network_adaptor/frame_length_controller_unittest.cc
@@ -42,7 +42,7 @@
 std::unique_ptr<FrameLengthController> CreateController(
     const std::map<FrameLengthController::Config::FrameLengthChange, int>&
         frame_length_change_criteria,
-    const std::vector<int>& encoder_frame_lengths_ms,
+    const std::set<int>& encoder_frame_lengths_ms,
     int initial_frame_length_ms) {
   std::unique_ptr<FrameLengthController> controller(
       new FrameLengthController(FrameLengthController::Config(
diff --git a/modules/audio_coding/codecs/audio_format_conversion.cc b/modules/audio_coding/codecs/audio_format_conversion.cc
deleted file mode 100644
index f068301..0000000
--- a/modules/audio_coding/codecs/audio_format_conversion.cc
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- *  Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
- *
- *  Use of this source code is governed by a BSD-style license
- *  that can be found in the LICENSE file in the root of the source
- *  tree. An additional intellectual property rights grant can be found
- *  in the file PATENTS.  All contributing project authors may
- *  be found in the AUTHORS file in the root of the source tree.
- */
-
-#include "modules/audio_coding/codecs/audio_format_conversion.h"
-
-#include <string.h>
-#include <string>
-#include <utility>
-
-#include "absl/strings/match.h"
-#include "api/array_view.h"
-#include "rtc_base/checks.h"
-#include "rtc_base/sanitizer.h"
-
-namespace webrtc {
-
-namespace {
-
-CodecInst MakeCodecInst(int payload_type,
-                        const char* name,
-                        int sample_rate,
-                        size_t num_channels) {
-  // Create a CodecInst with some fields set. The remaining fields are zeroed,
-  // but we tell MSan to consider them uninitialized.
-  CodecInst ci = {0};
-  rtc::MsanMarkUninitialized(rtc::MakeArrayView(&ci, 1));
-  ci.pltype = payload_type;
-  strncpy(ci.plname, name, sizeof(ci.plname));
-  ci.plname[sizeof(ci.plname) - 1] = '\0';
-  ci.plfreq = sample_rate;
-  ci.channels = num_channels;
-  return ci;
-}
-
-}  // namespace
-
-SdpAudioFormat CodecInstToSdp(const CodecInst& ci) {
-  if (absl::EqualsIgnoreCase(ci.plname, "g722")) {
-    RTC_CHECK_EQ(16000, ci.plfreq);
-    RTC_CHECK(ci.channels == 1 || ci.channels == 2);
-    return {"g722", 8000, ci.channels};
-  } else if (absl::EqualsIgnoreCase(ci.plname, "opus")) {
-    RTC_CHECK_EQ(48000, ci.plfreq);
-    RTC_CHECK(ci.channels == 1 || ci.channels == 2);
-    return ci.channels == 1
-               ? SdpAudioFormat("opus", 48000, 2)
-               : SdpAudioFormat("opus", 48000, 2, {{"stereo", "1"}});
-  } else {
-    return {ci.plname, ci.plfreq, ci.channels};
-  }
-}
-
-CodecInst SdpToCodecInst(int payload_type, const SdpAudioFormat& audio_format) {
-  if (absl::EqualsIgnoreCase(audio_format.name, "g722")) {
-    RTC_CHECK_EQ(8000, audio_format.clockrate_hz);
-    RTC_CHECK(audio_format.num_channels == 1 || audio_format.num_channels == 2);
-    return MakeCodecInst(payload_type, "g722", 16000,
-                         audio_format.num_channels);
-  } else if (absl::EqualsIgnoreCase(audio_format.name, "opus")) {
-    RTC_CHECK_EQ(48000, audio_format.clockrate_hz);
-    RTC_CHECK_EQ(2, audio_format.num_channels);
-    const int num_channels = [&] {
-      auto stereo = audio_format.parameters.find("stereo");
-      if (stereo != audio_format.parameters.end()) {
-        if (stereo->second == "0") {
-          return 1;
-        } else if (stereo->second == "1") {
-          return 2;
-        } else {
-          RTC_CHECK(false);  // Bad stereo parameter.
-        }
-      }
-      return 1;  // Default to mono.
-    }();
-    return MakeCodecInst(payload_type, "opus", 48000, num_channels);
-  } else {
-    return MakeCodecInst(payload_type, audio_format.name.c_str(),
-                         audio_format.clockrate_hz, audio_format.num_channels);
-  }
-}
-
-}  // namespace webrtc
diff --git a/modules/audio_coding/codecs/audio_format_conversion.h b/modules/audio_coding/codecs/audio_format_conversion.h
deleted file mode 100644
index d981741..0000000
--- a/modules/audio_coding/codecs/audio_format_conversion.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- *  Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
- *
- *  Use of this source code is governed by a BSD-style license
- *  that can be found in the LICENSE file in the root of the source
- *  tree. An additional intellectual property rights grant can be found
- *  in the file PATENTS.  All contributing project authors may
- *  be found in the AUTHORS file in the root of the source tree.
- */
-
-#ifndef MODULES_AUDIO_CODING_CODECS_AUDIO_FORMAT_CONVERSION_H_
-#define MODULES_AUDIO_CODING_CODECS_AUDIO_FORMAT_CONVERSION_H_
-
-#include "api/audio_codecs/audio_format.h"
-#include "common_types.h"  // NOLINT(build/include)
-
-namespace webrtc {
-
-SdpAudioFormat CodecInstToSdp(const CodecInst& codec_inst);
-CodecInst SdpToCodecInst(int payload_type, const SdpAudioFormat& audio_format);
-
-}  // namespace webrtc
-
-#endif  // MODULES_AUDIO_CODING_CODECS_AUDIO_FORMAT_CONVERSION_H_
diff --git a/modules/audio_coding/codecs/builtin_audio_encoder_factory_unittest.cc b/modules/audio_coding/codecs/builtin_audio_encoder_factory_unittest.cc
index 64f0159..a548be8 100644
--- a/modules/audio_coding/codecs/builtin_audio_encoder_factory_unittest.cc
+++ b/modules/audio_coding/codecs/builtin_audio_encoder_factory_unittest.cc
@@ -103,9 +103,9 @@
   }
 }
 
-INSTANTIATE_TEST_CASE_P(BuiltinAudioEncoderFactoryTest,
-                        AudioEncoderFactoryTest,
-                        ::testing::Values(CreateBuiltinAudioEncoderFactory()));
+INSTANTIATE_TEST_SUITE_P(BuiltinAudioEncoderFactoryTest,
+                         AudioEncoderFactoryTest,
+                         ::testing::Values(CreateBuiltinAudioEncoderFactory()));
 
 TEST(BuiltinAudioEncoderFactoryTest, SupportsTheExpectedFormats) {
   using ::testing::ElementsAreArray;
@@ -116,6 +116,7 @@
 
   const std::vector<SdpAudioFormat> supported_formats = [&specs] {
     std::vector<SdpAudioFormat> formats;
+    formats.reserve(specs.size());
     for (const auto& spec : specs) {
       formats.push_back(spec.format);
     }
diff --git a/modules/audio_coding/codecs/cng/audio_encoder_cng_unittest.cc b/modules/audio_coding/codecs/cng/audio_encoder_cng_unittest.cc
index e3655b4..3ecefd4 100644
--- a/modules/audio_coding/codecs/cng/audio_encoder_cng_unittest.cc
+++ b/modules/audio_coding/codecs/cng/audio_encoder_cng_unittest.cc
@@ -13,7 +13,7 @@
 
 #include "common_audio/vad/mock/mock_vad.h"
 #include "modules/audio_coding/codecs/cng/audio_encoder_cng.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 #include "rtc_base/numerics/safe_conversions.h"
 #include "test/gtest.h"
 #include "test/mock_audio_encoder.h"
diff --git a/modules/audio_coding/codecs/cng/cng_unittest.cc b/modules/audio_coding/codecs/cng/cng_unittest.cc
index 81688b1..80349e2 100644
--- a/modules/audio_coding/codecs/cng/cng_unittest.cc
+++ b/modules/audio_coding/codecs/cng/cng_unittest.cc
@@ -12,7 +12,7 @@
 
 #include "modules/audio_coding/codecs/cng/webrtc_cng.h"
 #include "test/gtest.h"
-#include "test/testsupport/fileutils.h"
+#include "test/testsupport/file_utils.h"
 
 namespace webrtc {
 
diff --git a/modules/audio_coding/codecs/g711/audio_decoder_pcm.h b/modules/audio_coding/codecs/g711/audio_decoder_pcm.h
index 9a01b8a..8fae71c 100644
--- a/modules/audio_coding/codecs/g711/audio_decoder_pcm.h
+++ b/modules/audio_coding/codecs/g711/audio_decoder_pcm.h
@@ -18,7 +18,7 @@
 #include "api/audio_codecs/audio_decoder.h"
 #include "rtc_base/buffer.h"
 #include "rtc_base/checks.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
diff --git a/modules/audio_coding/codecs/g711/audio_encoder_pcm.cc b/modules/audio_coding/codecs/g711/audio_encoder_pcm.cc
index dce1635..fd560e4 100644
--- a/modules/audio_coding/codecs/g711/audio_encoder_pcm.cc
+++ b/modules/audio_coding/codecs/g711/audio_encoder_pcm.cc
@@ -12,25 +12,11 @@
 
 #include <cstdint>
 
-#include "common_types.h"
 #include "modules/audio_coding/codecs/g711/g711_interface.h"
 #include "rtc_base/checks.h"
 
 namespace webrtc {
 
-namespace {
-
-template <typename T>
-typename T::Config CreateConfig(const CodecInst& codec_inst) {
-  typename T::Config config;
-  config.frame_size_ms = codec_inst.pacsize / 8;
-  config.num_channels = codec_inst.channels;
-  config.payload_type = codec_inst.pltype;
-  return config;
-}
-
-}  // namespace
-
 bool AudioEncoderPcm::Config::IsOk() const {
   return (frame_size_ms % 10 == 0) && (num_channels >= 1);
 }
@@ -103,9 +89,6 @@
   speech_buffer_.clear();
 }
 
-AudioEncoderPcmA::AudioEncoderPcmA(const CodecInst& codec_inst)
-    : AudioEncoderPcmA(CreateConfig<AudioEncoderPcmA>(codec_inst)) {}
-
 size_t AudioEncoderPcmA::EncodeCall(const int16_t* audio,
                                     size_t input_len,
                                     uint8_t* encoded) {
@@ -120,9 +103,6 @@
   return AudioEncoder::CodecType::kPcmA;
 }
 
-AudioEncoderPcmU::AudioEncoderPcmU(const CodecInst& codec_inst)
-    : AudioEncoderPcmU(CreateConfig<AudioEncoderPcmU>(codec_inst)) {}
-
 size_t AudioEncoderPcmU::EncodeCall(const int16_t* audio,
                                     size_t input_len,
                                     uint8_t* encoded) {
diff --git a/modules/audio_coding/codecs/g711/audio_encoder_pcm.h b/modules/audio_coding/codecs/g711/audio_encoder_pcm.h
index 37b67cf..e41c2a3 100644
--- a/modules/audio_coding/codecs/g711/audio_encoder_pcm.h
+++ b/modules/audio_coding/codecs/g711/audio_encoder_pcm.h
@@ -14,7 +14,7 @@
 #include <vector>
 
 #include "api/audio_codecs/audio_encoder.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
@@ -69,8 +69,6 @@
   uint32_t first_timestamp_in_buffer_;
 };
 
-struct CodecInst;
-
 class AudioEncoderPcmA final : public AudioEncoderPcm {
  public:
   struct Config : public AudioEncoderPcm::Config {
@@ -79,7 +77,6 @@
 
   explicit AudioEncoderPcmA(const Config& config)
       : AudioEncoderPcm(config, kSampleRateHz) {}
-  explicit AudioEncoderPcmA(const CodecInst& codec_inst);
 
  protected:
   size_t EncodeCall(const int16_t* audio,
@@ -103,7 +100,6 @@
 
   explicit AudioEncoderPcmU(const Config& config)
       : AudioEncoderPcm(config, kSampleRateHz) {}
-  explicit AudioEncoderPcmU(const CodecInst& codec_inst);
 
  protected:
   size_t EncodeCall(const int16_t* audio,
diff --git a/modules/audio_coding/codecs/g722/audio_decoder_g722.h b/modules/audio_coding/codecs/g722/audio_decoder_g722.h
index 3240448..6911e0b 100644
--- a/modules/audio_coding/codecs/g722/audio_decoder_g722.h
+++ b/modules/audio_coding/codecs/g722/audio_decoder_g722.h
@@ -12,7 +12,7 @@
 #define MODULES_AUDIO_CODING_CODECS_G722_AUDIO_DECODER_G722_H_
 
 #include "api/audio_codecs/audio_decoder.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 typedef struct WebRtcG722DecInst G722DecInst;
 
diff --git a/modules/audio_coding/codecs/g722/audio_encoder_g722.cc b/modules/audio_coding/codecs/g722/audio_encoder_g722.cc
index e63d590..d293163 100644
--- a/modules/audio_coding/codecs/g722/audio_encoder_g722.cc
+++ b/modules/audio_coding/codecs/g722/audio_encoder_g722.cc
@@ -12,7 +12,6 @@
 
 #include <cstdint>
 
-#include "common_types.h"
 #include "modules/audio_coding/codecs/g722/g722_interface.h"
 #include "rtc_base/checks.h"
 #include "rtc_base/numerics/safe_conversions.h"
@@ -23,13 +22,6 @@
 
 const size_t kSampleRateHz = 16000;
 
-AudioEncoderG722Config CreateConfig(const CodecInst& codec_inst) {
-  AudioEncoderG722Config config;
-  config.num_channels = rtc::dchecked_cast<int>(codec_inst.channels);
-  config.frame_size_ms = codec_inst.pacsize / 16;
-  return config;
-}
-
 }  // namespace
 
 AudioEncoderG722Impl::AudioEncoderG722Impl(const AudioEncoderG722Config& config,
@@ -52,9 +44,6 @@
   Reset();
 }
 
-AudioEncoderG722Impl::AudioEncoderG722Impl(const CodecInst& codec_inst)
-    : AudioEncoderG722Impl(CreateConfig(codec_inst), codec_inst.pltype) {}
-
 AudioEncoderG722Impl::~AudioEncoderG722Impl() = default;
 
 int AudioEncoderG722Impl::SampleRateHz() const {
diff --git a/modules/audio_coding/codecs/g722/audio_encoder_g722.h b/modules/audio_coding/codecs/g722/audio_encoder_g722.h
index 3cf1439..cf45fb5 100644
--- a/modules/audio_coding/codecs/g722/audio_encoder_g722.h
+++ b/modules/audio_coding/codecs/g722/audio_encoder_g722.h
@@ -17,16 +17,13 @@
 #include "api/audio_codecs/g722/audio_encoder_g722_config.h"
 #include "modules/audio_coding/codecs/g722/g722_interface.h"
 #include "rtc_base/buffer.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
-struct CodecInst;
-
 class AudioEncoderG722Impl final : public AudioEncoder {
  public:
   AudioEncoderG722Impl(const AudioEncoderG722Config& config, int payload_type);
-  explicit AudioEncoderG722Impl(const CodecInst& codec_inst);
   ~AudioEncoderG722Impl() override;
 
   int SampleRateHz() const override;
diff --git a/modules/audio_coding/codecs/ilbc/audio_decoder_ilbc.h b/modules/audio_coding/codecs/ilbc/audio_decoder_ilbc.h
index fcb2074..d73ef0d 100644
--- a/modules/audio_coding/codecs/ilbc/audio_decoder_ilbc.h
+++ b/modules/audio_coding/codecs/ilbc/audio_decoder_ilbc.h
@@ -17,7 +17,7 @@
 
 #include "api/audio_codecs/audio_decoder.h"
 #include "rtc_base/buffer.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 typedef struct iLBC_decinst_t_ IlbcDecoderInstance;
 
diff --git a/modules/audio_coding/codecs/ilbc/audio_encoder_ilbc.cc b/modules/audio_coding/codecs/ilbc/audio_encoder_ilbc.cc
index 8801fd5..ac9214b 100644
--- a/modules/audio_coding/codecs/ilbc/audio_encoder_ilbc.cc
+++ b/modules/audio_coding/codecs/ilbc/audio_encoder_ilbc.cc
@@ -13,7 +13,6 @@
 #include <algorithm>
 #include <cstdint>
 
-#include "common_types.h"
 #include "modules/audio_coding/codecs/ilbc/ilbc.h"
 #include "rtc_base/checks.h"
 #include "rtc_base/numerics/safe_conversions.h"
@@ -24,12 +23,6 @@
 
 const int kSampleRateHz = 8000;
 
-AudioEncoderIlbcConfig CreateConfig(const CodecInst& codec_inst) {
-  AudioEncoderIlbcConfig config;
-  config.frame_size_ms = codec_inst.pacsize / 8;
-  return config;
-}
-
 int GetIlbcBitrate(int ptime) {
   switch (ptime) {
     case 20:
@@ -58,9 +51,6 @@
   Reset();
 }
 
-AudioEncoderIlbcImpl::AudioEncoderIlbcImpl(const CodecInst& codec_inst)
-    : AudioEncoderIlbcImpl(CreateConfig(codec_inst), codec_inst.pltype) {}
-
 AudioEncoderIlbcImpl::~AudioEncoderIlbcImpl() {
   RTC_CHECK_EQ(0, WebRtcIlbcfix_EncoderFree(encoder_));
 }
diff --git a/modules/audio_coding/codecs/ilbc/audio_encoder_ilbc.h b/modules/audio_coding/codecs/ilbc/audio_encoder_ilbc.h
index a238689..ada613b 100644
--- a/modules/audio_coding/codecs/ilbc/audio_encoder_ilbc.h
+++ b/modules/audio_coding/codecs/ilbc/audio_encoder_ilbc.h
@@ -14,16 +14,13 @@
 #include "api/audio_codecs/audio_encoder.h"
 #include "api/audio_codecs/ilbc/audio_encoder_ilbc_config.h"
 #include "modules/audio_coding/codecs/ilbc/ilbc.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
-struct CodecInst;
-
 class AudioEncoderIlbcImpl final : public AudioEncoder {
  public:
   AudioEncoderIlbcImpl(const AudioEncoderIlbcConfig& config, int payload_type);
-  explicit AudioEncoderIlbcImpl(const CodecInst& codec_inst);
   ~AudioEncoderIlbcImpl() override;
 
   int SampleRateHz() const override;
diff --git a/modules/audio_coding/codecs/ilbc/ilbc_unittest.cc b/modules/audio_coding/codecs/ilbc/ilbc_unittest.cc
index 5ec1219..689292f 100644
--- a/modules/audio_coding/codecs/ilbc/ilbc_unittest.cc
+++ b/modules/audio_coding/codecs/ilbc/ilbc_unittest.cc
@@ -103,7 +103,7 @@
 // Also test the maximum number of frames in one packet for 20 and 30 ms.
 // The maximum is defined by the largest payload length that can be uniquely
 // resolved to a frame size of either 38 bytes (20 ms) or 50 bytes (30 ms).
-INSTANTIATE_TEST_CASE_P(
+INSTANTIATE_TEST_SUITE_P(
     IlbcTest,
     SplitIlbcTest,
     ::testing::Values(std::pair<int, int>(1, 20),  // 1 frame, 20 ms.
diff --git a/modules/audio_coding/codecs/isac/audio_decoder_isac_t.h b/modules/audio_coding/codecs/isac/audio_decoder_isac_t.h
index f840ffa..7cadd91 100644
--- a/modules/audio_coding/codecs/isac/audio_decoder_isac_t.h
+++ b/modules/audio_coding/codecs/isac/audio_decoder_isac_t.h
@@ -15,9 +15,9 @@
 
 #include "absl/types/optional.h"
 #include "api/audio_codecs/audio_decoder.h"
+#include "api/scoped_refptr.h"
 #include "modules/audio_coding/codecs/isac/locked_bandwidth_info.h"
-#include "rtc_base/constructormagic.h"
-#include "rtc_base/scoped_ref_ptr.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
diff --git a/modules/audio_coding/codecs/isac/audio_encoder_isac_t.h b/modules/audio_coding/codecs/isac/audio_encoder_isac_t.h
index 541b90c..c6ef795 100644
--- a/modules/audio_coding/codecs/isac/audio_encoder_isac_t.h
+++ b/modules/audio_coding/codecs/isac/audio_encoder_isac_t.h
@@ -14,14 +14,12 @@
 #include <vector>
 
 #include "api/audio_codecs/audio_encoder.h"
+#include "api/scoped_refptr.h"
 #include "modules/audio_coding/codecs/isac/locked_bandwidth_info.h"
-#include "rtc_base/constructormagic.h"
-#include "rtc_base/scoped_ref_ptr.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
-struct CodecInst;
-
 template <typename T>
 class AudioEncoderIsacT final : public AudioEncoder {
  public:
@@ -52,9 +50,6 @@
   };
 
   explicit AudioEncoderIsacT(const Config& config);
-  explicit AudioEncoderIsacT(
-      const CodecInst& codec_inst,
-      const rtc::scoped_refptr<LockedIsacBandwidthInfo>& bwinfo);
   ~AudioEncoderIsacT() override;
 
   int SampleRateHz() const override;
diff --git a/modules/audio_coding/codecs/isac/audio_encoder_isac_t_impl.h b/modules/audio_coding/codecs/isac/audio_encoder_isac_t_impl.h
index cbf15fc..3448139 100644
--- a/modules/audio_coding/codecs/isac/audio_encoder_isac_t_impl.h
+++ b/modules/audio_coding/codecs/isac/audio_encoder_isac_t_impl.h
@@ -11,28 +11,11 @@
 #ifndef MODULES_AUDIO_CODING_CODECS_ISAC_AUDIO_ENCODER_ISAC_T_IMPL_H_
 #define MODULES_AUDIO_CODING_CODECS_ISAC_AUDIO_ENCODER_ISAC_T_IMPL_H_
 
-#include "common_types.h"  // NOLINT(build/include)
 #include "rtc_base/checks.h"
 
 namespace webrtc {
 
 template <typename T>
-typename AudioEncoderIsacT<T>::Config CreateIsacConfig(
-    const CodecInst& codec_inst,
-    const rtc::scoped_refptr<LockedIsacBandwidthInfo>& bwinfo) {
-  typename AudioEncoderIsacT<T>::Config config;
-  config.bwinfo = bwinfo;
-  config.payload_type = codec_inst.pltype;
-  config.sample_rate_hz = codec_inst.plfreq;
-  config.frame_size_ms =
-      rtc::CheckedDivExact(1000 * codec_inst.pacsize, config.sample_rate_hz);
-  config.adaptive_mode = (codec_inst.rate == -1);
-  if (codec_inst.rate != -1)
-    config.bit_rate = codec_inst.rate;
-  return config;
-}
-
-template <typename T>
 bool AudioEncoderIsacT<T>::Config::IsOk() const {
   if (max_bit_rate < 32000 && max_bit_rate != -1)
     return false;
@@ -67,12 +50,6 @@
 }
 
 template <typename T>
-AudioEncoderIsacT<T>::AudioEncoderIsacT(
-    const CodecInst& codec_inst,
-    const rtc::scoped_refptr<LockedIsacBandwidthInfo>& bwinfo)
-    : AudioEncoderIsacT(CreateIsacConfig<T>(codec_inst, bwinfo)) {}
-
-template <typename T>
 AudioEncoderIsacT<T>::~AudioEncoderIsacT() {
   RTC_CHECK_EQ(0, T::Free(isac_state_));
 }
diff --git a/modules/audio_coding/codecs/isac/fix/source/pitch_filter.c b/modules/audio_coding/codecs/isac/fix/source/pitch_filter.c
index e565e85..7355330 100644
--- a/modules/audio_coding/codecs/isac/fix/source/pitch_filter.c
+++ b/modules/audio_coding/codecs/isac/fix/source/pitch_filter.c
@@ -9,7 +9,6 @@
  */
 
 #include "modules/audio_coding/codecs/isac/fix/source/pitch_estimator.h"
-
 #include "common_audio/signal_processing/include/signal_processing_library.h"
 #include "modules/audio_coding/codecs/isac/fix/source/settings.h"
 #include "modules/audio_coding/codecs/isac/fix/source/structs.h"
@@ -55,7 +54,8 @@
   const int16_t Gain = 21299;     // 1.3 in Q14
   int16_t oldLagQ7;
   int16_t oldGainQ12, lagdeltaQ7, curLagQ7, gaindeltaQ12, curGainQ12;
-  size_t indW32 = 0, frcQQ = 0;
+  size_t frcQQ = 0;
+  int32_t indW32 = 0;
   const int16_t* fracoeffQQ = NULL;
 
   // Assumptions in ARM assembly for WebRtcIsacfix_PitchFilterCoreARM().
diff --git a/modules/audio_coding/codecs/isac/locked_bandwidth_info.h b/modules/audio_coding/codecs/isac/locked_bandwidth_info.h
index 37074f8..0b1bc7d 100644
--- a/modules/audio_coding/codecs/isac/locked_bandwidth_info.h
+++ b/modules/audio_coding/codecs/isac/locked_bandwidth_info.h
@@ -12,8 +12,8 @@
 #define MODULES_AUDIO_CODING_CODECS_ISAC_LOCKED_BANDWIDTH_INFO_H_
 
 #include "modules/audio_coding/codecs/isac/bandwidth_info.h"
-#include "rtc_base/atomicops.h"
-#include "rtc_base/criticalsection.h"
+#include "rtc_base/atomic_ops.h"
+#include "rtc_base/critical_section.h"
 #include "rtc_base/thread_annotations.h"
 
 namespace webrtc {
diff --git a/modules/audio_coding/codecs/isac/main/source/isac_unittest.cc b/modules/audio_coding/codecs/isac/main/source/isac_unittest.cc
index 3ec28cc..6d9b013 100644
--- a/modules/audio_coding/codecs/isac/main/source/isac_unittest.cc
+++ b/modules/audio_coding/codecs/isac/main/source/isac_unittest.cc
@@ -11,7 +11,7 @@
 
 #include "modules/audio_coding/codecs/isac/main/include/isac.h"
 #include "test/gtest.h"
-#include "test/testsupport/fileutils.h"
+#include "test/testsupport/file_utils.h"
 
 struct WebRtcISACStruct;
 
diff --git a/modules/audio_coding/codecs/isac/unittest.cc b/modules/audio_coding/codecs/isac/unittest.cc
index 5855d56..076510b 100644
--- a/modules/audio_coding/codecs/isac/unittest.cc
+++ b/modules/audio_coding/codecs/isac/unittest.cc
@@ -19,7 +19,7 @@
 #include "rtc_base/numerics/safe_conversions.h"
 #include "rtc_base/strings/string_builder.h"
 #include "test/gtest.h"
-#include "test/testsupport/fileutils.h"
+#include "test/testsupport/file_utils.h"
 
 namespace webrtc {
 
@@ -252,6 +252,6 @@
   return cases;
 }
 
-INSTANTIATE_TEST_CASE_P(, IsacCommonTest, testing::ValuesIn(TestCases()));
+INSTANTIATE_TEST_SUITE_P(, IsacCommonTest, testing::ValuesIn(TestCases()));
 
 }  // namespace webrtc
diff --git a/modules/audio_coding/codecs/legacy_encoded_audio_frame_unittest.cc b/modules/audio_coding/codecs/legacy_encoded_audio_frame_unittest.cc
index 9079bcd..2ca1d4c 100644
--- a/modules/audio_coding/codecs/legacy_encoded_audio_frame_unittest.cc
+++ b/modules/audio_coding/codecs/legacy_encoded_audio_frame_unittest.cc
@@ -10,12 +10,28 @@
 
 #include "modules/audio_coding/codecs/legacy_encoded_audio_frame.h"
 
-#include "modules/audio_coding/acm2/rent_a_codec.h"
 #include "rtc_base/numerics/safe_conversions.h"
 #include "test/gtest.h"
 
 namespace webrtc {
 
+enum class NetEqDecoder {
+  kDecoderPCMu,
+  kDecoderPCMa,
+  kDecoderPCMu_2ch,
+  kDecoderPCMa_2ch,
+  kDecoderPCM16B,
+  kDecoderPCM16Bwb,
+  kDecoderPCM16Bswb32kHz,
+  kDecoderPCM16Bswb48kHz,
+  kDecoderPCM16B_2ch,
+  kDecoderPCM16Bwb_2ch,
+  kDecoderPCM16Bswb32kHz_2ch,
+  kDecoderPCM16Bswb48kHz_2ch,
+  kDecoderPCM16B_5ch,
+  kDecoderG722,
+};
+
 class SplitBySamplesTest : public ::testing::TestWithParam<NetEqDecoder> {
  protected:
   virtual void SetUp() {
@@ -144,7 +160,7 @@
   }
 }
 
-INSTANTIATE_TEST_CASE_P(
+INSTANTIATE_TEST_SUITE_P(
     LegacyEncodedAudioFrame,
     SplitBySamplesTest,
     ::testing::Values(NetEqDecoder::kDecoderPCMu,
diff --git a/modules/audio_coding/codecs/opus/audio_decoder_opus.cc b/modules/audio_coding/codecs/opus/audio_decoder_opus.cc
index 357cb1a..b6eada9 100644
--- a/modules/audio_coding/codecs/opus/audio_decoder_opus.cc
+++ b/modules/audio_coding/codecs/opus/audio_decoder_opus.cc
@@ -71,8 +71,10 @@
 
 AudioDecoderOpusImpl::AudioDecoderOpusImpl(size_t num_channels)
     : channels_(num_channels) {
-  RTC_DCHECK(num_channels == 1 || num_channels == 2);
-  WebRtcOpus_DecoderCreate(&dec_state_, channels_);
+  RTC_DCHECK(num_channels == 1 || num_channels == 2 || num_channels == 4 ||
+             num_channels == 6 || num_channels == 8);
+  const int error = WebRtcOpus_DecoderCreate(&dec_state_, channels_);
+  RTC_DCHECK(error == 0);
   WebRtcOpus_DecoderInit(dec_state_);
 }
 
diff --git a/modules/audio_coding/codecs/opus/audio_decoder_opus.h b/modules/audio_coding/codecs/opus/audio_decoder_opus.h
index 8043425..d8cc5c1 100644
--- a/modules/audio_coding/codecs/opus/audio_decoder_opus.h
+++ b/modules/audio_coding/codecs/opus/audio_decoder_opus.h
@@ -18,7 +18,7 @@
 #include "api/audio_codecs/audio_decoder.h"
 #include "modules/audio_coding/codecs/opus/opus_interface.h"
 #include "rtc_base/buffer.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
diff --git a/modules/audio_coding/codecs/opus/audio_encoder_opus.cc b/modules/audio_coding/codecs/opus/audio_encoder_opus.cc
index 1a88acf..69aa8b9 100644
--- a/modules/audio_coding/codecs/opus/audio_encoder_opus.cc
+++ b/modules/audio_coding/codecs/opus/audio_encoder_opus.cc
@@ -12,11 +12,11 @@
 
 #include <algorithm>
 #include <iterator>
+#include <string>
 #include <utility>
 
 #include "absl/memory/memory.h"
 #include "absl/strings/match.h"
-#include "common_types.h"
 #include "modules/audio_coding/audio_network_adaptor/audio_network_adaptor_impl.h"
 #include "modules/audio_coding/audio_network_adaptor/controller_manager.h"
 #include "modules/audio_coding/codecs/opus/opus_interface.h"
@@ -26,9 +26,8 @@
 #include "rtc_base/numerics/exp_filter.h"
 #include "rtc_base/numerics/safe_conversions.h"
 #include "rtc_base/numerics/safe_minmax.h"
-#include "rtc_base/protobuf_utils.h"
 #include "rtc_base/string_to_number.h"
-#include "rtc_base/timeutils.h"
+#include "rtc_base/time_utils.h"
 #include "system_wrappers/include/field_trial.h"
 
 namespace webrtc {
@@ -334,19 +333,6 @@
   return absl::nullopt;
 }
 
-AudioEncoderOpusConfig AudioEncoderOpusImpl::CreateConfig(
-    const CodecInst& codec_inst) {
-  AudioEncoderOpusConfig config;
-  config.frame_size_ms = rtc::CheckedDivExact(codec_inst.pacsize, 48);
-  config.num_channels = codec_inst.channels;
-  config.bitrate_bps = codec_inst.rate;
-  config.application = config.num_channels == 1
-                           ? AudioEncoderOpusConfig::ApplicationMode::kVoip
-                           : AudioEncoderOpusConfig::ApplicationMode::kAudio;
-  config.supported_frame_lengths_ms.push_back(config.frame_size_ms);
-  return config;
-}
-
 absl::optional<AudioEncoderOpusConfig> AudioEncoderOpusImpl::SdpToConfig(
     const SdpAudioFormat& format) {
   if (!absl::EqualsIgnoreCase(format.name, "opus") ||
@@ -457,7 +443,7 @@
     : AudioEncoderOpusImpl(
           config,
           payload_type,
-          [this](const ProtoString& config_string, RtcEventLog* event_log) {
+          [this](const std::string& config_string, RtcEventLog* event_log) {
             return DefaultAudioNetworkAdaptorCreator(config_string, event_log);
           },
           // We choose 5sec as initial time constant due to empirical data.
@@ -494,9 +480,6 @@
   SetProjectedPacketLossRate(packet_loss_rate_);
 }
 
-AudioEncoderOpusImpl::AudioEncoderOpusImpl(const CodecInst& codec_inst)
-    : AudioEncoderOpusImpl(CreateConfig(codec_inst), codec_inst.pltype) {}
-
 AudioEncoderOpusImpl::AudioEncoderOpusImpl(int payload_type,
                                            const SdpAudioFormat& format)
     : AudioEncoderOpusImpl(*SdpToConfig(format), payload_type) {}
@@ -784,7 +767,9 @@
                               AudioEncoderOpusConfig::ApplicationMode::kVoip
                           ? 0
                           : 1));
-  RTC_CHECK_EQ(0, WebRtcOpus_SetBitRate(inst_, GetBitrateBps(config)));
+  const int bitrate = GetBitrateBps(config);
+  RTC_CHECK_EQ(0, WebRtcOpus_SetBitRate(inst_, bitrate));
+  RTC_LOG(LS_INFO) << "Set Opus bitrate to " << bitrate << " bps.";
   if (config.fec_enabled) {
     RTC_CHECK_EQ(0, WebRtcOpus_EnableFec(inst_));
   } else {
@@ -847,17 +832,23 @@
 }
 
 void AudioEncoderOpusImpl::SetTargetBitrate(int bits_per_second) {
-  config_.bitrate_bps = rtc::SafeClamp<int>(
+  const int new_bitrate = rtc::SafeClamp<int>(
       bits_per_second, AudioEncoderOpusConfig::kMinBitrateBps,
       AudioEncoderOpusConfig::kMaxBitrateBps);
-  RTC_DCHECK(config_.IsOk());
-  RTC_CHECK_EQ(0, WebRtcOpus_SetBitRate(inst_, GetBitrateBps(config_)));
+  if (config_.bitrate_bps && *config_.bitrate_bps != new_bitrate) {
+    config_.bitrate_bps = new_bitrate;
+    RTC_DCHECK(config_.IsOk());
+    const int bitrate = GetBitrateBps(config_);
+    RTC_CHECK_EQ(0, WebRtcOpus_SetBitRate(inst_, bitrate));
+    RTC_LOG(LS_INFO) << "Set Opus bitrate to " << bitrate << " bps.";
+    bitrate_changed_ = true;
+  }
+
   const auto new_complexity = GetNewComplexity(config_);
   if (new_complexity && complexity_ != *new_complexity) {
     complexity_ = *new_complexity;
     RTC_CHECK_EQ(0, WebRtcOpus_SetComplexity(inst_, complexity_));
   }
-  bitrate_changed_ = true;
 }
 
 void AudioEncoderOpusImpl::ApplyAudioNetworkAdaptor() {
@@ -879,7 +870,7 @@
 
 std::unique_ptr<AudioNetworkAdaptor>
 AudioEncoderOpusImpl::DefaultAudioNetworkAdaptorCreator(
-    const ProtoString& config_string,
+    const std::string& config_string,
     RtcEventLog* event_log) const {
   AudioNetworkAdaptorImpl::Config config;
   config.event_log = event_log;
diff --git a/modules/audio_coding/codecs/opus/audio_encoder_opus.h b/modules/audio_coding/codecs/opus/audio_encoder_opus.h
index 150423f..dc14620 100644
--- a/modules/audio_coding/codecs/opus/audio_encoder_opus.h
+++ b/modules/audio_coding/codecs/opus/audio_encoder_opus.h
@@ -23,15 +23,12 @@
 #include "common_audio/smoothing_filter.h"
 #include "modules/audio_coding/audio_network_adaptor/include/audio_network_adaptor.h"
 #include "modules/audio_coding/codecs/opus/opus_interface.h"
-#include "rtc_base/constructormagic.h"
-#include "rtc_base/protobuf_utils.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
 class RtcEventLog;
 
-struct CodecInst;
-
 class AudioEncoderOpusImpl final : public AudioEncoder {
  public:
   class NewPacketLossRateOptimizer {
@@ -43,9 +40,9 @@
     float OptimizePacketLossRate(float packet_loss_rate) const;
 
     // Getters for testing.
-    float min_packet_loss_rate() const { return min_packet_loss_rate_; };
-    float max_packet_loss_rate() const { return max_packet_loss_rate_; };
-    float slope() const { return slope_; };
+    float min_packet_loss_rate() const { return min_packet_loss_rate_; }
+    float max_packet_loss_rate() const { return max_packet_loss_rate_; }
+    float slope() const { return slope_; }
 
    private:
     const float min_packet_loss_rate_;
@@ -54,8 +51,6 @@
     RTC_DISALLOW_COPY_AND_ASSIGN(NewPacketLossRateOptimizer);
   };
 
-  static AudioEncoderOpusConfig CreateConfig(const CodecInst& codec_inst);
-
   // Returns empty if the current bitrate falls within the hysteresis window,
   // defined by complexity_threshold_bps +/- complexity_threshold_window_bps.
   // Otherwise, returns the current complexity depending on whether the
@@ -83,7 +78,6 @@
       const AudioNetworkAdaptorCreator& audio_network_adaptor_creator,
       std::unique_ptr<SmoothingFilter> bitrate_smoother);
 
-  explicit AudioEncoderOpusImpl(const CodecInst& codec_inst);
   AudioEncoderOpusImpl(int payload_type, const SdpAudioFormat& format);
   ~AudioEncoderOpusImpl() override;
 
@@ -176,7 +170,7 @@
 
   void ApplyAudioNetworkAdaptor();
   std::unique_ptr<AudioNetworkAdaptor> DefaultAudioNetworkAdaptorCreator(
-      const ProtoString& config_string,
+      const std::string& config_string,
       RtcEventLog* event_log) const;
 
   void MaybeUpdateUplinkBandwidth();
diff --git a/modules/audio_coding/codecs/opus/audio_encoder_opus_unittest.cc b/modules/audio_coding/codecs/opus/audio_encoder_opus_unittest.cc
index d5c2c84..b3b531f 100644
--- a/modules/audio_coding/codecs/opus/audio_encoder_opus_unittest.cc
+++ b/modules/audio_coding/codecs/opus/audio_encoder_opus_unittest.cc
@@ -15,17 +15,16 @@
 #include "absl/memory/memory.h"
 #include "api/audio_codecs/opus/audio_encoder_opus.h"
 #include "common_audio/mocks/mock_smoothing_filter.h"
-#include "common_types.h"  // NOLINT(build/include)
 #include "modules/audio_coding/audio_network_adaptor/mock/mock_audio_network_adaptor.h"
 #include "modules/audio_coding/codecs/opus/audio_encoder_opus.h"
 #include "modules/audio_coding/codecs/opus/opus_interface.h"
 #include "modules/audio_coding/neteq/tools/audio_loop.h"
 #include "rtc_base/checks.h"
-#include "rtc_base/fakeclock.h"
+#include "rtc_base/fake_clock.h"
 #include "test/field_trial.h"
 #include "test/gmock.h"
 #include "test/gtest.h"
-#include "test/testsupport/fileutils.h"
+#include "test/testsupport/file_utils.h"
 
 namespace webrtc {
 using ::testing::NiceMock;
@@ -33,21 +32,11 @@
 
 namespace {
 
-const CodecInst kDefaultOpusSettings = {105, "opus", 48000, 960, 1, 32000};
+constexpr int kDefaultOpusPayloadType = 105;
+constexpr int kDefaultOpusRate = 32000;
+constexpr int kDefaultOpusPacSize = 960;
 constexpr int64_t kInitialTimeUs = 12345678;
 
-AudioEncoderOpusConfig CreateConfig(const CodecInst& codec_inst) {
-  AudioEncoderOpusConfig config;
-  config.frame_size_ms = rtc::CheckedDivExact(codec_inst.pacsize, 48);
-  config.num_channels = codec_inst.channels;
-  config.bitrate_bps = codec_inst.rate;
-  config.application = config.num_channels == 1
-                           ? AudioEncoderOpusConfig::ApplicationMode::kVoip
-                           : AudioEncoderOpusConfig::ApplicationMode::kAudio;
-  config.supported_frame_lengths_ms.push_back(config.frame_size_ms);
-  return config;
-}
-
 AudioEncoderOpusConfig CreateConfigWithParameters(
     const SdpAudioFormat::Parameters& params) {
   const SdpAudioFormat format("opus", 48000, 2, params);
@@ -79,16 +68,23 @@
         return adaptor;
       };
 
-  CodecInst codec_inst = kDefaultOpusSettings;
-  codec_inst.channels = num_channels;
-  states->config = CreateConfig(codec_inst);
+  AudioEncoderOpusConfig config;
+  config.frame_size_ms = rtc::CheckedDivExact(kDefaultOpusPacSize, 48);
+  config.num_channels = num_channels;
+  config.bitrate_bps = kDefaultOpusRate;
+  config.application = num_channels == 1
+                           ? AudioEncoderOpusConfig::ApplicationMode::kVoip
+                           : AudioEncoderOpusConfig::ApplicationMode::kAudio;
+  config.supported_frame_lengths_ms.push_back(config.frame_size_ms);
+  states->config = config;
+
   std::unique_ptr<MockSmoothingFilter> bitrate_smoother(
       new MockSmoothingFilter());
   states->mock_bitrate_smoother = bitrate_smoother.get();
 
-  states->encoder.reset(new AudioEncoderOpusImpl(
-      states->config, codec_inst.pltype, std::move(creator),
-      std::move(bitrate_smoother)));
+  states->encoder.reset(
+      new AudioEncoderOpusImpl(states->config, kDefaultOpusPayloadType, creator,
+                               std::move(bitrate_smoother)));
   return states;
 }
 
@@ -436,12 +432,12 @@
 
   auto states = CreateCodec(2);
 
-  states->encoder->OnReceivedUplinkBandwidth(kDefaultOpusSettings.rate * 2,
+  states->encoder->OnReceivedUplinkBandwidth(kDefaultOpusRate * 2,
                                              absl::nullopt);
 
   // Since |OnReceivedOverhead| has not been called, the codec bitrate should
   // not change.
-  EXPECT_EQ(kDefaultOpusSettings.rate, states->encoder->GetTargetBitrate());
+  EXPECT_EQ(kDefaultOpusRate, states->encoder->GetTargetBitrate());
 }
 
 TEST(AudioEncoderOpusTest, OverheadRemovedFromTargetAudioBitrate) {
@@ -456,7 +452,7 @@
   constexpr int kTargetBitrateBps = 40000;
   states->encoder->OnReceivedUplinkBandwidth(kTargetBitrateBps, absl::nullopt);
 
-  int packet_rate = rtc::CheckedDivExact(48000, kDefaultOpusSettings.pacsize);
+  int packet_rate = rtc::CheckedDivExact(48000, kDefaultOpusPacSize);
   EXPECT_EQ(kTargetBitrateBps -
                 8 * static_cast<int>(kOverheadBytesPerPacket) * packet_rate,
             states->encoder->GetTargetBitrate());
@@ -474,7 +470,7 @@
   constexpr size_t kOverheadBytesPerPacket = 64;
   states->encoder->OnReceivedOverhead(kOverheadBytesPerPacket);
 
-  int packet_rate = rtc::CheckedDivExact(48000, kDefaultOpusSettings.pacsize);
+  int packet_rate = rtc::CheckedDivExact(48000, kDefaultOpusPacSize);
 
   // Set a target rate that is smaller than |kMinBitrateBps| when overhead is
   // subtracted. The eventual codec rate should be bounded by |kMinBitrateBps|.
diff --git a/modules/audio_coding/codecs/opus/opus_bandwidth_unittest.cc b/modules/audio_coding/codecs/opus/opus_bandwidth_unittest.cc
index 7e6b626..2c8edf0 100644
--- a/modules/audio_coding/codecs/opus/opus_bandwidth_unittest.cc
+++ b/modules/audio_coding/codecs/opus/opus_bandwidth_unittest.cc
@@ -16,7 +16,7 @@
 #include "modules/audio_coding/neteq/tools/audio_loop.h"
 #include "test/field_trial.h"
 #include "test/gtest.h"
-#include "test/testsupport/fileutils.h"
+#include "test/testsupport/file_utils.h"
 
 namespace webrtc {
 namespace {
diff --git a/modules/audio_coding/codecs/opus/opus_complexity_unittest.cc b/modules/audio_coding/codecs/opus/opus_complexity_unittest.cc
index 4c9174d..84bad33 100644
--- a/modules/audio_coding/codecs/opus/opus_complexity_unittest.cc
+++ b/modules/audio_coding/codecs/opus/opus_complexity_unittest.cc
@@ -11,9 +11,9 @@
 #include "api/audio_codecs/opus/audio_encoder_opus.h"
 #include "modules/audio_coding/neteq/tools/audio_loop.h"
 #include "rtc_base/format_macros.h"
-#include "rtc_base/timeutils.h"
+#include "rtc_base/time_utils.h"
 #include "test/gtest.h"
-#include "test/testsupport/fileutils.h"
+#include "test/testsupport/file_utils.h"
 #include "test/testsupport/perf_test.h"
 
 namespace webrtc {
diff --git a/modules/audio_coding/codecs/opus/opus_fec_test.cc b/modules/audio_coding/codecs/opus/opus_fec_test.cc
index 4fab8a7..7552c20 100644
--- a/modules/audio_coding/codecs/opus/opus_fec_test.cc
+++ b/modules/audio_coding/codecs/opus/opus_fec_test.cc
@@ -13,7 +13,7 @@
 #include "modules/audio_coding/codecs/opus/opus_interface.h"
 #include "rtc_base/format_macros.h"
 #include "test/gtest.h"
-#include "test/testsupport/fileutils.h"
+#include "test/testsupport/file_utils.h"
 
 using std::string;
 using std::tuple;
@@ -238,6 +238,6 @@
                     string("pcm"))};
 
 // 64 kbps, stereo
-INSTANTIATE_TEST_CASE_P(AllTest, OpusFecTest, ::testing::ValuesIn(param_set));
+INSTANTIATE_TEST_SUITE_P(AllTest, OpusFecTest, ::testing::ValuesIn(param_set));
 
 }  // namespace webrtc
diff --git a/modules/audio_coding/codecs/opus/opus_inst.h b/modules/audio_coding/codecs/opus/opus_inst.h
index 2473a5c..0b31181 100644
--- a/modules/audio_coding/codecs/opus/opus_inst.h
+++ b/modules/audio_coding/codecs/opus/opus_inst.h
@@ -17,16 +17,23 @@
 
 RTC_PUSH_IGNORING_WUNDEF()
 #include "opus.h"
+#include "opus_multistream.h"
 RTC_POP_IGNORING_WUNDEF()
 
 struct WebRtcOpusEncInst {
-  OpusEncoder* encoder;
+  union {
+    OpusEncoder* encoder;
+    OpusMSEncoder* multistream_encoder;
+  } encoder;
   size_t channels;
   int in_dtx_mode;
 };
 
 struct WebRtcOpusDecInst {
-  OpusDecoder* decoder;
+  union {
+    OpusDecoder* decoder;
+    OpusMSDecoder* multistream_decoder;
+  } decoder;
   int prev_decoded_samples;
   size_t channels;
   int in_dtx_mode;
diff --git a/modules/audio_coding/codecs/opus/opus_interface.c b/modules/audio_coding/codecs/opus/opus_interface.c
index d219098..3369f8e 100644
--- a/modules/audio_coding/codecs/opus/opus_interface.c
+++ b/modules/audio_coding/codecs/opus/opus_interface.c
@@ -37,6 +37,40 @@
   kWebRtcOpusDefaultFrameSize = 960,
 };
 
+int16_t GetSurroundParameters(int channels,
+                              int *streams,
+                              int *coupled_streams,
+                              unsigned char *mapping) {
+  int opus_error;
+  int ret = 0;
+  // Use 'surround encoder create' to get values for 'coupled_streams',
+  // 'streams' and 'mapping'.
+  OpusMSEncoder* ms_encoder_ptr = opus_multistream_surround_encoder_create(
+      48000,
+      channels,
+      /* mapping family */ channels <= 2 ? 0 : 1,
+      streams,
+      coupled_streams,
+      mapping,
+      OPUS_APPLICATION_VOIP, // Application type shouldn't affect
+                             // streams/mapping values.
+      &opus_error);
+
+  // This shouldn't fail; if it fails,
+  // signal an error and return invalid values.
+  if (opus_error != OPUS_OK || ms_encoder_ptr == NULL) {
+    ret = -1;
+    *streams = -1;
+    *coupled_streams = -1;
+  }
+
+  // We don't need the encoder.
+  if (ms_encoder_ptr != NULL) {
+    opus_multistream_encoder_destroy(ms_encoder_ptr);
+  }
+  return ret;
+}
+
 int16_t WebRtcOpus_EncoderCreate(OpusEncInst** inst,
                                  size_t channels,
                                  int32_t application) {
@@ -55,13 +89,34 @@
       return -1;
   }
 
-  OpusEncInst* state = calloc(1, sizeof(OpusEncInst));
+  OpusEncInst* state = (OpusEncInst*)calloc(1, sizeof(OpusEncInst));
   RTC_DCHECK(state);
 
   int error;
-  state->encoder = opus_encoder_create(48000, (int)channels, opus_app,
-                                       &error);
-  if (error != OPUS_OK || !state->encoder) {
+  if (channels <= 2) {
+    state->encoder.encoder = opus_encoder_create(48000, (int)channels, opus_app,
+                                         &error);
+
+  } else {
+    unsigned char mapping[255];
+    memset(mapping, 0, 255);
+    int streams = -1;
+    int coupled_streams = -1;
+
+    state->encoder.multistream_encoder =
+        opus_multistream_surround_encoder_create(
+        48000,
+        channels,
+        /* mapping family */ 1,
+        &streams,
+        &coupled_streams,
+        mapping,
+        opus_app,
+        &error);
+  }
+
+  if (error != OPUS_OK || (!state->encoder.encoder &&
+                           !state->encoder.multistream_encoder)) {
     WebRtcOpus_EncoderFree(state);
     return -1;
   }
@@ -75,7 +130,11 @@
 
 int16_t WebRtcOpus_EncoderFree(OpusEncInst* inst) {
   if (inst) {
-    opus_encoder_destroy(inst->encoder);
+    if (inst->channels <= 2) {
+      opus_encoder_destroy(inst->encoder.encoder);
+    } else {
+      opus_multistream_encoder_destroy(inst->encoder.multistream_encoder);
+    }
     free(inst);
     return 0;
   } else {
@@ -94,11 +153,19 @@
     return -1;
   }
 
-  res = opus_encode(inst->encoder,
-                    (const opus_int16*)audio_in,
-                    (int)samples,
-                    encoded,
-                    (opus_int32)length_encoded_buffer);
+  if (inst->channels <= 2) {
+    res = opus_encode(inst->encoder.encoder,
+                      (const opus_int16*)audio_in,
+                      (int)samples,
+                      encoded,
+                      (opus_int32)length_encoded_buffer);
+  } else {
+    res = opus_multistream_encode(inst->encoder.multistream_encoder,
+                                  (const opus_int16*)audio_in,
+                                  (int)samples,
+                                  encoded,
+                                  (opus_int32)length_encoded_buffer);
+  }
 
   if (res <= 0) {
     return -1;
@@ -120,9 +187,15 @@
   return res;
 }
 
+#define ENCODER_CTL(inst, vargs) (                                      \
+    inst->channels <= 2 ?                                               \
+    opus_encoder_ctl(inst->encoder.encoder, vargs)                      \
+    : opus_multistream_encoder_ctl(inst->encoder.multistream_encoder, vargs))
+
+
 int16_t WebRtcOpus_SetBitRate(OpusEncInst* inst, int32_t rate) {
   if (inst) {
-    return opus_encoder_ctl(inst->encoder, OPUS_SET_BITRATE(rate));
+    return ENCODER_CTL(inst, OPUS_SET_BITRATE(rate));
   } else {
     return -1;
   }
@@ -130,8 +203,7 @@
 
 int16_t WebRtcOpus_SetPacketLossRate(OpusEncInst* inst, int32_t loss_rate) {
   if (inst) {
-    return opus_encoder_ctl(inst->encoder,
-                            OPUS_SET_PACKET_LOSS_PERC(loss_rate));
+    return ENCODER_CTL(inst, OPUS_SET_PACKET_LOSS_PERC(loss_rate));
   } else {
     return -1;
   }
@@ -154,13 +226,52 @@
   } else {
     set_bandwidth = OPUS_BANDWIDTH_FULLBAND;
   }
-  return opus_encoder_ctl(inst->encoder,
-                          OPUS_SET_MAX_BANDWIDTH(set_bandwidth));
+  return ENCODER_CTL(inst, OPUS_SET_MAX_BANDWIDTH(set_bandwidth));
+}
+
+int16_t WebRtcOpus_GetMaxPlaybackRate(OpusEncInst* const inst,
+                                      int32_t* result_hz) {
+  if (inst->channels <= 2) {
+    if (opus_encoder_ctl(
+            inst->encoder.encoder,
+            OPUS_GET_MAX_BANDWIDTH(result_hz)) == OPUS_OK) {
+      return 0;
+    }
+    return -1;
+  }
+
+  opus_int32 max_bandwidth;
+  int s;
+  int ret;
+
+  max_bandwidth = 0;
+  ret = OPUS_OK;
+  s = 0;
+  while (ret == OPUS_OK) {
+    OpusEncoder *enc;
+    opus_int32 bandwidth;
+
+    ret = ENCODER_CTL(inst, OPUS_MULTISTREAM_GET_ENCODER_STATE(s, &enc));
+    if (ret == OPUS_BAD_ARG)
+      break;
+    if (ret != OPUS_OK)
+      return -1;
+    if (opus_encoder_ctl(enc, OPUS_GET_MAX_BANDWIDTH(&bandwidth)) != OPUS_OK)
+      return -1;
+
+    if (max_bandwidth != 0 && max_bandwidth != bandwidth)
+      return -1;
+
+    max_bandwidth = bandwidth;
+    s++;
+  }
+  *result_hz = max_bandwidth;
+  return 0;
 }
 
 int16_t WebRtcOpus_EnableFec(OpusEncInst* inst) {
   if (inst) {
-    return opus_encoder_ctl(inst->encoder, OPUS_SET_INBAND_FEC(1));
+    return ENCODER_CTL(inst, OPUS_SET_INBAND_FEC(1));
   } else {
     return -1;
   }
@@ -168,7 +279,7 @@
 
 int16_t WebRtcOpus_DisableFec(OpusEncInst* inst) {
   if (inst) {
-    return opus_encoder_ctl(inst->encoder, OPUS_SET_INBAND_FEC(0));
+    return ENCODER_CTL(inst, OPUS_SET_INBAND_FEC(0));
   } else {
     return -1;
   }
@@ -184,21 +295,21 @@
   // last long during a pure silence, if the signal type is not forced.
   // TODO(minyue): Remove the signal type forcing when Opus DTX works properly
   // without it.
-  int ret = opus_encoder_ctl(inst->encoder,
-                             OPUS_SET_SIGNAL(OPUS_SIGNAL_VOICE));
+  int ret = ENCODER_CTL(inst,
+                        OPUS_SET_SIGNAL(OPUS_SIGNAL_VOICE));
   if (ret != OPUS_OK)
     return ret;
 
-  return opus_encoder_ctl(inst->encoder, OPUS_SET_DTX(1));
+  return ENCODER_CTL(inst, OPUS_SET_DTX(1));
 }
 
 int16_t WebRtcOpus_DisableDtx(OpusEncInst* inst) {
   if (inst) {
-    int ret = opus_encoder_ctl(inst->encoder,
-                               OPUS_SET_SIGNAL(OPUS_AUTO));
+    int ret = ENCODER_CTL(inst,
+                          OPUS_SET_SIGNAL(OPUS_AUTO));
     if (ret != OPUS_OK)
       return ret;
-    return opus_encoder_ctl(inst->encoder, OPUS_SET_DTX(0));
+    return ENCODER_CTL(inst, OPUS_SET_DTX(0));
   } else {
     return -1;
   }
@@ -206,7 +317,7 @@
 
 int16_t WebRtcOpus_EnableCbr(OpusEncInst* inst) {
   if (inst) {
-    return opus_encoder_ctl(inst->encoder, OPUS_SET_VBR(0));
+    return ENCODER_CTL(inst, OPUS_SET_VBR(0));
   } else {
     return -1;
   }
@@ -214,7 +325,7 @@
 
 int16_t WebRtcOpus_DisableCbr(OpusEncInst* inst) {
   if (inst) {
-    return opus_encoder_ctl(inst->encoder, OPUS_SET_VBR(1));
+    return ENCODER_CTL(inst, OPUS_SET_VBR(1));
   } else {
     return -1;
   }
@@ -222,7 +333,8 @@
 
 int16_t WebRtcOpus_SetComplexity(OpusEncInst* inst, int32_t complexity) {
   if (inst) {
-    return opus_encoder_ctl(inst->encoder, OPUS_SET_COMPLEXITY(complexity));
+    return ENCODER_CTL(inst,
+                       OPUS_SET_COMPLEXITY(complexity));
   } else {
     return -1;
   }
@@ -233,7 +345,8 @@
     return -1;
   }
   int32_t bandwidth;
-  if (opus_encoder_ctl(inst->encoder, OPUS_GET_BANDWIDTH(&bandwidth)) == 0) {
+  if (ENCODER_CTL(inst,
+                  OPUS_GET_BANDWIDTH(&bandwidth)) == 0) {
     return bandwidth;
   } else {
     return -1;
@@ -243,7 +356,8 @@
 
 int16_t WebRtcOpus_SetBandwidth(OpusEncInst* inst, int32_t bandwidth) {
   if (inst) {
-    return opus_encoder_ctl(inst->encoder, OPUS_SET_BANDWIDTH(bandwidth));
+    return ENCODER_CTL(inst,
+                       OPUS_SET_BANDWIDTH(bandwidth));
   } else {
     return -1;
   }
@@ -253,11 +367,11 @@
   if (!inst)
     return -1;
   if (num_channels == 0) {
-    return opus_encoder_ctl(inst->encoder,
+    return ENCODER_CTL(inst,
                             OPUS_SET_FORCE_CHANNELS(OPUS_AUTO));
   } else if (num_channels == 1 || num_channels == 2) {
-    return opus_encoder_ctl(inst->encoder,
-                            OPUS_SET_FORCE_CHANNELS(num_channels));
+    return ENCODER_CTL(inst,
+                       OPUS_SET_FORCE_CHANNELS(num_channels));
   } else {
     return -1;
   }
@@ -268,16 +382,37 @@
   OpusDecInst* state;
 
   if (inst != NULL) {
-    /* Create Opus decoder state. */
+    // Create Opus decoder state.
     state = (OpusDecInst*) calloc(1, sizeof(OpusDecInst));
     if (state == NULL) {
       return -1;
     }
 
-    /* Create new memory, always at 48000 Hz. */
-    state->decoder = opus_decoder_create(48000, (int)channels, &error);
-    if (error == OPUS_OK && state->decoder != NULL) {
-      /* Creation of memory all ok. */
+    if (channels <= 2) {
+      state->decoder.decoder = opus_decoder_create(48000,
+                                                   (int)channels, &error);
+    } else {
+      unsigned char mapping[255];
+      memset(mapping, 0, 255);
+      int streams = -1;
+      int coupled_streams = -1;
+      if (GetSurroundParameters(channels, &streams,
+                                &coupled_streams, mapping) != 0) {
+        free(state);
+        return -1;
+      }
+
+      // Create new memory, always at 48000 Hz.
+      state->decoder.multistream_decoder = opus_multistream_decoder_create(
+          48000, (int)channels,
+          /* streams = */ streams,
+          /* coupled streams = */ coupled_streams,
+          mapping,
+          &error);
+    }
+    if (error == OPUS_OK && (state->decoder.decoder ||
+                             state->decoder.multistream_decoder)) {
+      // Creation of memory all ok.
       state->channels = channels;
       state->prev_decoded_samples = kWebRtcOpusDefaultFrameSize;
       state->in_dtx_mode = 0;
@@ -285,9 +420,12 @@
       return 0;
     }
 
-    /* If memory allocation was unsuccessful, free the entire state. */
-    if (state->decoder) {
-      opus_decoder_destroy(state->decoder);
+    // If memory allocation was unsuccessful, free the entire state.
+    if (state->decoder.decoder) {
+      opus_decoder_destroy(state->decoder.decoder);
+
+    } else if (state->decoder.multistream_decoder) {
+      opus_multistream_decoder_destroy(state->decoder.multistream_decoder);
     }
     free(state);
   }
@@ -296,7 +434,11 @@
 
 int16_t WebRtcOpus_DecoderFree(OpusDecInst* inst) {
   if (inst) {
-    opus_decoder_destroy(inst->decoder);
+    if (inst->channels <= 2) {
+      opus_decoder_destroy(inst->decoder.decoder);
+    } else if (inst->channels > 2) {
+      opus_multistream_decoder_destroy(inst->decoder.multistream_decoder);
+    }
     free(inst);
     return 0;
   } else {
@@ -309,7 +451,12 @@
 }
 
 void WebRtcOpus_DecoderInit(OpusDecInst* inst) {
-  opus_decoder_ctl(inst->decoder, OPUS_RESET_STATE);
+  if (inst->channels <= 2) {
+    opus_decoder_ctl(inst->decoder.decoder, OPUS_RESET_STATE);
+  } else {
+    opus_multistream_decoder_ctl(inst->decoder.multistream_decoder,
+                                 OPUS_RESET_STATE);
+  }
   inst->in_dtx_mode = 0;
 }
 
@@ -324,6 +471,10 @@
     // fact a 1-byte TOC with a 1-byte payload. That will be erroneously
     // interpreted as comfort noise output, but such a payload is probably
     // faulty anyway.
+
+    // TODO(webrtc:10218): This is wrong for multistream opus. Then are several
+    // single-stream packets glued together with some packet size bytes in
+    // between. See https://tools.ietf.org/html/rfc6716#appendix-B
     inst->in_dtx_mode = 1;
     return 2;  // Comfort noise.
   } else {
@@ -338,8 +489,15 @@
 static int DecodeNative(OpusDecInst* inst, const uint8_t* encoded,
                         size_t encoded_bytes, int frame_size,
                         int16_t* decoded, int16_t* audio_type, int decode_fec) {
-  int res = opus_decode(inst->decoder, encoded, (opus_int32)encoded_bytes,
-                        (opus_int16*)decoded, frame_size, decode_fec);
+  int res = -1;
+  if (inst->channels <= 2) {
+    res = opus_decode(inst->decoder.decoder, encoded, (opus_int32)encoded_bytes,
+                      (opus_int16*)decoded, frame_size, decode_fec);
+  } else {
+    res = opus_multistream_decode(
+        inst->decoder.multistream_decoder, encoded, (opus_int32)encoded_bytes,
+        (opus_int16*)decoded, frame_size, decode_fec);
+  }
 
   if (res <= 0)
     return -1;
diff --git a/modules/audio_coding/codecs/opus/opus_interface.h b/modules/audio_coding/codecs/opus/opus_interface.h
index ddb4ff9..0e97734 100644
--- a/modules/audio_coding/codecs/opus/opus_interface.h
+++ b/modules/audio_coding/codecs/opus/opus_interface.h
@@ -125,6 +125,22 @@
  */
 int16_t WebRtcOpus_SetMaxPlaybackRate(OpusEncInst* inst, int32_t frequency_hz);
 
+/****************************************************************************
+ * WebRtcOpus_GetMaxPlaybackRate(...)
+ *
+ * Queries the maximum playback rate for encoding. If different single-stream
+ * encoders have different maximum playback rates, this function fails.
+ *
+ * Input:
+ *      - inst               : Encoder context.
+ * Output:
+ *      - result_hz          : The maximum playback rate in Hz.
+ * Return value              :  0 - Success
+ *                             -1 - Error
+ */
+int16_t WebRtcOpus_GetMaxPlaybackRate(OpusEncInst* const inst,
+                                      int32_t* result_hz);
+
 /* TODO(minyue): Check whether an API to check the FEC and the packet loss rate
  * is needed. It might not be very useful since there are not many use cases and
  * the caller can always maintain the states. */
diff --git a/modules/audio_coding/codecs/opus/opus_speed_test.cc b/modules/audio_coding/codecs/opus/opus_speed_test.cc
index 03b59ed..1a629a8 100644
--- a/modules/audio_coding/codecs/opus/opus_speed_test.cc
+++ b/modules/audio_coding/codecs/opus/opus_speed_test.cc
@@ -96,17 +96,17 @@
     EncodeDecode(kDurationSec);                                        \
   }
 
-ADD_TEST(10);
-ADD_TEST(9);
-ADD_TEST(8);
-ADD_TEST(7);
-ADD_TEST(6);
-ADD_TEST(5);
-ADD_TEST(4);
-ADD_TEST(3);
-ADD_TEST(2);
-ADD_TEST(1);
-ADD_TEST(0);
+ADD_TEST(10)
+ADD_TEST(9)
+ADD_TEST(8)
+ADD_TEST(7)
+ADD_TEST(6)
+ADD_TEST(5)
+ADD_TEST(4)
+ADD_TEST(3)
+ADD_TEST(2)
+ADD_TEST(1)
+ADD_TEST(0)
 
 #define ADD_BANDWIDTH_TEST(bandwidth)                                \
   TEST_P(OpusSpeedTest, OpusSetBandwidthTest##bandwidth) {           \
@@ -116,11 +116,11 @@
     EncodeDecode(kDurationSec);                                      \
   }
 
-ADD_BANDWIDTH_TEST(OPUS_BANDWIDTH_NARROWBAND);
-ADD_BANDWIDTH_TEST(OPUS_BANDWIDTH_MEDIUMBAND);
-ADD_BANDWIDTH_TEST(OPUS_BANDWIDTH_WIDEBAND);
-ADD_BANDWIDTH_TEST(OPUS_BANDWIDTH_SUPERWIDEBAND);
-ADD_BANDWIDTH_TEST(OPUS_BANDWIDTH_FULLBAND);
+ADD_BANDWIDTH_TEST(OPUS_BANDWIDTH_NARROWBAND)
+ADD_BANDWIDTH_TEST(OPUS_BANDWIDTH_MEDIUMBAND)
+ADD_BANDWIDTH_TEST(OPUS_BANDWIDTH_WIDEBAND)
+ADD_BANDWIDTH_TEST(OPUS_BANDWIDTH_SUPERWIDEBAND)
+ADD_BANDWIDTH_TEST(OPUS_BANDWIDTH_FULLBAND)
 
 // List all test cases: (channel, bit rat, filename, extension).
 const coding_param param_set[] = {
@@ -140,6 +140,8 @@
                     string("pcm"),
                     true)};
 
-INSTANTIATE_TEST_CASE_P(AllTest, OpusSpeedTest, ::testing::ValuesIn(param_set));
+INSTANTIATE_TEST_SUITE_P(AllTest,
+                         OpusSpeedTest,
+                         ::testing::ValuesIn(param_set));
 
 }  // namespace webrtc
diff --git a/modules/audio_coding/codecs/opus/opus_unittest.cc b/modules/audio_coding/codecs/opus/opus_unittest.cc
index 034f8cd..56dfd6a 100644
--- a/modules/audio_coding/codecs/opus/opus_unittest.cc
+++ b/modules/audio_coding/codecs/opus/opus_unittest.cc
@@ -17,7 +17,7 @@
 #include "rtc_base/checks.h"
 #include "rtc_base/numerics/safe_conversions.h"
 #include "test/gtest.h"
-#include "test/testsupport/fileutils.h"
+#include "test/testsupport/file_utils.h"
 
 namespace webrtc {
 
@@ -27,7 +27,7 @@
 using ::testing::Combine;
 
 // Maximum number of bytes in output bitstream.
-const size_t kMaxBytes = 1000;
+const size_t kMaxBytes = 2000;
 // Sample rate of Opus.
 const size_t kOpusRateKhz = 48;
 // Number of samples-per-channel in a 20 ms frame, sampled at 48 kHz.
@@ -86,10 +86,14 @@
 void OpusTest::PrepareSpeechData(size_t channel,
                                  int block_length_ms,
                                  int loop_length_ms) {
+  std::map<int, std::string> channel_to_basename = {
+      {1, "audio_coding/testfile32kHz"},
+      {2, "audio_coding/teststereo32kHz"},
+      {4, "audio_coding/speech_4_channels_48k_one_second"}};
+  std::map<int, std::string> channel_to_suffix = {
+      {1, "pcm"}, {2, "pcm"}, {4, "wav"}};
   const std::string file_name = webrtc::test::ResourcePath(
-      (channel == 1) ? "audio_coding/testfile32kHz"
-                     : "audio_coding/teststereo32kHz",
-      "pcm");
+      channel_to_basename[channel], channel_to_suffix[channel]);
   if (loop_length_ms < block_length_ms) {
     loop_length_ms = block_length_ms;
   }
@@ -103,7 +107,7 @@
                                   int32_t set) {
   opus_int32 bandwidth;
   EXPECT_EQ(0, WebRtcOpus_SetMaxPlaybackRate(opus_encoder_, set));
-  opus_encoder_ctl(opus_encoder_->encoder, OPUS_GET_MAX_BANDWIDTH(&bandwidth));
+  EXPECT_EQ(0, WebRtcOpus_GetMaxPlaybackRate(opus_encoder_, &bandwidth));
   EXPECT_EQ(expect, bandwidth);
 }
 
@@ -354,13 +358,13 @@
   // Test to see that an invalid pointer is caught.
   EXPECT_EQ(-1, WebRtcOpus_EncoderCreate(NULL, 1, 0));
   // Invalid channel number.
-  EXPECT_EQ(-1, WebRtcOpus_EncoderCreate(&opus_encoder, 3, 0));
+  EXPECT_EQ(-1, WebRtcOpus_EncoderCreate(&opus_encoder, 257, 0));
   // Invalid applciation mode.
   EXPECT_EQ(-1, WebRtcOpus_EncoderCreate(&opus_encoder, 1, 2));
 
   EXPECT_EQ(-1, WebRtcOpus_DecoderCreate(NULL, 1));
   // Invalid channel number.
-  EXPECT_EQ(-1, WebRtcOpus_DecoderCreate(&opus_decoder, 3));
+  EXPECT_EQ(-1, WebRtcOpus_DecoderCreate(&opus_decoder, 257));
 }
 
 // Test failing Free.
@@ -382,6 +386,11 @@
   EXPECT_EQ(0, WebRtcOpus_DecoderFree(opus_decoder_));
 }
 
+#define ENCODER_CTL(inst, vargs)                       \
+  inst->channels <= 2                                  \
+      ? opus_encoder_ctl(inst->encoder.encoder, vargs) \
+      : opus_multistream_encoder_ctl(inst->encoder.multistream_encoder, vargs)
+
 TEST_P(OpusTest, OpusEncodeDecode) {
   PrepareSpeechData(channels_, 20, 20);
 
@@ -399,7 +408,7 @@
 
   // Check application mode.
   opus_int32 app;
-  opus_encoder_ctl(opus_encoder_->encoder, OPUS_GET_APPLICATION(&app));
+  ENCODER_CTL(opus_encoder_, OPUS_GET_APPLICATION(&app));
   EXPECT_EQ(application_ == 0 ? OPUS_APPLICATION_VOIP : OPUS_APPLICATION_AUDIO,
             app);
 
@@ -450,6 +459,11 @@
 }
 
 TEST_P(OpusTest, OpusSetBandwidth) {
+  if (channels_ > 2) {
+    // TODO(webrtc:10217): investigate why multi-stream Opus reports
+    // narrowband when it's configured with FULLBAND.
+    return;
+  }
   PrepareSpeechData(channels_, 20, 20);
 
   int16_t audio_type;
@@ -495,7 +509,7 @@
   ASSERT_EQ(0,
             WebRtcOpus_EncoderCreate(&opus_encoder_, channels_, application_));
 
-  if (channels_ == 2) {
+  if (channels_ >= 2) {
     EXPECT_EQ(-1, WebRtcOpus_SetForceChannels(opus_encoder_, 3));
     EXPECT_EQ(0, WebRtcOpus_SetForceChannels(opus_encoder_, 2));
     EXPECT_EQ(0, WebRtcOpus_SetForceChannels(opus_encoder_, 1));
@@ -568,17 +582,17 @@
   opus_int32 dtx;
 
   // DTX is off by default.
-  opus_encoder_ctl(opus_encoder_->encoder, OPUS_GET_DTX(&dtx));
+  ENCODER_CTL(opus_encoder_, OPUS_GET_DTX(&dtx));
   EXPECT_EQ(0, dtx);
 
   // Test to enable DTX.
   EXPECT_EQ(0, WebRtcOpus_EnableDtx(opus_encoder_));
-  opus_encoder_ctl(opus_encoder_->encoder, OPUS_GET_DTX(&dtx));
+  ENCODER_CTL(opus_encoder_, OPUS_GET_DTX(&dtx));
   EXPECT_EQ(1, dtx);
 
   // Test to disable DTX.
   EXPECT_EQ(0, WebRtcOpus_DisableDtx(opus_encoder_));
-  opus_encoder_ctl(opus_encoder_->encoder, OPUS_GET_DTX(&dtx));
+  ENCODER_CTL(opus_encoder_, OPUS_GET_DTX(&dtx));
   EXPECT_EQ(0, dtx);
 
   // Free memory.
@@ -592,6 +606,11 @@
 }
 
 TEST_P(OpusTest, OpusDtxOn) {
+  if (channels_ > 2) {
+    // TODO(webrtc:10218): adapt the test to the sizes and order of multi-stream
+    // DTX packets.
+    return;
+  }
   TestDtxEffect(true, 10);
   TestDtxEffect(true, 20);
   TestDtxEffect(true, 40);
@@ -723,6 +742,12 @@
 }
 
 TEST_P(OpusTest, OpusDecodeRepacketized) {
+  if (channels_ > 2) {
+    // As per the Opus documentation
+    // https://mf4.xiph.org/jenkins/view/opus/job/opus/ws/doc/html/group__opus__repacketizer.html#details,
+    // multiple streams are not supported.
+    return;
+  }
   constexpr size_t kPackets = 6;
 
   PrepareSpeechData(channels_, 20, 20 * kPackets);
@@ -785,8 +810,8 @@
   EXPECT_EQ(0, WebRtcOpus_DecoderFree(opus_decoder_));
 }
 
-INSTANTIATE_TEST_CASE_P(VariousMode,
-                        OpusTest,
-                        Combine(Values(1, 2), Values(0, 1)));
+INSTANTIATE_TEST_SUITE_P(VariousMode,
+                         OpusTest,
+                         Combine(Values(1, 2, 4), Values(0, 1)));
 
 }  // namespace webrtc
diff --git a/modules/audio_coding/codecs/pcm16b/audio_decoder_pcm16b.h b/modules/audio_coding/codecs/pcm16b/audio_decoder_pcm16b.h
index 9b478d8..0334104 100644
--- a/modules/audio_coding/codecs/pcm16b/audio_decoder_pcm16b.h
+++ b/modules/audio_coding/codecs/pcm16b/audio_decoder_pcm16b.h
@@ -17,7 +17,7 @@
 
 #include "api/audio_codecs/audio_decoder.h"
 #include "rtc_base/buffer.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
diff --git a/modules/audio_coding/codecs/pcm16b/audio_encoder_pcm16b.cc b/modules/audio_coding/codecs/pcm16b/audio_encoder_pcm16b.cc
index 106ab16..9445b1e 100644
--- a/modules/audio_coding/codecs/pcm16b/audio_encoder_pcm16b.cc
+++ b/modules/audio_coding/codecs/pcm16b/audio_encoder_pcm16b.cc
@@ -10,7 +10,6 @@
 
 #include "modules/audio_coding/codecs/pcm16b/audio_encoder_pcm16b.h"
 
-#include "common_types.h"
 #include "modules/audio_coding/codecs/pcm16b/pcm16b.h"
 #include "rtc_base/checks.h"
 
@@ -30,20 +29,6 @@
   return CodecType::kOther;
 }
 
-namespace {
-
-AudioEncoderPcm16B::Config CreateConfig(const CodecInst& codec_inst) {
-  AudioEncoderPcm16B::Config config;
-  config.num_channels = codec_inst.channels;
-  config.sample_rate_hz = codec_inst.plfreq;
-  config.frame_size_ms = rtc::CheckedDivExact(
-      codec_inst.pacsize, rtc::CheckedDivExact(config.sample_rate_hz, 1000));
-  config.payload_type = codec_inst.pltype;
-  return config;
-}
-
-}  // namespace
-
 bool AudioEncoderPcm16B::Config::IsOk() const {
   if ((sample_rate_hz != 8000) && (sample_rate_hz != 16000) &&
       (sample_rate_hz != 32000) && (sample_rate_hz != 48000))
@@ -51,7 +36,4 @@
   return AudioEncoderPcm::Config::IsOk();
 }
 
-AudioEncoderPcm16B::AudioEncoderPcm16B(const CodecInst& codec_inst)
-    : AudioEncoderPcm16B(CreateConfig(codec_inst)) {}
-
 }  // namespace webrtc
diff --git a/modules/audio_coding/codecs/pcm16b/audio_encoder_pcm16b.h b/modules/audio_coding/codecs/pcm16b/audio_encoder_pcm16b.h
index d6fd6e1..71c7572 100644
--- a/modules/audio_coding/codecs/pcm16b/audio_encoder_pcm16b.h
+++ b/modules/audio_coding/codecs/pcm16b/audio_encoder_pcm16b.h
@@ -12,12 +12,10 @@
 #define MODULES_AUDIO_CODING_CODECS_PCM16B_AUDIO_ENCODER_PCM16B_H_
 
 #include "modules/audio_coding/codecs/g711/audio_encoder_pcm.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
-struct CodecInst;
-
 class AudioEncoderPcm16B final : public AudioEncoderPcm {
  public:
   struct Config : public AudioEncoderPcm::Config {
@@ -30,7 +28,6 @@
 
   explicit AudioEncoderPcm16B(const Config& config)
       : AudioEncoderPcm(config, config.sample_rate_hz) {}
-  explicit AudioEncoderPcm16B(const CodecInst& codec_inst);
 
  protected:
   size_t EncodeCall(const int16_t* audio,
diff --git a/modules/audio_coding/codecs/red/audio_encoder_copy_red.h b/modules/audio_coding/codecs/red/audio_encoder_copy_red.h
index 5a68876..f05de19 100644
--- a/modules/audio_coding/codecs/red/audio_encoder_copy_red.h
+++ b/modules/audio_coding/codecs/red/audio_encoder_copy_red.h
@@ -19,7 +19,7 @@
 #include "api/array_view.h"
 #include "api/audio_codecs/audio_encoder.h"
 #include "rtc_base/buffer.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
diff --git a/modules/audio_coding/codecs/tools/audio_codec_speed_test.cc b/modules/audio_coding/codecs/tools/audio_codec_speed_test.cc
index c539152..1e6b4f0 100644
--- a/modules/audio_coding/codecs/tools/audio_codec_speed_test.cc
+++ b/modules/audio_coding/codecs/tools/audio_codec_speed_test.cc
@@ -12,7 +12,7 @@
 
 #include "rtc_base/format_macros.h"
 #include "test/gtest.h"
-#include "test/testsupport/fileutils.h"
+#include "test/testsupport/file_utils.h"
 
 using ::std::get;
 
diff --git a/modules/audio_coding/include/audio_coding_module.h b/modules/audio_coding/include/audio_coding_module.h
index f9fdba5..7e5bf1b 100644
--- a/modules/audio_coding/include/audio_coding_module.h
+++ b/modules/audio_coding/include/audio_coding_module.h
@@ -13,12 +13,12 @@
 
 #include <memory>
 #include <string>
+#include <utility>
 #include <vector>
 
 #include "absl/types/optional.h"
 #include "api/audio_codecs/audio_decoder_factory.h"
 #include "api/audio_codecs/audio_encoder.h"
-#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/function_view.h"
@@ -27,12 +27,11 @@
 namespace webrtc {
 
 // forward declarations
-struct CodecInst;
-struct WebRtcRTPHeader;
 class AudioDecoder;
 class AudioEncoder;
 class AudioFrame;
 class RTPFragmentationHeader;
+struct RTPHeader;
 
 #define WEBRTC_10MS_PCM_AUDIO 960  // 16 bits super wideband 48 kHz
 
@@ -77,80 +76,6 @@
   virtual ~AudioCodingModule() = default;
 
   ///////////////////////////////////////////////////////////////////////////
-  //   Utility functions
-  //
-
-  ///////////////////////////////////////////////////////////////////////////
-  // uint8_t NumberOfCodecs()
-  // Returns number of supported codecs.
-  //
-  // Return value:
-  //   number of supported codecs.
-  ///
-  static int NumberOfCodecs();
-
-  ///////////////////////////////////////////////////////////////////////////
-  // int32_t Codec()
-  // Get supported codec with list number.
-  //
-  // Input:
-  //   -list_id             : list number.
-  //
-  // Output:
-  //   -codec              : a structure where the parameters of the codec,
-  //                         given by list number is written to.
-  //
-  // Return value:
-  //   -1 if the list number (list_id) is invalid.
-  //    0 if succeeded.
-  //
-  static int Codec(int list_id, CodecInst* codec);
-
-  ///////////////////////////////////////////////////////////////////////////
-  // int32_t Codec()
-  // Get supported codec with the given codec name, sampling frequency, and
-  // a given number of channels.
-  //
-  // Input:
-  //   -payload_name       : name of the codec.
-  //   -sampling_freq_hz   : sampling frequency of the codec. Note! for RED
-  //                         a sampling frequency of -1 is a valid input.
-  //   -channels           : number of channels ( 1 - mono, 2 - stereo).
-  //
-  // Output:
-  //   -codec              : a structure where the function returns the
-  //                         default parameters of the codec.
-  //
-  // Return value:
-  //   -1 if no codec matches the given parameters.
-  //    0 if succeeded.
-  //
-  static int Codec(const char* payload_name,
-                   CodecInst* codec,
-                   int sampling_freq_hz,
-                   size_t channels);
-
-  ///////////////////////////////////////////////////////////////////////////
-  // int32_t Codec()
-  //
-  // Returns the list number of the given codec name, sampling frequency, and
-  // a given number of channels.
-  //
-  // Input:
-  //   -payload_name        : name of the codec.
-  //   -sampling_freq_hz    : sampling frequency of the codec. Note! for RED
-  //                          a sampling frequency of -1 is a valid input.
-  //   -channels            : number of channels ( 1 - mono, 2 - stereo).
-  //
-  // Return value:
-  //   if the codec is found, the index of the codec in the list,
-  //   -1 if the codec is not found.
-  //
-  static int Codec(const char* payload_name,
-                   int sampling_freq_hz,
-                   size_t channels);
-
-  ///////////////////////////////////////////////////////////////////////////
   //   Sender
   //
 
@@ -170,15 +95,6 @@
   }
 
   ///////////////////////////////////////////////////////////////////////////
-  // int32_t SendCodec()
-  // Get parameters for the codec currently registered as send codec.
-  //
-  // Return value:
-  //   The send codec, or nothing if we don't have one
-  //
-  virtual absl::optional<CodecInst> SendCodec() 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.
   //
@@ -302,60 +218,17 @@
   virtual void SetReceiveCodecs(
       const std::map<int, SdpAudioFormat>& codecs) = 0;
 
-  // Registers a decoder for the given payload type. Returns true iff
-  // successful.
-  virtual bool RegisterReceiveCodec(int rtp_payload_type,
-                                    const SdpAudioFormat& audio_format) = 0;
-
-  // Registers an external decoder. The name is only used to provide information
-  // back to the caller about the decoder. Hence, the name is arbitrary, and may
-  // be empty.
-  virtual int RegisterExternalReceiveCodec(int rtp_payload_type,
-                                           AudioDecoder* external_decoder,
-                                           int sample_rate_hz,
-                                           int num_channels,
-                                           const std::string& name) = 0;
-
   ///////////////////////////////////////////////////////////////////////////
-  // int32_t UnregisterReceiveCodec()
-  // Unregister the codec currently registered with a specific payload type
-  // from the list of possible receive codecs.
-  //
-  // Input:
-  //   -payload_type        : The number representing the payload type to
-  //                         unregister.
-  //
-  // Output:
-  //   -1 if fails to unregister.
-  //    0 if the given codec is successfully unregistered.
-  //
-  virtual int UnregisterReceiveCodec(uint8_t payload_type) = 0;
-
-  ///////////////////////////////////////////////////////////////////////////
-  // int32_t ReceiveCodec()
-  // Get the codec associated with last received payload.
-  //
-  // Output:
-  //   -curr_receive_codec : parameters of the codec associated with the last
-  //                         received payload, c.f. common_types.h for
-  //                         the definition of CodecInst.
+  // absl::optional<std::pair<int, SdpAudioFormat>> ReceiveCodec()
+  // Get the codec info associated with last received payload.
   //
   // Return value:
-  //   -1 if failed to retrieve the codec,
-  //    0 if the codec is successfully retrieved.
-  //
-  virtual int32_t ReceiveCodec(CodecInst* curr_receive_codec) const = 0;
-
-  ///////////////////////////////////////////////////////////////////////////
-  // absl::optional<SdpAudioFormat> ReceiveFormat()
-  // Get the format associated with last received payload.
-  //
-  // Return value:
-  //    An SdpAudioFormat describing the format associated with the last
-  //    received payload.
+  //    A payload type and SdpAudioFormat describing the format associated with
+  //    the last received payload.
   //    An empty Optional if no payload has yet been received.
   //
-  virtual absl::optional<SdpAudioFormat> ReceiveFormat() const = 0;
+  virtual absl::optional<std::pair<int, SdpAudioFormat>>
+      ReceiveCodec() const = 0;
 
   ///////////////////////////////////////////////////////////////////////////
   // int32_t IncomingPacket()
@@ -373,7 +246,7 @@
   //
   virtual int32_t IncomingPacket(const uint8_t* incoming_payload,
                                  const size_t payload_len_bytes,
-                                 const WebRtcRTPHeader& rtp_info) = 0;
+                                 const RTPHeader& rtp_header) = 0;
 
   ///////////////////////////////////////////////////////////////////////////
   // int SetMinimumPlayoutDelay()
@@ -402,6 +275,15 @@
   //
   virtual int SetMaximumPlayoutDelay(int time_ms) = 0;
 
+  // Sets a base minimum for the playout delay. Base minimum delay sets lower
+  // bound minimum delay value which is set via SetMinimumPlayoutDelay.
+  //
+  // Returns true if value was successfully set, false overwise.
+  virtual bool SetBaseMinimumPlayoutDelayMs(int delay_ms) = 0;
+
+  // Returns current value of base minimum delay in milliseconds.
+  virtual int GetBaseMinimumPlayoutDelayMs() const = 0;
+
   ///////////////////////////////////////////////////////////////////////////
   // int32_t PlayoutTimestamp()
   // The send timestamp of an RTP packet is associated with the decoded
diff --git a/modules/audio_coding/include/audio_coding_module_typedefs.h b/modules/audio_coding/include/audio_coding_module_typedefs.h
index bafff72..7aa7f8b 100644
--- a/modules/audio_coding/include/audio_coding_module_typedefs.h
+++ b/modules/audio_coding/include/audio_coding_module_typedefs.h
@@ -80,6 +80,7 @@
   uint64_t concealedSamples;
   uint64_t concealmentEvents;
   uint64_t jitterBufferDelayMs;
+  uint64_t jitterBufferEmittedCount;
   // Stats below DO NOT correspond directly to anything in the WebRTC stats
   // Loss rate (network + late); fraction between 0 and 1, scaled to Q14.
   uint16_t currentPacketLossRate;
@@ -121,6 +122,8 @@
   uint64_t packetBufferFlushes;
   // number of samples expanded due to delayed packets
   uint64_t delayedPacketOutageSamples;
+  // arrival delay of incoming packets
+  uint64_t relativePacketArrivalDelayMs;
 };
 
 }  // namespace webrtc
diff --git a/modules/audio_coding/neteq/accelerate.h b/modules/audio_coding/neteq/accelerate.h
index 1a3af42..124b633 100644
--- a/modules/audio_coding/neteq/accelerate.h
+++ b/modules/audio_coding/neteq/accelerate.h
@@ -15,7 +15,7 @@
 #include <stdint.h>
 
 #include "modules/audio_coding/neteq/time_stretch.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
diff --git a/modules/audio_coding/neteq/audio_decoder_unittest.cc b/modules/audio_coding/neteq/audio_decoder_unittest.cc
index 1ad4835..42d96db 100644
--- a/modules/audio_coding/neteq/audio_decoder_unittest.cc
+++ b/modules/audio_coding/neteq/audio_decoder_unittest.cc
@@ -31,7 +31,7 @@
 #include "modules/audio_coding/codecs/pcm16b/audio_encoder_pcm16b.h"
 #include "modules/audio_coding/neteq/tools/resample_input_audio_file.h"
 #include "test/gtest.h"
-#include "test/testsupport/fileutils.h"
+#include "test/testsupport/file_utils.h"
 
 namespace webrtc {
 
diff --git a/modules/audio_coding/neteq/audio_multi_vector.h b/modules/audio_coding/neteq/audio_multi_vector.h
index a2dd3c3..a21bf57 100644
--- a/modules/audio_coding/neteq/audio_multi_vector.h
+++ b/modules/audio_coding/neteq/audio_multi_vector.h
@@ -17,7 +17,7 @@
 
 #include "api/array_view.h"
 #include "modules/audio_coding/neteq/audio_vector.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 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 5b2ec20..d1351d8 100644
--- a/modules/audio_coding/neteq/audio_multi_vector_unittest.cc
+++ b/modules/audio_coding/neteq/audio_multi_vector_unittest.cc
@@ -309,9 +309,9 @@
   }
 }
 
-INSTANTIATE_TEST_CASE_P(TestNumChannels,
-                        AudioMultiVectorTest,
-                        ::testing::Values(static_cast<size_t>(1),
-                                          static_cast<size_t>(2),
-                                          static_cast<size_t>(5)));
+INSTANTIATE_TEST_SUITE_P(TestNumChannels,
+                         AudioMultiVectorTest,
+                         ::testing::Values(static_cast<size_t>(1),
+                                           static_cast<size_t>(2),
+                                           static_cast<size_t>(5)));
 }  // namespace webrtc
diff --git a/modules/audio_coding/neteq/audio_vector.h b/modules/audio_coding/neteq/audio_vector.h
index d0db332..c8279da 100644
--- a/modules/audio_coding/neteq/audio_vector.h
+++ b/modules/audio_coding/neteq/audio_vector.h
@@ -16,7 +16,7 @@
 #include <memory>
 
 #include "rtc_base/checks.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
diff --git a/modules/audio_coding/neteq/background_noise.h b/modules/audio_coding/neteq/background_noise.h
index 84d7eb9..d047942 100644
--- a/modules/audio_coding/neteq/background_noise.h
+++ b/modules/audio_coding/neteq/background_noise.h
@@ -14,7 +14,7 @@
 #include <string.h>  // size_t
 #include <memory>
 
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
diff --git a/modules/audio_coding/neteq/buffer_level_filter.h b/modules/audio_coding/neteq/buffer_level_filter.h
index c8d27dc..83388fb 100644
--- a/modules/audio_coding/neteq/buffer_level_filter.h
+++ b/modules/audio_coding/neteq/buffer_level_filter.h
@@ -13,7 +13,7 @@
 
 #include <stddef.h>
 
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
diff --git a/modules/audio_coding/neteq/comfort_noise.h b/modules/audio_coding/neteq/comfort_noise.h
index 3a9bfde..f748772 100644
--- a/modules/audio_coding/neteq/comfort_noise.h
+++ b/modules/audio_coding/neteq/comfort_noise.h
@@ -13,7 +13,7 @@
 
 #include <stddef.h>
 
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
diff --git a/modules/audio_coding/neteq/decision_logic.cc b/modules/audio_coding/neteq/decision_logic.cc
index 83c2b3b..fda12c3 100644
--- a/modules/audio_coding/neteq/decision_logic.cc
+++ b/modules/audio_coding/neteq/decision_logic.cc
@@ -23,34 +23,10 @@
 #include "rtc_base/checks.h"
 #include "rtc_base/logging.h"
 #include "rtc_base/numerics/safe_conversions.h"
-#include "system_wrappers/include/field_trial.h"
 
 namespace {
-constexpr char kPostponeDecodingFieldTrial[] =
-    "WebRTC-Audio-NetEqPostponeDecodingAfterExpand";
 
-int GetPostponeDecodingLevel() {
-  const bool enabled =
-      webrtc::field_trial::IsEnabled(kPostponeDecodingFieldTrial);
-  if (!enabled)
-    return 0;
-
-  constexpr int kDefaultPostponeDecodingLevel = 50;
-  const std::string field_trial_string =
-      webrtc::field_trial::FindFullName(kPostponeDecodingFieldTrial);
-  int value = -1;
-  if (sscanf(field_trial_string.c_str(), "Enabled-%d", &value) == 1) {
-    if (value >= 0 && value <= 100) {
-      return value;
-    } else {
-      RTC_LOG(LS_WARNING)
-          << "Wrong value (" << value
-          << ") for postpone decoding after expand, using default ("
-          << kDefaultPostponeDecodingLevel << ")";
-    }
-  }
-  return kDefaultPostponeDecodingLevel;
-}
+constexpr int kPostponeDecodingLevel = 50;
 
 }  // namespace
 
@@ -89,8 +65,7 @@
       disallow_time_stretching_(disallow_time_stretching),
       timescale_countdown_(
           tick_timer_->GetNewCountdown(kMinTimescaleInterval + 1)),
-      num_consecutive_expands_(0),
-      postpone_decoding_level_(GetPostponeDecodingLevel()) {
+      num_consecutive_expands_(0) {
   delay_manager_->set_streaming_mode(false);
   SetSampleRate(fs_hz, output_size_samples);
 }
@@ -141,6 +116,7 @@
 
   const size_t samples_left =
       sync_buffer.FutureLength() - expand.overlap_length();
+  // TODO(jakobi): Use buffer span instead of num samples.
   const size_t cur_size_samples =
       samples_left + packet_buffer_.NumSamplesInBuffer(decoder_frame_length);
 
@@ -194,13 +170,14 @@
   // if the mute factor is low enough (otherwise the expansion was short enough
   // to not be noticable).
   // Note that the MuteFactor is in Q14, so a value of 16384 corresponds to 1.
+  size_t current_span =
+      samples_left + packet_buffer_.GetSpanSamples(decoder_frame_length);
   if ((prev_mode == kModeExpand || prev_mode == kModeCodecPlc) &&
       expand.MuteFactor(0) < 16384 / 2 &&
-      cur_size_samples < static_cast<size_t>(
-              delay_manager_->TargetLevel() * packet_length_samples_ *
-              postpone_decoding_level_ / 100) >> 8 &&
+      current_span < static_cast<size_t>(delay_manager_->TargetLevel() *
+                                         packet_length_samples_ *
+                                         kPostponeDecodingLevel / 100)>> 8 &&
       !packet_buffer_.ContainsDtxOrCngPacket(decoder_database_)) {
-    RTC_DCHECK(webrtc::field_trial::IsEnabled(kPostponeDecodingFieldTrial));
     return kExpand;
   }
 
diff --git a/modules/audio_coding/neteq/decision_logic.h b/modules/audio_coding/neteq/decision_logic.h
index 2a53359..ad8e2cd 100644
--- a/modules/audio_coding/neteq/decision_logic.h
+++ b/modules/audio_coding/neteq/decision_logic.h
@@ -13,7 +13,7 @@
 
 #include "modules/audio_coding/neteq/defines.h"
 #include "modules/audio_coding/neteq/tick_timer.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
@@ -108,10 +108,6 @@
   }
   void set_prev_time_scale(bool value) { prev_time_scale_ = value; }
 
-  int postpone_decoding_level_for_test() const {
-    return postpone_decoding_level_;
-  }
-
  private:
   // The value 5 sets maximum time-stretch rate to about 100 ms/s.
   static const int kMinTimescaleInterval = 5;
@@ -184,7 +180,6 @@
   bool disallow_time_stretching_;
   std::unique_ptr<TickTimer::Countdown> timescale_countdown_;
   int num_consecutive_expands_;
-  const int postpone_decoding_level_;
 
   RTC_DISALLOW_COPY_AND_ASSIGN(DecisionLogic);
 };
diff --git a/modules/audio_coding/neteq/decision_logic_unittest.cc b/modules/audio_coding/neteq/decision_logic_unittest.cc
index 183b9c7..5c3d489 100644
--- a/modules/audio_coding/neteq/decision_logic_unittest.cc
+++ b/modules/audio_coding/neteq/decision_logic_unittest.cc
@@ -16,8 +16,8 @@
 #include "modules/audio_coding/neteq/delay_manager.h"
 #include "modules/audio_coding/neteq/delay_peak_detector.h"
 #include "modules/audio_coding/neteq/packet_buffer.h"
+#include "modules/audio_coding/neteq/statistics_calculator.h"
 #include "modules/audio_coding/neteq/tick_timer.h"
-#include "test/field_trial.h"
 #include "test/gtest.h"
 #include "test/mock_audio_decoder_factory.h"
 
@@ -29,72 +29,18 @@
   DecoderDatabase decoder_database(
       new rtc::RefCountedObject<MockAudioDecoderFactory>, absl::nullopt);
   TickTimer tick_timer;
+  StatisticsCalculator stats;
   PacketBuffer packet_buffer(10, &tick_timer);
-  DelayPeakDetector delay_peak_detector(&tick_timer);
-  DelayManager delay_manager(240, 0, &delay_peak_detector, &tick_timer);
+  DelayPeakDetector delay_peak_detector(&tick_timer, false);
+  auto delay_manager = DelayManager::Create(240, 0, false, &delay_peak_detector,
+                                            &tick_timer, &stats);
   BufferLevelFilter buffer_level_filter;
   DecisionLogic* logic = DecisionLogic::Create(
       fs_hz, output_size_samples, false, &decoder_database, packet_buffer,
-      &delay_manager, &buffer_level_filter, &tick_timer);
+      delay_manager.get(), &buffer_level_filter, &tick_timer);
   delete logic;
 }
 
-TEST(DecisionLogic, PostponeDecodingAfterExpansionSettings) {
-  constexpr int kDefaultPostponeDecodingLevel = 50;
-  constexpr int kFsHz = 8000;
-  constexpr int kOutputSizeSamples = kFsHz / 100;  // Samples per 10 ms.
-  DecoderDatabase decoder_database(
-      new rtc::RefCountedObject<MockAudioDecoderFactory>, absl::nullopt);
-  TickTimer tick_timer;
-  PacketBuffer packet_buffer(10, &tick_timer);
-  DelayPeakDetector delay_peak_detector(&tick_timer);
-  DelayManager delay_manager(240, 0, &delay_peak_detector, &tick_timer);
-  BufferLevelFilter buffer_level_filter;
-  {
-    test::ScopedFieldTrials field_trial(
-        "WebRTC-Audio-NetEqPostponeDecodingAfterExpand/Enabled/");
-    DecisionLogic logic(kFsHz, kOutputSizeSamples, false, &decoder_database,
-                        packet_buffer, &delay_manager, &buffer_level_filter,
-                        &tick_timer);
-    EXPECT_EQ(kDefaultPostponeDecodingLevel,
-              logic.postpone_decoding_level_for_test());
-  }
-  {
-    test::ScopedFieldTrials field_trial(
-        "WebRTC-Audio-NetEqPostponeDecodingAfterExpand/Enabled-65/");
-    DecisionLogic logic(kFsHz, kOutputSizeSamples, false, &decoder_database,
-                        packet_buffer, &delay_manager, &buffer_level_filter,
-                        &tick_timer);
-    EXPECT_EQ(65, logic.postpone_decoding_level_for_test());
-  }
-  {
-    test::ScopedFieldTrials field_trial(
-        "WebRTC-Audio-NetEqPostponeDecodingAfterExpand/Disabled/");
-    DecisionLogic logic(kFsHz, kOutputSizeSamples, false, &decoder_database,
-                        packet_buffer, &delay_manager, &buffer_level_filter,
-                        &tick_timer);
-    EXPECT_EQ(0, logic.postpone_decoding_level_for_test());
-  }
-  {
-    test::ScopedFieldTrials field_trial(
-        "WebRTC-Audio-NetEqPostponeDecodingAfterExpand/Enabled--1/");
-    DecisionLogic logic(kFsHz, kOutputSizeSamples, false, &decoder_database,
-                        packet_buffer, &delay_manager, &buffer_level_filter,
-                        &tick_timer);
-    EXPECT_EQ(kDefaultPostponeDecodingLevel,
-              logic.postpone_decoding_level_for_test());
-  }
-  {
-    test::ScopedFieldTrials field_trial(
-        "WebRTC-Audio-NetEqPostponeDecodingAfterExpand/Enabled-101/");
-    DecisionLogic logic(kFsHz, kOutputSizeSamples, false, &decoder_database,
-                        packet_buffer, &delay_manager, &buffer_level_filter,
-                        &tick_timer);
-    EXPECT_EQ(kDefaultPostponeDecodingLevel,
-              logic.postpone_decoding_level_for_test());
-  }
-}
-
 // TODO(hlundin): Write more tests.
 
 }  // namespace webrtc
diff --git a/modules/audio_coding/neteq/decoder_database.cc b/modules/audio_coding/neteq/decoder_database.cc
index 0890beb..2049569 100644
--- a/modules/audio_coding/neteq/decoder_database.cc
+++ b/modules/audio_coding/neteq/decoder_database.cc
@@ -18,7 +18,6 @@
 
 #include "absl/strings/match.h"
 #include "api/audio_codecs/audio_decoder.h"
-#include "common_types.h"
 #include "rtc_base/checks.h"
 #include "rtc_base/logging.h"
 #include "rtc_base/strings/audio_format_to_string.h"
@@ -44,7 +43,6 @@
       audio_format_(audio_format),
       codec_pair_id_(codec_pair_id),
       factory_(factory),
-      external_decoder_(nullptr),
       cng_decoder_(CngDecoder::Create(audio_format)),
       subtype_(SubtypeFromFormat(audio_format)) {}
 
@@ -54,48 +52,14 @@
     AudioDecoderFactory* factory)
     : DecoderInfo(audio_format, codec_pair_id, factory, audio_format.name) {}
 
-DecoderDatabase::DecoderInfo::DecoderInfo(
-    NetEqDecoder ct,
-    absl::optional<AudioCodecPairId> codec_pair_id,
-    AudioDecoderFactory* factory)
-    : DecoderInfo(*NetEqDecoderToSdpAudioFormat(ct), codec_pair_id, factory) {}
-
-DecoderDatabase::DecoderInfo::DecoderInfo(const SdpAudioFormat& audio_format,
-                                          AudioDecoder* ext_dec,
-                                          const std::string& codec_name)
-    : name_(codec_name),
-      audio_format_(audio_format),
-      codec_pair_id_(absl::nullopt),
-      factory_(nullptr),
-      external_decoder_(ext_dec),
-      subtype_(Subtype::kNormal) {
-  RTC_CHECK(ext_dec);
-}
-
 DecoderDatabase::DecoderInfo::DecoderInfo(DecoderInfo&&) = default;
 DecoderDatabase::DecoderInfo::~DecoderInfo() = default;
 
-bool DecoderDatabase::DecoderInfo::CanGetDecoder() const {
-  if (subtype_ == Subtype::kNormal && !external_decoder_ && !decoder_) {
-    // TODO(ossu): Keep a check here for now, since a number of tests create
-    // DecoderInfos without factories.
-    RTC_DCHECK(factory_);
-    return factory_->IsSupportedDecoder(audio_format_);
-  } else {
-    return true;
-  }
-}
-
 AudioDecoder* DecoderDatabase::DecoderInfo::GetDecoder() const {
   if (subtype_ != Subtype::kNormal) {
     // These are handled internally, so they have no AudioDecoder objects.
     return nullptr;
   }
-  if (external_decoder_) {
-    RTC_DCHECK(!decoder_);
-    RTC_DCHECK(!cng_decoder_);
-    return external_decoder_;
-  }
   if (!decoder_) {
     // TODO(ossu): Keep a check here for now, since a number of tests create
     // DecoderInfos without factories.
@@ -187,32 +151,6 @@
   return changed_payload_types;
 }
 
-int DecoderDatabase::RegisterPayload(uint8_t rtp_payload_type,
-                                     NetEqDecoder codec_type,
-                                     const std::string& name) {
-  if (rtp_payload_type > 0x7F) {
-    return kInvalidRtpPayloadType;
-  }
-  if (codec_type == NetEqDecoder::kDecoderArbitrary) {
-    return kCodecNotSupported;  // Only supported through InsertExternal.
-  }
-  const auto opt_format = NetEqDecoderToSdpAudioFormat(codec_type);
-  if (!opt_format) {
-    return kCodecNotSupported;
-  }
-  DecoderInfo info(*opt_format, codec_pair_id_, decoder_factory_, name);
-  if (!info.CanGetDecoder()) {
-    return kCodecNotSupported;
-  }
-  auto ret =
-      decoders_.insert(std::make_pair(rtp_payload_type, std::move(info)));
-  if (ret.second == false) {
-    // Database already contains a decoder with type |rtp_payload_type|.
-    return kDecoderExists;
-  }
-  return kOK;
-}
-
 int DecoderDatabase::RegisterPayload(int rtp_payload_type,
                                      const SdpAudioFormat& audio_format) {
   if (rtp_payload_type < 0 || rtp_payload_type > 0x7f) {
@@ -228,31 +166,6 @@
   return kOK;
 }
 
-int DecoderDatabase::InsertExternal(uint8_t rtp_payload_type,
-                                    NetEqDecoder codec_type,
-                                    const std::string& codec_name,
-                                    AudioDecoder* decoder) {
-  if (rtp_payload_type > 0x7F) {
-    return kInvalidRtpPayloadType;
-  }
-  if (!decoder) {
-    return kInvalidPointer;
-  }
-
-  const auto opt_db_format = NetEqDecoderToSdpAudioFormat(codec_type);
-  const SdpAudioFormat format =
-      opt_db_format.value_or(SdpAudioFormat("arbitrary", 0, 0));
-
-  std::pair<DecoderMap::iterator, bool> ret;
-  DecoderInfo info(format, decoder, codec_name);
-  ret = decoders_.insert(std::make_pair(rtp_payload_type, std::move(info)));
-  if (ret.second == false) {
-    // Database already contains a decoder with type |rtp_payload_type|.
-    return kDecoderExists;
-  }
-  return kOK;
-}
-
 int DecoderDatabase::Remove(uint8_t rtp_payload_type) {
   if (decoders_.erase(rtp_payload_type) == 0) {
     // No decoder with that |rtp_payload_type|.
diff --git a/modules/audio_coding/neteq/decoder_database.h b/modules/audio_coding/neteq/decoder_database.h
index 131e769..e0a3fe3 100644
--- a/modules/audio_coding/neteq/decoder_database.h
+++ b/modules/audio_coding/neteq/decoder_database.h
@@ -17,12 +17,10 @@
 
 #include "api/audio_codecs/audio_decoder_factory.h"
 #include "api/audio_codecs/audio_format.h"
-#include "common_types.h"  // NOLINT(build/include)  // NULL
+#include "api/scoped_refptr.h"
 #include "modules/audio_coding/codecs/cng/webrtc_cng.h"
-#include "modules/audio_coding/neteq/neteq_decoder_enum.h"
 #include "modules/audio_coding/neteq/packet.h"
-#include "rtc_base/constructormagic.h"
-#include "rtc_base/scoped_ref_ptr.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
@@ -48,19 +46,9 @@
     explicit DecoderInfo(const SdpAudioFormat& audio_format,
                          absl::optional<AudioCodecPairId> codec_pair_id,
                          AudioDecoderFactory* factory = nullptr);
-    explicit DecoderInfo(NetEqDecoder ct,
-                         absl::optional<AudioCodecPairId> codec_pair_id,
-                         AudioDecoderFactory* factory = nullptr);
-    DecoderInfo(const SdpAudioFormat& audio_format,
-                AudioDecoder* ext_dec,
-                const std::string& codec_name);
     DecoderInfo(DecoderInfo&&);
     ~DecoderInfo();
 
-    // Was this info object created with a specification that allows us to
-    // actually produce a decoder?
-    bool CanGetDecoder() const;
-
     // Get the AudioDecoder object, creating it first if necessary.
     AudioDecoder* GetDecoder() const;
 
@@ -110,9 +98,6 @@
     AudioDecoderFactory* const factory_;
     mutable std::unique_ptr<AudioDecoder> decoder_;
 
-    // Set iff this is an external decoder.
-    AudioDecoder* const external_decoder_;
-
     // Set iff this is a comfort noise decoder.
     struct CngDecoder {
       static absl::optional<CngDecoder> Create(const SdpAudioFormat& format);
@@ -153,26 +138,11 @@
   virtual std::vector<int> SetCodecs(
       const std::map<int, SdpAudioFormat>& codecs);
 
-  // Registers |rtp_payload_type| as a decoder of type |codec_type|. The |name|
-  // is only used to populate the name field in the DecoderInfo struct in the
-  // database, and can be arbitrary (including empty). Returns kOK on success;
-  // otherwise an error code.
-  virtual int RegisterPayload(uint8_t rtp_payload_type,
-                              NetEqDecoder codec_type,
-                              const std::string& name);
-
   // Registers a decoder for the given payload type. Returns kOK on success;
   // otherwise an error code.
   virtual int RegisterPayload(int rtp_payload_type,
                               const SdpAudioFormat& audio_format);
 
-  // Registers an externally created AudioDecoder object, and associates it
-  // as a decoder of type |codec_type| with |rtp_payload_type|.
-  virtual int InsertExternal(uint8_t rtp_payload_type,
-                             NetEqDecoder codec_type,
-                             const std::string& codec_name,
-                             AudioDecoder* decoder);
-
   // Removes the entry for |rtp_payload_type| from the database.
   // Returns kDecoderNotFound or kOK depending on the outcome of the operation.
   virtual int Remove(uint8_t rtp_payload_type);
diff --git a/modules/audio_coding/neteq/decoder_database_unittest.cc b/modules/audio_coding/neteq/decoder_database_unittest.cc
index 3c49faa..9a28cac 100644
--- a/modules/audio_coding/neteq/decoder_database_unittest.cc
+++ b/modules/audio_coding/neteq/decoder_database_unittest.cc
@@ -15,7 +15,7 @@
 #include <string>
 
 #include "api/audio_codecs/builtin_audio_decoder_factory.h"
-#include "rtc_base/refcountedobject.h"
+#include "rtc_base/ref_counted_object.h"
 #include "test/gmock.h"
 #include "test/gtest.h"
 #include "test/mock_audio_decoder.h"
@@ -36,17 +36,12 @@
 TEST(DecoderDatabase, InsertAndRemove) {
   rtc::scoped_refptr<MockAudioDecoderFactory> factory(
       new rtc::RefCountedObject<MockAudioDecoderFactory>);
-  EXPECT_CALL(*factory, IsSupportedDecoder(_))
-      .WillOnce(Invoke([](const SdpAudioFormat& format) {
-        EXPECT_EQ("pcmu", format.name);
-        return true;
-      }));
   DecoderDatabase db(factory, absl::nullopt);
   const uint8_t kPayloadType = 0;
   const std::string kCodecName = "Robert\'); DROP TABLE Students;";
   EXPECT_EQ(
       DecoderDatabase::kOK,
-      db.RegisterPayload(kPayloadType, NetEqDecoder::kDecoderPCMu, kCodecName));
+      db.RegisterPayload(kPayloadType, SdpAudioFormat(kCodecName, 8000, 1)));
   EXPECT_EQ(1, db.Size());
   EXPECT_FALSE(db.Empty());
   EXPECT_EQ(DecoderDatabase::kOK, db.Remove(kPayloadType));
@@ -57,22 +52,13 @@
 TEST(DecoderDatabase, InsertAndRemoveAll) {
   rtc::scoped_refptr<MockAudioDecoderFactory> factory(
       new rtc::RefCountedObject<MockAudioDecoderFactory>);
-  EXPECT_CALL(*factory, IsSupportedDecoder(_))
-      .WillOnce(Invoke([](const SdpAudioFormat& format) {
-        EXPECT_EQ("pcmu", format.name);
-        return true;
-      }))
-      .WillOnce(Invoke([](const SdpAudioFormat& format) {
-        EXPECT_EQ("pcma", format.name);
-        return true;
-      }));
   DecoderDatabase db(factory, absl::nullopt);
   const std::string kCodecName1 = "Robert\'); DROP TABLE Students;";
   const std::string kCodecName2 = "https://xkcd.com/327/";
   EXPECT_EQ(DecoderDatabase::kOK,
-            db.RegisterPayload(0, NetEqDecoder::kDecoderPCMu, kCodecName1));
+            db.RegisterPayload(0, SdpAudioFormat(kCodecName1, 8000, 1)));
   EXPECT_EQ(DecoderDatabase::kOK,
-            db.RegisterPayload(1, NetEqDecoder::kDecoderPCMa, kCodecName2));
+            db.RegisterPayload(1, SdpAudioFormat(kCodecName2, 8000, 1)));
   EXPECT_EQ(2, db.Size());
   EXPECT_FALSE(db.Empty());
   db.RemoveAll();
@@ -83,11 +69,6 @@
 TEST(DecoderDatabase, GetDecoderInfo) {
   rtc::scoped_refptr<MockAudioDecoderFactory> factory(
       new rtc::RefCountedObject<MockAudioDecoderFactory>);
-  EXPECT_CALL(*factory, IsSupportedDecoder(_))
-      .WillOnce(Invoke([](const SdpAudioFormat& format) {
-        EXPECT_EQ("pcmu", format.name);
-        return true;
-      }));
   auto* decoder = new MockAudioDecoder;
   EXPECT_CALL(*factory, MakeAudioDecoderMock(_, _, _))
       .WillOnce(Invoke([decoder](const SdpAudioFormat& format,
@@ -98,10 +79,10 @@
       }));
   DecoderDatabase db(factory, absl::nullopt);
   const uint8_t kPayloadType = 0;
-  const std::string kCodecName = "Robert\'); DROP TABLE Students;";
+  const std::string kCodecName = "pcmu";
   EXPECT_EQ(
       DecoderDatabase::kOK,
-      db.RegisterPayload(kPayloadType, NetEqDecoder::kDecoderPCMu, kCodecName));
+      db.RegisterPayload(kPayloadType, SdpAudioFormat(kCodecName, 8000, 1)));
   const DecoderDatabase::DecoderInfo* info;
   info = db.GetDecoderInfo(kPayloadType);
   ASSERT_TRUE(info != NULL);
@@ -115,10 +96,8 @@
 TEST(DecoderDatabase, GetDecoder) {
   DecoderDatabase db(CreateBuiltinAudioDecoderFactory(), absl::nullopt);
   const uint8_t kPayloadType = 0;
-  const std::string kCodecName = "Robert\'); DROP TABLE Students;";
   EXPECT_EQ(DecoderDatabase::kOK,
-            db.RegisterPayload(kPayloadType, NetEqDecoder::kDecoderPCM16B,
-                               kCodecName));
+            db.RegisterPayload(kPayloadType, SdpAudioFormat("l16", 8000, 1)));
   AudioDecoder* dec = db.GetDecoder(kPayloadType);
   ASSERT_TRUE(dec != NULL);
 }
@@ -126,11 +105,6 @@
 TEST(DecoderDatabase, TypeTests) {
   rtc::scoped_refptr<MockAudioDecoderFactory> factory(
       new rtc::RefCountedObject<MockAudioDecoderFactory>);
-  EXPECT_CALL(*factory, IsSupportedDecoder(_))
-      .WillOnce(Invoke([](const SdpAudioFormat& format) {
-        EXPECT_EQ("pcmu", format.name);
-        return true;
-      }));
   DecoderDatabase db(factory, absl::nullopt);
   const uint8_t kPayloadTypePcmU = 0;
   const uint8_t kPayloadTypeCng = 13;
@@ -140,16 +114,15 @@
   // Load into database.
   EXPECT_EQ(
       DecoderDatabase::kOK,
-      db.RegisterPayload(kPayloadTypePcmU, NetEqDecoder::kDecoderPCMu, "pcmu"));
+      db.RegisterPayload(kPayloadTypePcmU, SdpAudioFormat("pcmu", 8000, 1)));
   EXPECT_EQ(DecoderDatabase::kOK,
-            db.RegisterPayload(kPayloadTypeCng, NetEqDecoder::kDecoderCNGnb,
-                               "cng-nb"));
+            db.RegisterPayload(kPayloadTypeCng, SdpAudioFormat("cn", 8000, 1)));
+  EXPECT_EQ(DecoderDatabase::kOK,
+            db.RegisterPayload(kPayloadTypeDtmf,
+                               SdpAudioFormat("telephone-event", 8000, 1)));
   EXPECT_EQ(
       DecoderDatabase::kOK,
-      db.RegisterPayload(kPayloadTypeDtmf, NetEqDecoder::kDecoderAVT, "avt"));
-  EXPECT_EQ(
-      DecoderDatabase::kOK,
-      db.RegisterPayload(kPayloadTypeRed, NetEqDecoder::kDecoderRED, "red"));
+      db.RegisterPayload(kPayloadTypeRed, SdpAudioFormat("red", 8000, 1)));
   EXPECT_EQ(4, db.Size());
   // Test.
   EXPECT_FALSE(db.IsComfortNoise(kPayloadNotUsed));
@@ -165,52 +138,18 @@
   EXPECT_TRUE(db.IsRed(kPayloadTypeRed));
 }
 
-TEST(DecoderDatabase, ExternalDecoder) {
-  DecoderDatabase db(new rtc::RefCountedObject<MockAudioDecoderFactory>,
-                     absl::nullopt);
-  const uint8_t kPayloadType = 0;
-  const std::string kCodecName = "Robert\'); DROP TABLE Students;";
-  MockAudioDecoder decoder;
-  // Load into database.
-  EXPECT_EQ(DecoderDatabase::kOK,
-            db.InsertExternal(kPayloadType, NetEqDecoder::kDecoderPCMu,
-                              kCodecName, &decoder));
-  EXPECT_EQ(1, db.Size());
-  // Get decoder and make sure we get the external one.
-  EXPECT_EQ(&decoder, db.GetDecoder(kPayloadType));
-  // Get the decoder info struct and check it too.
-  const DecoderDatabase::DecoderInfo* info;
-  info = db.GetDecoderInfo(kPayloadType);
-  ASSERT_TRUE(info != NULL);
-  EXPECT_TRUE(info->IsType("pcmu"));
-  EXPECT_EQ(info->get_name(), kCodecName);
-  EXPECT_EQ(kCodecName, info->get_name());
-  // Expect not to delete the decoder when removing it from the database, since
-  // it was declared externally.
-  EXPECT_CALL(decoder, Die()).Times(0);
-  EXPECT_EQ(DecoderDatabase::kOK, db.Remove(kPayloadType));
-  EXPECT_TRUE(db.Empty());
-
-  EXPECT_CALL(decoder, Die()).Times(1);  // Will be called when |db| is deleted.
-}
-
 TEST(DecoderDatabase, CheckPayloadTypes) {
   constexpr int kNumPayloads = 10;
   rtc::scoped_refptr<MockAudioDecoderFactory> factory(
       new rtc::RefCountedObject<MockAudioDecoderFactory>);
-  EXPECT_CALL(*factory, IsSupportedDecoder(_))
-      .Times(kNumPayloads)
-      .WillRepeatedly(Invoke([](const SdpAudioFormat& format) {
-        EXPECT_EQ("pcmu", format.name);
-        return true;
-      }));
   DecoderDatabase db(factory, absl::nullopt);
   // Load a number of payloads into the database. Payload types are 0, 1, ...,
   // while the decoder type is the same for all payload types (this does not
   // matter for the test).
   for (uint8_t payload_type = 0; payload_type < kNumPayloads; ++payload_type) {
-    EXPECT_EQ(DecoderDatabase::kOK,
-              db.RegisterPayload(payload_type, NetEqDecoder::kDecoderPCMu, ""));
+    EXPECT_EQ(
+        DecoderDatabase::kOK,
+        db.RegisterPayload(payload_type, SdpAudioFormat("pcmu", 8000, 1)));
   }
   PacketList packet_list;
   for (int i = 0; i < kNumPayloads + 1; ++i) {
@@ -247,11 +186,11 @@
   DecoderDatabase db(CreateBuiltinAudioDecoderFactory(), absl::nullopt);
   // Load payload types.
   ASSERT_EQ(DecoderDatabase::kOK,
-            db.RegisterPayload(0, NetEqDecoder::kDecoderPCMu, "pcmu"));
+            db.RegisterPayload(0, SdpAudioFormat("pcmu", 8000, 1)));
   ASSERT_EQ(DecoderDatabase::kOK,
-            db.RegisterPayload(103, NetEqDecoder::kDecoderISAC, "isac"));
+            db.RegisterPayload(103, SdpAudioFormat("isac", 16000, 1)));
   ASSERT_EQ(DecoderDatabase::kOK,
-            db.RegisterPayload(13, NetEqDecoder::kDecoderCNGnb, "cng-nb"));
+            db.RegisterPayload(13, SdpAudioFormat("cn", 8000, 1)));
   // Verify that no decoders are active from the start.
   EXPECT_EQ(NULL, db.GetActiveDecoder());
   EXPECT_EQ(NULL, db.GetActiveCngDecoder());
diff --git a/modules/audio_coding/neteq/delay_manager.cc b/modules/audio_coding/neteq/delay_manager.cc
index 67e6a13..4e2f3c7 100644
--- a/modules/audio_coding/neteq/delay_manager.cc
+++ b/modules/audio_coding/neteq/delay_manager.cc
@@ -17,23 +17,39 @@
 #include <numeric>
 #include <string>
 
+#include "absl/memory/memory.h"
 #include "modules/audio_coding/neteq/delay_peak_detector.h"
+#include "modules/audio_coding/neteq/histogram.h"
+#include "modules/audio_coding/neteq/statistics_calculator.h"
 #include "modules/include/module_common_types_public.h"
 #include "rtc_base/checks.h"
 #include "rtc_base/logging.h"
 #include "rtc_base/numerics/safe_conversions.h"
+#include "rtc_base/numerics/safe_minmax.h"
 #include "system_wrappers/include/field_trial.h"
 
 namespace {
 
-constexpr int kLimitProbability = 53687091;         // 1/20 in Q30.
-constexpr int kLimitProbabilityStreaming = 536871;  // 1/2000 in Q30.
-constexpr int kMaxStreamingPeakPeriodMs = 600000;   // 10 minutes in ms.
+constexpr int kLimitProbability = 1020054733;           // 19/20 in Q30.
+constexpr int kLimitProbabilityStreaming = 1073204953;  // 1999/2000 in Q30.
+constexpr int kMaxStreamingPeakPeriodMs = 600000;       // 10 minutes in ms.
 constexpr int kCumulativeSumDrift = 2;  // Drift term for cumulative sum
                                         // |iat_cumulative_sum_|.
-// Steady-state forgetting factor for |iat_vector_|, 0.9993 in Q15.
-constexpr int kIatFactor_ = 32745;
-constexpr int kMaxIat = 64;  // Max inter-arrival time to register.
+constexpr int kMinBaseMinimumDelayMs = 0;
+constexpr int kMaxBaseMinimumDelayMs = 10000;
+constexpr int kIatFactor = 32745;  // 0.9993 in Q15.
+constexpr int kMaxIat = 64;        // Max inter-arrival time to register.
+constexpr int kMaxReorderedPackets =
+    10;  // Max number of consecutive reordered packets.
+constexpr int kMaxHistoryPackets =
+    100;  // Max number of packets used to calculate relative packet arrival
+          // delay.
+constexpr int kDelayBuckets = 100;
+constexpr int kBucketSizeMs = 20;
+
+int PercentileToQuantile(double percentile) {
+  return static_cast<int>((1 << 30) * percentile / 100.0 + 0.5);
+}
 
 absl::optional<int> GetForcedLimitProbability() {
   constexpr char kForceTargetDelayPercentileFieldTrial[] =
@@ -46,8 +62,8 @@
     double percentile = -1.0;
     if (sscanf(field_trial_string.c_str(), "Enabled-%lf", &percentile) == 1 &&
         percentile >= 0.0 && percentile <= 100.0) {
-      return absl::make_optional<int>(static_cast<int>(
-          (1 << 30) * (100.0 - percentile) / 100.0 + 0.5));  // in Q30.
+      return absl::make_optional<int>(
+          PercentileToQuantile(percentile));  // in Q30.
     } else {
       RTC_LOG(LS_WARNING) << "Invalid parameter for "
                           << kForceTargetDelayPercentileFieldTrial
@@ -57,64 +73,111 @@
   return absl::nullopt;
 }
 
+struct DelayHistogramConfig {
+  int quantile = 1020054733;  // 0.95 in Q30.
+  int forget_factor = 32745;  // 0.9993 in Q15.
+};
+
+absl::optional<DelayHistogramConfig> GetDelayHistogramConfig() {
+  constexpr char kDelayHistogramFieldTrial[] =
+      "WebRTC-Audio-NetEqDelayHistogram";
+  const bool use_new_delay_manager =
+      webrtc::field_trial::IsEnabled(kDelayHistogramFieldTrial);
+  if (use_new_delay_manager) {
+    const auto field_trial_string =
+        webrtc::field_trial::FindFullName(kDelayHistogramFieldTrial);
+    DelayHistogramConfig config;
+    double percentile = -1.0;
+    double forget_factor = -1.0;
+    if (sscanf(field_trial_string.c_str(), "Enabled-%lf-%lf", &percentile,
+               &forget_factor) == 2 &&
+        percentile >= 0.0 && percentile <= 100.0 && forget_factor >= 0.0 &&
+        forget_factor <= 1.0) {
+      config.quantile = PercentileToQuantile(percentile);
+      config.forget_factor = (1 << 15) * forget_factor;
+    }
+    RTC_LOG(LS_INFO) << "Delay histogram config:"
+                     << " quantile=" << config.quantile
+                     << " forget_factor=" << config.forget_factor;
+    return absl::make_optional(config);
+  }
+  return absl::nullopt;
+}
+
 }  // namespace
 
 namespace webrtc {
 
 DelayManager::DelayManager(size_t max_packets_in_buffer,
-                           int base_min_target_delay_ms,
+                           int base_minimum_delay_ms,
+                           int histogram_quantile,
+                           HistogramMode histogram_mode,
+                           bool enable_rtx_handling,
                            DelayPeakDetector* peak_detector,
-                           const TickTimer* tick_timer)
+                           const TickTimer* tick_timer,
+                           StatisticsCalculator* statistics,
+                           std::unique_ptr<Histogram> histogram)
     : first_packet_received_(false),
       max_packets_in_buffer_(max_packets_in_buffer),
-      iat_vector_(kMaxIat + 1, 0),
-      iat_factor_(0),
+      histogram_(std::move(histogram)),
+      histogram_quantile_(histogram_quantile),
+      histogram_mode_(histogram_mode),
       tick_timer_(tick_timer),
-      base_min_target_delay_ms_(base_min_target_delay_ms),
+      statistics_(statistics),
+      base_minimum_delay_ms_(base_minimum_delay_ms),
+      effective_minimum_delay_ms_(base_minimum_delay_ms),
       base_target_level_(4),                   // In Q0 domain.
       target_level_(base_target_level_ << 8),  // In Q8 domain.
       packet_len_ms_(0),
       streaming_mode_(false),
       last_seq_no_(0),
       last_timestamp_(0),
-      minimum_delay_ms_(base_min_target_delay_ms_),
-      maximum_delay_ms_(target_level_),
+      minimum_delay_ms_(0),
+      maximum_delay_ms_(0),
       iat_cumulative_sum_(0),
       max_iat_cumulative_sum_(0),
       peak_detector_(*peak_detector),
       last_pack_cng_or_dtmf_(1),
       frame_length_change_experiment_(
           field_trial::IsEnabled("WebRTC-Audio-NetEqFramelengthExperiment")),
-      forced_limit_probability_(GetForcedLimitProbability()) {
+      enable_rtx_handling_(enable_rtx_handling) {
   assert(peak_detector);  // Should never be NULL.
-  RTC_DCHECK_GE(base_min_target_delay_ms_, 0);
-  RTC_DCHECK_LE(minimum_delay_ms_, maximum_delay_ms_);
+  RTC_CHECK(histogram_);
+  RTC_DCHECK_GE(base_minimum_delay_ms_, 0);
 
   Reset();
 }
 
-DelayManager::~DelayManager() {}
-
-const DelayManager::IATVector& DelayManager::iat_vector() const {
-  return iat_vector_;
-}
-
-// Set the histogram vector to an exponentially decaying distribution
-// iat_vector_[i] = 0.5^(i+1), i = 0, 1, 2, ...
-// iat_vector_ is in Q30.
-void DelayManager::ResetHistogram() {
-  // Set temp_prob to (slightly more than) 1 in Q14. This ensures that the sum
-  // of iat_vector_ is 1.
-  uint16_t temp_prob = 0x4002;  // 16384 + 2 = 100000000000010 binary.
-  IATVector::iterator it = iat_vector_.begin();
-  for (; it < iat_vector_.end(); it++) {
-    temp_prob >>= 1;
-    (*it) = temp_prob << 16;
+std::unique_ptr<DelayManager> DelayManager::Create(
+    size_t max_packets_in_buffer,
+    int base_minimum_delay_ms,
+    bool enable_rtx_handling,
+    DelayPeakDetector* peak_detector,
+    const TickTimer* tick_timer,
+    StatisticsCalculator* statistics) {
+  int quantile;
+  std::unique_ptr<Histogram> histogram;
+  HistogramMode mode;
+  auto delay_histogram_config = GetDelayHistogramConfig();
+  if (delay_histogram_config) {
+    DelayHistogramConfig config = delay_histogram_config.value();
+    quantile = config.quantile;
+    histogram =
+        absl::make_unique<Histogram>(kDelayBuckets, config.forget_factor);
+    mode = RELATIVE_ARRIVAL_DELAY;
+  } else {
+    quantile = GetForcedLimitProbability().value_or(kLimitProbability);
+    histogram = absl::make_unique<Histogram>(kMaxIat + 1, kIatFactor);
+    mode = INTER_ARRIVAL_TIME;
   }
-  base_target_level_ = 4;
-  target_level_ = base_target_level_ << 8;
+  return absl::make_unique<DelayManager>(
+      max_packets_in_buffer, base_minimum_delay_ms, quantile, mode,
+      enable_rtx_handling, peak_detector, tick_timer, statistics,
+      std::move(histogram));
 }
 
+DelayManager::~DelayManager() {}
+
 int DelayManager::Update(uint16_t sequence_number,
                          uint32_t timestamp,
                          int sample_rate_hz) {
@@ -146,34 +209,62 @@
         rtc::saturated_cast<int>(1000 * packet_len_samp / sample_rate_hz);
   }
 
+  bool reordered = false;
   if (packet_len_ms > 0) {
     // Cannot update statistics unless |packet_len_ms| is valid.
-    // Calculate inter-arrival time (IAT) in integer "packet times"
-    // (rounding down). This is the value used as index to the histogram
-    // vector |iat_vector_|.
-    int iat_packets = packet_iat_stopwatch_->ElapsedMs() / packet_len_ms;
-
     if (streaming_mode_) {
       UpdateCumulativeSums(packet_len_ms, sequence_number);
     }
 
+    // Inter-arrival time (IAT) in integer "packet times" (rounding down). This
+    // is the value added to the inter-arrival time histogram.
+    int iat_ms = packet_iat_stopwatch_->ElapsedMs();
+    int iat_packets = iat_ms / packet_len_ms;
     // Check for discontinuous packet sequence and re-ordering.
     if (IsNewerSequenceNumber(sequence_number, last_seq_no_ + 1)) {
       // Compensate for gap in the sequence numbers. Reduce IAT with the
-      // expected extra time due to lost packets, but ensure that the IAT is
-      // not negative.
-      iat_packets -= static_cast<uint16_t>(sequence_number - last_seq_no_ - 1);
-      iat_packets = std::max(iat_packets, 0);
+      // expected extra time due to lost packets.
+      int packet_offset =
+          static_cast<uint16_t>(sequence_number - last_seq_no_ - 1);
+      iat_packets -= packet_offset;
+      iat_ms -= packet_offset * packet_len_ms;
     } else if (!IsNewerSequenceNumber(sequence_number, last_seq_no_)) {
-      iat_packets += static_cast<uint16_t>(last_seq_no_ + 1 - sequence_number);
+      int packet_offset =
+          static_cast<uint16_t>(last_seq_no_ + 1 - sequence_number);
+      iat_packets += packet_offset;
+      iat_ms += packet_offset * packet_len_ms;
+      reordered = true;
     }
 
-    // Saturate IAT at maximum value.
-    const int max_iat = kMaxIat;
-    iat_packets = std::min(iat_packets, max_iat);
-    UpdateHistogram(iat_packets);
+    int iat_delay = iat_ms - packet_len_ms;
+    int relative_delay;
+    if (reordered) {
+      relative_delay = std::max(iat_delay, 0);
+    } else {
+      UpdateDelayHistory(iat_delay);
+      relative_delay = CalculateRelativePacketArrivalDelay();
+    }
+    statistics_->RelativePacketArrivalDelay(relative_delay);
+
+    switch (histogram_mode_) {
+      case RELATIVE_ARRIVAL_DELAY: {
+        const int index = relative_delay / kBucketSizeMs;
+        if (index < histogram_->NumBuckets()) {
+          // Maximum delay to register is 2000 ms.
+          histogram_->Add(index);
+        }
+        break;
+      }
+      case INTER_ARRIVAL_TIME: {
+        // Saturate IAT between 0 and maximum value.
+        iat_packets =
+            std::max(std::min(iat_packets, histogram_->NumBuckets() - 1), 0);
+        histogram_->Add(iat_packets);
+        break;
+      }
+    }
     // Calculate new |target_level_| based on updated statistics.
-    target_level_ = CalculateTargetLevel(iat_packets);
+    target_level_ = CalculateTargetLevel(iat_packets, reordered);
     if (streaming_mode_) {
       target_level_ = std::max(target_level_, max_iat_cumulative_sum_);
     }
@@ -181,6 +272,12 @@
     LimitTargetLevel();
   }  // End if (packet_len_ms > 0).
 
+  if (enable_rtx_handling_ && reordered &&
+      num_reordered_packets_ < kMaxReorderedPackets) {
+    ++num_reordered_packets_;
+    return 0;
+  }
+  num_reordered_packets_ = 0;
   // Prepare for next packet arrival.
   packet_iat_stopwatch_ = tick_timer_->GetNewStopwatch();
   last_seq_no_ = sequence_number;
@@ -188,6 +285,26 @@
   return 0;
 }
 
+void DelayManager::UpdateDelayHistory(int iat_delay) {
+  delay_history_.push_back(iat_delay);
+  if (delay_history_.size() > kMaxHistoryPackets) {
+    delay_history_.pop_front();
+  }
+}
+
+int DelayManager::CalculateRelativePacketArrivalDelay() const {
+  // This effectively calculates arrival delay of a packet relative to the
+  // packet preceding the history window. If the arrival delay ever becomes
+  // smaller than zero, it means the reference packet is invalid, and we
+  // move the reference.
+  int relative_delay = 0;
+  for (int delay : delay_history_) {
+    relative_delay += delay;
+    relative_delay = std::max(relative_delay, 0);
+  }
+  return relative_delay;
+}
+
 void DelayManager::UpdateCumulativeSums(int packet_len_ms,
                                         uint16_t sequence_number) {
   // Calculate IAT in Q8, including fractions of a packet (i.e., more
@@ -214,69 +331,19 @@
   }
 }
 
-// Each element in the vector is first multiplied by the forgetting factor
-// |iat_factor_|. Then the vector element indicated by |iat_packets| is then
-// increased (additive) by 1 - |iat_factor_|. This way, the probability of
-// |iat_packets| is slightly increased, while the sum of the histogram remains
-// constant (=1).
-// Due to inaccuracies in the fixed-point arithmetic, the histogram may no
-// longer sum up to 1 (in Q30) after the update. To correct this, a correction
-// term is added or subtracted from the first element (or elements) of the
-// vector.
-// The forgetting factor |iat_factor_| is also updated. When the DelayManager
-// is reset, the factor is set to 0 to facilitate rapid convergence in the
-// beginning. With each update of the histogram, the factor is increased towards
-// the steady-state value |kIatFactor_|.
-void DelayManager::UpdateHistogram(size_t iat_packets) {
-  assert(iat_packets < iat_vector_.size());
-  int vector_sum = 0;  // Sum up the vector elements as they are processed.
-  // Multiply each element in |iat_vector_| with |iat_factor_|.
-  for (IATVector::iterator it = iat_vector_.begin(); it != iat_vector_.end();
-       ++it) {
-    *it = (static_cast<int64_t>(*it) * iat_factor_) >> 15;
-    vector_sum += *it;
-  }
-
-  // Increase the probability for the currently observed inter-arrival time
-  // by 1 - |iat_factor_|. The factor is in Q15, |iat_vector_| in Q30.
-  // Thus, left-shift 15 steps to obtain result in Q30.
-  iat_vector_[iat_packets] += (32768 - iat_factor_) << 15;
-  vector_sum += (32768 - iat_factor_) << 15;  // Add to vector sum.
-
-  // |iat_vector_| should sum up to 1 (in Q30), but it may not due to
-  // fixed-point rounding errors.
-  vector_sum -= 1 << 30;  // Should be zero. Compensate if not.
-  if (vector_sum != 0) {
-    // Modify a few values early in |iat_vector_|.
-    int flip_sign = vector_sum > 0 ? -1 : 1;
-    IATVector::iterator it = iat_vector_.begin();
-    while (it != iat_vector_.end() && abs(vector_sum) > 0) {
-      // Add/subtract 1/16 of the element, but not more than |vector_sum|.
-      int correction = flip_sign * std::min(abs(vector_sum), (*it) >> 4);
-      *it += correction;
-      vector_sum += correction;
-      ++it;
-    }
-  }
-  assert(vector_sum == 0);  // Verify that the above is correct.
-
-  // Update |iat_factor_| (changes only during the first seconds after a reset).
-  // The factor converges to |kIatFactor_|.
-  iat_factor_ += (kIatFactor_ - iat_factor_ + 3) >> 2;
-}
-
 // Enforces upper and lower limits for |target_level_|. The upper limit is
 // chosen to be minimum of i) 75% of |max_packets_in_buffer_|, to leave some
 // headroom for natural fluctuations around the target, and ii) equivalent of
 // |maximum_delay_ms_| in packets. Note that in practice, if no
 // |maximum_delay_ms_| is specified, this does not have any impact, since the
 // target level is far below the buffer capacity in all reasonable cases.
-// The lower limit is equivalent of |minimum_delay_ms_| in packets. We update
-// |least_required_level_| while the above limits are applied.
+// The lower limit is equivalent of |effective_minimum_delay_ms_| in packets.
+// We update |least_required_level_| while the above limits are applied.
 // TODO(hlundin): Move this check to the buffer logistics class.
 void DelayManager::LimitTargetLevel() {
-  if (packet_len_ms_ > 0 && minimum_delay_ms_ > 0) {
-    int minimum_delay_packet_q8 = (minimum_delay_ms_ << 8) / packet_len_ms_;
+  if (packet_len_ms_ > 0 && effective_minimum_delay_ms_ > 0) {
+    int minimum_delay_packet_q8 =
+        (effective_minimum_delay_ms_ << 8) / packet_len_ms_;
     target_level_ = std::max(target_level_, minimum_delay_packet_q8);
   }
 
@@ -294,40 +361,31 @@
   target_level_ = std::max(target_level_, 1 << 8);
 }
 
-int DelayManager::CalculateTargetLevel(int iat_packets) {
-  int limit_probability = forced_limit_probability_.value_or(kLimitProbability);
+int DelayManager::CalculateTargetLevel(int iat_packets, bool reordered) {
+  int limit_probability = histogram_quantile_;
   if (streaming_mode_) {
     limit_probability = kLimitProbabilityStreaming;
   }
 
-  // Calculate target buffer level from inter-arrival time histogram.
-  // Find the |iat_index| for which the probability of observing an
-  // inter-arrival time larger than or equal to |iat_index| is less than or
-  // equal to |limit_probability|. The sought probability is estimated using
-  // the histogram as the reverse cumulant PDF, i.e., the sum of elements from
-  // the end up until |iat_index|. Now, since the sum of all elements is 1
-  // (in Q30) by definition, and since the solution is often a low value for
-  // |iat_index|, it is more efficient to start with |sum| = 1 and subtract
-  // elements from the start of the histogram.
-  size_t index = 0;           // Start from the beginning of |iat_vector_|.
-  int sum = 1 << 30;          // Assign to 1 in Q30.
-  sum -= iat_vector_[index];  // Ensure that target level is >= 1.
-
-  do {
-    // Subtract the probabilities one by one until the sum is no longer greater
-    // than limit_probability.
-    ++index;
-    sum -= iat_vector_[index];
-  } while ((sum > limit_probability) && (index < iat_vector_.size() - 1));
-
-  // This is the base value for the target buffer level.
-  int target_level = static_cast<int>(index);
-  base_target_level_ = static_cast<int>(index);
-
-  // Update detector for delay peaks.
-  bool delay_peak_found = peak_detector_.Update(iat_packets, target_level);
-  if (delay_peak_found) {
-    target_level = std::max(target_level, peak_detector_.MaxPeakHeight());
+  int bucket_index = histogram_->Quantile(limit_probability);
+  int target_level;
+  switch (histogram_mode_) {
+    case RELATIVE_ARRIVAL_DELAY: {
+      target_level = 1 + bucket_index * kBucketSizeMs / packet_len_ms_;
+      base_target_level_ = target_level;
+      break;
+    }
+    case INTER_ARRIVAL_TIME: {
+      target_level = bucket_index;
+      base_target_level_ = target_level;
+      // Update detector for delay peaks.
+      bool delay_peak_found =
+          peak_detector_.Update(iat_packets, reordered, target_level);
+      if (delay_peak_found) {
+        target_level = std::max(target_level, peak_detector_.MaxPeakHeight());
+      }
+      break;
+    }
   }
 
   // Sanity check. |target_level| must be strictly positive.
@@ -342,8 +400,10 @@
     RTC_LOG_F(LS_ERROR) << "length_ms = " << length_ms;
     return -1;
   }
-  if (frame_length_change_experiment_ && packet_len_ms_ != length_ms) {
-    iat_vector_ = ScaleHistogram(iat_vector_, packet_len_ms_, length_ms);
+  if (histogram_mode_ == INTER_ARRIVAL_TIME &&
+      frame_length_change_experiment_ && packet_len_ms_ != length_ms &&
+      packet_len_ms_ > 0) {
+    histogram_->Scale(packet_len_ms_, length_ms);
   }
 
   packet_len_ms_ = length_ms;
@@ -357,8 +417,9 @@
   packet_len_ms_ = 0;  // Packet size unknown.
   streaming_mode_ = false;
   peak_detector_.Reset();
-  ResetHistogram();  // Resets target levels too.
-  iat_factor_ = 0;   // Adapt the histogram faster for the first few packets.
+  histogram_->Reset();
+  base_target_level_ = 4;
+  target_level_ = base_target_level_ << 8;
   packet_iat_stopwatch_ = tick_timer_->GetNewStopwatch();
   max_iat_stopwatch_ = tick_timer_->GetNewStopwatch();
   iat_cumulative_sum_ = 0;
@@ -368,12 +429,14 @@
 
 double DelayManager::EstimatedClockDriftPpm() const {
   double sum = 0.0;
-  // Calculate the expected value based on the probabilities in |iat_vector_|.
-  for (size_t i = 0; i < iat_vector_.size(); ++i) {
-    sum += static_cast<double>(iat_vector_[i]) * i;
+  // Calculate the expected value based on the probabilities in
+  // |histogram_|.
+  auto buckets = histogram_->buckets();
+  for (size_t i = 0; i < buckets.size(); ++i) {
+    sum += static_cast<double>(buckets[i]) * i;
   }
-  // The probabilities in |iat_vector_| are in Q30. Divide by 1 << 30 to convert
-  // to Q0; subtract the nominal inter-arrival time (1) to make a zero
+  // The probabilities in |histogram_| are in Q30. Divide by 1 << 30 to
+  // convert to Q0; subtract the nominal inter-arrival time (1) to make a zero
   // clockdrift represent as 0; mulitply by 1000000 to produce parts-per-million
   // (ppm).
   return (sum / (1 << 30) - 1) * 1e6;
@@ -425,87 +488,53 @@
   ++last_seq_no_;
 }
 
-DelayManager::IATVector DelayManager::ScaleHistogram(const IATVector& histogram,
-                                                     int old_packet_length,
-                                                     int new_packet_length) {
-  if (old_packet_length == 0) {
-    // If we don't know the previous frame length, don't make any changes to the
-    // histogram.
-    return histogram;
-  }
-  RTC_DCHECK_GT(new_packet_length, 0);
-  RTC_DCHECK_EQ(old_packet_length % 10, 0);
-  RTC_DCHECK_EQ(new_packet_length % 10, 0);
-  IATVector new_histogram(histogram.size(), 0);
-  int64_t acc = 0;
-  int time_counter = 0;
-  size_t new_histogram_idx = 0;
-  for (size_t i = 0; i < histogram.size(); i++) {
-    acc += histogram[i];
-    time_counter += old_packet_length;
-    // The bins should be scaled, to ensure the histogram still sums to one.
-    const int64_t scaled_acc = acc * new_packet_length / time_counter;
-    int64_t actually_used_acc = 0;
-    while (time_counter >= new_packet_length) {
-      const int64_t old_histogram_val = new_histogram[new_histogram_idx];
-      new_histogram[new_histogram_idx] =
-          rtc::saturated_cast<int>(old_histogram_val + scaled_acc);
-      actually_used_acc += new_histogram[new_histogram_idx] - old_histogram_val;
-      new_histogram_idx =
-          std::min(new_histogram_idx + 1, new_histogram.size() - 1);
-      time_counter -= new_packet_length;
-    }
-    // Only subtract the part that was succesfully written to the new histogram.
-    acc -= actually_used_acc;
-  }
-  // If there is anything left in acc (due to rounding errors), add it to the
-  // last bin. If we cannot add everything to the last bin we need to add as
-  // much as possible to the bins after the last bin (this is only possible
-  // when compressing a histogram).
-  while (acc > 0 && new_histogram_idx < new_histogram.size()) {
-    const int64_t old_histogram_val = new_histogram[new_histogram_idx];
-    new_histogram[new_histogram_idx] =
-        rtc::saturated_cast<int>(old_histogram_val + acc);
-    acc -= new_histogram[new_histogram_idx] - old_histogram_val;
-    new_histogram_idx++;
-  }
-  RTC_DCHECK_EQ(histogram.size(), new_histogram.size());
-  if (acc == 0) {
-    // If acc is non-zero, we were not able to add everything to the new
-    // histogram, so this check will not hold.
-    RTC_DCHECK_EQ(accumulate(histogram.begin(), histogram.end(), 0ll),
-                  accumulate(new_histogram.begin(), new_histogram.end(), 0ll));
-  }
-  return new_histogram;
+bool DelayManager::IsValidMinimumDelay(int delay_ms) const {
+  return 0 <= delay_ms && delay_ms <= MinimumDelayUpperBound();
+}
+
+bool DelayManager::IsValidBaseMinimumDelay(int delay_ms) const {
+  return kMinBaseMinimumDelayMs <= delay_ms &&
+         delay_ms <= kMaxBaseMinimumDelayMs;
 }
 
 bool DelayManager::SetMinimumDelay(int delay_ms) {
-  // Minimum delay shouldn't be more than maximum delay, if any maximum is set.
-  // Also, if possible check |delay| to less than 75% of
-  // |max_packets_in_buffer_|.
-  if ((maximum_delay_ms_ > 0 && delay_ms > maximum_delay_ms_) ||
-      (packet_len_ms_ > 0 &&
-       delay_ms >
-           static_cast<int>(3 * max_packets_in_buffer_ * packet_len_ms_ / 4))) {
+  if (!IsValidMinimumDelay(delay_ms)) {
     return false;
   }
-  minimum_delay_ms_ = std::max(delay_ms, base_min_target_delay_ms_);
+
+  minimum_delay_ms_ = delay_ms;
+  UpdateEffectiveMinimumDelay();
   return true;
 }
 
 bool DelayManager::SetMaximumDelay(int delay_ms) {
-  if (delay_ms == 0) {
-    // Zero input unsets the maximum delay.
-    maximum_delay_ms_ = 0;
-    return true;
-  } else if (delay_ms < minimum_delay_ms_ || delay_ms < packet_len_ms_) {
+  // If |delay_ms| is zero then it unsets the maximum delay and target level is
+  // unconstrained by maximum delay.
+  if (delay_ms != 0 &&
+      (delay_ms < minimum_delay_ms_ || delay_ms < packet_len_ms_)) {
     // Maximum delay shouldn't be less than minimum delay or less than a packet.
     return false;
   }
+
   maximum_delay_ms_ = delay_ms;
+  UpdateEffectiveMinimumDelay();
   return true;
 }
 
+bool DelayManager::SetBaseMinimumDelay(int delay_ms) {
+  if (!IsValidBaseMinimumDelay(delay_ms)) {
+    return false;
+  }
+
+  base_minimum_delay_ms_ = delay_ms;
+  UpdateEffectiveMinimumDelay();
+  return true;
+}
+
+int DelayManager::GetBaseMinimumDelay() const {
+  return base_minimum_delay_ms_;
+}
+
 int DelayManager::base_target_level() const {
   return base_target_level_;
 }
@@ -519,4 +548,28 @@
 void DelayManager::set_last_pack_cng_or_dtmf(int value) {
   last_pack_cng_or_dtmf_ = value;
 }
+
+void DelayManager::UpdateEffectiveMinimumDelay() {
+  // Clamp |base_minimum_delay_ms_| into the range which can be effectively
+  // used.
+  const int base_minimum_delay_ms =
+      rtc::SafeClamp(base_minimum_delay_ms_, 0, MinimumDelayUpperBound());
+  effective_minimum_delay_ms_ =
+      std::max(minimum_delay_ms_, base_minimum_delay_ms);
+}
+
+int DelayManager::MinimumDelayUpperBound() const {
+  // Choose the lowest possible bound discarding 0 cases which mean the value
+  // is not set and unconstrained.
+  int q75 = MaxBufferTimeQ75();
+  q75 = q75 > 0 ? q75 : kMaxBaseMinimumDelayMs;
+  const int maximum_delay_ms =
+      maximum_delay_ms_ > 0 ? maximum_delay_ms_ : kMaxBaseMinimumDelayMs;
+  return std::min(maximum_delay_ms, q75);
+}
+
+int DelayManager::MaxBufferTimeQ75() const {
+  const int max_buffer_time = max_packets_in_buffer_ * packet_len_ms_;
+  return rtc::dchecked_cast<int>(3 * max_buffer_time / 4);
+}
 }  // namespace webrtc
diff --git a/modules/audio_coding/neteq/delay_manager.h b/modules/audio_coding/neteq/delay_manager.h
index 2c8081b..e54e950 100644
--- a/modules/audio_coding/neteq/delay_manager.h
+++ b/modules/audio_coding/neteq/delay_manager.h
@@ -13,12 +13,14 @@
 
 #include <string.h>  // Provide access to size_t.
 
+#include <deque>
 #include <memory>
-#include <vector>
 
 #include "absl/types/optional.h"
+#include "modules/audio_coding/neteq/histogram.h"
+#include "modules/audio_coding/neteq/statistics_calculator.h"
 #include "modules/audio_coding/neteq/tick_timer.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
@@ -27,23 +29,35 @@
 
 class DelayManager {
  public:
-  typedef std::vector<int> IATVector;
+  enum HistogramMode {
+    INTER_ARRIVAL_TIME,
+    RELATIVE_ARRIVAL_DELAY,
+  };
+
+  DelayManager(size_t max_packets_in_buffer,
+               int base_minimum_delay_ms,
+               int histogram_quantile,
+               HistogramMode histogram_mode,
+               bool enable_rtx_handling,
+               DelayPeakDetector* peak_detector,
+               const TickTimer* tick_timer,
+               StatisticsCalculator* statistics,
+               std::unique_ptr<Histogram> histogram);
 
   // Create a DelayManager object. Notify the delay manager that the packet
   // buffer can hold no more than |max_packets_in_buffer| packets (i.e., this
   // is the number of packet slots in the buffer) and that the target delay
-  // should be greater than or equal to |base_min_target_delay_ms|. Supply a
+  // should be greater than or equal to |base_minimum_delay_ms|. Supply a
   // PeakDetector object to the DelayManager.
-  DelayManager(size_t max_packets_in_buffer,
-               int base_min_target_delay_ms,
-               DelayPeakDetector* peak_detector,
-               const TickTimer* tick_timer);
+  static std::unique_ptr<DelayManager> Create(size_t max_packets_in_buffer,
+                                              int base_minimum_delay_ms,
+                                              bool enable_rtx_handling,
+                                              DelayPeakDetector* peak_detector,
+                                              const TickTimer* tick_timer,
+                                              StatisticsCalculator* statistics);
 
   virtual ~DelayManager();
 
-  // Read the inter-arrival time histogram. Mainly for testing purposes.
-  virtual const IATVector& iat_vector() const;
-
   // Updates the delay manager with a new incoming packet, with
   // |sequence_number| and |timestamp| from the RTP header. This updates the
   // inter-arrival time histogram and other statistics, as well as the
@@ -57,7 +71,7 @@
   // Sets target_level_ (in Q8) and returns the same value. Also calculates
   // and updates base_target_level_, which is the target buffer level before
   // taking delay peaks into account.
-  virtual int CalculateTargetLevel(int iat_packets);
+  virtual int CalculateTargetLevel(int iat_packets, bool reordered);
 
   // Notifies the DelayManager of how much audio data is carried in each packet.
   // The method updates the DelayPeakDetector too, and resets the inter-arrival
@@ -101,53 +115,74 @@
   // packet will shift the sequence numbers for the following packets.
   virtual void RegisterEmptyPacket();
 
-  // Apply compression or stretching to the IAT histogram, for a change in frame
-  // size. This returns an updated histogram. This function is public for
-  // testability.
-  static IATVector ScaleHistogram(const IATVector& histogram,
-                                  int old_packet_length,
-                                  int new_packet_length);
-
   // Accessors and mutators.
   // Assuming |delay| is in valid range.
   virtual bool SetMinimumDelay(int delay_ms);
   virtual bool SetMaximumDelay(int delay_ms);
+  virtual bool SetBaseMinimumDelay(int delay_ms);
+  virtual int GetBaseMinimumDelay() const;
   virtual int base_target_level() const;
   virtual void set_streaming_mode(bool value);
   virtual int last_pack_cng_or_dtmf() const;
   virtual void set_last_pack_cng_or_dtmf(int value);
 
   // This accessor is only intended for testing purposes.
-  const absl::optional<int>& forced_limit_probability_for_test() const {
-    return forced_limit_probability_;
+  int effective_minimum_delay_ms_for_test() const {
+    return effective_minimum_delay_ms_;
   }
 
+  // This accessor is only intended for testing purposes.
+  HistogramMode histogram_mode() const { return histogram_mode_; }
+  int histogram_quantile() const { return histogram_quantile_; }
+  int histogram_forget_factor() const { return histogram_->forget_factor(); }
+
  private:
-  // Sets |iat_vector_| to the default start distribution and sets the
-  // |base_target_level_| and |target_level_| to the corresponding values.
-  void ResetHistogram();
+  // Provides value which minimum delay can't exceed based on current buffer
+  // size and given |maximum_delay_ms_|. Lower bound is a constant 0.
+  int MinimumDelayUpperBound() const;
+
+  // Provides 75% of currently possible maximum buffer size in milliseconds.
+  int MaxBufferTimeQ75() const;
+
+  // Updates |delay_history_|.
+  void UpdateDelayHistory(int iat_delay);
+
+  // Calculate relative packet arrival delay from |delay_history_|.
+  int CalculateRelativePacketArrivalDelay() const;
 
   // Updates |iat_cumulative_sum_| and |max_iat_cumulative_sum_|. (These are
   // used by the streaming mode.) This method is called by Update().
   void UpdateCumulativeSums(int packet_len_ms, uint16_t sequence_number);
 
-  // Updates the histogram |iat_vector_|. The probability for inter-arrival time
-  // equal to |iat_packets| (in integer packets) is increased slightly, while
-  // all other entries are decreased. This method is called by Update().
-  void UpdateHistogram(size_t iat_packets);
+  // Updates |effective_minimum_delay_ms_| delay based on current
+  // |minimum_delay_ms_|, |base_minimum_delay_ms_| and |maximum_delay_ms_|
+  // and buffer size.
+  void UpdateEffectiveMinimumDelay();
 
   // Makes sure that |target_level_| is not too large, taking
   // |max_packets_in_buffer_| and |extra_delay_ms_| into account. This method is
   // called by Update().
   void LimitTargetLevel();
 
+  // Makes sure that |delay_ms| is less than maximum delay, if any maximum
+  // is set. Also, if possible check |delay_ms| to be less than 75% of
+  // |max_packets_in_buffer_|.
+  bool IsValidMinimumDelay(int delay_ms) const;
+
+  bool IsValidBaseMinimumDelay(int delay_ms) const;
+
   bool first_packet_received_;
   const size_t max_packets_in_buffer_;  // Capacity of the packet buffer.
-  IATVector iat_vector_;                // Histogram of inter-arrival times.
-  int iat_factor_;  // Forgetting factor for updating the IAT histogram (Q15).
+  std::unique_ptr<Histogram> histogram_;
+  const int histogram_quantile_;
+  const HistogramMode histogram_mode_;
   const TickTimer* tick_timer_;
-  const int base_min_target_delay_ms_;  // Lower bound for target_level_ and
-                                        // minimum_delay_ms_.
+  StatisticsCalculator* statistics_;
+  int base_minimum_delay_ms_;
+  // Provides delay which is used by LimitTargetLevel as lower bound on target
+  // delay.
+  int effective_minimum_delay_ms_;
+
   // Time elapsed since last packet.
   std::unique_ptr<TickTimer::Stopwatch> packet_iat_stopwatch_;
   int base_target_level_;  // Currently preferred buffer level before peak
@@ -169,7 +204,9 @@
   DelayPeakDetector& peak_detector_;
   int last_pack_cng_or_dtmf_;
   const bool frame_length_change_experiment_;
-  const absl::optional<int> forced_limit_probability_;
+  const bool enable_rtx_handling_;
+  int num_reordered_packets_ = 0;  // Number of consecutive reordered packets.
+  std::deque<int> delay_history_;
 
   RTC_DISALLOW_COPY_AND_ASSIGN(DelayManager);
 };
diff --git a/modules/audio_coding/neteq/delay_manager_unittest.cc b/modules/audio_coding/neteq/delay_manager_unittest.cc
index 6281a15..c57f074 100644
--- a/modules/audio_coding/neteq/delay_manager_unittest.cc
+++ b/modules/audio_coding/neteq/delay_manager_unittest.cc
@@ -14,25 +14,36 @@
 
 #include <math.h>
 
+#include "absl/memory/memory.h"
+#include "modules/audio_coding/neteq/histogram.h"
 #include "modules/audio_coding/neteq/mock/mock_delay_peak_detector.h"
+#include "modules/audio_coding/neteq/mock/mock_histogram.h"
+#include "modules/audio_coding/neteq/mock/mock_statistics_calculator.h"
+#include "rtc_base/checks.h"
 #include "test/field_trial.h"
 #include "test/gmock.h"
 #include "test/gtest.h"
 
 namespace webrtc {
 
+namespace {
+constexpr int kMaxNumberOfPackets = 240;
+constexpr int kMinDelayMs = 0;
+constexpr int kTimeStepMs = 10;
+constexpr int kFs = 8000;
+constexpr int kFrameSizeMs = 20;
+constexpr int kTsIncrement = kFrameSizeMs * kFs / 1000;
+constexpr int kMaxBufferSizeMs = kMaxNumberOfPackets * kFrameSizeMs;
+constexpr int kDefaultHistogramQuantile = 1020054733;
+constexpr int kMaxIat = 64;
+constexpr int kForgetFactor = 32745;
+}  // namespace
+
 using ::testing::Return;
 using ::testing::_;
 
 class DelayManagerTest : public ::testing::Test {
  protected:
-  static const int kMaxNumberOfPackets = 240;
-  static const int kMinDelayMs = 0;
-  static const int kTimeStepMs = 10;
-  static const int kFs = 8000;
-  static const int kFrameSizeMs = 20;
-  static const int kTsIncrement = kFrameSizeMs * kFs / 1000;
-
   DelayManagerTest();
   virtual void SetUp();
   virtual void TearDown();
@@ -43,13 +54,22 @@
 
   std::unique_ptr<DelayManager> dm_;
   TickTimer tick_timer_;
+  MockStatisticsCalculator stats_;
   MockDelayPeakDetector detector_;
+  MockHistogram* mock_histogram_;
   uint16_t seq_no_;
   uint32_t ts_;
+  bool enable_rtx_handling_ = false;
+  bool use_mock_histogram_ = false;
+  DelayManager::HistogramMode histogram_mode_ =
+      DelayManager::HistogramMode::INTER_ARRIVAL_TIME;
 };
 
 DelayManagerTest::DelayManagerTest()
-    : dm_(nullptr), detector_(&tick_timer_), seq_no_(0x1234), ts_(0x12345678) {}
+    : dm_(nullptr),
+      detector_(&tick_timer_, false),
+      seq_no_(0x1234),
+      ts_(0x12345678) {}
 
 void DelayManagerTest::SetUp() {
   RecreateDelayManager();
@@ -57,8 +77,18 @@
 
 void DelayManagerTest::RecreateDelayManager() {
   EXPECT_CALL(detector_, Reset()).Times(1);
-  dm_.reset(new DelayManager(kMaxNumberOfPackets, kMinDelayMs, &detector_,
-                             &tick_timer_));
+  if (use_mock_histogram_) {
+    mock_histogram_ = new MockHistogram(kMaxIat, kForgetFactor);
+    std::unique_ptr<Histogram> histogram(mock_histogram_);
+    dm_ = absl::make_unique<DelayManager>(
+        kMaxNumberOfPackets, kMinDelayMs, kDefaultHistogramQuantile,
+        histogram_mode_, enable_rtx_handling_, &detector_, &tick_timer_,
+        &stats_, std::move(histogram));
+  } else {
+    dm_ = DelayManager::Create(kMaxNumberOfPackets, kMinDelayMs,
+                               enable_rtx_handling_, &detector_, &tick_timer_,
+                               &stats_);
+  }
 }
 
 void DelayManagerTest::SetPacketAudioLength(int lengt_ms) {
@@ -86,17 +116,6 @@
   // object.
 }
 
-TEST_F(DelayManagerTest, VectorInitialization) {
-  const DelayManager::IATVector& vec = dm_->iat_vector();
-  double sum = 0.0;
-  for (size_t i = 0; i < vec.size(); i++) {
-    EXPECT_NEAR(ldexp(pow(0.5, static_cast<int>(i + 1)), 30), vec[i], 65537);
-    // Tolerance 65537 in Q30 corresponds to a delta of approximately 0.00006.
-    sum += vec[i];
-  }
-  EXPECT_EQ(1 << 30, static_cast<int>(sum));  // Should be 1 in Q30.
-}
-
 TEST_F(DelayManagerTest, SetPacketAudioLength) {
   const int kLengthMs = 30;
   // Expect DelayManager to pass on the new length to the detector object.
@@ -126,7 +145,7 @@
   // Expect detector update method to be called once with inter-arrival time
   // equal to 1 packet, and (base) target level equal to 1 as well.
   // Return false to indicate no peaks found.
-  EXPECT_CALL(detector_, Update(1, 1)).WillOnce(Return(false));
+  EXPECT_CALL(detector_, Update(1, false, 1)).WillOnce(Return(false));
   InsertNextPacket();
   EXPECT_EQ(1 << 8, dm_->TargetLevel());  // In Q8.
   EXPECT_EQ(1, dm_->base_target_level());
@@ -149,7 +168,7 @@
   // Expect detector update method to be called once with inter-arrival time
   // equal to 1 packet, and (base) target level equal to 1 as well.
   // Return false to indicate no peaks found.
-  EXPECT_CALL(detector_, Update(2, 2)).WillOnce(Return(false));
+  EXPECT_CALL(detector_, Update(2, false, 2)).WillOnce(Return(false));
   InsertNextPacket();
   EXPECT_EQ(2 << 8, dm_->TargetLevel());  // In Q8.
   EXPECT_EQ(2, dm_->base_target_level());
@@ -172,7 +191,7 @@
   // Expect detector update method to be called once with inter-arrival time
   // equal to 1 packet, and (base) target level equal to 1 as well.
   // Return true to indicate that peaks are found. Let the peak height be 5.
-  EXPECT_CALL(detector_, Update(1, 1)).WillOnce(Return(true));
+  EXPECT_CALL(detector_, Update(1, false, 1)).WillOnce(Return(true));
   EXPECT_CALL(detector_, MaxPeakHeight()).WillOnce(Return(5));
   InsertNextPacket();
   EXPECT_EQ(5 << 8, dm_->TargetLevel());
@@ -194,7 +213,7 @@
   // Expect detector update method to be called once with inter-arrival time
   // equal to 1 packet, and (base) target level equal to 1 as well.
   // Return false to indicate no peaks found.
-  EXPECT_CALL(detector_, Update(1, 1)).WillOnce(Return(false));
+  EXPECT_CALL(detector_, Update(1, false, 1)).WillOnce(Return(false));
   InsertNextPacket();
   const int kExpectedTarget = 1;
   EXPECT_EQ(kExpectedTarget << 8, dm_->TargetLevel());  // In Q8.
@@ -216,7 +235,7 @@
   // Second packet arrival.
   // Expect detector update method to be called once with inter-arrival time
   // equal to |kExpectedTarget| packet. Return true to indicate peaks found.
-  EXPECT_CALL(detector_, Update(kExpectedTarget, _))
+  EXPECT_CALL(detector_, Update(kExpectedTarget, false, _))
       .WillRepeatedly(Return(true));
   EXPECT_CALL(detector_, MaxPeakHeight())
       .WillRepeatedly(Return(kExpectedTarget));
@@ -246,7 +265,7 @@
   // Second packet arrival.
   // Expect detector update method to be called once with inter-arrival time
   // equal to |kExpectedTarget| packet. Return true to indicate peaks found.
-  EXPECT_CALL(detector_, Update(kExpectedTarget, _))
+  EXPECT_CALL(detector_, Update(kExpectedTarget, false, _))
       .WillRepeatedly(Return(true));
   EXPECT_CALL(detector_, MaxPeakHeight())
       .WillRepeatedly(Return(kExpectedTarget));
@@ -264,6 +283,236 @@
   EXPECT_EQ(kMinDelayPackets << 8, dm_->TargetLevel());
 }
 
+TEST_F(DelayManagerTest, BaseMinimumDelayCheckValidRange) {
+  SetPacketAudioLength(kFrameSizeMs);
+
+  // Base minimum delay should be between [0, 10000] milliseconds.
+  EXPECT_FALSE(dm_->SetBaseMinimumDelay(-1));
+  EXPECT_FALSE(dm_->SetBaseMinimumDelay(10001));
+  EXPECT_EQ(dm_->GetBaseMinimumDelay(), 0);
+
+  EXPECT_TRUE(dm_->SetBaseMinimumDelay(7999));
+  EXPECT_EQ(dm_->GetBaseMinimumDelay(), 7999);
+}
+
+TEST_F(DelayManagerTest, BaseMinimumDelayLowerThanMinimumDelay) {
+  SetPacketAudioLength(kFrameSizeMs);
+  constexpr int kBaseMinimumDelayMs = 100;
+  constexpr int kMinimumDelayMs = 200;
+
+  // Base minimum delay sets lower bound on minimum. That is why when base
+  // minimum delay is lower than minimum delay we use minimum delay.
+  RTC_DCHECK_LT(kBaseMinimumDelayMs, kMinimumDelayMs);
+
+  EXPECT_TRUE(dm_->SetBaseMinimumDelay(kBaseMinimumDelayMs));
+  EXPECT_TRUE(dm_->SetMinimumDelay(kMinimumDelayMs));
+  EXPECT_EQ(dm_->effective_minimum_delay_ms_for_test(), kMinimumDelayMs);
+}
+
+TEST_F(DelayManagerTest, BaseMinimumDelayGreaterThanMinimumDelay) {
+  SetPacketAudioLength(kFrameSizeMs);
+  constexpr int kBaseMinimumDelayMs = 70;
+  constexpr int kMinimumDelayMs = 30;
+
+  // Base minimum delay sets lower bound on minimum. That is why when base
+  // minimum delay is greater than minimum delay we use base minimum delay.
+  RTC_DCHECK_GT(kBaseMinimumDelayMs, kMinimumDelayMs);
+
+  EXPECT_TRUE(dm_->SetBaseMinimumDelay(kBaseMinimumDelayMs));
+  EXPECT_TRUE(dm_->SetMinimumDelay(kMinimumDelayMs));
+  EXPECT_EQ(dm_->effective_minimum_delay_ms_for_test(), kBaseMinimumDelayMs);
+}
+
+TEST_F(DelayManagerTest, BaseMinimumDelayGreaterThanBufferSize) {
+  SetPacketAudioLength(kFrameSizeMs);
+  constexpr int kBaseMinimumDelayMs = kMaxBufferSizeMs + 1;
+  constexpr int kMinimumDelayMs = 12;
+  constexpr int kMaximumDelayMs = 20;
+  constexpr int kMaxBufferSizeMsQ75 = 3 * kMaxBufferSizeMs / 4;
+
+  EXPECT_TRUE(dm_->SetMaximumDelay(kMaximumDelayMs));
+
+  // Base minimum delay is greater than minimum delay, that is why we clamp
+  // it to current the highest possible value which is maximum delay.
+  RTC_DCHECK_GT(kBaseMinimumDelayMs, kMinimumDelayMs);
+  RTC_DCHECK_GT(kBaseMinimumDelayMs, kMaxBufferSizeMs);
+  RTC_DCHECK_GT(kBaseMinimumDelayMs, kMaximumDelayMs);
+  RTC_DCHECK_LT(kMaximumDelayMs, kMaxBufferSizeMsQ75);
+
+  EXPECT_TRUE(dm_->SetMinimumDelay(kMinimumDelayMs));
+  EXPECT_TRUE(dm_->SetBaseMinimumDelay(kBaseMinimumDelayMs));
+
+  // Unset maximum value.
+  EXPECT_TRUE(dm_->SetMaximumDelay(0));
+
+  // With maximum value unset, the highest possible value now is 75% of
+  // currently possible maximum buffer size.
+  EXPECT_EQ(dm_->effective_minimum_delay_ms_for_test(), kMaxBufferSizeMsQ75);
+}
+
+TEST_F(DelayManagerTest, BaseMinimumDelayGreaterThanMaximumDelay) {
+  SetPacketAudioLength(kFrameSizeMs);
+  constexpr int kMaximumDelayMs = 400;
+  constexpr int kBaseMinimumDelayMs = kMaximumDelayMs + 1;
+  constexpr int kMinimumDelayMs = 20;
+
+  // Base minimum delay is greater than minimum delay, that is why we clamp
+  // it to current the highest possible value which is kMaximumDelayMs.
+  RTC_DCHECK_GT(kBaseMinimumDelayMs, kMinimumDelayMs);
+  RTC_DCHECK_GT(kBaseMinimumDelayMs, kMaximumDelayMs);
+  RTC_DCHECK_LT(kMaximumDelayMs, kMaxBufferSizeMs);
+
+  EXPECT_TRUE(dm_->SetMaximumDelay(kMaximumDelayMs));
+  EXPECT_TRUE(dm_->SetMinimumDelay(kMinimumDelayMs));
+  EXPECT_TRUE(dm_->SetBaseMinimumDelay(kBaseMinimumDelayMs));
+  EXPECT_EQ(dm_->effective_minimum_delay_ms_for_test(), kMaximumDelayMs);
+}
+
+TEST_F(DelayManagerTest, BaseMinimumDelayLowerThanMaxSize) {
+  SetPacketAudioLength(kFrameSizeMs);
+  constexpr int kMaximumDelayMs = 400;
+  constexpr int kBaseMinimumDelayMs = kMaximumDelayMs - 1;
+  constexpr int kMinimumDelayMs = 20;
+
+  // Base minimum delay is greater than minimum delay, and lower than maximum
+  // delays that is why it is used.
+  RTC_DCHECK_GT(kBaseMinimumDelayMs, kMinimumDelayMs);
+  RTC_DCHECK_LT(kBaseMinimumDelayMs, kMaximumDelayMs);
+
+  EXPECT_TRUE(dm_->SetMaximumDelay(kMaximumDelayMs));
+  EXPECT_TRUE(dm_->SetMinimumDelay(kMinimumDelayMs));
+  EXPECT_TRUE(dm_->SetBaseMinimumDelay(kBaseMinimumDelayMs));
+  EXPECT_EQ(dm_->effective_minimum_delay_ms_for_test(), kBaseMinimumDelayMs);
+}
+
+TEST_F(DelayManagerTest, MinimumDelayMemorization) {
+  // Check that when we increase base minimum delay to value higher than
+  // minimum delay then minimum delay is still memorized. This allows to
+  // restore effective minimum delay to memorized minimum delay value when we
+  // decrease base minimum delay.
+  SetPacketAudioLength(kFrameSizeMs);
+
+  constexpr int kBaseMinimumDelayMsLow = 10;
+  constexpr int kMinimumDelayMs = 20;
+  constexpr int kBaseMinimumDelayMsHigh = 30;
+
+  EXPECT_TRUE(dm_->SetBaseMinimumDelay(kBaseMinimumDelayMsLow));
+  EXPECT_TRUE(dm_->SetMinimumDelay(kMinimumDelayMs));
+  // Minimum delay is used as it is higher than base minimum delay.
+  EXPECT_EQ(dm_->effective_minimum_delay_ms_for_test(), kMinimumDelayMs);
+
+  EXPECT_TRUE(dm_->SetBaseMinimumDelay(kBaseMinimumDelayMsHigh));
+  // Base minimum delay is used as it is now higher than minimum delay.
+  EXPECT_EQ(dm_->effective_minimum_delay_ms_for_test(),
+            kBaseMinimumDelayMsHigh);
+
+  EXPECT_TRUE(dm_->SetBaseMinimumDelay(kBaseMinimumDelayMsLow));
+  // Check that minimum delay is memorized and is used again.
+  EXPECT_EQ(dm_->effective_minimum_delay_ms_for_test(), kMinimumDelayMs);
+}
+
+TEST_F(DelayManagerTest, BaseMinimumDelay) {
+  const int kExpectedTarget = 5;
+  const int kTimeIncrement = kExpectedTarget * kFrameSizeMs;
+  SetPacketAudioLength(kFrameSizeMs);
+  // First packet arrival.
+  InsertNextPacket();
+  // Second packet arrival.
+  // Expect detector update method to be called once with inter-arrival time
+  // equal to |kExpectedTarget| packet. Return true to indicate peaks found.
+  EXPECT_CALL(detector_, Update(kExpectedTarget, false, _))
+      .WillRepeatedly(Return(true));
+  EXPECT_CALL(detector_, MaxPeakHeight())
+      .WillRepeatedly(Return(kExpectedTarget));
+  IncreaseTime(kTimeIncrement);
+  InsertNextPacket();
+
+  // No limit is applied.
+  EXPECT_EQ(kExpectedTarget << 8, dm_->TargetLevel());
+
+  constexpr int kBaseMinimumDelayPackets = kExpectedTarget + 2;
+  constexpr int kBaseMinimumDelayMs = kBaseMinimumDelayPackets * kFrameSizeMs;
+  EXPECT_TRUE(dm_->SetBaseMinimumDelay(kBaseMinimumDelayMs));
+  EXPECT_EQ(dm_->GetBaseMinimumDelay(), kBaseMinimumDelayMs);
+
+  IncreaseTime(kTimeIncrement);
+  InsertNextPacket();
+  EXPECT_EQ(dm_->GetBaseMinimumDelay(), kBaseMinimumDelayMs);
+  EXPECT_EQ(kBaseMinimumDelayPackets << 8, dm_->TargetLevel());
+}
+
+TEST_F(DelayManagerTest, BaseMinimumDealyAffectTargetLevel) {
+  const int kExpectedTarget = 5;
+  const int kTimeIncrement = kExpectedTarget * kFrameSizeMs;
+  SetPacketAudioLength(kFrameSizeMs);
+  // First packet arrival.
+  InsertNextPacket();
+  // Second packet arrival.
+  // Expect detector update method to be called once with inter-arrival time
+  // equal to |kExpectedTarget|. Return true to indicate peaks found.
+  EXPECT_CALL(detector_, Update(kExpectedTarget, false, _))
+      .WillRepeatedly(Return(true));
+  EXPECT_CALL(detector_, MaxPeakHeight())
+      .WillRepeatedly(Return(kExpectedTarget));
+  IncreaseTime(kTimeIncrement);
+  InsertNextPacket();
+
+  // No limit is applied.
+  EXPECT_EQ(kExpectedTarget << 8, dm_->TargetLevel());
+
+  // Minimum delay is lower than base minimum delay, that is why base minimum
+  // delay is used to calculate target level.
+  constexpr int kMinimumDelayPackets = kExpectedTarget + 1;
+  constexpr int kBaseMinimumDelayPackets = kExpectedTarget + 2;
+
+  constexpr int kMinimumDelayMs = kMinimumDelayPackets * kFrameSizeMs;
+  constexpr int kBaseMinimumDelayMs = kBaseMinimumDelayPackets * kFrameSizeMs;
+
+  EXPECT_TRUE(kMinimumDelayMs < kBaseMinimumDelayMs);
+  EXPECT_TRUE(dm_->SetMinimumDelay(kMinimumDelayMs));
+  EXPECT_TRUE(dm_->SetBaseMinimumDelay(kBaseMinimumDelayMs));
+  EXPECT_EQ(dm_->GetBaseMinimumDelay(), kBaseMinimumDelayMs);
+
+  IncreaseTime(kTimeIncrement);
+  InsertNextPacket();
+  EXPECT_EQ(dm_->GetBaseMinimumDelay(), kBaseMinimumDelayMs);
+  EXPECT_EQ(kBaseMinimumDelayPackets << 8, dm_->TargetLevel());
+}
+
+TEST_F(DelayManagerTest, UpdateReorderedPacket) {
+  SetPacketAudioLength(kFrameSizeMs);
+  InsertNextPacket();
+
+  // Insert packet that was sent before the previous packet.
+  EXPECT_CALL(detector_, Update(_, true, _));
+  EXPECT_EQ(0, dm_->Update(seq_no_ - 1, ts_ - kFrameSizeMs, kFs));
+}
+
+TEST_F(DelayManagerTest, EnableRtxHandling) {
+  enable_rtx_handling_ = true;
+  use_mock_histogram_ = true;
+  RecreateDelayManager();
+  EXPECT_TRUE(mock_histogram_);
+
+  // Insert first packet.
+  SetPacketAudioLength(kFrameSizeMs);
+  InsertNextPacket();
+
+  // Insert reordered packet.
+  EXPECT_CALL(*mock_histogram_, Add(3));
+  EXPECT_EQ(0, dm_->Update(seq_no_ - 3, ts_ - 3 * kFrameSizeMs, kFs));
+
+  // Insert another reordered packet.
+  EXPECT_CALL(*mock_histogram_, Add(2));
+  EXPECT_EQ(0, dm_->Update(seq_no_ - 2, ts_ - 2 * kFrameSizeMs, kFs));
+
+  // Insert the next packet in order and verify that the inter-arrival time is
+  // estimated correctly.
+  IncreaseTime(kFrameSizeMs);
+  EXPECT_CALL(*mock_histogram_, Add(1));
+  InsertNextPacket();
+}
+
 // Tests that skipped sequence numbers (simulating empty packets) are handled
 // correctly.
 TEST_F(DelayManagerTest, EmptyPacketsReported) {
@@ -285,7 +534,7 @@
   // Expect detector update method to be called once with inter-arrival time
   // equal to 1 packet, and (base) target level equal to 1 as well.
   // Return false to indicate no peaks found.
-  EXPECT_CALL(detector_, Update(1, 1)).WillOnce(Return(false));
+  EXPECT_CALL(detector_, Update(1, false, 1)).WillOnce(Return(false));
   InsertNextPacket();
 
   EXPECT_EQ(1 << 8, dm_->TargetLevel());  // In Q8.
@@ -309,7 +558,7 @@
   // Expect detector update method to be called once with inter-arrival time
   // equal to 1 packet, and (base) target level equal to 1 as well.
   // Return false to indicate no peaks found.
-  EXPECT_CALL(detector_, Update(10, 10)).WillOnce(Return(false));
+  EXPECT_CALL(detector_, Update(10, false, 10)).WillOnce(Return(false));
   InsertNextPacket();
 
   // Note 10 times higher target value.
@@ -337,8 +586,7 @@
   test::ScopedFieldTrials field_trial(
       "WebRTC-Audio-NetEqForceTargetDelayPercentile/Enabled-0/");
   RecreateDelayManager();
-  EXPECT_EQ(absl::make_optional<int>(1 << 30),
-            dm_->forced_limit_probability_for_test());
+  EXPECT_EQ(0, dm_->histogram_quantile());
 
   SetPacketAudioLength(kFrameSizeMs);
   // First packet arrival.
@@ -348,7 +596,7 @@
   // Second packet arrival.
   // Expect detector update method to be called once with inter-arrival time
   // equal to 1 packet.
-  EXPECT_CALL(detector_, Update(1, 1)).WillOnce(Return(false));
+  EXPECT_CALL(detector_, Update(1, false, 1)).WillOnce(Return(false));
   InsertNextPacket();
   constexpr int kExpectedTarget = 1;
   EXPECT_EQ(kExpectedTarget << 8, dm_->TargetLevel());  // In Q8.
@@ -359,145 +607,122 @@
     test::ScopedFieldTrials field_trial(
         "WebRTC-Audio-NetEqForceTargetDelayPercentile/Enabled-95/");
     RecreateDelayManager();
-    EXPECT_EQ(absl::make_optional<int>(53687091),
-              dm_->forced_limit_probability_for_test());  // 1/20 in Q30
+    EXPECT_EQ(kDefaultHistogramQuantile, dm_->histogram_quantile());
   }
   {
     test::ScopedFieldTrials field_trial(
         "WebRTC-Audio-NetEqForceTargetDelayPercentile/Enabled-99.95/");
     RecreateDelayManager();
-    EXPECT_EQ(absl::make_optional<int>(536871),
-              dm_->forced_limit_probability_for_test());  // 1/2000 in Q30
+    EXPECT_EQ(1073204953, dm_->histogram_quantile());  // 0.9995 in Q30.
   }
   {
     test::ScopedFieldTrials field_trial(
         "WebRTC-Audio-NetEqForceTargetDelayPercentile/Disabled/");
     RecreateDelayManager();
-    EXPECT_EQ(absl::nullopt, dm_->forced_limit_probability_for_test());
+    EXPECT_EQ(kDefaultHistogramQuantile, dm_->histogram_quantile());
   }
   {
     test::ScopedFieldTrials field_trial(
         "WebRTC-Audio-NetEqForceTargetDelayPercentile/Enabled--1/");
-    EXPECT_EQ(absl::nullopt, dm_->forced_limit_probability_for_test());
+    EXPECT_EQ(kDefaultHistogramQuantile, dm_->histogram_quantile());
   }
   {
     test::ScopedFieldTrials field_trial(
         "WebRTC-Audio-NetEqForceTargetDelayPercentile/Enabled-100.1/");
     RecreateDelayManager();
-    EXPECT_EQ(absl::nullopt, dm_->forced_limit_probability_for_test());
+    EXPECT_EQ(kDefaultHistogramQuantile, dm_->histogram_quantile());
   }
 }
 
-// Test if the histogram is stretched correctly if the packet size is decreased.
-TEST(DelayManagerIATScalingTest, StretchTest) {
-  using IATVector = DelayManager::IATVector;
-  // Test a straightforward 60ms to 20ms change.
-  IATVector iat = {12, 0, 0, 0, 0, 0};
-  IATVector expected_result = {4, 4, 4, 0, 0, 0};
-  IATVector stretched_iat = DelayManager::ScaleHistogram(iat, 60, 20);
-  EXPECT_EQ(stretched_iat, expected_result);
-
-  // Test an example where the last bin in the stretched histogram should
-  // contain the sum of the elements that don't fit into the new histogram.
-  iat = {18, 15, 12, 9, 6, 3, 0};
-  expected_result = {6, 6, 6, 5, 5, 5, 30};
-  stretched_iat = DelayManager::ScaleHistogram(iat, 60, 20);
-  EXPECT_EQ(stretched_iat, expected_result);
-
-  // Test a 120ms to 60ms change.
-  iat = {18, 16, 14, 4, 0};
-  expected_result = {9, 9, 8, 8, 18};
-  stretched_iat = DelayManager::ScaleHistogram(iat, 120, 60);
-  EXPECT_EQ(stretched_iat, expected_result);
-
-  // Test a 120ms to 20ms change.
-  iat = {19, 12, 0, 0, 0, 0, 0, 0};
-  expected_result = {3, 3, 3, 3, 3, 3, 2, 11};
-  stretched_iat = DelayManager::ScaleHistogram(iat, 120, 20);
-  EXPECT_EQ(stretched_iat, expected_result);
-
-  // Test a 70ms to 40ms change.
-  iat = {13, 7, 5, 3, 1, 5, 12, 11, 3, 0, 0, 0};
-  expected_result = {7, 5, 5, 3, 3, 2, 2, 1, 2, 2, 6, 22};
-  stretched_iat = DelayManager::ScaleHistogram(iat, 70, 40);
-  EXPECT_EQ(stretched_iat, expected_result);
-
-  // Test a 30ms to 20ms change.
-  iat = {13, 7, 5, 3, 1, 5, 12, 11, 3, 0, 0, 0};
-  expected_result = {8, 6, 6, 3, 2, 2, 1, 3, 3, 8, 7, 11};
-  stretched_iat = DelayManager::ScaleHistogram(iat, 30, 20);
-  EXPECT_EQ(stretched_iat, expected_result);
+TEST_F(DelayManagerTest, DelayHistogramFieldTrial) {
+  {
+    test::ScopedFieldTrials field_trial(
+        "WebRTC-Audio-NetEqDelayHistogram/Enabled-96-0.998/");
+    RecreateDelayManager();
+    EXPECT_EQ(DelayManager::HistogramMode::RELATIVE_ARRIVAL_DELAY,
+              dm_->histogram_mode());
+    EXPECT_EQ(1030792151, dm_->histogram_quantile());  // 0.96 in Q30.
+    EXPECT_EQ(32702, dm_->histogram_forget_factor());  // 0.998 in Q15.
+  }
+  {
+    test::ScopedFieldTrials field_trial(
+        "WebRTC-Audio-NetEqDelayHistogram/Enabled-97.5-0.998/");
+    RecreateDelayManager();
+    EXPECT_EQ(DelayManager::HistogramMode::RELATIVE_ARRIVAL_DELAY,
+              dm_->histogram_mode());
+    EXPECT_EQ(1046898278, dm_->histogram_quantile());  // 0.975 in Q30.
+    EXPECT_EQ(32702, dm_->histogram_forget_factor());  // 0.998 in Q15.
+  }
+  {
+    // NetEqDelayHistogram should take precedence over
+    // NetEqForceTargetDelayPercentile.
+    test::ScopedFieldTrials field_trial(
+        "WebRTC-Audio-NetEqForceTargetDelayPercentile/Enabled-99.95/"
+        "WebRTC-Audio-NetEqDelayHistogram/Enabled-96-0.998/");
+    RecreateDelayManager();
+    EXPECT_EQ(DelayManager::HistogramMode::RELATIVE_ARRIVAL_DELAY,
+              dm_->histogram_mode());
+    EXPECT_EQ(1030792151, dm_->histogram_quantile());  // 0.96 in Q30.
+    EXPECT_EQ(32702, dm_->histogram_forget_factor());  // 0.998 in Q15.
+  }
+  {
+    // Invalid parameters.
+    test::ScopedFieldTrials field_trial(
+        "WebRTC-Audio-NetEqDelayHistogram/Enabled-96/");
+    RecreateDelayManager();
+    EXPECT_EQ(DelayManager::HistogramMode::RELATIVE_ARRIVAL_DELAY,
+              dm_->histogram_mode());
+    EXPECT_EQ(kDefaultHistogramQuantile,
+              dm_->histogram_quantile());                      // 0.95 in Q30.
+    EXPECT_EQ(kForgetFactor, dm_->histogram_forget_factor());  // 0.9993 in Q15.
+  }
+  {
+    test::ScopedFieldTrials field_trial(
+        "WebRTC-Audio-NetEqDelayHistogram/Disabled/");
+    RecreateDelayManager();
+    EXPECT_EQ(DelayManager::HistogramMode::INTER_ARRIVAL_TIME,
+              dm_->histogram_mode());
+    EXPECT_EQ(kDefaultHistogramQuantile,
+              dm_->histogram_quantile());                      // 0.95 in Q30.
+    EXPECT_EQ(kForgetFactor, dm_->histogram_forget_factor());  // 0.9993 in Q15.
+  }
 }
 
-// Test if the histogram is compressed correctly if the packet size is
-// increased.
-TEST(DelayManagerIATScalingTest, CompressionTest) {
-  using IATVector = DelayManager::IATVector;
-  // Test a 20 to 60 ms change.
-  IATVector iat = {12, 11, 10, 3, 2, 1};
-  IATVector expected_result = {33, 6, 0, 0, 0, 0};
-  IATVector compressed_iat = DelayManager::ScaleHistogram(iat, 20, 60);
-  EXPECT_EQ(compressed_iat, expected_result);
+TEST_F(DelayManagerTest, RelativeArrivalDelayMode) {
+  histogram_mode_ = DelayManager::HistogramMode::RELATIVE_ARRIVAL_DELAY;
+  use_mock_histogram_ = true;
+  RecreateDelayManager();
 
-  // Test a 60ms to 120ms change.
-  iat = {18, 16, 14, 4, 1};
-  expected_result = {34, 18, 1, 0, 0};
-  compressed_iat = DelayManager::ScaleHistogram(iat, 60, 120);
-  EXPECT_EQ(compressed_iat, expected_result);
+  SetPacketAudioLength(kFrameSizeMs);
+  InsertNextPacket();
 
-  // Test a 20ms to 120ms change.
-  iat = {18, 12, 5, 4, 4, 3, 5, 1};
-  expected_result = {46, 6, 0, 0, 0, 0, 0, 0};
-  compressed_iat = DelayManager::ScaleHistogram(iat, 20, 120);
-  EXPECT_EQ(compressed_iat, expected_result);
+  IncreaseTime(kFrameSizeMs);
+  EXPECT_CALL(*mock_histogram_, Add(0));  // Not delayed.
+  InsertNextPacket();
 
-  // Test a 70ms to 80ms change.
-  iat = {13, 7, 5, 3, 1, 5, 12, 11, 3};
-  expected_result = {11, 8, 6, 2, 5, 12, 13, 3, 0};
-  compressed_iat = DelayManager::ScaleHistogram(iat, 70, 80);
-  EXPECT_EQ(compressed_iat, expected_result);
+  IncreaseTime(2 * kFrameSizeMs);
+  EXPECT_CALL(*mock_histogram_, Add(1));  // 20ms delayed.
+  EXPECT_EQ(0, dm_->Update(seq_no_, ts_, kFs));
 
-  // Test a 50ms to 110ms change.
-  iat = {13, 7, 5, 3, 1, 5, 12, 11, 3};
-  expected_result = {18, 8, 16, 16, 2, 0, 0, 0, 0};
-  compressed_iat = DelayManager::ScaleHistogram(iat, 50, 110);
-  EXPECT_EQ(compressed_iat, expected_result);
+  IncreaseTime(2 * kFrameSizeMs);
+  EXPECT_CALL(*mock_histogram_, Add(2));  // 40ms delayed.
+  EXPECT_EQ(0, dm_->Update(seq_no_ + 1, ts_ + kTsIncrement, kFs));
+
+  EXPECT_CALL(*mock_histogram_, Add(1));  // Reordered, 20ms delayed.
+  EXPECT_EQ(0, dm_->Update(seq_no_, ts_, kFs));
 }
 
-// Test if the histogram scaling function handles overflows correctly.
-TEST(DelayManagerIATScalingTest, OverflowTest) {
-  using IATVector = DelayManager::IATVector;
-  // Test a compression operation that can cause overflow.
-  IATVector iat = {733544448, 0, 0, 0, 0, 0, 0, 340197376, 0, 0, 0, 0, 0, 0};
-  IATVector expected_result = {733544448, 340197376, 0, 0, 0, 0, 0,
-                               0,         0,         0, 0, 0, 0, 0};
-  IATVector scaled_iat = DelayManager::ScaleHistogram(iat, 10, 60);
-  EXPECT_EQ(scaled_iat, expected_result);
+TEST_F(DelayManagerTest, RelativeArrivalDelayStatistic) {
+  SetPacketAudioLength(kFrameSizeMs);
+  InsertNextPacket();
 
-  iat = {655591163, 39962288, 360736736, 1930514, 4003853, 1782764,
-         114119,    2072996,  0,         2149354, 0};
-  expected_result = {1056290187, 7717131, 2187115, 2149354, 0, 0,
-                     0,          0,       0,       0,       0};
-  scaled_iat = DelayManager::ScaleHistogram(iat, 20, 60);
-  EXPECT_EQ(scaled_iat, expected_result);
+  IncreaseTime(kFrameSizeMs);
+  EXPECT_CALL(stats_, RelativePacketArrivalDelay(0));
+  InsertNextPacket();
 
-  // In this test case we will not be able to add everything to the final bin in
-  // the scaled histogram. Check that the last bin doesn't overflow.
-  iat = {2000000000, 2000000000, 2000000000,
-         2000000000, 2000000000, 2000000000};
-  expected_result = {666666666, 666666666, 666666666,
-                     666666667, 666666667, 2147483647};
-  scaled_iat = DelayManager::ScaleHistogram(iat, 60, 20);
-  EXPECT_EQ(scaled_iat, expected_result);
-
-  // In this test case we will not be able to add enough to each of the bins,
-  // so the values should be smeared out past the end of the normal range.
-  iat = {2000000000, 2000000000, 2000000000,
-         2000000000, 2000000000, 2000000000};
-  expected_result = {2147483647, 2147483647, 2147483647,
-                     2147483647, 2147483647, 1262581765};
-  scaled_iat = DelayManager::ScaleHistogram(iat, 20, 60);
-  EXPECT_EQ(scaled_iat, expected_result);
+  IncreaseTime(2 * kFrameSizeMs);
+  EXPECT_CALL(stats_, RelativePacketArrivalDelay(20));
+  InsertNextPacket();
 }
 
 }  // namespace webrtc
diff --git a/modules/audio_coding/neteq/delay_peak_detector.cc b/modules/audio_coding/neteq/delay_peak_detector.cc
index 893ce3e..5669d72 100644
--- a/modules/audio_coding/neteq/delay_peak_detector.cc
+++ b/modules/audio_coding/neteq/delay_peak_detector.cc
@@ -26,10 +26,12 @@
 
 DelayPeakDetector::~DelayPeakDetector() = default;
 
-DelayPeakDetector::DelayPeakDetector(const TickTimer* tick_timer)
+DelayPeakDetector::DelayPeakDetector(const TickTimer* tick_timer,
+                                     bool ignore_reordered_packets)
     : peak_found_(false),
       peak_detection_threshold_(0),
       tick_timer_(tick_timer),
+      ignore_reordered_packets_(ignore_reordered_packets),
       frame_length_change_experiment_(
           field_trial::IsEnabled("WebRTC-Audio-NetEqFramelengthExperiment")) {
   RTC_DCHECK(!peak_period_stopwatch_);
@@ -79,7 +81,12 @@
   return max_period_element->period_ms;
 }
 
-bool DelayPeakDetector::Update(int inter_arrival_time, int target_level) {
+bool DelayPeakDetector::Update(int inter_arrival_time,
+                               bool reordered,
+                               int target_level) {
+  if (ignore_reordered_packets_ && reordered) {
+    return CheckPeakConditions();
+  }
   if (inter_arrival_time > target_level + peak_detection_threshold_ ||
       inter_arrival_time > 2 * target_level) {
     // A delay peak is observed.
diff --git a/modules/audio_coding/neteq/delay_peak_detector.h b/modules/audio_coding/neteq/delay_peak_detector.h
index 272d50e..8cd198d 100644
--- a/modules/audio_coding/neteq/delay_peak_detector.h
+++ b/modules/audio_coding/neteq/delay_peak_detector.h
@@ -17,13 +17,13 @@
 #include <memory>
 
 #include "modules/audio_coding/neteq/tick_timer.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
 class DelayPeakDetector {
  public:
-  DelayPeakDetector(const TickTimer* tick_timer);
+  DelayPeakDetector(const TickTimer* tick_timer, bool ignore_reordered_packets);
   virtual ~DelayPeakDetector();
   virtual void Reset();
 
@@ -43,10 +43,11 @@
   // larger than 0), or 0 if no delay peaks have been observed recently.
   virtual uint64_t MaxPeakPeriod() const;
 
-  // Updates the DelayPeakDetector with a new inter-arrival time (in packets)
-  // and the current target buffer level (needed to decide if a peak is observed
-  // or not). Returns true if peak-mode is active, false if not.
-  virtual bool Update(int inter_arrival_time, int target_level);
+  // Updates the DelayPeakDetector with a new inter-arrival time (in packets),
+  // the current target buffer level (needed to decide if a peak is observed or
+  // not) and if the new inter-arrival time includes a compensation for
+  // reordering. Returns true if peak-mode is active, false if not.
+  virtual bool Update(int inter_arrival_time, bool reordered, int target_level);
 
  private:
   static const size_t kMaxNumPeaks = 8;
@@ -66,6 +67,7 @@
   int peak_detection_threshold_;
   const TickTimer* tick_timer_;
   std::unique_ptr<TickTimer::Stopwatch> peak_period_stopwatch_;
+  const bool ignore_reordered_packets_;
   const bool frame_length_change_experiment_;
 
   RTC_DISALLOW_COPY_AND_ASSIGN(DelayPeakDetector);
diff --git a/modules/audio_coding/neteq/delay_peak_detector_unittest.cc b/modules/audio_coding/neteq/delay_peak_detector_unittest.cc
index fd4dded..6590dc2 100644
--- a/modules/audio_coding/neteq/delay_peak_detector_unittest.cc
+++ b/modules/audio_coding/neteq/delay_peak_detector_unittest.cc
@@ -18,14 +18,14 @@
 
 TEST(DelayPeakDetector, CreateAndDestroy) {
   TickTimer tick_timer;
-  DelayPeakDetector* detector = new DelayPeakDetector(&tick_timer);
+  DelayPeakDetector* detector = new DelayPeakDetector(&tick_timer, false);
   EXPECT_FALSE(detector->peak_found());
   delete detector;
 }
 
 TEST(DelayPeakDetector, EmptyHistory) {
   TickTimer tick_timer;
-  DelayPeakDetector detector(&tick_timer);
+  DelayPeakDetector detector(&tick_timer, false);
   EXPECT_EQ(-1, detector.MaxPeakHeight());
   EXPECT_EQ(0u, detector.MaxPeakPeriod());
 }
@@ -35,7 +35,7 @@
 // start. This should then continue until it is disengaged due to lack of peaks.
 TEST(DelayPeakDetector, TriggerPeakMode) {
   TickTimer tick_timer;
-  DelayPeakDetector detector(&tick_timer);
+  DelayPeakDetector detector(&tick_timer, false);
   const int kPacketSizeMs = 30;
   detector.SetPacketAudioLength(kPacketSizeMs);
 
@@ -69,9 +69,9 @@
           (arrival_times_ms[next] - arrival_times_ms[next - 1]) / kPacketSizeMs;
       const int kTargetBufferLevel = 1;  // Define peaks to be iat > 2.
       if (time < peak_mode_start_ms || time > peak_mode_end_ms) {
-        EXPECT_FALSE(detector.Update(iat_packets, kTargetBufferLevel));
+        EXPECT_FALSE(detector.Update(iat_packets, false, kTargetBufferLevel));
       } else {
-        EXPECT_TRUE(detector.Update(iat_packets, kTargetBufferLevel));
+        EXPECT_TRUE(detector.Update(iat_packets, false, kTargetBufferLevel));
         EXPECT_EQ(kWorstPeakPeriod, detector.MaxPeakPeriod());
         EXPECT_EQ(kPeakDelayMs / kPacketSizeMs + 1, detector.MaxPeakHeight());
       }
@@ -87,7 +87,7 @@
 // The delay pattern has peaks with delay = 3, thus should not trigger.
 TEST(DelayPeakDetector, DoNotTriggerPeakMode) {
   TickTimer tick_timer;
-  DelayPeakDetector detector(&tick_timer);
+  DelayPeakDetector detector(&tick_timer, false);
   const int kPacketSizeMs = 30;
   detector.SetPacketAudioLength(kPacketSizeMs);
 
@@ -115,7 +115,7 @@
       int iat_packets =
           (arrival_times_ms[next] - arrival_times_ms[next - 1]) / kPacketSizeMs;
       const int kTargetBufferLevel = 2;  // Define peaks to be iat > 4.
-      EXPECT_FALSE(detector.Update(iat_packets, kTargetBufferLevel));
+      EXPECT_FALSE(detector.Update(iat_packets, false, kTargetBufferLevel));
       ++next;
     }
     tick_timer.Increment();
@@ -129,15 +129,33 @@
 // problems.
 TEST(DelayPeakDetector, ZeroDistancePeaks) {
   TickTimer tick_timer;
-  DelayPeakDetector detector(&tick_timer);
+  DelayPeakDetector detector(&tick_timer, false);
   const int kPacketSizeMs = 30;
   detector.SetPacketAudioLength(kPacketSizeMs);
 
   const int kTargetBufferLevel = 2;  // Define peaks to be iat > 4.
-  const int kInterArrivalTime = 3 * kTargetBufferLevel;  // Will trigger a peak.
-  EXPECT_FALSE(detector.Update(kInterArrivalTime, kTargetBufferLevel));
-  EXPECT_FALSE(detector.Update(kInterArrivalTime, kTargetBufferLevel));
-  EXPECT_FALSE(detector.Update(kInterArrivalTime, kTargetBufferLevel));
+  const int kInterArrivalTime =
+      3 * kTargetBufferLevel;  // Above peak threshold.
+  EXPECT_FALSE(detector.Update(kInterArrivalTime, false, kTargetBufferLevel));
+  tick_timer.Increment();
+  EXPECT_FALSE(detector.Update(kInterArrivalTime, false, kTargetBufferLevel));
+  // The following would fail if there were non-zero time between the updates.
+  EXPECT_FALSE(detector.Update(kInterArrivalTime, false, kTargetBufferLevel));
+}
+
+TEST(DelayPeakDetector, IgnoreReorderedPacket) {
+  TickTimer tick_timer;
+  DelayPeakDetector detector(&tick_timer, true);
+
+  const int kTargetBufferLevel = 2;  // Define peaks to be iat > 4.
+  const int kInterArrivalTime =
+      3 * kTargetBufferLevel;  // Above peak threshold.
+  EXPECT_FALSE(detector.Update(kInterArrivalTime, false, kTargetBufferLevel));
+  tick_timer.Increment();
+  EXPECT_FALSE(detector.Update(kInterArrivalTime, false, kTargetBufferLevel));
+  tick_timer.Increment();
+  // The following would fail if the packet was not reordered.
+  EXPECT_FALSE(detector.Update(kInterArrivalTime, true, kTargetBufferLevel));
 }
 
 }  // namespace webrtc
diff --git a/modules/audio_coding/neteq/dsp_helper.h b/modules/audio_coding/neteq/dsp_helper.h
index 8379461..82fe14e 100644
--- a/modules/audio_coding/neteq/dsp_helper.h
+++ b/modules/audio_coding/neteq/dsp_helper.h
@@ -16,7 +16,7 @@
 
 #include "modules/audio_coding/neteq/audio_multi_vector.h"
 #include "modules/audio_coding/neteq/audio_vector.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
diff --git a/modules/audio_coding/neteq/dtmf_buffer.h b/modules/audio_coding/neteq/dtmf_buffer.h
index 24b14ec..a994e3a 100644
--- a/modules/audio_coding/neteq/dtmf_buffer.h
+++ b/modules/audio_coding/neteq/dtmf_buffer.h
@@ -15,7 +15,7 @@
 #include <stdint.h>
 #include <list>
 
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
diff --git a/modules/audio_coding/neteq/dtmf_tone_generator.h b/modules/audio_coding/neteq/dtmf_tone_generator.h
index 22e166e..968bc7f 100644
--- a/modules/audio_coding/neteq/dtmf_tone_generator.h
+++ b/modules/audio_coding/neteq/dtmf_tone_generator.h
@@ -15,7 +15,7 @@
 #include <stdint.h>
 
 #include "modules/audio_coding/neteq/audio_multi_vector.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
diff --git a/modules/audio_coding/neteq/expand.h b/modules/audio_coding/neteq/expand.h
index 30c34a2..7c041b8 100644
--- a/modules/audio_coding/neteq/expand.h
+++ b/modules/audio_coding/neteq/expand.h
@@ -15,7 +15,7 @@
 #include <memory>
 
 #include "modules/audio_coding/neteq/audio_vector.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
diff --git a/modules/audio_coding/neteq/expand_uma_logger.h b/modules/audio_coding/neteq/expand_uma_logger.h
index bd079c6..7cb11b1 100644
--- a/modules/audio_coding/neteq/expand_uma_logger.h
+++ b/modules/audio_coding/neteq/expand_uma_logger.h
@@ -16,7 +16,7 @@
 
 #include "absl/types/optional.h"
 #include "modules/audio_coding/neteq/tick_timer.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
diff --git a/modules/audio_coding/neteq/expand_unittest.cc b/modules/audio_coding/neteq/expand_unittest.cc
index 09914da..4c8c174 100644
--- a/modules/audio_coding/neteq/expand_unittest.cc
+++ b/modules/audio_coding/neteq/expand_unittest.cc
@@ -20,7 +20,7 @@
 #include "modules/audio_coding/neteq/tools/resample_input_audio_file.h"
 #include "rtc_base/numerics/safe_conversions.h"
 #include "test/gtest.h"
-#include "test/testsupport/fileutils.h"
+#include "test/testsupport/file_utils.h"
 
 namespace webrtc {
 
diff --git a/modules/audio_coding/neteq/histogram.cc b/modules/audio_coding/neteq/histogram.cc
new file mode 100644
index 0000000..b8e4e52
--- /dev/null
+++ b/modules/audio_coding/neteq/histogram.cc
@@ -0,0 +1,174 @@
+/*
+ *  Copyright (c) 2019 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include <algorithm>
+#include <numeric>
+
+#include "modules/audio_coding/neteq/histogram.h"
+#include "rtc_base/checks.h"
+#include "rtc_base/numerics/safe_conversions.h"
+
+namespace webrtc {
+
+Histogram::Histogram(size_t num_buckets, int forget_factor)
+    : buckets_(num_buckets, 0),
+      forget_factor_(0),
+      base_forget_factor_(forget_factor) {}
+
+Histogram::~Histogram() {}
+
+// Each element in the vector is first multiplied by the forgetting factor
+// |forget_factor_|. Then the vector element indicated by |iat_packets| is then
+// increased (additive) by 1 - |forget_factor_|. This way, the probability of
+// |iat_packets| is slightly increased, while the sum of the histogram remains
+// constant (=1).
+// Due to inaccuracies in the fixed-point arithmetic, the histogram may no
+// longer sum up to 1 (in Q30) after the update. To correct this, a correction
+// term is added or subtracted from the first element (or elements) of the
+// vector.
+// The forgetting factor |forget_factor_| is also updated. When the DelayManager
+// is reset, the factor is set to 0 to facilitate rapid convergence in the
+// beginning. With each update of the histogram, the factor is increased towards
+// the steady-state value |kIatFactor_|.
+void Histogram::Add(int value) {
+  RTC_DCHECK(value >= 0);
+  RTC_DCHECK(value < static_cast<int>(buckets_.size()));
+  int vector_sum = 0;  // Sum up the vector elements as they are processed.
+  // Multiply each element in |buckets_| with |forget_factor_|.
+  for (int& bucket : buckets_) {
+    bucket = (static_cast<int64_t>(bucket) * forget_factor_) >> 15;
+    vector_sum += bucket;
+  }
+
+  // Increase the probability for the currently observed inter-arrival time
+  // by 1 - |forget_factor_|. The factor is in Q15, |buckets_| in Q30.
+  // Thus, left-shift 15 steps to obtain result in Q30.
+  buckets_[value] += (32768 - forget_factor_) << 15;
+  vector_sum += (32768 - forget_factor_) << 15;  // Add to vector sum.
+
+  // |buckets_| should sum up to 1 (in Q30), but it may not due to
+  // fixed-point rounding errors.
+  vector_sum -= 1 << 30;  // Should be zero. Compensate if not.
+  if (vector_sum != 0) {
+    // Modify a few values early in |buckets_|.
+    int flip_sign = vector_sum > 0 ? -1 : 1;
+    for (int& bucket : buckets_) {
+      // Add/subtract 1/16 of the element, but not more than |vector_sum|.
+      int correction = flip_sign * std::min(abs(vector_sum), bucket >> 4);
+      bucket += correction;
+      vector_sum += correction;
+      if (abs(vector_sum) == 0) {
+        break;
+      }
+    }
+  }
+  RTC_DCHECK(vector_sum == 0);  // Verify that the above is correct.
+
+  // Update |forget_factor_| (changes only during the first seconds after a
+  // reset). The factor converges to |base_forget_factor_|.
+  forget_factor_ += (base_forget_factor_ - forget_factor_ + 3) >> 2;
+}
+
+int Histogram::Quantile(int probability) {
+  // Find the bucket for which the probability of observing an
+  // inter-arrival time larger than or equal to |index| is larger than or
+  // equal to |probability|. The sought probability is estimated using
+  // the histogram as the reverse cumulant PDF, i.e., the sum of elements from
+  // the end up until |index|. Now, since the sum of all elements is 1
+  // (in Q30) by definition, and since the solution is often a low value for
+  // |iat_index|, it is more efficient to start with |sum| = 1 and subtract
+  // elements from the start of the histogram.
+  int inverse_probability = (1 << 30) - probability;
+  size_t index = 0;        // Start from the beginning of |buckets_|.
+  int sum = 1 << 30;       // Assign to 1 in Q30.
+  sum -= buckets_[index];  // Ensure that target level is >= 1.
+
+  do {
+    // Subtract the probabilities one by one until the sum is no longer greater
+    // than |inverse_probability|.
+    ++index;
+    sum -= buckets_[index];
+  } while ((sum > inverse_probability) && (index < buckets_.size() - 1));
+  return static_cast<int>(index);
+}
+
+// Set the histogram vector to an exponentially decaying distribution
+// buckets_[i] = 0.5^(i+1), i = 0, 1, 2, ...
+// buckets_ is in Q30.
+void Histogram::Reset() {
+  // Set temp_prob to (slightly more than) 1 in Q14. This ensures that the sum
+  // of buckets_ is 1.
+  uint16_t temp_prob = 0x4002;  // 16384 + 2 = 100000000000010 binary.
+  for (int& bucket : buckets_) {
+    temp_prob >>= 1;
+    bucket = temp_prob << 16;
+  }
+  forget_factor_ = 0;  // Adapt the histogram faster for the first few packets.
+}
+
+int Histogram::NumBuckets() const {
+  return buckets_.size();
+}
+
+void Histogram::Scale(int old_bucket_width, int new_bucket_width) {
+  buckets_ = ScaleBuckets(buckets_, old_bucket_width, new_bucket_width);
+}
+
+std::vector<int> Histogram::ScaleBuckets(const std::vector<int>& buckets,
+                                         int old_bucket_width,
+                                         int new_bucket_width) {
+  RTC_DCHECK_GT(old_bucket_width, 0);
+  RTC_DCHECK_GT(new_bucket_width, 0);
+  RTC_DCHECK_EQ(old_bucket_width % 10, 0);
+  RTC_DCHECK_EQ(new_bucket_width % 10, 0);
+  std::vector<int> new_histogram(buckets.size(), 0);
+  int64_t acc = 0;
+  int time_counter = 0;
+  size_t new_histogram_idx = 0;
+  for (size_t i = 0; i < buckets.size(); i++) {
+    acc += buckets[i];
+    time_counter += old_bucket_width;
+    // The bins should be scaled, to ensure the histogram still sums to one.
+    const int64_t scaled_acc = acc * new_bucket_width / time_counter;
+    int64_t actually_used_acc = 0;
+    while (time_counter >= new_bucket_width) {
+      const int64_t old_histogram_val = new_histogram[new_histogram_idx];
+      new_histogram[new_histogram_idx] =
+          rtc::saturated_cast<int>(old_histogram_val + scaled_acc);
+      actually_used_acc += new_histogram[new_histogram_idx] - old_histogram_val;
+      new_histogram_idx =
+          std::min(new_histogram_idx + 1, new_histogram.size() - 1);
+      time_counter -= new_bucket_width;
+    }
+    // Only subtract the part that was succesfully written to the new histogram.
+    acc -= actually_used_acc;
+  }
+  // If there is anything left in acc (due to rounding errors), add it to the
+  // last bin. If we cannot add everything to the last bin we need to add as
+  // much as possible to the bins after the last bin (this is only possible
+  // when compressing a histogram).
+  while (acc > 0 && new_histogram_idx < new_histogram.size()) {
+    const int64_t old_histogram_val = new_histogram[new_histogram_idx];
+    new_histogram[new_histogram_idx] =
+        rtc::saturated_cast<int>(old_histogram_val + acc);
+    acc -= new_histogram[new_histogram_idx] - old_histogram_val;
+    new_histogram_idx++;
+  }
+  RTC_DCHECK_EQ(buckets.size(), new_histogram.size());
+  if (acc == 0) {
+    // If acc is non-zero, we were not able to add everything to the new
+    // histogram, so this check will not hold.
+    RTC_DCHECK_EQ(accumulate(buckets.begin(), buckets.end(), 0ll),
+                  accumulate(new_histogram.begin(), new_histogram.end(), 0ll));
+  }
+  return new_histogram;
+}
+
+}  // namespace webrtc
diff --git a/modules/audio_coding/neteq/histogram.h b/modules/audio_coding/neteq/histogram.h
new file mode 100644
index 0000000..fc8f612
--- /dev/null
+++ b/modules/audio_coding/neteq/histogram.h
@@ -0,0 +1,61 @@
+/*
+ *  Copyright (c) 2019 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef MODULES_AUDIO_CODING_NETEQ_HISTOGRAM_H_
+#define MODULES_AUDIO_CODING_NETEQ_HISTOGRAM_H_
+
+#include <string.h>  // Provide access to size_t.
+
+#include <vector>
+
+namespace webrtc {
+
+class Histogram {
+ public:
+  // Creates histogram with capacity |num_buckets| and |forget_factor| in Q15.
+  Histogram(size_t num_buckets, int forget_factor);
+
+  virtual ~Histogram();
+
+  // Resets the histogram to the default start distribution.
+  virtual void Reset();
+
+  // Add entry in bucket |index|.
+  virtual void Add(int index);
+
+  // Calculates the quantile at |probability| (in Q30) of the histogram
+  // distribution.
+  virtual int Quantile(int probability);
+
+  // Apply compression or stretching to the histogram.
+  virtual void Scale(int old_bucket_width, int new_bucket_width);
+
+  // Returns the number of buckets in the histogram.
+  virtual int NumBuckets() const;
+
+  // Returns the probability for each bucket in Q30.
+  std::vector<int> buckets() const { return buckets_; }
+
+  int forget_factor() const { return base_forget_factor_; }
+
+  // Made public for testing.
+  static std::vector<int> ScaleBuckets(const std::vector<int>& buckets,
+                                       int old_bucket_width,
+                                       int new_bucket_width);
+
+ private:
+  std::vector<int> buckets_;
+  int forget_factor_;  // Q15
+  const int base_forget_factor_;
+};
+
+}  // namespace webrtc
+
+#endif  // MODULES_AUDIO_CODING_NETEQ_HISTOGRAM_H_
diff --git a/modules/audio_coding/neteq/histogram_unittest.cc b/modules/audio_coding/neteq/histogram_unittest.cc
new file mode 100644
index 0000000..7a887c8
--- /dev/null
+++ b/modules/audio_coding/neteq/histogram_unittest.cc
@@ -0,0 +1,171 @@
+/*
+ *  Copyright (c) 2019 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include <cmath>
+
+#include "modules/audio_coding/neteq/histogram.h"
+#include "test/gtest.h"
+
+namespace webrtc {
+
+TEST(HistogramTest, Initialization) {
+  Histogram histogram(65, 32440);
+  histogram.Reset();
+  const auto& buckets = histogram.buckets();
+  double sum = 0.0;
+  for (size_t i = 0; i < buckets.size(); i++) {
+    EXPECT_NEAR(ldexp(std::pow(0.5, static_cast<int>(i + 1)), 30), buckets[i],
+                65537);
+    // Tolerance 65537 in Q30 corresponds to a delta of approximately 0.00006.
+    sum += buckets[i];
+  }
+  EXPECT_EQ(1 << 30, static_cast<int>(sum));  // Should be 1 in Q30.
+}
+
+TEST(HistogramTest, Add) {
+  Histogram histogram(10, 32440);
+  histogram.Reset();
+  const std::vector<int> before = histogram.buckets();
+  const int index = 5;
+  histogram.Add(index);
+  const std::vector<int> after = histogram.buckets();
+  EXPECT_GT(after[index], before[index]);
+  int sum = 0;
+  for (int bucket : after) {
+    sum += bucket;
+  }
+  EXPECT_EQ(1 << 30, sum);
+}
+
+TEST(HistogramTest, ForgetFactor) {
+  Histogram histogram(10, 32440);
+  histogram.Reset();
+  const std::vector<int> before = histogram.buckets();
+  const int index = 4;
+  histogram.Add(index);
+  const std::vector<int> after = histogram.buckets();
+  for (int i = 0; i < histogram.NumBuckets(); ++i) {
+    if (i != index) {
+      EXPECT_LT(after[i], before[i]);
+    }
+  }
+}
+
+// Test if the histogram is scaled correctly if the bucket width is decreased.
+TEST(HistogramTest, DownScale) {
+  // Test a straightforward 60 to 20 change.
+  std::vector<int> buckets = {12, 0, 0, 0, 0, 0};
+  std::vector<int> expected_result = {4, 4, 4, 0, 0, 0};
+  std::vector<int> stretched_buckets = Histogram::ScaleBuckets(buckets, 60, 20);
+  EXPECT_EQ(stretched_buckets, expected_result);
+
+  // Test an example where the last bin in the stretched histogram should
+  // contain the sum of the elements that don't fit into the new histogram.
+  buckets = {18, 15, 12, 9, 6, 3, 0};
+  expected_result = {6, 6, 6, 5, 5, 5, 30};
+  stretched_buckets = Histogram::ScaleBuckets(buckets, 60, 20);
+  EXPECT_EQ(stretched_buckets, expected_result);
+
+  // Test a 120 to 60 change.
+  buckets = {18, 16, 14, 4, 0};
+  expected_result = {9, 9, 8, 8, 18};
+  stretched_buckets = Histogram::ScaleBuckets(buckets, 120, 60);
+  EXPECT_EQ(stretched_buckets, expected_result);
+
+  // Test a 120 to 20 change.
+  buckets = {19, 12, 0, 0, 0, 0, 0, 0};
+  expected_result = {3, 3, 3, 3, 3, 3, 2, 11};
+  stretched_buckets = Histogram::ScaleBuckets(buckets, 120, 20);
+  EXPECT_EQ(stretched_buckets, expected_result);
+
+  // Test a 70 to 40 change.
+  buckets = {13, 7, 5, 3, 1, 5, 12, 11, 3, 0, 0, 0};
+  expected_result = {7, 5, 5, 3, 3, 2, 2, 1, 2, 2, 6, 22};
+  stretched_buckets = Histogram::ScaleBuckets(buckets, 70, 40);
+  EXPECT_EQ(stretched_buckets, expected_result);
+
+  // Test a 30 to 20 change.
+  buckets = {13, 7, 5, 3, 1, 5, 12, 11, 3, 0, 0, 0};
+  expected_result = {8, 6, 6, 3, 2, 2, 1, 3, 3, 8, 7, 11};
+  stretched_buckets = Histogram::ScaleBuckets(buckets, 30, 20);
+  EXPECT_EQ(stretched_buckets, expected_result);
+}
+
+// Test if the histogram is scaled correctly if the bucket width is increased.
+TEST(HistogramTest, UpScale) {
+  // Test a 20 to 60 change.
+  std::vector<int> buckets = {12, 11, 10, 3, 2, 1};
+  std::vector<int> expected_result = {33, 6, 0, 0, 0, 0};
+  std::vector<int> compressed_buckets =
+      Histogram::ScaleBuckets(buckets, 20, 60);
+  EXPECT_EQ(compressed_buckets, expected_result);
+
+  // Test a 60 to 120 change.
+  buckets = {18, 16, 14, 4, 1};
+  expected_result = {34, 18, 1, 0, 0};
+  compressed_buckets = Histogram::ScaleBuckets(buckets, 60, 120);
+  EXPECT_EQ(compressed_buckets, expected_result);
+
+  // Test a 20 to 120 change.
+  buckets = {18, 12, 5, 4, 4, 3, 5, 1};
+  expected_result = {46, 6, 0, 0, 0, 0, 0, 0};
+  compressed_buckets = Histogram::ScaleBuckets(buckets, 20, 120);
+  EXPECT_EQ(compressed_buckets, expected_result);
+
+  // Test a 70 to 80 change.
+  buckets = {13, 7, 5, 3, 1, 5, 12, 11, 3};
+  expected_result = {11, 8, 6, 2, 5, 12, 13, 3, 0};
+  compressed_buckets = Histogram::ScaleBuckets(buckets, 70, 80);
+  EXPECT_EQ(compressed_buckets, expected_result);
+
+  // Test a 50 to 110 change.
+  buckets = {13, 7, 5, 3, 1, 5, 12, 11, 3};
+  expected_result = {18, 8, 16, 16, 2, 0, 0, 0, 0};
+  compressed_buckets = Histogram::ScaleBuckets(buckets, 50, 110);
+  EXPECT_EQ(compressed_buckets, expected_result);
+}
+
+// Test if the histogram scaling function handles overflows correctly.
+TEST(HistogramTest, OverflowTest) {
+  // Test a upscale operation that can cause overflow.
+  std::vector<int> buckets = {733544448, 0, 0, 0, 0, 0, 0,
+                              340197376, 0, 0, 0, 0, 0, 0};
+  std::vector<int> expected_result = {733544448, 340197376, 0, 0, 0, 0, 0,
+                                      0,         0,         0, 0, 0, 0, 0};
+  std::vector<int> scaled_buckets = Histogram::ScaleBuckets(buckets, 10, 60);
+  EXPECT_EQ(scaled_buckets, expected_result);
+
+  buckets = {655591163, 39962288, 360736736, 1930514, 4003853, 1782764,
+             114119,    2072996,  0,         2149354, 0};
+  expected_result = {1056290187, 7717131, 2187115, 2149354, 0, 0,
+                     0,          0,       0,       0,       0};
+  scaled_buckets = Histogram::ScaleBuckets(buckets, 20, 60);
+  EXPECT_EQ(scaled_buckets, expected_result);
+
+  // In this test case we will not be able to add everything to the final bin in
+  // the scaled histogram. Check that the last bin doesn't overflow.
+  buckets = {2000000000, 2000000000, 2000000000,
+             2000000000, 2000000000, 2000000000};
+  expected_result = {666666666, 666666666, 666666666,
+                     666666667, 666666667, 2147483647};
+  scaled_buckets = Histogram::ScaleBuckets(buckets, 60, 20);
+  EXPECT_EQ(scaled_buckets, expected_result);
+
+  // In this test case we will not be able to add enough to each of the bins,
+  // so the values should be smeared out past the end of the normal range.
+  buckets = {2000000000, 2000000000, 2000000000,
+             2000000000, 2000000000, 2000000000};
+  expected_result = {2147483647, 2147483647, 2147483647,
+                     2147483647, 2147483647, 1262581765};
+  scaled_buckets = Histogram::ScaleBuckets(buckets, 20, 60);
+  EXPECT_EQ(scaled_buckets, expected_result);
+}
+
+}  // namespace webrtc
diff --git a/modules/audio_coding/neteq/include/neteq.h b/modules/audio_coding/neteq/include/neteq.h
index 2820fd8..549d355 100644
--- a/modules/audio_coding/neteq/include/neteq.h
+++ b/modules/audio_coding/neteq/include/neteq.h
@@ -13,18 +13,18 @@
 
 #include <string.h>  // Provide access to size_t.
 
+#include <map>
 #include <string>
 #include <vector>
 
 #include "absl/types/optional.h"
 #include "api/audio_codecs/audio_codec_pair_id.h"
 #include "api/audio_codecs/audio_decoder.h"
+#include "api/audio_codecs/audio_format.h"
 #include "api/rtp_headers.h"
-#include "common_types.h"  // NOLINT(build/include)
+#include "api/scoped_refptr.h"
 #include "modules/audio_coding/neteq/defines.h"
-#include "modules/audio_coding/neteq/neteq_decoder_enum.h"
-#include "rtc_base/constructormagic.h"
-#include "rtc_base/scoped_ref_ptr.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
@@ -70,9 +70,19 @@
   uint64_t concealed_samples = 0;
   uint64_t concealment_events = 0;
   uint64_t jitter_buffer_delay_ms = 0;
-  // Below stat is not part of the spec.
+  uint64_t jitter_buffer_emitted_count = 0;
+  // Below stats are not part of the spec.
   uint64_t voice_concealed_samples = 0;
   uint64_t delayed_packet_outage_samples = 0;
+  // This is sum of relative packet arrival delays of received packets so far.
+  // Since end-to-end delay of a packet is difficult to measure and is not
+  // necessarily useful for measuring jitter buffer performance, we report a
+  // relative packet arrival delay. The relative packet arrival delay of a
+  // packet is defined as the arrival delay compared to the first packet
+  // received, given that it had zero delay. To avoid clock drift, the "first"
+  // packet can be made dynamic.
+  uint64_t relative_packet_arrival_delay_ms = 0;
+  uint64_t jitter_buffer_packets_received = 0;
 };
 
 // Metrics that describe the operations performed in NetEq, and the internal
@@ -85,6 +95,8 @@
   uint64_t accelerate_samples = 0;
   // Count of the number of buffer flushes.
   uint64_t packet_buffer_flushes = 0;
+  // The number of primary packets that were discarded.
+  uint64_t discarded_primary_packets = 0;
   // The statistics below are not cumulative.
   // The waiting time of the last decoded packet.
   uint64_t last_waiting_time_ms = 0;
@@ -111,11 +123,12 @@
 
     int sample_rate_hz = 16000;  // Initial value. Will change with input data.
     bool enable_post_decode_vad = false;
-    size_t max_packets_in_buffer = 50;
-    int max_delay_ms = 2000;
+    size_t max_packets_in_buffer = 200;
+    int max_delay_ms = 0;
     int min_delay_ms = 0;
     bool enable_fast_accelerate = false;
     bool enable_muted_state = false;
+    bool enable_rtx_handling = false;
     absl::optional<AudioCodecPairId> codec_pair_id;
     bool for_test_no_time_stretching = false;  // Use only for testing.
   };
@@ -165,25 +178,6 @@
   // Replaces the current set of decoders with the given one.
   virtual void SetCodecs(const std::map<int, SdpAudioFormat>& codecs) = 0;
 
-  // Associates |rtp_payload_type| with |codec| and |codec_name|, and stores the
-  // information in the codec database. Returns 0 on success, -1 on failure.
-  // The name is only used to provide information back to the caller about the
-  // decoders. Hence, the name is arbitrary, and may be empty.
-  virtual int RegisterPayloadType(NetEqDecoder codec,
-                                  const std::string& codec_name,
-                                  uint8_t rtp_payload_type) = 0;
-
-  // Provides an externally created decoder object |decoder| to insert in the
-  // decoder database. The decoder implements a decoder of type |codec| and
-  // associates it with |rtp_payload_type| and |codec_name|. Returns kOK on
-  // success, kFail on failure. The name is only used to provide information
-  // back to the caller about the decoders. Hence, the name is arbitrary, and
-  // may be empty.
-  virtual int RegisterExternalDecoder(AudioDecoder* decoder,
-                                      NetEqDecoder codec,
-                                      const std::string& codec_name,
-                                      uint8_t rtp_payload_type) = 0;
-
   // Associates |rtp_payload_type| with the given codec, which NetEq will
   // instantiate when it needs it. Returns true iff successful.
   virtual bool RegisterPayloadType(int rtp_payload_type,
@@ -209,13 +203,20 @@
   // the |max_delay_ms| value in the NetEq::Config struct.
   virtual bool SetMaximumDelay(int delay_ms) = 0;
 
+  // Sets a base minimum delay in milliseconds for packet buffer. The minimum
+  // delay which is set via |SetMinimumDelay| can't be lower than base minimum
+  // delay. Calling this method is similar to setting the |min_delay_ms| value
+  // in the NetEq::Config struct. Returns true if the base minimum is
+  // successfully applied, otherwise false is returned.
+  virtual bool SetBaseMinimumDelayMs(int delay_ms) = 0;
+
+  // Returns current value of base minimum delay in milliseconds.
+  virtual int GetBaseMinimumDelayMs() const = 0;
+
   // Returns the current target delay in ms. This includes any extra delay
   // requested through SetMinimumDelay.
   virtual int TargetDelayMs() const = 0;
 
-  // Returns the current total delay (packet buffer and sync buffer) in ms.
-  virtual int CurrentDelayMs() const = 0;
-
   // Returns the current total delay (packet buffer and sync buffer) in ms,
   // with smoothing applied to even out short-time fluctuations due to jitter.
   // The packet buffer part of the delay is not updated during DTX/CNG periods.
@@ -249,11 +250,7 @@
   // (Config::sample_rate_hz) is returned.
   virtual int last_output_sample_rate_hz() const = 0;
 
-  // Returns info about the decoder for the given payload type, or an empty
-  // value if we have no decoder for that payload type.
-  virtual absl::optional<CodecInst> GetDecoder(int payload_type) const = 0;
-
-  // Returns the decoder format for the given payload type. Returns empty if no
+  // Returns the decoder info for the given payload type. Returns empty if no
   // such payload type was registered.
   virtual absl::optional<SdpAudioFormat> GetDecoderFormat(
       int payload_type) const = 0;
diff --git a/modules/audio_coding/neteq/merge.h b/modules/audio_coding/neteq/merge.h
index e7e0bf9..a062a95 100644
--- a/modules/audio_coding/neteq/merge.h
+++ b/modules/audio_coding/neteq/merge.h
@@ -12,7 +12,7 @@
 #define MODULES_AUDIO_CODING_NETEQ_MERGE_H_
 
 #include "modules/audio_coding/neteq/audio_multi_vector.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
diff --git a/modules/audio_coding/neteq/mock/mock_decoder_database.h b/modules/audio_coding/neteq/mock/mock_decoder_database.h
index b1d8151..d1db213 100644
--- a/modules/audio_coding/neteq/mock/mock_decoder_database.h
+++ b/modules/audio_coding/neteq/mock/mock_decoder_database.h
@@ -29,17 +29,8 @@
   MOCK_CONST_METHOD0(Empty, bool());
   MOCK_CONST_METHOD0(Size, int());
   MOCK_METHOD0(Reset, void());
-  MOCK_METHOD3(RegisterPayload,
-               int(uint8_t rtp_payload_type,
-                   NetEqDecoder codec_type,
-                   const std::string& name));
   MOCK_METHOD2(RegisterPayload,
                int(int rtp_payload_type, const SdpAudioFormat& audio_format));
-  MOCK_METHOD4(InsertExternal,
-               int(uint8_t rtp_payload_type,
-                   NetEqDecoder codec_type,
-                   const std::string& codec_name,
-                   AudioDecoder* decoder));
   MOCK_METHOD1(Remove, int(uint8_t rtp_payload_type));
   MOCK_METHOD0(RemoveAll, void());
   MOCK_CONST_METHOD1(GetDecoderInfo,
diff --git a/modules/audio_coding/neteq/mock/mock_delay_manager.h b/modules/audio_coding/neteq/mock/mock_delay_manager.h
index 206cea7..3a128ce 100644
--- a/modules/audio_coding/neteq/mock/mock_delay_manager.h
+++ b/modules/audio_coding/neteq/mock/mock_delay_manager.h
@@ -11,8 +11,11 @@
 #ifndef MODULES_AUDIO_CODING_NETEQ_MOCK_MOCK_DELAY_MANAGER_H_
 #define MODULES_AUDIO_CODING_NETEQ_MOCK_MOCK_DELAY_MANAGER_H_
 
-#include "modules/audio_coding/neteq/delay_manager.h"
+#include <algorithm>
 
+#include "modules/audio_coding/neteq/delay_manager.h"
+#include "modules/audio_coding/neteq/histogram.h"
+#include "modules/audio_coding/neteq/statistics_calculator.h"
 #include "test/gmock.h"
 
 namespace webrtc {
@@ -21,26 +24,37 @@
  public:
   MockDelayManager(size_t max_packets_in_buffer,
                    int base_min_target_delay_ms,
+                   int histogram_quantile,
+                   HistogramMode histogram_mode,
+                   bool enable_rtx_handling,
                    DelayPeakDetector* peak_detector,
-                   const TickTimer* tick_timer)
+                   const TickTimer* tick_timer,
+                   StatisticsCalculator* stats,
+                   std::unique_ptr<Histogram> histogram)
       : DelayManager(max_packets_in_buffer,
                      base_min_target_delay_ms,
+                     histogram_quantile,
+                     histogram_mode,
+                     enable_rtx_handling,
                      peak_detector,
-                     tick_timer) {}
+                     tick_timer,
+                     stats,
+                     std::move(histogram)) {}
   virtual ~MockDelayManager() { Die(); }
   MOCK_METHOD0(Die, void());
-  MOCK_CONST_METHOD0(iat_vector, const IATVector&());
   MOCK_METHOD3(Update,
                int(uint16_t sequence_number,
                    uint32_t timestamp,
                    int sample_rate_hz));
-  MOCK_METHOD1(CalculateTargetLevel, int(int iat_packets));
+  MOCK_METHOD2(CalculateTargetLevel, int(int iat_packets, bool reordered));
   MOCK_METHOD1(SetPacketAudioLength, int(int length_ms));
   MOCK_METHOD0(Reset, void());
   MOCK_CONST_METHOD0(PeakFound, bool());
   MOCK_METHOD1(UpdateCounters, void(int elapsed_time_ms));
   MOCK_METHOD0(ResetPacketIatCount, void());
   MOCK_CONST_METHOD2(BufferLimits, void(int* lower_limit, int* higher_limit));
+  MOCK_METHOD1(SetBaseMinimumDelay, bool(int delay_ms));
+  MOCK_CONST_METHOD0(GetBaseMinimumDelay, int());
   MOCK_CONST_METHOD0(TargetLevel, int());
   MOCK_METHOD0(RegisterEmptyPacket, void());
   MOCK_METHOD1(set_extra_delay_ms, void(int16_t delay));
diff --git a/modules/audio_coding/neteq/mock/mock_delay_peak_detector.h b/modules/audio_coding/neteq/mock/mock_delay_peak_detector.h
index f6cdea0..f7f0465 100644
--- a/modules/audio_coding/neteq/mock/mock_delay_peak_detector.h
+++ b/modules/audio_coding/neteq/mock/mock_delay_peak_detector.h
@@ -19,8 +19,9 @@
 
 class MockDelayPeakDetector : public DelayPeakDetector {
  public:
-  MockDelayPeakDetector(const TickTimer* tick_timer)
-      : DelayPeakDetector(tick_timer) {}
+  MockDelayPeakDetector(const TickTimer* tick_timer,
+                        bool ignore_reordered_packets)
+      : DelayPeakDetector(tick_timer, ignore_reordered_packets) {}
   virtual ~MockDelayPeakDetector() { Die(); }
   MOCK_METHOD0(Die, void());
   MOCK_METHOD0(Reset, void());
@@ -28,7 +29,8 @@
   MOCK_METHOD0(peak_found, bool());
   MOCK_CONST_METHOD0(MaxPeakHeight, int());
   MOCK_CONST_METHOD0(MaxPeakPeriod, uint64_t());
-  MOCK_METHOD2(Update, bool(int inter_arrival_time, int target_level));
+  MOCK_METHOD3(Update,
+               bool(int inter_arrival_time, bool reordered, int target_level));
 };
 
 }  // 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
deleted file mode 100644
index 1fb3db5..0000000
--- a/modules/audio_coding/neteq/mock/mock_external_decoder_pcm16b.h
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- *  Copyright (c) 2013 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_CODING_NETEQ_MOCK_MOCK_EXTERNAL_DECODER_PCM16B_H_
-#define MODULES_AUDIO_CODING_NETEQ_MOCK_MOCK_EXTERNAL_DECODER_PCM16B_H_
-
-#include "api/audio_codecs/audio_decoder.h"
-#include "modules/audio_coding/codecs/pcm16b/pcm16b.h"
-#include "rtc_base/constructormagic.h"
-#include "test/gmock.h"
-
-namespace webrtc {
-
-using ::testing::_;
-using ::testing::Invoke;
-
-// Implement an external version of the PCM16b decoder.
-class ExternalPcm16B : public AudioDecoder {
- public:
-  explicit ExternalPcm16B(int sample_rate_hz)
-      : sample_rate_hz_(sample_rate_hz) {}
-  void Reset() override {}
-
-  int DecodeInternal(const uint8_t* encoded,
-                     size_t encoded_len,
-                     int sample_rate_hz,
-                     int16_t* decoded,
-                     SpeechType* speech_type) override {
-    EXPECT_EQ(sample_rate_hz_, sample_rate_hz);
-    size_t ret = WebRtcPcm16b_Decode(encoded, encoded_len, decoded);
-    *speech_type = ConvertSpeechType(1);
-    return static_cast<int>(ret);
-  }
-  int SampleRateHz() const override { return sample_rate_hz_; }
-  size_t Channels() const override { return 1; }
-
- private:
-  const int sample_rate_hz_;
-  RTC_DISALLOW_COPY_AND_ASSIGN(ExternalPcm16B);
-};
-
-// Create a mock of ExternalPcm16B which delegates all calls to the real object.
-// The reason is that we can then track that the correct calls are being made.
-class MockExternalPcm16B : public AudioDecoder {
- public:
-  explicit MockExternalPcm16B(int sample_rate_hz) : real_(sample_rate_hz) {
-    // By default, all calls are delegated to the real object.
-    ON_CALL(*this, DecodeInternal(_, _, _, _, _))
-        .WillByDefault(Invoke(&real_, &ExternalPcm16B::DecodeInternal));
-    ON_CALL(*this, HasDecodePlc())
-        .WillByDefault(Invoke(&real_, &ExternalPcm16B::HasDecodePlc));
-    ON_CALL(*this, DecodePlc(_, _))
-        .WillByDefault(Invoke(&real_, &ExternalPcm16B::DecodePlc));
-    ON_CALL(*this, Reset())
-        .WillByDefault(Invoke(&real_, &ExternalPcm16B::Reset));
-    ON_CALL(*this, IncomingPacket(_, _, _, _, _))
-        .WillByDefault(Invoke(&real_, &ExternalPcm16B::IncomingPacket));
-    ON_CALL(*this, ErrorCode())
-        .WillByDefault(Invoke(&real_, &ExternalPcm16B::ErrorCode));
-  }
-  virtual ~MockExternalPcm16B() { Die(); }
-
-  MOCK_METHOD0(Die, void());
-  MOCK_METHOD5(DecodeInternal,
-               int(const uint8_t* encoded,
-                   size_t encoded_len,
-                   int sample_rate_hz,
-                   int16_t* decoded,
-                   SpeechType* speech_type));
-  MOCK_CONST_METHOD0(HasDecodePlc, bool());
-  MOCK_METHOD2(DecodePlc, size_t(size_t num_frames, int16_t* decoded));
-  MOCK_METHOD0(Reset, void());
-  MOCK_METHOD5(IncomingPacket,
-               int(const uint8_t* payload,
-                   size_t payload_len,
-                   uint16_t rtp_sequence_number,
-                   uint32_t rtp_timestamp,
-                   uint32_t arrival_timestamp));
-  MOCK_METHOD0(ErrorCode, int());
-
-  int SampleRateHz() const /* override */ { return real_.SampleRateHz(); }
-  size_t Channels() const /* override */ { return real_.Channels(); }
-
- private:
-  ExternalPcm16B real_;
-};
-
-}  // namespace webrtc
-#endif  // MODULES_AUDIO_CODING_NETEQ_MOCK_MOCK_EXTERNAL_DECODER_PCM16B_H_
diff --git a/modules/audio_coding/neteq/mock/mock_histogram.h b/modules/audio_coding/neteq/mock/mock_histogram.h
new file mode 100644
index 0000000..09b1b89
--- /dev/null
+++ b/modules/audio_coding/neteq/mock/mock_histogram.h
@@ -0,0 +1,31 @@
+/*
+ *  Copyright (c) 2019 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef MODULES_AUDIO_CODING_NETEQ_MOCK_MOCK_HISTOGRAM_H_
+#define MODULES_AUDIO_CODING_NETEQ_MOCK_MOCK_HISTOGRAM_H_
+
+#include "modules/audio_coding/neteq/histogram.h"
+
+#include "test/gmock.h"
+
+namespace webrtc {
+
+class MockHistogram : public Histogram {
+ public:
+  MockHistogram(size_t num_buckets, int forget_factor)
+      : Histogram(num_buckets, forget_factor) {}
+  virtual ~MockHistogram() {}
+
+  MOCK_METHOD1(Add, void(int));
+  MOCK_METHOD1(Quantile, int(int));
+};
+
+}  // namespace webrtc
+#endif  // MODULES_AUDIO_CODING_NETEQ_MOCK_MOCK_HISTOGRAM_H_
diff --git a/modules/audio_coding/neteq/mock/mock_statistics_calculator.h b/modules/audio_coding/neteq/mock/mock_statistics_calculator.h
index 85f2620..aedb1df 100644
--- a/modules/audio_coding/neteq/mock/mock_statistics_calculator.h
+++ b/modules/audio_coding/neteq/mock/mock_statistics_calculator.h
@@ -21,6 +21,7 @@
  public:
   MOCK_METHOD1(PacketsDiscarded, void(size_t num_packets));
   MOCK_METHOD1(SecondaryPacketsDiscarded, void(size_t num_packets));
+  MOCK_METHOD1(RelativePacketArrivalDelay, void(size_t delay_ms));
 };
 
 }  // namespace webrtc
diff --git a/modules/audio_coding/neteq/neteq.cc b/modules/audio_coding/neteq/neteq.cc
index 0e6147e..a84c942 100644
--- a/modules/audio_coding/neteq/neteq.cc
+++ b/modules/audio_coding/neteq/neteq.cc
@@ -28,9 +28,10 @@
   ss << "sample_rate_hz=" << sample_rate_hz << ", enable_post_decode_vad="
      << (enable_post_decode_vad ? "true" : "false")
      << ", max_packets_in_buffer=" << max_packets_in_buffer
-     << ", enable_fast_accelerate="
-     << (enable_fast_accelerate ? " true" : "false")
-     << ", enable_muted_state=" << (enable_muted_state ? " true" : "false");
+     << ", min_delay_ms=" << min_delay_ms << ", enable_fast_accelerate="
+     << (enable_fast_accelerate ? "true" : "false")
+     << ", enable_muted_state=" << (enable_muted_state ? "true" : "false")
+     << ", enable_rtx_handling=" << (enable_rtx_handling ? "true" : "false");
   return ss.str();
 }
 
diff --git a/modules/audio_coding/neteq/neteq_decoder_enum.cc b/modules/audio_coding/neteq/neteq_decoder_enum.cc
deleted file mode 100644
index e3b633e..0000000
--- a/modules/audio_coding/neteq/neteq_decoder_enum.cc
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- *  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 <map>
-#include <string>
-
-#include "modules/audio_coding/neteq/neteq_decoder_enum.h"
-
-namespace webrtc {
-
-absl::optional<SdpAudioFormat> NetEqDecoderToSdpAudioFormat(NetEqDecoder nd) {
-  switch (nd) {
-    case NetEqDecoder::kDecoderPCMu:
-      return SdpAudioFormat("pcmu", 8000, 1);
-    case NetEqDecoder::kDecoderPCMa:
-      return SdpAudioFormat("pcma", 8000, 1);
-    case NetEqDecoder::kDecoderPCMu_2ch:
-      return SdpAudioFormat("pcmu", 8000, 2);
-    case NetEqDecoder::kDecoderPCMa_2ch:
-      return SdpAudioFormat("pcma", 8000, 2);
-    case NetEqDecoder::kDecoderILBC:
-      return SdpAudioFormat("ilbc", 8000, 1);
-    case NetEqDecoder::kDecoderISAC:
-      return SdpAudioFormat("isac", 16000, 1);
-    case NetEqDecoder::kDecoderISACswb:
-      return SdpAudioFormat("isac", 32000, 1);
-    case NetEqDecoder::kDecoderPCM16B:
-      return SdpAudioFormat("l16", 8000, 1);
-    case NetEqDecoder::kDecoderPCM16Bwb:
-      return SdpAudioFormat("l16", 16000, 1);
-    case NetEqDecoder::kDecoderPCM16Bswb32kHz:
-      return SdpAudioFormat("l16", 32000, 1);
-    case NetEqDecoder::kDecoderPCM16Bswb48kHz:
-      return SdpAudioFormat("l16", 48000, 1);
-    case NetEqDecoder::kDecoderPCM16B_2ch:
-      return SdpAudioFormat("l16", 8000, 2);
-    case NetEqDecoder::kDecoderPCM16Bwb_2ch:
-      return SdpAudioFormat("l16", 16000, 2);
-    case NetEqDecoder::kDecoderPCM16Bswb32kHz_2ch:
-      return SdpAudioFormat("l16", 32000, 2);
-    case NetEqDecoder::kDecoderPCM16Bswb48kHz_2ch:
-      return SdpAudioFormat("l16", 48000, 2);
-    case NetEqDecoder::kDecoderPCM16B_5ch:
-      return SdpAudioFormat("l16", 8000, 5);
-    case NetEqDecoder::kDecoderG722:
-      return SdpAudioFormat("g722", 8000, 1);
-    case NetEqDecoder::kDecoderG722_2ch:
-      return SdpAudioFormat("g722", 8000, 2);
-    case NetEqDecoder::kDecoderOpus:
-      return SdpAudioFormat("opus", 48000, 2);
-    case NetEqDecoder::kDecoderOpus_2ch:
-      return SdpAudioFormat(
-          "opus", 48000, 2,
-          std::map<std::string, std::string>{{"stereo", "1"}});
-    case NetEqDecoder::kDecoderRED:
-      return SdpAudioFormat("red", 8000, 1);
-    case NetEqDecoder::kDecoderAVT:
-      return SdpAudioFormat("telephone-event", 8000, 1);
-    case NetEqDecoder::kDecoderAVT16kHz:
-      return SdpAudioFormat("telephone-event", 16000, 1);
-    case NetEqDecoder::kDecoderAVT32kHz:
-      return SdpAudioFormat("telephone-event", 32000, 1);
-    case NetEqDecoder::kDecoderAVT48kHz:
-      return SdpAudioFormat("telephone-event", 48000, 1);
-    case NetEqDecoder::kDecoderCNGnb:
-      return SdpAudioFormat("cn", 8000, 1);
-    case NetEqDecoder::kDecoderCNGwb:
-      return SdpAudioFormat("cn", 16000, 1);
-    case NetEqDecoder::kDecoderCNGswb32kHz:
-      return SdpAudioFormat("cn", 32000, 1);
-    case NetEqDecoder::kDecoderCNGswb48kHz:
-      return SdpAudioFormat("cn", 48000, 1);
-    default:
-      return absl::nullopt;
-  }
-}
-
-}  // namespace webrtc
diff --git a/modules/audio_coding/neteq/neteq_decoder_enum.h b/modules/audio_coding/neteq/neteq_decoder_enum.h
deleted file mode 100644
index 00629bc..0000000
--- a/modules/audio_coding/neteq/neteq_decoder_enum.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- *  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.
- */
-
-#ifndef MODULES_AUDIO_CODING_NETEQ_NETEQ_DECODER_ENUM_H_
-#define MODULES_AUDIO_CODING_NETEQ_NETEQ_DECODER_ENUM_H_
-
-#include "absl/types/optional.h"
-#include "api/audio_codecs/audio_format.h"
-
-namespace webrtc {
-
-enum class NetEqDecoder {
-  kDecoderPCMu,
-  kDecoderPCMa,
-  kDecoderPCMu_2ch,
-  kDecoderPCMa_2ch,
-  kDecoderILBC,
-  kDecoderISAC,
-  kDecoderISACswb,
-  kDecoderPCM16B,
-  kDecoderPCM16Bwb,
-  kDecoderPCM16Bswb32kHz,
-  kDecoderPCM16Bswb48kHz,
-  kDecoderPCM16B_2ch,
-  kDecoderPCM16Bwb_2ch,
-  kDecoderPCM16Bswb32kHz_2ch,
-  kDecoderPCM16Bswb48kHz_2ch,
-  kDecoderPCM16B_5ch,
-  kDecoderG722,
-  kDecoderG722_2ch,
-  kDecoderRED,
-  kDecoderAVT,
-  kDecoderAVT16kHz,
-  kDecoderAVT32kHz,
-  kDecoderAVT48kHz,
-  kDecoderCNGnb,
-  kDecoderCNGwb,
-  kDecoderCNGswb32kHz,
-  kDecoderCNGswb48kHz,
-  kDecoderArbitrary,
-  kDecoderOpus,
-  kDecoderOpus_2ch,
-};
-
-absl::optional<SdpAudioFormat> NetEqDecoderToSdpAudioFormat(NetEqDecoder nd);
-
-}  // namespace webrtc
-
-#endif  // MODULES_AUDIO_CODING_NETEQ_NETEQ_DECODER_ENUM_H_
diff --git a/modules/audio_coding/neteq/neteq_decoder_plc_unittest.cc b/modules/audio_coding/neteq/neteq_decoder_plc_unittest.cc
index 8d0972c..21b15a9 100644
--- a/modules/audio_coding/neteq/neteq_decoder_plc_unittest.cc
+++ b/modules/audio_coding/neteq/neteq_decoder_plc_unittest.cc
@@ -14,6 +14,7 @@
 #include <utility>
 #include <vector>
 
+#include "absl/memory/memory.h"
 #include "absl/types/optional.h"
 #include "modules/audio_coding/codecs/pcm16b/audio_encoder_pcm16b.h"
 #include "modules/audio_coding/neteq/tools/audio_checksum.h"
@@ -23,8 +24,10 @@
 #include "modules/audio_coding/neteq/tools/input_audio_file.h"
 #include "modules/audio_coding/neteq/tools/neteq_test.h"
 #include "rtc_base/numerics/safe_conversions.h"
+#include "rtc_base/ref_counted_object.h"
+#include "test/audio_decoder_proxy_factory.h"
 #include "test/gtest.h"
-#include "test/testsupport/fileutils.h"
+#include "test/testsupport/file_utils.h"
 
 namespace webrtc {
 namespace test {
@@ -174,10 +177,7 @@
       webrtc::test::ResourcePath("audio_coding/testfile32kHz", "pcm"));
   AudioDecoderPlc dec(std::move(input_file), kSampleRateHz);
   // Masquerading as a PCM16b decoder.
-  NetEqTest::ExternalDecoderInfo dec_info = {
-      &dec, NetEqDecoder::kDecoderPCM16Bswb32kHz, "pcm16b_PLC"};
-  NetEqTest::ExtDecoderMap external_decoders;
-  external_decoders.insert(std::make_pair(kPayloadType, dec_info));
+  decoders.emplace(kPayloadType, SdpAudioFormat("l16", 32000, 1));
 
   // Output is simply a checksum calculator.
   auto output = absl::make_unique<AudioChecksumWithOutput>(checksum);
@@ -185,8 +185,9 @@
   // No callback objects.
   NetEqTest::Callbacks callbacks;
 
-  NetEqTest neteq_test(config, decoders, external_decoders,
-                       std::move(lossy_input), std::move(output), callbacks);
+  NetEqTest neteq_test(
+      config, new rtc::RefCountedObject<test::AudioDecoderProxyFactory>(&dec),
+      decoders, nullptr, std::move(lossy_input), std::move(output), callbacks);
   EXPECT_LE(kRunTimeMs, neteq_test.Run());
 
   auto lifetime_stats = neteq_test.LifetimeStats();
diff --git a/modules/audio_coding/neteq/neteq_external_decoder_unittest.cc b/modules/audio_coding/neteq/neteq_external_decoder_unittest.cc
index 872829c..8214ed2 100644
--- a/modules/audio_coding/neteq/neteq_external_decoder_unittest.cc
+++ b/modules/audio_coding/neteq/neteq_external_decoder_unittest.cc
@@ -14,14 +14,13 @@
 
 #include "api/audio/audio_frame.h"
 #include "api/audio_codecs/builtin_audio_decoder_factory.h"
-#include "common_types.h"  // NOLINT(build/include)
 #include "modules/audio_coding/neteq/mock/mock_external_decoder_pcm16b.h"
 #include "modules/audio_coding/neteq/tools/input_audio_file.h"
 #include "modules/audio_coding/neteq/tools/neteq_external_decoder_test.h"
 #include "modules/audio_coding/neteq/tools/rtp_generator.h"
 #include "rtc_base/strings/string_builder.h"
 #include "test/gmock.h"
-#include "test/testsupport/fileutils.h"
+#include "test/testsupport/file_utils.h"
 
 namespace webrtc {
 
diff --git a/modules/audio_coding/neteq/neteq_impl.cc b/modules/audio_coding/neteq/neteq_impl.cc
index 2a025f3..f1e8527 100644
--- a/modules/audio_coding/neteq/neteq_impl.cc
+++ b/modules/audio_coding/neteq/neteq_impl.cc
@@ -41,6 +41,7 @@
 #include "modules/audio_coding/neteq/post_decode_vad.h"
 #include "modules/audio_coding/neteq/preemptive_expand.h"
 #include "modules/audio_coding/neteq/red_payload_splitter.h"
+#include "modules/audio_coding/neteq/statistics_calculator.h"
 #include "modules/audio_coding/neteq/sync_buffer.h"
 #include "modules/audio_coding/neteq/tick_timer.h"
 #include "modules/audio_coding/neteq/time_stretch.h"
@@ -58,14 +59,18 @@
     const NetEq::Config& config,
     const rtc::scoped_refptr<AudioDecoderFactory>& decoder_factory)
     : tick_timer(new TickTimer),
+      stats(new StatisticsCalculator),
       buffer_level_filter(new BufferLevelFilter),
       decoder_database(
           new DecoderDatabase(decoder_factory, config.codec_pair_id)),
-      delay_peak_detector(new DelayPeakDetector(tick_timer.get())),
-      delay_manager(new DelayManager(config.max_packets_in_buffer,
-                                     config.min_delay_ms,
-                                     delay_peak_detector.get(),
-                                     tick_timer.get())),
+      delay_peak_detector(
+          new DelayPeakDetector(tick_timer.get(), config.enable_rtx_handling)),
+      delay_manager(DelayManager::Create(config.max_packets_in_buffer,
+                                         config.min_delay_ms,
+                                         config.enable_rtx_handling,
+                                         delay_peak_detector.get(),
+                                         tick_timer.get(),
+                                         stats.get())),
       dtmf_buffer(new DtmfBuffer(config.sample_rate_hz)),
       dtmf_tone_generator(new DtmfToneGenerator),
       packet_buffer(
@@ -95,6 +100,7 @@
       expand_factory_(std::move(deps.expand_factory)),
       accelerate_factory_(std::move(deps.accelerate_factory)),
       preemptive_expand_factory_(std::move(deps.preemptive_expand_factory)),
+      stats_(std::move(deps.stats)),
       last_mode_(kModeNormal),
       decoded_buffer_length_(kMaxFrameSize),
       decoded_buffer_(new int16_t[decoded_buffer_length_]),
@@ -102,7 +108,6 @@
       new_codec_(false),
       timestamp_(0),
       reset_decoder_(false),
-      ssrc_(0),
       first_packet_(true),
       enable_fast_accelerate_(config.enable_fast_accelerate),
       nack_enabled_(false),
@@ -113,7 +118,8 @@
       speech_expand_uma_logger_("WebRTC.Audio.SpeechExpandRatePercent",
                                 10,  // Report once every 10 s.
                                 tick_timer_.get()),
-      no_time_stretching_(config.for_test_no_time_stretching) {
+      no_time_stretching_(config.for_test_no_time_stretching),
+      enable_rtx_handling_(config.enable_rtx_handling) {
   RTC_LOG(LS_INFO) << "NetEq config: " << config.ToString();
   int fs = config.sample_rate_hz;
   if (fs != 8000 && fs != 16000 && fs != 32000 && fs != 48000) {
@@ -231,44 +237,10 @@
   const std::vector<int> changed_payload_types =
       decoder_database_->SetCodecs(codecs);
   for (const int pt : changed_payload_types) {
-    packet_buffer_->DiscardPacketsWithPayloadType(pt, &stats_);
+    packet_buffer_->DiscardPacketsWithPayloadType(pt, stats_.get());
   }
 }
 
-int NetEqImpl::RegisterPayloadType(NetEqDecoder codec,
-                                   const std::string& name,
-                                   uint8_t rtp_payload_type) {
-  rtc::CritScope lock(&crit_sect_);
-  RTC_LOG(LS_VERBOSE) << "RegisterPayloadType "
-                      << static_cast<int>(rtp_payload_type) << " "
-                      << static_cast<int>(codec);
-  if (decoder_database_->RegisterPayload(rtp_payload_type, codec, name) !=
-      DecoderDatabase::kOK) {
-    return kFail;
-  }
-  return kOK;
-}
-
-int NetEqImpl::RegisterExternalDecoder(AudioDecoder* decoder,
-                                       NetEqDecoder codec,
-                                       const std::string& codec_name,
-                                       uint8_t rtp_payload_type) {
-  rtc::CritScope lock(&crit_sect_);
-  RTC_LOG(LS_VERBOSE) << "RegisterExternalDecoder "
-                      << static_cast<int>(rtp_payload_type) << " "
-                      << static_cast<int>(codec);
-  if (!decoder) {
-    RTC_LOG(LS_ERROR) << "Cannot register external decoder with NULL pointer";
-    assert(false);
-    return kFail;
-  }
-  if (decoder_database_->InsertExternal(rtp_payload_type, codec, codec_name,
-                                        decoder) != DecoderDatabase::kOK) {
-    return kFail;
-  }
-  return kOK;
-}
-
 bool NetEqImpl::RegisterPayloadType(int rtp_payload_type,
                                     const SdpAudioFormat& audio_format) {
   RTC_LOG(LS_VERBOSE) << "NetEqImpl::RegisterPayloadType: payload type "
@@ -283,7 +255,8 @@
   rtc::CritScope lock(&crit_sect_);
   int ret = decoder_database_->Remove(rtp_payload_type);
   if (ret == DecoderDatabase::kOK || ret == DecoderDatabase::kDecoderNotFound) {
-    packet_buffer_->DiscardPacketsWithPayloadType(rtp_payload_type, &stats_);
+    packet_buffer_->DiscardPacketsWithPayloadType(rtp_payload_type,
+                                                  stats_.get());
     return kOK;
   }
   return kFail;
@@ -312,6 +285,19 @@
   return false;
 }
 
+bool NetEqImpl::SetBaseMinimumDelayMs(int delay_ms) {
+  rtc::CritScope lock(&crit_sect_);
+  if (delay_ms >= 0 && delay_ms <= 10000) {
+    return delay_manager_->SetBaseMinimumDelay(delay_ms);
+  }
+  return false;
+}
+
+int NetEqImpl::GetBaseMinimumDelayMs() const {
+  rtc::CritScope lock(&crit_sect_);
+  return delay_manager_->GetBaseMinimumDelay();
+}
+
 int NetEqImpl::TargetDelayMs() const {
   rtc::CritScope lock(&crit_sect_);
   RTC_DCHECK(delay_manager_.get());
@@ -322,21 +308,6 @@
          rtc::CheckedDivExact(fs_hz_, 1000);
 }
 
-int NetEqImpl::CurrentDelayMs() const {
-  rtc::CritScope lock(&crit_sect_);
-  if (fs_hz_ == 0)
-    return 0;
-  // Sum up the samples in the packet buffer with the future length of the sync
-  // buffer, and divide the sum by the sample rate.
-  const size_t delay_samples =
-      packet_buffer_->NumSamplesInBuffer(decoder_frame_length_) +
-      sync_buffer_->FutureLength();
-  // The division below will truncate.
-  const int delay_ms =
-      static_cast<int>(delay_samples) / rtc::CheckedDivExact(fs_hz_, 1000);
-  return delay_ms;
-}
-
 int NetEqImpl::FilteredCurrentDelayMs() const {
   rtc::CritScope lock(&crit_sect_);
   // Calculate the filtered packet buffer level in samples. The value from
@@ -363,20 +334,21 @@
   assert(decision_logic_.get());
   const int ms_per_packet = rtc::dchecked_cast<int>(
       decision_logic_->packet_length_samples() / (fs_hz_ / 1000));
-  stats_.PopulateDelayManagerStats(ms_per_packet, *delay_manager_.get(), stats);
-  stats_.GetNetworkStatistics(fs_hz_, total_samples_in_buffers,
-                              decoder_frame_length_, stats);
+  stats_->PopulateDelayManagerStats(ms_per_packet, *delay_manager_.get(),
+                                    stats);
+  stats_->GetNetworkStatistics(fs_hz_, total_samples_in_buffers,
+                               decoder_frame_length_, stats);
   return 0;
 }
 
 NetEqLifetimeStatistics NetEqImpl::GetLifetimeStatistics() const {
   rtc::CritScope lock(&crit_sect_);
-  return stats_.GetLifetimeStatistics();
+  return stats_->GetLifetimeStatistics();
 }
 
 NetEqOperationsAndState NetEqImpl::GetOperationsAndState() const {
   rtc::CritScope lock(&crit_sect_);
-  auto result = stats_.GetOperationsAndState();
+  auto result = stats_->GetOperationsAndState();
   result.current_buffer_size_ms =
       (packet_buffer_->NumSamplesInBuffer(decoder_frame_length_) +
        sync_buffer_->FutureLength()) *
@@ -417,27 +389,6 @@
   return last_output_sample_rate_hz_;
 }
 
-absl::optional<CodecInst> NetEqImpl::GetDecoder(int payload_type) const {
-  rtc::CritScope lock(&crit_sect_);
-  const DecoderDatabase::DecoderInfo* di =
-      decoder_database_->GetDecoderInfo(payload_type);
-  if (!di) {
-    return absl::nullopt;
-  }
-
-  // Create a CodecInst with some fields set. The remaining fields are zeroed,
-  // but we tell MSan to consider them uninitialized.
-  CodecInst ci = {0};
-  rtc::MsanMarkUninitialized(rtc::MakeArrayView(&ci, 1));
-  ci.pltype = payload_type;
-  std::strncpy(ci.plname, di->get_name().c_str(), sizeof(ci.plname));
-  ci.plname[sizeof(ci.plname) - 1] = '\0';
-  ci.plfreq = di->IsRed() ? 8000 : di->SampleRateHz();
-  AudioDecoder* const decoder = di->GetDecoder();
-  ci.channels = decoder ? decoder->Channels() : 1;
-  return ci;
-}
-
 absl::optional<SdpAudioFormat> NetEqImpl::GetDecoderFormat(
     int payload_type) const {
   rtc::CritScope lock(&crit_sect_);
@@ -446,7 +397,13 @@
   if (!di) {
     return absl::nullopt;  // Payload type not registered.
   }
-  return di->GetFormat();
+
+  SdpAudioFormat format = di->GetFormat();
+  // TODO(solenberg): This is legacy but messed up - mixing RTP rate and SR.
+  format.clockrate_hz = di->IsRed() ? 8000 : di->SampleRateHz();
+  const AudioDecoder* const decoder = di->GetDecoder();
+  format.num_channels = decoder ? decoder->Channels() : 1;
+  return format;
 }
 
 void NetEqImpl::FlushBuffers() {
@@ -518,6 +475,7 @@
     RTC_LOG_F(LS_ERROR) << "payload is empty";
     return kInvalidPointer;
   }
+  stats_->ReceivedPacket();
 
   PacketList packet_list;
   // Insert packet in a packet list.
@@ -533,8 +491,7 @@
     return packet;
   }());
 
-  bool update_sample_rate_and_channels =
-      first_packet_ || (rtp_header.ssrc != ssrc_);
+  bool update_sample_rate_and_channels = first_packet_;
 
   if (update_sample_rate_and_channels) {
     // Reset timestamp scaling.
@@ -561,9 +518,6 @@
     packet_buffer_->Flush();
     dtmf_buffer_->Flush();
 
-    // Store new SSRC.
-    ssrc_ = rtp_header.ssrc;
-
     // Update audio buffer timestamp.
     sync_buffer_->IncreaseEndTimestamp(main_timestamp - timestamp_);
 
@@ -707,7 +661,7 @@
   // Insert packets in buffer.
   const int ret = packet_buffer_->InsertPacketList(
       &parsed_packet_list, *decoder_database_, &current_rtp_payload_type_,
-      &current_cng_rtp_payload_type_, &stats_);
+      &current_cng_rtp_payload_type_, stats_.get());
   if (ret == PacketBuffer::kFlushed) {
     // Reset DSP timestamp etc. if packet buffer flushed.
     new_codec_ = true;
@@ -777,9 +731,11 @@
     }
 
     // Update statistics.
-    if ((int32_t)(main_timestamp - timestamp_) >= 0 && !new_codec_) {
+    if ((enable_rtx_handling_ || (int32_t)(main_timestamp - timestamp_) >= 0) &&
+        !new_codec_) {
       // Only update statistics if incoming packet is not older than last played
-      // out packet, and if new codec flag is not set.
+      // out packet or RTX handling is enabled, and if new codec flag is not
+      // set.
       delay_manager_->Update(main_sequence_number, main_timestamp, fs_hz_);
     }
   } else if (delay_manager_->last_pack_cng_or_dtmf() == -1) {
@@ -802,8 +758,8 @@
   *muted = false;
   last_decoded_timestamps_.clear();
   tick_timer_->Increment();
-  stats_.IncreaseCounter(output_size_samples_, fs_hz_);
-  const auto lifetime_stats = stats_.GetLifetimeStatistics();
+  stats_->IncreaseCounter(output_size_samples_, fs_hz_);
+  const auto lifetime_stats = stats_->GetLifetimeStatistics();
   expand_uma_logger_.UpdateSampleCounter(lifetime_stats.concealed_samples,
                                          fs_hz_);
   speech_expand_uma_logger_.UpdateSampleCounter(
@@ -823,7 +779,7 @@
             : timestamp_scaler_->ToExternal(playout_timestamp_) -
                   static_cast<uint32_t>(audio_frame->samples_per_channel_);
     audio_frame->num_channels_ = sync_buffer_->Channels();
-    stats_.ExpandedNoiseSamples(output_size_samples_, false);
+    stats_->ExpandedNoiseSamples(output_size_samples_, false);
     *muted = true;
     return 0;
   }
@@ -1032,7 +988,7 @@
   if (!new_codec_) {
     const uint32_t five_seconds_samples = 5 * fs_hz_;
     packet_buffer_->DiscardOldPackets(end_timestamp, five_seconds_samples,
-                                      &stats_);
+                                      stats_.get());
   }
   const Packet* packet = packet_buffer_->PeekNextPacket();
 
@@ -1052,12 +1008,14 @@
            (end_timestamp >= packet->timestamp ||
             end_timestamp + generated_noise_samples > packet->timestamp)) {
       // Don't use this packet, discard it.
-      if (packet_buffer_->DiscardNextPacket(&stats_) != PacketBuffer::kOK) {
+      if (packet_buffer_->DiscardNextPacket(stats_.get()) !=
+          PacketBuffer::kOK) {
         assert(false);  // Must be ok by design.
       }
       // Check buffer again.
       if (!new_codec_) {
-        packet_buffer_->DiscardOldPackets(end_timestamp, 5 * fs_hz_, &stats_);
+        packet_buffer_->DiscardOldPackets(end_timestamp, 5 * fs_hz_,
+                                          stats_.get());
       }
       packet = packet_buffer_->PeekNextPacket();
     }
@@ -1139,7 +1097,7 @@
     decision_logic_->SoftReset();
     buffer_level_filter_->Reset();
     delay_manager_->Reset();
-    stats_.ResetMcu();
+    stats_->ResetMcu();
   }
 
   size_t required_samples = output_size_samples_;
@@ -1244,7 +1202,7 @@
       // if comfort noise is not played. If comfort noise was just played,
       // this adjustment of timestamp is only done to get back in sync with the
       // stream timestamp; no loss to report.
-      stats_.LostSamples(packet->timestamp - end_timestamp);
+      stats_->LostSamples(packet->timestamp - end_timestamp);
     }
 
     if (*operation != kRfc3389Cng) {
@@ -1511,10 +1469,10 @@
   // Update in-call and post-call statistics.
   if (expand_->MuteFactor(0) == 0) {
     // Expand generates only noise.
-    stats_.ExpandedNoiseSamplesCorrection(expand_length_correction);
+    stats_->ExpandedNoiseSamplesCorrection(expand_length_correction);
   } else {
     // Expansion generates more than only noise.
-    stats_.ExpandedVoiceSamplesCorrection(expand_length_correction);
+    stats_->ExpandedVoiceSamplesCorrection(expand_length_correction);
   }
 
   last_mode_ = kModeMerge;
@@ -1555,12 +1513,12 @@
   if (std::all_of(concealment_audio_.cbegin(), concealment_audio_.cend(),
                   [](int16_t i) { return i == 0; })) {
     // Expand operation generates only noise.
-    stats_.ExpandedNoiseSamples(concealed_samples_per_channel,
-                                is_new_concealment_event);
+    stats_->ExpandedNoiseSamples(concealed_samples_per_channel,
+                                 is_new_concealment_event);
   } else {
     // Expand operation generates more than only noise.
-    stats_.ExpandedVoiceSamples(concealed_samples_per_channel,
-                                is_new_concealment_event);
+    stats_->ExpandedVoiceSamples(concealed_samples_per_channel,
+                                 is_new_concealment_event);
   }
   last_mode_ = kModeCodecPlc;
   if (!generated_noise_stopwatch_) {
@@ -1581,10 +1539,10 @@
     // Update in-call and post-call statistics.
     if (expand_->MuteFactor(0) == 0) {
       // Expand operation generates only noise.
-      stats_.ExpandedNoiseSamples(length, is_new_concealment_event);
+      stats_->ExpandedNoiseSamples(length, is_new_concealment_event);
     } else {
       // Expand operation generates more than only noise.
-      stats_.ExpandedVoiceSamples(length, is_new_concealment_event);
+      stats_->ExpandedVoiceSamples(length, is_new_concealment_event);
     }
 
     last_mode_ = kModeExpand;
@@ -1633,7 +1591,7 @@
   Accelerate::ReturnCodes return_code =
       accelerate_->Process(decoded_buffer, decoded_length, fast_accelerate,
                            algorithm_buffer_.get(), &samples_removed);
-  stats_.AcceleratedSamples(samples_removed);
+  stats_->AcceleratedSamples(samples_removed);
   switch (return_code) {
     case Accelerate::kSuccess:
       last_mode_ = kModeAccelerateSuccess;
@@ -1711,7 +1669,7 @@
   PreemptiveExpand::ReturnCodes return_code = preemptive_expand_->Process(
       decoded_buffer, decoded_length, old_borrowed_samples_per_channel,
       algorithm_buffer_.get(), &samples_added);
-  stats_.PreemptiveExpandedSamples(samples_added);
+  stats_->PreemptiveExpandedSamples(samples_added);
   switch (return_code) {
     case PreemptiveExpand::kSuccess:
       last_mode_ = kModePreemptiveExpandSuccess;
@@ -1926,7 +1884,7 @@
       return -1;
     }
     const uint64_t waiting_time_ms = packet->waiting_time->ElapsedMs();
-    stats_.StoreWaitingTime(waiting_time_ms);
+    stats_->StoreWaitingTime(waiting_time_ms);
     RTC_DCHECK(!packet->empty());
 
     if (first_packet) {
@@ -1950,7 +1908,7 @@
       packet_duration = packet->frame->Duration();
       // TODO(ossu): Is this the correct way to track Opus FEC packets?
       if (packet->priority.codec_level > 0) {
-        stats_.SecondaryDecodedSamples(
+        stats_->SecondaryDecodedSamples(
             rtc::dchecked_cast<int>(packet_duration));
       }
     } else if (!has_cng_packet) {
@@ -1966,7 +1924,7 @@
     }
     extracted_samples = packet->timestamp - first_timestamp + packet_duration;
 
-    stats_.JitterBufferDelay(extracted_samples, waiting_time_ms);
+    stats_->JitterBufferDelay(packet_duration, waiting_time_ms);
 
     packet_list->push_back(std::move(*packet));  // Store packet in list.
     packet = absl::nullopt;  // Ensure it's never used after the move.
@@ -1978,13 +1936,14 @@
         !has_cng_packet) {
       int16_t seq_no_diff = next_packet->sequence_number - prev_sequence_number;
       size_t ts_diff = next_packet->timestamp - prev_timestamp;
-      if (seq_no_diff == 1 ||
-          (seq_no_diff == 0 && ts_diff == decoder_frame_length_)) {
+      if ((seq_no_diff == 1 || seq_no_diff == 0) &&
+          ts_diff <= packet_duration) {
         // The next sequence number is available, or the next part of a packet
         // that was split into pieces upon insertion.
         next_packet_available = true;
       }
       prev_sequence_number = next_packet->sequence_number;
+      prev_timestamp = next_packet->timestamp;
     }
   } while (extracted_samples < required_samples && next_packet_available);
 
@@ -1993,7 +1952,7 @@
     // we could end up in the situation where we never decode anything, since
     // all incoming packets are considered too old but the buffer will also
     // never be flooded and flushed.
-    packet_buffer_->DiscardAllOldPackets(timestamp_, &stats_);
+    packet_buffer_->DiscardAllOldPackets(timestamp_, stats_.get());
   }
 
   return rtc::dchecked_cast<int>(extracted_samples);
@@ -2003,7 +1962,7 @@
   // Delete objects and create new ones.
   expand_.reset(expand_factory_->Create(background_noise_.get(),
                                         sync_buffer_.get(), &random_vector_,
-                                        &stats_, fs_hz, channels));
+                                        stats_.get(), fs_hz, channels));
   merge_.reset(new Merge(fs_hz, channels, expand_.get(), sync_buffer_.get()));
 }
 
diff --git a/modules/audio_coding/neteq/neteq_impl.h b/modules/audio_coding/neteq/neteq_impl.h
index 525ae61..34a5c71 100644
--- a/modules/audio_coding/neteq/neteq_impl.h
+++ b/modules/audio_coding/neteq/neteq_impl.h
@@ -24,8 +24,8 @@
 #include "modules/audio_coding/neteq/random_vector.h"
 #include "modules/audio_coding/neteq/statistics_calculator.h"
 #include "modules/audio_coding/neteq/tick_timer.h"
-#include "rtc_base/constructormagic.h"
-#include "rtc_base/criticalsection.h"
+#include "rtc_base/constructor_magic.h"
+#include "rtc_base/critical_section.h"
 #include "rtc_base/thread_annotations.h"
 
 namespace webrtc {
@@ -99,6 +99,7 @@
     ~Dependencies();
 
     std::unique_ptr<TickTimer> tick_timer;
+    std::unique_ptr<StatisticsCalculator> stats;
     std::unique_ptr<BufferLevelFilter> buffer_level_filter;
     std::unique_ptr<DecoderDatabase> decoder_database;
     std::unique_ptr<DelayPeakDetector> delay_peak_detector;
@@ -137,15 +138,6 @@
 
   void SetCodecs(const std::map<int, SdpAudioFormat>& codecs) override;
 
-  int RegisterPayloadType(NetEqDecoder codec,
-                          const std::string& codec_name,
-                          uint8_t rtp_payload_type) override;
-
-  int RegisterExternalDecoder(AudioDecoder* decoder,
-                              NetEqDecoder codec,
-                              const std::string& codec_name,
-                              uint8_t rtp_payload_type) override;
-
   bool RegisterPayloadType(int rtp_payload_type,
                            const SdpAudioFormat& audio_format) override;
 
@@ -159,9 +151,11 @@
 
   bool SetMaximumDelay(int delay_ms) override;
 
-  int TargetDelayMs() const override;
+  bool SetBaseMinimumDelayMs(int delay_ms) override;
 
-  int CurrentDelayMs() const override;
+  int GetBaseMinimumDelayMs() const override;
+
+  int TargetDelayMs() const override;
 
   int FilteredCurrentDelayMs() const override;
 
@@ -184,8 +178,6 @@
 
   int last_output_sample_rate_hz() const override;
 
-  absl::optional<CodecInst> GetDecoder(int payload_type) const override;
-
   absl::optional<SdpAudioFormat> GetDecoderFormat(
       int payload_type) const override;
 
@@ -370,6 +362,7 @@
       RTC_GUARDED_BY(crit_sect_);
   const std::unique_ptr<PreemptiveExpandFactory> preemptive_expand_factory_
       RTC_GUARDED_BY(crit_sect_);
+  const std::unique_ptr<StatisticsCalculator> stats_ RTC_GUARDED_BY(crit_sect_);
 
   std::unique_ptr<BackgroundNoise> background_noise_ RTC_GUARDED_BY(crit_sect_);
   std::unique_ptr<DecisionLogic> decision_logic_ RTC_GUARDED_BY(crit_sect_);
@@ -384,7 +377,6 @@
       RTC_GUARDED_BY(crit_sect_);
   RandomVector random_vector_ RTC_GUARDED_BY(crit_sect_);
   std::unique_ptr<ComfortNoise> comfort_noise_ RTC_GUARDED_BY(crit_sect_);
-  StatisticsCalculator stats_ RTC_GUARDED_BY(crit_sect_);
   int fs_hz_ RTC_GUARDED_BY(crit_sect_);
   int fs_mult_ RTC_GUARDED_BY(crit_sect_);
   int last_output_sample_rate_hz_ RTC_GUARDED_BY(crit_sect_);
@@ -401,7 +393,6 @@
   absl::optional<uint8_t> current_rtp_payload_type_ RTC_GUARDED_BY(crit_sect_);
   absl::optional<uint8_t> current_cng_rtp_payload_type_
       RTC_GUARDED_BY(crit_sect_);
-  uint32_t ssrc_ RTC_GUARDED_BY(crit_sect_);
   bool first_packet_ RTC_GUARDED_BY(crit_sect_);
   bool enable_fast_accelerate_ RTC_GUARDED_BY(crit_sect_);
   std::unique_ptr<NackTracker> nack_ RTC_GUARDED_BY(crit_sect_);
@@ -416,6 +407,7 @@
   ExpandUmaLogger speech_expand_uma_logger_ RTC_GUARDED_BY(crit_sect_);
   bool no_time_stretching_ RTC_GUARDED_BY(crit_sect_);  // Only used for test.
   rtc::BufferT<int16_t> concealment_audio_ RTC_GUARDED_BY(crit_sect_);
+  const bool enable_rtx_handling_ RTC_GUARDED_BY(crit_sect_);
 
  private:
   RTC_DISALLOW_COPY_AND_ASSIGN(NetEqImpl);
diff --git a/modules/audio_coding/neteq/neteq_impl_unittest.cc b/modules/audio_coding/neteq/neteq_impl_unittest.cc
index 0e087c8..5875493 100644
--- a/modules/audio_coding/neteq/neteq_impl_unittest.cc
+++ b/modules/audio_coding/neteq/neteq_impl_unittest.cc
@@ -10,10 +10,11 @@
 
 #include <memory>
 
+#include "absl/memory/memory.h"
 #include "api/audio_codecs/builtin_audio_decoder_factory.h"
-#include "common_types.h"  // NOLINT(build/include)
 #include "modules/audio_coding/neteq/accelerate.h"
 #include "modules/audio_coding/neteq/expand.h"
+#include "modules/audio_coding/neteq/histogram.h"
 #include "modules/audio_coding/neteq/include/neteq.h"
 #include "modules/audio_coding/neteq/mock/mock_buffer_level_filter.h"
 #include "modules/audio_coding/neteq/mock/mock_decoder_database.h"
@@ -25,9 +26,12 @@
 #include "modules/audio_coding/neteq/mock/mock_red_payload_splitter.h"
 #include "modules/audio_coding/neteq/neteq_impl.h"
 #include "modules/audio_coding/neteq/preemptive_expand.h"
+#include "modules/audio_coding/neteq/statistics_calculator.h"
 #include "modules/audio_coding/neteq/sync_buffer.h"
 #include "modules/audio_coding/neteq/timestamp_scaler.h"
 #include "rtc_base/numerics/safe_conversions.h"
+#include "test/audio_decoder_proxy_factory.h"
+#include "test/function_audio_decoder_factory.h"
 #include "test/gmock.h"
 #include "test/gtest.h"
 #include "test/mock_audio_decoder.h"
@@ -59,8 +63,10 @@
  protected:
   NetEqImplTest() { config_.sample_rate_hz = 8000; }
 
-  void CreateInstance() {
-    NetEqImpl::Dependencies deps(config_, CreateBuiltinAudioDecoderFactory());
+  void CreateInstance(
+      const rtc::scoped_refptr<AudioDecoderFactory>& decoder_factory) {
+    ASSERT_TRUE(decoder_factory);
+    NetEqImpl::Dependencies deps(config_, decoder_factory);
 
     // Get a local pointer to NetEq's TickTimer object.
     tick_timer_ = deps.tick_timer.get();
@@ -83,7 +89,7 @@
 
     if (use_mock_delay_peak_detector_) {
       std::unique_ptr<MockDelayPeakDetector> mock(
-          new MockDelayPeakDetector(tick_timer_));
+          new MockDelayPeakDetector(tick_timer_, config_.enable_rtx_handling));
       mock_delay_peak_detector_ = mock.get();
       EXPECT_CALL(*mock_delay_peak_detector_, Reset()).Times(1);
       deps.delay_peak_detector = std::move(mock);
@@ -92,8 +98,10 @@
 
     if (use_mock_delay_manager_) {
       std::unique_ptr<MockDelayManager> mock(new MockDelayManager(
-          config_.max_packets_in_buffer, config_.min_delay_ms,
-          delay_peak_detector_, tick_timer_));
+          config_.max_packets_in_buffer, config_.min_delay_ms, 1020054733,
+          DelayManager::HistogramMode::INTER_ARRIVAL_TIME,
+          config_.enable_rtx_handling, delay_peak_detector_, tick_timer_,
+          deps.stats.get(), absl::make_unique<Histogram>(50, 32745)));
       mock_delay_manager_ = mock.get();
       EXPECT_CALL(*mock_delay_manager_, set_streaming_mode(false)).Times(1);
       deps.delay_manager = std::move(mock);
@@ -137,6 +145,8 @@
     ASSERT_TRUE(neteq_ != NULL);
   }
 
+  void CreateInstance() { CreateInstance(CreateBuiltinAudioDecoderFactory()); }
+
   void UseNoMocks() {
     ASSERT_TRUE(neteq_ == NULL) << "Must call UseNoMocks before CreateInstance";
     use_mock_buffer_level_filter_ = false;
@@ -173,7 +183,7 @@
     }
   }
 
-  void TestDtmfPacket(NetEqDecoder decoder_type) {
+  void TestDtmfPacket(int sample_rate_hz) {
     const size_t kPayloadLength = 4;
     const uint8_t kPayloadType = 110;
     const uint32_t kReceiveTime = 17;
@@ -189,8 +199,8 @@
     rtp_header.timestamp = 0x12345678;
     rtp_header.ssrc = 0x87654321;
 
-    EXPECT_EQ(NetEq::kOK, neteq_->RegisterPayloadType(
-        decoder_type, "telephone-event", kPayloadType));
+    EXPECT_TRUE(neteq_->RegisterPayloadType(
+        kPayloadType, SdpAudioFormat("telephone-event", sample_rate_hz, 1)));
 
     // Insert first packet.
     EXPECT_EQ(NetEq::kOK,
@@ -257,16 +267,6 @@
   delete neteq;
 }
 
-TEST_F(NetEqImplTest, RegisterPayloadTypeNetEqDecoder) {
-  CreateInstance();
-  uint8_t rtp_payload_type = 0;
-  NetEqDecoder codec_type = NetEqDecoder::kDecoderPCMu;
-  const std::string kCodecName = "Robert\'); DROP TABLE Students;";
-  EXPECT_CALL(*mock_decoder_database_,
-              RegisterPayload(rtp_payload_type, codec_type, kCodecName));
-  neteq_->RegisterPayloadType(codec_type, kCodecName, rtp_payload_type);
-}
-
 TEST_F(NetEqImplTest, RegisterPayloadType) {
   CreateInstance();
   constexpr int rtp_payload_type = 0;
@@ -335,8 +335,8 @@
 
         *dec = std::move(mock_decoder);
       }));
-  DecoderDatabase::DecoderInfo info(NetEqDecoder::kDecoderPCMu, absl::nullopt,
-                                    mock_decoder_factory);
+  DecoderDatabase::DecoderInfo info(SdpAudioFormat("pcmu", 8000, 1),
+                                    absl::nullopt, mock_decoder_factory);
 
   // Expectations for decoder database.
   EXPECT_CALL(*mock_decoder_database_, GetDecoderInfo(kPayloadType))
@@ -405,8 +405,8 @@
   rtp_header.timestamp = 0x12345678;
   rtp_header.ssrc = 0x87654321;
 
-  EXPECT_EQ(NetEq::kOK, neteq_->RegisterPayloadType(
-                            NetEqDecoder::kDecoderPCM16B, "", kPayloadType));
+  EXPECT_TRUE(neteq_->RegisterPayloadType(kPayloadType,
+                                          SdpAudioFormat("l16", 8000, 1)));
 
   // Insert packets. The buffer should not flush.
   for (size_t i = 1; i <= config_.max_packets_in_buffer; ++i) {
@@ -428,27 +428,24 @@
 }
 
 TEST_F(NetEqImplTest, TestDtmfPacketAVT) {
-  TestDtmfPacket(NetEqDecoder::kDecoderAVT);
+  TestDtmfPacket(8000);
 }
 
 TEST_F(NetEqImplTest, TestDtmfPacketAVT16kHz) {
-  TestDtmfPacket(NetEqDecoder::kDecoderAVT16kHz);
+  TestDtmfPacket(16000);
 }
 
 TEST_F(NetEqImplTest, TestDtmfPacketAVT32kHz) {
-  TestDtmfPacket(NetEqDecoder::kDecoderAVT32kHz);
+  TestDtmfPacket(32000);
 }
 
 TEST_F(NetEqImplTest, TestDtmfPacketAVT48kHz) {
-  TestDtmfPacket(NetEqDecoder::kDecoderAVT48kHz);
+  TestDtmfPacket(48000);
 }
 
 // This test verifies that timestamps propagate from the incoming packets
 // through to the sync buffer and to the playout timestamp.
 TEST_F(NetEqImplTest, VerifyTimestampPropagation) {
-  UseNoMocks();
-  CreateInstance();
-
   const uint8_t kPayloadType = 17;   // Just an arbitrary number.
   const uint32_t kReceiveTime = 17;  // Value doesn't matter for this test.
   const int kSampleRateHz = 8000;
@@ -494,9 +491,14 @@
     int16_t next_value_;
   } decoder_;
 
-  EXPECT_EQ(NetEq::kOK, neteq_->RegisterExternalDecoder(
-                            &decoder_, NetEqDecoder::kDecoderPCM16B,
-                            "dummy name", kPayloadType));
+  rtc::scoped_refptr<AudioDecoderFactory> decoder_factory =
+      new rtc::RefCountedObject<test::AudioDecoderProxyFactory>(&decoder_);
+
+  UseNoMocks();
+  CreateInstance(decoder_factory);
+
+  EXPECT_TRUE(neteq_->RegisterPayloadType(kPayloadType,
+                                          SdpAudioFormat("L16", 8000, 1)));
 
   // Insert one packet.
   EXPECT_EQ(NetEq::kOK,
@@ -541,7 +543,11 @@
 
 TEST_F(NetEqImplTest, ReorderedPacket) {
   UseNoMocks();
-  CreateInstance();
+  // Create a mock decoder object.
+  MockAudioDecoder mock_decoder;
+
+  CreateInstance(
+      new rtc::RefCountedObject<test::AudioDecoderProxyFactory>(&mock_decoder));
 
   const uint8_t kPayloadType = 17;   // Just an arbitrary number.
   const uint32_t kReceiveTime = 17;  // Value doesn't matter for this test.
@@ -556,8 +562,6 @@
   rtp_header.timestamp = 0x12345678;
   rtp_header.ssrc = 0x87654321;
 
-  // Create a mock decoder object.
-  MockAudioDecoder mock_decoder;
   EXPECT_CALL(mock_decoder, Reset()).WillRepeatedly(Return());
   EXPECT_CALL(mock_decoder, SampleRateHz())
       .WillRepeatedly(Return(kSampleRateHz));
@@ -575,9 +579,8 @@
                                           dummy_output + kPayloadLengthSamples),
                       SetArgPointee<4>(AudioDecoder::kSpeech),
                       Return(rtc::checked_cast<int>(kPayloadLengthSamples))));
-  EXPECT_EQ(NetEq::kOK, neteq_->RegisterExternalDecoder(
-                            &mock_decoder, NetEqDecoder::kDecoderPCM16B,
-                            "dummy name", kPayloadType));
+  EXPECT_TRUE(neteq_->RegisterPayloadType(kPayloadType,
+                                          SdpAudioFormat("L16", 8000, 1)));
 
   // Insert one packet.
   EXPECT_EQ(NetEq::kOK,
@@ -662,8 +665,8 @@
   EXPECT_EQ(AudioFrame::kPLC, output.speech_type_);
 
   // Register the payload type.
-  EXPECT_EQ(NetEq::kOK, neteq_->RegisterPayloadType(
-                            NetEqDecoder::kDecoderPCM16B, "", kPayloadType));
+  EXPECT_TRUE(neteq_->RegisterPayloadType(kPayloadType,
+                                          SdpAudioFormat("l16", 8000, 1)));
 
   // Insert 10 packets.
   for (size_t i = 0; i < 10; ++i) {
@@ -689,7 +692,10 @@
 // internal CNG mode properly.
 TEST_F(NetEqImplTest, CodecInternalCng) {
   UseNoMocks();
-  CreateInstance();
+  // Create a mock decoder object.
+  MockAudioDecoder mock_decoder;
+  CreateInstance(
+      new rtc::RefCountedObject<test::AudioDecoderProxyFactory>(&mock_decoder));
 
   const uint8_t kPayloadType = 17;   // Just an arbitrary number.
   const uint32_t kReceiveTime = 17;  // Value doesn't matter for this test.
@@ -706,8 +712,6 @@
   rtp_header.timestamp = 0x12345678;
   rtp_header.ssrc = 0x87654321;
 
-  // Create a mock decoder object.
-  MockAudioDecoder mock_decoder;
   EXPECT_CALL(mock_decoder, Reset()).WillRepeatedly(Return());
   EXPECT_CALL(mock_decoder, SampleRateHz())
       .WillRepeatedly(Return(kSampleRateKhz * 1000));
@@ -751,9 +755,8 @@
                       SetArgPointee<4>(AudioDecoder::kSpeech),
                       Return(rtc::checked_cast<int>(kPayloadLengthSamples))));
 
-  EXPECT_EQ(NetEq::kOK, neteq_->RegisterExternalDecoder(
-                            &mock_decoder, NetEqDecoder::kDecoderOpus,
-                            "dummy name", kPayloadType));
+  EXPECT_TRUE(neteq_->RegisterPayloadType(kPayloadType,
+                                          SdpAudioFormat("opus", 48000, 2)));
 
   // Insert one packet (decoder will return speech).
   EXPECT_EQ(NetEq::kOK,
@@ -834,7 +837,10 @@
 
 TEST_F(NetEqImplTest, UnsupportedDecoder) {
   UseNoMocks();
-  CreateInstance();
+  ::testing::NiceMock<MockAudioDecoder> decoder;
+
+  CreateInstance(
+      new rtc::RefCountedObject<test::AudioDecoderProxyFactory>(&decoder));
   static const size_t kNetEqMaxFrameSize = 5760;  // 120 ms @ 48 kHz.
   static const size_t kChannels = 2;
 
@@ -853,8 +859,6 @@
   rtp_header.timestamp = 0x12345678;
   rtp_header.ssrc = 0x87654321;
 
-  ::testing::NiceMock<MockAudioDecoder> decoder;
-
   const uint8_t kFirstPayloadValue = 1;
   const uint8_t kSecondPayloadValue = 2;
 
@@ -886,9 +890,8 @@
   EXPECT_CALL(decoder, Channels())
       .WillRepeatedly(Return(kChannels));
 
-  EXPECT_EQ(NetEq::kOK, neteq_->RegisterExternalDecoder(
-                            &decoder, NetEqDecoder::kDecoderPCM16B,
-                            "dummy name", kPayloadType));
+  EXPECT_TRUE(neteq_->RegisterPayloadType(kPayloadType,
+                                          SdpAudioFormat("L16", 8000, 1)));
 
   // Insert one packet.
   payload[0] = kFirstPayloadValue;  // This will make Decode() fail.
@@ -945,8 +948,8 @@
   rtp_header.timestamp = 0x12345678;
   rtp_header.ssrc = 0x87654321;
 
-  EXPECT_EQ(NetEq::kOK, neteq_->RegisterPayloadType(
-                            NetEqDecoder::kDecoderPCM16B, "", kPayloadType));
+  EXPECT_TRUE(neteq_->RegisterPayloadType(kPayloadType,
+                                          SdpAudioFormat("l16", 8000, 1)));
 
   // Insert packets until the buffer flushes.
   for (size_t i = 0; i <= config_.max_packets_in_buffer; ++i) {
@@ -965,7 +968,11 @@
 
 TEST_F(NetEqImplTest, DecodedPayloadTooShort) {
   UseNoMocks();
-  CreateInstance();
+  // Create a mock decoder object.
+  MockAudioDecoder mock_decoder;
+
+  CreateInstance(
+      new rtc::RefCountedObject<test::AudioDecoderProxyFactory>(&mock_decoder));
 
   const uint8_t kPayloadType = 17;   // Just an arbitrary number.
   const uint32_t kReceiveTime = 17;  // Value doesn't matter for this test.
@@ -980,8 +987,6 @@
   rtp_header.timestamp = 0x12345678;
   rtp_header.ssrc = 0x87654321;
 
-  // Create a mock decoder object.
-  MockAudioDecoder mock_decoder;
   EXPECT_CALL(mock_decoder, Reset()).WillRepeatedly(Return());
   EXPECT_CALL(mock_decoder, SampleRateHz())
       .WillRepeatedly(Return(kSampleRateHz));
@@ -1001,9 +1006,8 @@
                                     dummy_output + kPayloadLengthSamples - 5),
                 SetArgPointee<4>(AudioDecoder::kSpeech),
                 Return(rtc::checked_cast<int>(kPayloadLengthSamples - 5))));
-  EXPECT_EQ(NetEq::kOK, neteq_->RegisterExternalDecoder(
-                            &mock_decoder, NetEqDecoder::kDecoderPCM16B,
-                            "dummy name", kPayloadType));
+  EXPECT_TRUE(neteq_->RegisterPayloadType(kPayloadType,
+                                          SdpAudioFormat("L16", 8000, 1)));
 
   // Insert one packet.
   EXPECT_EQ(NetEq::kOK,
@@ -1026,7 +1030,11 @@
 // This test checks the behavior of NetEq when audio decoder fails.
 TEST_F(NetEqImplTest, DecodingError) {
   UseNoMocks();
-  CreateInstance();
+  // Create a mock decoder object.
+  MockAudioDecoder mock_decoder;
+
+  CreateInstance(
+      new rtc::RefCountedObject<test::AudioDecoderProxyFactory>(&mock_decoder));
 
   const uint8_t kPayloadType = 17;   // Just an arbitrary number.
   const uint32_t kReceiveTime = 17;  // Value doesn't matter for this test.
@@ -1047,8 +1055,6 @@
   rtp_header.timestamp = 0x12345678;
   rtp_header.ssrc = 0x87654321;
 
-  // Create a mock decoder object.
-  MockAudioDecoder mock_decoder;
   EXPECT_CALL(mock_decoder, Reset()).WillRepeatedly(Return());
   EXPECT_CALL(mock_decoder, SampleRateHz())
       .WillRepeatedly(Return(kSampleRateHz));
@@ -1094,9 +1100,8 @@
                   Return(rtc::checked_cast<int>(kFrameLengthSamples))));
   }
 
-  EXPECT_EQ(NetEq::kOK, neteq_->RegisterExternalDecoder(
-                            &mock_decoder, NetEqDecoder::kDecoderPCM16B,
-                            "dummy name", kPayloadType));
+  EXPECT_TRUE(neteq_->RegisterPayloadType(kPayloadType,
+                                          SdpAudioFormat("L16", 8000, 1)));
 
   // Insert packets.
   for (int i = 0; i < 6; ++i) {
@@ -1140,7 +1145,11 @@
 // This test checks the behavior of NetEq when audio decoder fails during CNG.
 TEST_F(NetEqImplTest, DecodingErrorDuringInternalCng) {
   UseNoMocks();
-  CreateInstance();
+
+  // Create a mock decoder object.
+  MockAudioDecoder mock_decoder;
+  CreateInstance(
+      new rtc::RefCountedObject<test::AudioDecoderProxyFactory>(&mock_decoder));
 
   const uint8_t kPayloadType = 17;   // Just an arbitrary number.
   const uint32_t kReceiveTime = 17;  // Value doesn't matter for this test.
@@ -1161,8 +1170,6 @@
   rtp_header.timestamp = 0x12345678;
   rtp_header.ssrc = 0x87654321;
 
-  // Create a mock decoder object.
-  MockAudioDecoder mock_decoder;
   EXPECT_CALL(mock_decoder, Reset()).WillRepeatedly(Return());
   EXPECT_CALL(mock_decoder, SampleRateHz())
       .WillRepeatedly(Return(kSampleRateHz));
@@ -1204,9 +1211,8 @@
                   Return(rtc::checked_cast<int>(kFrameLengthSamples))));
   }
 
-  EXPECT_EQ(NetEq::kOK, neteq_->RegisterExternalDecoder(
-                            &mock_decoder, NetEqDecoder::kDecoderPCM16B,
-                            "dummy name", kPayloadType));
+  EXPECT_TRUE(neteq_->RegisterPayloadType(kPayloadType,
+                                          SdpAudioFormat("l16", 8000, 1)));
 
   // Insert 2 packets. This will make netEq into codec internal CNG mode.
   for (int i = 0; i < 2; ++i) {
@@ -1261,6 +1267,34 @@
   EXPECT_EQ(1u, tick_timer_->ticks());
 }
 
+TEST_F(NetEqImplTest, SetBaseMinimumDelay) {
+  UseNoMocks();
+  use_mock_delay_manager_ = true;
+  CreateInstance();
+
+  EXPECT_CALL(*mock_delay_manager_, SetBaseMinimumDelay(_))
+      .WillOnce(Return(true))
+      .WillOnce(Return(false));
+
+  const int delay_ms = 200;
+
+  EXPECT_EQ(true, neteq_->SetBaseMinimumDelayMs(delay_ms));
+  EXPECT_EQ(false, neteq_->SetBaseMinimumDelayMs(delay_ms));
+}
+
+TEST_F(NetEqImplTest, GetBaseMinimumDelayMs) {
+  UseNoMocks();
+  use_mock_delay_manager_ = true;
+  CreateInstance();
+
+  const int delay_ms = 200;
+
+  EXPECT_CALL(*mock_delay_manager_, GetBaseMinimumDelay())
+      .WillOnce(Return(delay_ms));
+
+  EXPECT_EQ(delay_ms, neteq_->GetBaseMinimumDelayMs());
+}
+
 TEST_F(NetEqImplTest, TargetDelayMs) {
   UseNoMocks();
   use_mock_delay_manager_ = true;
@@ -1289,6 +1323,43 @@
   neteq_->InsertEmptyPacket(rtp_header);
 }
 
+TEST_F(NetEqImplTest, EnableRtxHandling) {
+  UseNoMocks();
+  use_mock_delay_manager_ = true;
+  config_.enable_rtx_handling = true;
+  CreateInstance();
+  EXPECT_CALL(*mock_delay_manager_, BufferLimits(_, _))
+      .Times(1)
+      .WillOnce(DoAll(SetArgPointee<0>(0), SetArgPointee<1>(0)));
+
+  const int kPayloadLengthSamples = 80;
+  const size_t kPayloadLengthBytes = 2 * kPayloadLengthSamples;  // PCM 16-bit.
+  const uint8_t kPayloadType = 17;  // Just an arbitrary number.
+  const uint32_t kReceiveTime = 17;
+  uint8_t payload[kPayloadLengthBytes] = {0};
+  RTPHeader rtp_header;
+  rtp_header.payloadType = kPayloadType;
+  rtp_header.sequenceNumber = 0x1234;
+  rtp_header.timestamp = 0x12345678;
+  rtp_header.ssrc = 0x87654321;
+
+  EXPECT_TRUE(neteq_->RegisterPayloadType(kPayloadType,
+                                          SdpAudioFormat("l16", 8000, 1)));
+  EXPECT_EQ(NetEq::kOK,
+            neteq_->InsertPacket(rtp_header, payload, kReceiveTime));
+  AudioFrame output;
+  bool muted;
+  EXPECT_EQ(NetEq::kOK, neteq_->GetAudio(&output, &muted));
+
+  // Insert second packet that was sent before the first packet.
+  rtp_header.sequenceNumber -= 1;
+  rtp_header.timestamp -= kPayloadLengthSamples;
+  EXPECT_CALL(*mock_delay_manager_,
+              Update(rtp_header.sequenceNumber, rtp_header.timestamp, _));
+  EXPECT_EQ(NetEq::kOK,
+            neteq_->InsertPacket(rtp_header, payload, kReceiveTime));
+}
+
 class Decoder120ms : public AudioDecoder {
  public:
   Decoder120ms(int sample_rate_hz, SpeechType speech_type)
@@ -1328,13 +1399,17 @@
 
   void CreateInstanceNoMocks() {
     UseNoMocks();
-    CreateInstance();
+    CreateInstance(decoder_factory_);
+    EXPECT_TRUE(neteq_->RegisterPayloadType(
+        kPayloadType, SdpAudioFormat("opus", 48000, 2, {{"stereo", "1"}})));
   }
 
   void CreateInstanceWithDelayManagerMock() {
     UseNoMocks();
     use_mock_delay_manager_ = true;
-    CreateInstance();
+    CreateInstance(decoder_factory_);
+    EXPECT_TRUE(neteq_->RegisterPayloadType(
+        kPayloadType, SdpAudioFormat("opus", 48000, 2, {{"stereo", "1"}})));
   }
 
   uint32_t timestamp_diff_between_packets() const {
@@ -1364,14 +1439,18 @@
   }
 
   void Register120msCodec(AudioDecoder::SpeechType speech_type) {
-    decoder_.reset(new Decoder120ms(kSamplingFreq_, speech_type));
-    ASSERT_EQ(2u, decoder_->Channels());
-    EXPECT_EQ(NetEq::kOK, neteq_->RegisterExternalDecoder(
-                              decoder_.get(), NetEqDecoder::kDecoderOpus_2ch,
-                              "120ms codec", kPayloadType));
+    const uint32_t sampling_freq = kSamplingFreq_;
+    decoder_factory_ =
+        new rtc::RefCountedObject<test::FunctionAudioDecoderFactory>(
+            [sampling_freq, speech_type]() {
+              std::unique_ptr<AudioDecoder> decoder =
+                  absl::make_unique<Decoder120ms>(sampling_freq, speech_type);
+              RTC_CHECK_EQ(2, decoder->Channels());
+              return decoder;
+            });
   }
 
-  std::unique_ptr<Decoder120ms> decoder_;
+  rtc::scoped_refptr<AudioDecoderFactory> decoder_factory_;
   AudioFrame output_;
   const uint32_t kPayloadType = 17;
   const uint32_t kSamplingFreq_ = 48000;
@@ -1379,8 +1458,8 @@
 };
 
 TEST_F(NetEqImplTest120ms, CodecInternalCng) {
-  CreateInstanceNoMocks();
   Register120msCodec(AudioDecoder::kComfortNoise);
+  CreateInstanceNoMocks();
 
   InsertPacket(first_timestamp());
   GetFirstPacket();
@@ -1391,8 +1470,8 @@
 }
 
 TEST_F(NetEqImplTest120ms, Normal) {
-  CreateInstanceNoMocks();
   Register120msCodec(AudioDecoder::kSpeech);
+  CreateInstanceNoMocks();
 
   InsertPacket(first_timestamp());
   GetFirstPacket();
@@ -1401,9 +1480,9 @@
 }
 
 TEST_F(NetEqImplTest120ms, Merge) {
+  Register120msCodec(AudioDecoder::kSpeech);
   CreateInstanceWithDelayManagerMock();
 
-  Register120msCodec(AudioDecoder::kSpeech);
   InsertPacket(first_timestamp());
 
   GetFirstPacket();
@@ -1420,8 +1499,8 @@
 }
 
 TEST_F(NetEqImplTest120ms, Expand) {
-  CreateInstanceNoMocks();
   Register120msCodec(AudioDecoder::kSpeech);
+  CreateInstanceNoMocks();
 
   InsertPacket(first_timestamp());
   GetFirstPacket();
@@ -1432,8 +1511,8 @@
 }
 
 TEST_F(NetEqImplTest120ms, FastAccelerate) {
-  CreateInstanceWithDelayManagerMock();
   Register120msCodec(AudioDecoder::kSpeech);
+  CreateInstanceWithDelayManagerMock();
 
   InsertPacket(first_timestamp());
   GetFirstPacket();
@@ -1450,8 +1529,8 @@
 }
 
 TEST_F(NetEqImplTest120ms, PreemptiveExpand) {
-  CreateInstanceWithDelayManagerMock();
   Register120msCodec(AudioDecoder::kSpeech);
+  CreateInstanceWithDelayManagerMock();
 
   InsertPacket(first_timestamp());
   GetFirstPacket();
@@ -1469,8 +1548,8 @@
 }
 
 TEST_F(NetEqImplTest120ms, Accelerate) {
-  CreateInstanceWithDelayManagerMock();
   Register120msCodec(AudioDecoder::kSpeech);
+  CreateInstanceWithDelayManagerMock();
 
   InsertPacket(first_timestamp());
   GetFirstPacket();
diff --git a/modules/audio_coding/neteq/neteq_network_stats_unittest.cc b/modules/audio_coding/neteq/neteq_network_stats_unittest.cc
index 57fc682..79059b7 100644
--- a/modules/audio_coding/neteq/neteq_network_stats_unittest.cc
+++ b/modules/audio_coding/neteq/neteq_network_stats_unittest.cc
@@ -10,10 +10,15 @@
 
 #include <memory>
 
+#include "absl/memory/memory.h"
 #include "api/audio/audio_frame.h"
+#include "api/audio_codecs/audio_decoder.h"
 #include "common_types.h"  // NOLINT(build/include)
-#include "modules/audio_coding/neteq/tools/neteq_external_decoder_test.h"
+
+#include "modules/audio_coding/neteq/include/neteq.h"
 #include "modules/audio_coding/neteq/tools/rtp_generator.h"
+#include "rtc_base/ref_counted_object.h"
+#include "test/audio_decoder_proxy_factory.h"
 #include "test/gmock.h"
 
 namespace webrtc {
@@ -118,10 +123,12 @@
   bool fec_enabled_;
 };
 
-class NetEqNetworkStatsTest : public NetEqExternalDecoderTest {
+class NetEqNetworkStatsTest {
  public:
   static const int kPayloadSizeByte = 30;
   static const int kFrameSizeMs = 20;
+  static const uint8_t kPayloadType = 95;
+  static const int kOutputLengthMs = 10;
 
   enum logic {
     kIgnore,
@@ -146,17 +153,19 @@
     NetEqNetworkStatistics stats_ref;
   };
 
-  NetEqNetworkStatsTest(NetEqDecoder codec,
-                        int sample_rate_hz,
-                        MockAudioDecoder* decoder)
-      : NetEqExternalDecoderTest(codec, sample_rate_hz, decoder),
-        external_decoder_(decoder),
-        samples_per_ms_(sample_rate_hz / 1000),
+  NetEqNetworkStatsTest(const SdpAudioFormat& format, MockAudioDecoder* decoder)
+      : decoder_(decoder),
+        decoder_factory_(
+            new rtc::RefCountedObject<AudioDecoderProxyFactory>(decoder)),
+        samples_per_ms_(format.clockrate_hz / 1000),
         frame_size_samples_(kFrameSizeMs * samples_per_ms_),
-        rtp_generator_(new test::RtpGenerator(samples_per_ms_)),
+        rtp_generator_(new RtpGenerator(samples_per_ms_)),
         last_lost_time_(0),
         packet_loss_interval_(0xffffffff) {
-    Init();
+    NetEq::Config config;
+    config.sample_rate_hz = format.clockrate_hz;
+    neteq_ = absl::WrapUnique(NetEq::Create(config, decoder_factory_));
+    neteq_->RegisterPayloadType(kPayloadType, format);
   }
 
   bool Lost(uint32_t send_time) {
@@ -180,7 +189,7 @@
   // expects.x = 2, 'x' in current stats should > 'x' in |stats_ref|
   void CheckNetworkStatistics(NetEqNetworkStatsCheck expects) {
     NetEqNetworkStatistics stats;
-    neteq()->NetworkStatistics(&stats);
+    neteq_->NetworkStatistics(&stats);
 
 #define CHECK_NETEQ_NETWORK_STATS(x)           \
   switch (expects.x) {                         \
@@ -211,9 +220,6 @@
     CHECK_NETEQ_NETWORK_STATS(added_zero_samples);
 
 #undef CHECK_NETEQ_NETWORK_STATS
-
-    // Compare with CurrentDelay, which should be identical.
-    EXPECT_EQ(stats.current_buffer_size_ms, neteq()->CurrentDelayMs());
   }
 
   void RunTest(int num_loops, NetEqNetworkStatsCheck expects) {
@@ -230,18 +236,26 @@
             kPayloadType, frame_size_samples_, &rtp_header_);
         if (!Lost(next_send_time)) {
           static const uint8_t payload[kPayloadSizeByte] = {0};
-          InsertPacket(rtp_header_, payload, next_send_time);
+          ASSERT_EQ(NetEq::kOK,
+                    neteq_->InsertPacket(rtp_header_, payload, next_send_time));
         }
       }
-      GetOutputAudio(&output_frame_);
+      bool muted = true;
+      EXPECT_EQ(NetEq::kOK, neteq_->GetAudio(&output_frame_, &muted));
+      ASSERT_FALSE(muted);
+      EXPECT_EQ(decoder_->Channels(), output_frame_.num_channels_);
+      EXPECT_EQ(static_cast<size_t>(kOutputLengthMs * samples_per_ms_),
+                output_frame_.samples_per_channel_);
+      EXPECT_EQ(48000, neteq_->last_output_sample_rate_hz());
+
       time_now += kOutputLengthMs;
     }
     CheckNetworkStatistics(expects);
-    neteq()->FlushBuffers();
+    neteq_->FlushBuffers();
   }
 
   void DecodeFecTest() {
-    external_decoder_->set_fec_enabled(false);
+    decoder_->set_fec_enabled(false);
     NetEqNetworkStatsCheck expects = {kIgnore,  // current_buffer_size_ms
                                       kIgnore,  // preferred_buffer_size_ms
                                       kIgnore,  // jitter_peaks_found
@@ -264,7 +278,7 @@
     RunTest(50, expects);
 
     // Next we enable FEC.
-    external_decoder_->set_fec_enabled(true);
+    decoder_->set_fec_enabled(true);
     // If FEC fills in the lost packets, no packet loss will be counted.
     expects.stats_ref.packet_loss_rate = 0;
     expects.stats_ref.expand_rate = expects.stats_ref.speech_expand_rate = 0;
@@ -296,10 +310,13 @@
   }
 
  private:
-  MockAudioDecoder* external_decoder_;
+  MockAudioDecoder* decoder_;
+  rtc::scoped_refptr<AudioDecoderProxyFactory> decoder_factory_;
+  std::unique_ptr<NetEq> neteq_;
+
   const int samples_per_ms_;
   const size_t frame_size_samples_;
-  std::unique_ptr<test::RtpGenerator> rtp_generator_;
+  std::unique_ptr<RtpGenerator> rtp_generator_;
   RTPHeader rtp_header_;
   uint32_t last_lost_time_;
   uint32_t packet_loss_interval_;
@@ -308,21 +325,21 @@
 
 TEST(NetEqNetworkStatsTest, DecodeFec) {
   MockAudioDecoder decoder(48000, 1);
-  NetEqNetworkStatsTest test(NetEqDecoder::kDecoderOpus, 48000, &decoder);
+  NetEqNetworkStatsTest test(SdpAudioFormat("opus", 48000, 2), &decoder);
   test.DecodeFecTest();
   EXPECT_CALL(decoder, Die()).Times(1);
 }
 
 TEST(NetEqNetworkStatsTest, StereoDecodeFec) {
   MockAudioDecoder decoder(48000, 2);
-  NetEqNetworkStatsTest test(NetEqDecoder::kDecoderOpus, 48000, &decoder);
+  NetEqNetworkStatsTest test(SdpAudioFormat("opus", 48000, 2), &decoder);
   test.DecodeFecTest();
   EXPECT_CALL(decoder, Die()).Times(1);
 }
 
 TEST(NetEqNetworkStatsTest, NoiseExpansionTest) {
   MockAudioDecoder decoder(48000, 1);
-  NetEqNetworkStatsTest test(NetEqDecoder::kDecoderOpus, 48000, &decoder);
+  NetEqNetworkStatsTest test(SdpAudioFormat("opus", 48000, 2), &decoder);
   test.NoiseExpansionTest();
   EXPECT_CALL(decoder, Die()).Times(1);
 }
diff --git a/modules/audio_coding/neteq/neteq_stereo_unittest.cc b/modules/audio_coding/neteq/neteq_stereo_unittest.cc
index 3f86944..d25e8d6 100644
--- a/modules/audio_coding/neteq/neteq_stereo_unittest.cc
+++ b/modules/audio_coding/neteq/neteq_stereo_unittest.cc
@@ -17,14 +17,13 @@
 
 #include "api/audio/audio_frame.h"
 #include "api/audio_codecs/builtin_audio_decoder_factory.h"
-#include "common_types.h"  // NOLINT(build/include)
 #include "modules/audio_coding/codecs/pcm16b/pcm16b.h"
 #include "modules/audio_coding/neteq/include/neteq.h"
 #include "modules/audio_coding/neteq/tools/input_audio_file.h"
 #include "modules/audio_coding/neteq/tools/rtp_generator.h"
 #include "rtc_base/strings/string_builder.h"
 #include "test/gtest.h"
-#include "test/testsupport/fileutils.h"
+#include "test/testsupport/file_utils.h"
 
 namespace webrtc {
 
@@ -90,51 +89,12 @@
     const std::string file_name =
         webrtc::test::ResourcePath("audio_coding/testfile32kHz", "pcm");
     input_file_.reset(new test::InputAudioFile(file_name));
-    NetEqDecoder mono_decoder;
-    NetEqDecoder multi_decoder;
-    switch (sample_rate_hz_) {
-      case 8000:
-        mono_decoder = NetEqDecoder::kDecoderPCM16B;
-        if (num_channels_ == 2) {
-          multi_decoder = NetEqDecoder::kDecoderPCM16B_2ch;
-        } else if (num_channels_ == 5) {
-          multi_decoder = NetEqDecoder::kDecoderPCM16B_5ch;
-        } else {
-          FAIL() << "Only 2 and 5 channels supported for 8000 Hz.";
-        }
-        break;
-      case 16000:
-        mono_decoder = NetEqDecoder::kDecoderPCM16Bwb;
-        if (num_channels_ == 2) {
-          multi_decoder = NetEqDecoder::kDecoderPCM16Bwb_2ch;
-        } else {
-          FAIL() << "More than 2 channels is not supported for 16000 Hz.";
-        }
-        break;
-      case 32000:
-        mono_decoder = NetEqDecoder::kDecoderPCM16Bswb32kHz;
-        if (num_channels_ == 2) {
-          multi_decoder = NetEqDecoder::kDecoderPCM16Bswb32kHz_2ch;
-        } else {
-          FAIL() << "More than 2 channels is not supported for 32000 Hz.";
-        }
-        break;
-      case 48000:
-        mono_decoder = NetEqDecoder::kDecoderPCM16Bswb48kHz;
-        if (num_channels_ == 2) {
-          multi_decoder = NetEqDecoder::kDecoderPCM16Bswb48kHz_2ch;
-        } else {
-          FAIL() << "More than 2 channels is not supported for 48000 Hz.";
-        }
-        break;
-      default:
-        FAIL() << "We shouldn't get here.";
-    }
-    ASSERT_EQ(NetEq::kOK, neteq_mono_->RegisterPayloadType(mono_decoder, "mono",
-                                                           kPayloadTypeMono));
-    ASSERT_EQ(NetEq::kOK,
-              neteq_->RegisterPayloadType(multi_decoder, "multi-channel",
-                                          kPayloadTypeMulti));
+    RTC_CHECK_GE(num_channels_, 2);
+    ASSERT_TRUE(neteq_mono_->RegisterPayloadType(
+        kPayloadTypeMono, SdpAudioFormat("l16", sample_rate_hz_, 1)));
+    ASSERT_TRUE(neteq_->RegisterPayloadType(
+        kPayloadTypeMulti,
+        SdpAudioFormat("l16", sample_rate_hz_, num_channels_)));
   }
 
   virtual void TearDown() {}
@@ -404,24 +364,24 @@
 
 // Instantiate the tests. Each test is instantiated using the function above,
 // so that all different parameter combinations are tested.
-INSTANTIATE_TEST_CASE_P(MultiChannel,
-                        NetEqStereoTestNoJitter,
-                        ::testing::ValuesIn(GetTestParameters()));
+INSTANTIATE_TEST_SUITE_P(MultiChannel,
+                         NetEqStereoTestNoJitter,
+                         ::testing::ValuesIn(GetTestParameters()));
 
-INSTANTIATE_TEST_CASE_P(MultiChannel,
-                        NetEqStereoTestPositiveDrift,
-                        ::testing::ValuesIn(GetTestParameters()));
+INSTANTIATE_TEST_SUITE_P(MultiChannel,
+                         NetEqStereoTestPositiveDrift,
+                         ::testing::ValuesIn(GetTestParameters()));
 
-INSTANTIATE_TEST_CASE_P(MultiChannel,
-                        NetEqStereoTestNegativeDrift,
-                        ::testing::ValuesIn(GetTestParameters()));
+INSTANTIATE_TEST_SUITE_P(MultiChannel,
+                         NetEqStereoTestNegativeDrift,
+                         ::testing::ValuesIn(GetTestParameters()));
 
-INSTANTIATE_TEST_CASE_P(MultiChannel,
-                        NetEqStereoTestDelays,
-                        ::testing::ValuesIn(GetTestParameters()));
+INSTANTIATE_TEST_SUITE_P(MultiChannel,
+                         NetEqStereoTestDelays,
+                         ::testing::ValuesIn(GetTestParameters()));
 
-INSTANTIATE_TEST_CASE_P(MultiChannel,
-                        NetEqStereoTestLosses,
-                        ::testing::ValuesIn(GetTestParameters()));
+INSTANTIATE_TEST_SUITE_P(MultiChannel,
+                         NetEqStereoTestLosses,
+                         ::testing::ValuesIn(GetTestParameters()));
 
 }  // namespace webrtc
diff --git a/modules/audio_coding/neteq/neteq_unittest.cc b/modules/audio_coding/neteq/neteq_unittest.cc
index e8b5023..6c67ca8 100644
--- a/modules/audio_coding/neteq/neteq_unittest.cc
+++ b/modules/audio_coding/neteq/neteq_unittest.cc
@@ -27,17 +27,18 @@
 #include "modules/audio_coding/neteq/tools/neteq_packet_source_input.h"
 #include "modules/audio_coding/neteq/tools/neteq_test.h"
 #include "modules/audio_coding/neteq/tools/rtp_file_source.h"
+#include "modules/include/module_common_types_public.h"
 #include "modules/rtp_rtcp/include/rtcp_statistics.h"
+#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
 #include "rtc_base/ignore_wundef.h"
-#include "rtc_base/messagedigest.h"
+#include "rtc_base/message_digest.h"
 #include "rtc_base/numerics/safe_conversions.h"
-#include "rtc_base/protobuf_utils.h"
-#include "rtc_base/stringencode.h"
+#include "rtc_base/string_encode.h"
 #include "rtc_base/strings/string_builder.h"
 #include "rtc_base/system/arch.h"
 #include "test/field_trial.h"
 #include "test/gtest.h"
-#include "test/testsupport/fileutils.h"
+#include "test/testsupport/file_utils.h"
 
 // This must come after test/gtest.h
 #include "rtc_base/flags.h"  // NOLINT(build/include)
@@ -129,10 +130,8 @@
 void LoadDecoders(webrtc::NetEq* neteq) {
   ASSERT_EQ(true,
             neteq->RegisterPayloadType(0, SdpAudioFormat("pcmu", 8000, 1)));
-  // Use non-SdpAudioFormat argument when registering PCMa, so that we get test
-  // coverage for that as well.
-  ASSERT_EQ(0, neteq->RegisterPayloadType(webrtc::NetEqDecoder::kDecoderPCMa,
-                                          "pcma", 8));
+  ASSERT_EQ(true,
+            neteq->RegisterPayloadType(8, SdpAudioFormat("pcma", 8000, 1)));
 #ifdef WEBRTC_CODEC_ILBC
   ASSERT_EQ(true,
             neteq->RegisterPayloadType(102, SdpAudioFormat("ilbc", 8000, 1)));
@@ -208,7 +207,7 @@
   neteq_unittest::NetEqNetworkStatistics stats;
   Convert(stats_raw, &stats);
 
-  ProtoString stats_string;
+  std::string stats_string;
   ASSERT_TRUE(stats.SerializeToString(&stats_string));
   AddMessage(output_fp_, digest_.get(), stats_string);
 #else
@@ -221,7 +220,7 @@
   neteq_unittest::RtcpStatistics stats;
   Convert(stats_raw, &stats);
 
-  ProtoString stats_string;
+  std::string stats_string;
   ASSERT_TRUE(stats.SerializeToString(&stats_string));
   AddMessage(output_fp_, digest_.get(), stats_string);
 #else
@@ -258,7 +257,6 @@
   NetEqDecodingTest();
   virtual void SetUp();
   virtual void TearDown();
-  void SelectDecoders(NetEqDecoder* used_codec);
   void OpenInputFile(const std::string& rtp_file);
   void Process();
 
@@ -402,10 +400,6 @@
       ASSERT_EQ(0, neteq_->NetworkStatistics(&current_network_stats));
       ASSERT_NO_FATAL_FAILURE(network_stats.AddResult(current_network_stats));
 
-      // Compare with CurrentDelay, which should be identical.
-      EXPECT_EQ(current_network_stats.current_buffer_size_ms,
-                neteq_->CurrentDelayMs());
-
       // Verify that liftime stats and network stats report similar loss
       // concealment rates.
       auto lifetime_stats = neteq_->GetLifetimeStatistics();
@@ -464,16 +458,16 @@
       webrtc::test::ResourcePath("audio_coding/neteq_universal_new", "rtp");
 
   const std::string output_checksum =
-      PlatformChecksum("0c6dc227f781c81a229970f8fceda1a012498cba",
-                       "15c4a2202877a414515e218bdb7992f0ad53e5af", "not used",
-                       "0c6dc227f781c81a229970f8fceda1a012498cba",
-                       "25fc4c863caa499aa447a5b8d059f5452cbcc500");
+      PlatformChecksum("9652cee1d6771a9cbfda821ae1bbdb41b0dd4dee",
+                       "54a7e32f163663c0af35bf70bf45cefc24ad62ef", "not used",
+                       "9652cee1d6771a9cbfda821ae1bbdb41b0dd4dee",
+                       "79496b0a1ef0a3824f3ee04789748a461bed643f");
 
   const std::string network_stats_checksum =
-      PlatformChecksum("4b2370f5c794741d2a46be5c7935c66ef3fb53e9",
-                       "e339cb2adf5ab3dfc21cb7205d670a34751e8336", "not used",
-                       "4b2370f5c794741d2a46be5c7935c66ef3fb53e9",
-                       "4b2370f5c794741d2a46be5c7935c66ef3fb53e9");
+      PlatformChecksum("c59b1f9f282b6d8733cdff975e3c150ca4a47d51",
+                       "bca95e565996a4ffd6e2ac15736e08843bdca93b", "not used",
+                       "c59b1f9f282b6d8733cdff975e3c150ca4a47d51",
+                       "c59b1f9f282b6d8733cdff975e3c150ca4a47d51");
 
   DecodeAndCompare(input_rtp_file, output_checksum, network_stats_checksum,
                    FLAG_gen_ref);
@@ -1661,6 +1655,7 @@
   int packets_sent = 0;
   int packets_received = 0;
   int expected_delay = 0;
+  uint64_t expected_emitted_count = 0;
   while (packets_received < kNumPackets) {
     // Insert packet.
     if (packets_sent < kNumPackets) {
@@ -1684,6 +1679,7 @@
       // number of samples that are sent for play out.
       int current_delay_ms = packets_delay * kPacketLenMs;
       expected_delay += current_delay_ms * kSamples;
+      expected_emitted_count += kSamples;
     }
   }
 
@@ -1695,6 +1691,7 @@
   // Check jitter buffer delay.
   NetEqLifetimeStatistics stats = neteq_->GetLifetimeStatistics();
   EXPECT_EQ(expected_delay, static_cast<int>(stats.jitter_buffer_delay_ms));
+  EXPECT_EQ(expected_emitted_count, stats.jitter_buffer_emitted_count);
 }
 
 TEST_F(NetEqDecodingTestFaxMode, TestJitterBufferDelayWithoutLoss) {
@@ -1705,12 +1702,43 @@
   TestJitterBufferDelay(true);
 }
 
+TEST_F(NetEqDecodingTestFaxMode, TestJitterBufferDelayWithAcceleration) {
+  const int kPacketLenMs = 10;  // All packets are of 10 ms size.
+  const size_t kSamples = kPacketLenMs * 16;
+  const size_t kPayloadBytes = kSamples * 2;
+  RTPHeader rtp_info;
+  rtp_info.ssrc = 0x1234;     // Just an arbitrary SSRC.
+  rtp_info.payloadType = 94;  // PCM16b WB codec.
+  rtp_info.markerBit = 0;
+  const uint8_t payload[kPayloadBytes] = {0};
+
+  neteq_->InsertPacket(rtp_info, payload, 0);
+
+  bool muted;
+  neteq_->GetAudio(&out_frame_, &muted);
+
+  rtp_info.sequenceNumber += 1;
+  rtp_info.timestamp += kSamples;
+  neteq_->InsertPacket(rtp_info, payload, 0);
+  rtp_info.sequenceNumber += 1;
+  rtp_info.timestamp += kSamples;
+  neteq_->InsertPacket(rtp_info, payload, 0);
+
+  // We have two packets in the buffer and kAccelerate operation will
+  // extract 20 ms of data.
+  neteq_->GetAudio(&out_frame_, &muted, Operations::kAccelerate);
+
+  // Check jitter buffer delay.
+  NetEqLifetimeStatistics stats = neteq_->GetLifetimeStatistics();
+  EXPECT_EQ(10 * kSamples * 3, stats.jitter_buffer_delay_ms);
+  EXPECT_EQ(kSamples * 3, stats.jitter_buffer_emitted_count);
+}
+
 namespace test {
 TEST(NetEqNoTimeStretchingMode, RunTest) {
   NetEq::Config config;
   config.for_test_no_time_stretching = true;
   auto codecs = NetEqTest::StandardDecoderMap();
-  NetEqTest::ExtDecoderMap ext_codecs;
   NetEqPacketSourceInput::RtpHeaderExtensionMap rtp_ext_map = {
       {1, kRtpExtensionAudioLevel},
       {3, kRtpExtensionAbsoluteSendTime},
@@ -1724,8 +1752,8 @@
       new TimeLimitedNetEqInput(std::move(input), 20000));
   std::unique_ptr<AudioSink> output(new VoidAudioSink);
   NetEqTest::Callbacks callbacks;
-  NetEqTest test(config, codecs, ext_codecs, std::move(input_time_limit),
-                 std::move(output), callbacks);
+  NetEqTest test(config, CreateBuiltinAudioDecoderFactory(), codecs, nullptr,
+                 std::move(input_time_limit), std::move(output), callbacks);
   test.Run();
   const auto stats = test.SimulationStats();
   EXPECT_EQ(0, stats.accelerate_rate);
diff --git a/modules/audio_coding/neteq/normal.h b/modules/audio_coding/neteq/normal.h
index 80451b5..2059c5a 100644
--- a/modules/audio_coding/neteq/normal.h
+++ b/modules/audio_coding/neteq/normal.h
@@ -16,7 +16,7 @@
 
 #include "modules/audio_coding/neteq/defines.h"
 #include "rtc_base/checks.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 #include "rtc_base/numerics/safe_conversions.h"
 
 namespace webrtc {
diff --git a/modules/audio_coding/neteq/packet_buffer.cc b/modules/audio_coding/neteq/packet_buffer.cc
index 343763b..e90fadc 100644
--- a/modules/audio_coding/neteq/packet_buffer.cc
+++ b/modules/audio_coding/neteq/packet_buffer.cc
@@ -287,6 +287,20 @@
   return num_samples;
 }
 
+size_t PacketBuffer::GetSpanSamples(size_t last_decoded_length) const {
+  if (buffer_.size() == 0) {
+    return 0;
+  }
+
+  size_t span = buffer_.back().timestamp - buffer_.front().timestamp;
+  if (buffer_.back().frame && buffer_.back().frame->Duration() > 0) {
+    span += buffer_.back().frame->Duration();
+  } else {
+    span += last_decoded_length;
+  }
+  return span;
+}
+
 bool PacketBuffer::ContainsDtxOrCngPacket(
     const DecoderDatabase* decoder_database) const {
   RTC_DCHECK(decoder_database);
diff --git a/modules/audio_coding/neteq/packet_buffer.h b/modules/audio_coding/neteq/packet_buffer.h
index 0f5cd7f..0837027 100644
--- a/modules/audio_coding/neteq/packet_buffer.h
+++ b/modules/audio_coding/neteq/packet_buffer.h
@@ -15,7 +15,7 @@
 #include "modules/audio_coding/neteq/decoder_database.h"
 #include "modules/audio_coding/neteq/packet.h"
 #include "modules/include/module_common_types_public.h"  // IsNewerTimestamp
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
@@ -121,6 +121,10 @@
   // duplicate and redundant packets.
   virtual size_t NumSamplesInBuffer(size_t last_decoded_length) const;
 
+  // Returns the total duration in samples that the packets in the buffer spans
+  // across.
+  virtual size_t GetSpanSamples(size_t last_decoded_length) const;
+
   // Returns true if the packet buffer contains any DTX or CNG packets.
   virtual bool ContainsDtxOrCngPacket(
       const DecoderDatabase* decoder_database) const;
diff --git a/modules/audio_coding/neteq/packet_buffer_unittest.cc b/modules/audio_coding/neteq/packet_buffer_unittest.cc
index cb40d7d..7a381ee 100644
--- a/modules/audio_coding/neteq/packet_buffer_unittest.cc
+++ b/modules/audio_coding/neteq/packet_buffer_unittest.cc
@@ -175,7 +175,7 @@
 
   MockDecoderDatabase decoder_database;
   auto factory = CreateBuiltinAudioDecoderFactory();
-  const DecoderDatabase::DecoderInfo info(NetEqDecoder::kDecoderPCMu,
+  const DecoderDatabase::DecoderInfo info(SdpAudioFormat("pcmu", 8000, 1),
                                           absl::nullopt, factory);
   EXPECT_CALL(decoder_database, GetDecoderInfo(0))
       .WillRepeatedly(Return(&info));
@@ -220,11 +220,11 @@
 
   MockDecoderDatabase decoder_database;
   auto factory = CreateBuiltinAudioDecoderFactory();
-  const DecoderDatabase::DecoderInfo info0(NetEqDecoder::kDecoderPCMu,
+  const DecoderDatabase::DecoderInfo info0(SdpAudioFormat("pcmu", 8000, 1),
                                            absl::nullopt, factory);
   EXPECT_CALL(decoder_database, GetDecoderInfo(0))
       .WillRepeatedly(Return(&info0));
-  const DecoderDatabase::DecoderInfo info1(NetEqDecoder::kDecoderPCMa,
+  const DecoderDatabase::DecoderInfo info1(SdpAudioFormat("pcma", 8000, 1),
                                            absl::nullopt, factory);
   EXPECT_CALL(decoder_database, GetDecoderInfo(1))
       .WillRepeatedly(Return(&info1));
@@ -407,7 +407,7 @@
 
   MockDecoderDatabase decoder_database;
   auto factory = CreateBuiltinAudioDecoderFactory();
-  const DecoderDatabase::DecoderInfo info(NetEqDecoder::kDecoderPCMu,
+  const DecoderDatabase::DecoderInfo info(SdpAudioFormat("pcmu", 8000, 1),
                                           absl::nullopt, factory);
   EXPECT_CALL(decoder_database, GetDecoderInfo(0))
       .WillRepeatedly(Return(&info));
@@ -447,12 +447,12 @@
 
   MockDecoderDatabase decoder_database;
   auto factory = CreateBuiltinAudioDecoderFactory();
-  const DecoderDatabase::DecoderInfo info_cng(NetEqDecoder::kDecoderCNGnb,
+  const DecoderDatabase::DecoderInfo info_cng(SdpAudioFormat("cn", 8000, 1),
                                               absl::nullopt, factory);
   EXPECT_CALL(decoder_database, GetDecoderInfo(kCngPt))
       .WillRepeatedly(Return(&info_cng));
-  const DecoderDatabase::DecoderInfo info_speech(NetEqDecoder::kDecoderPCM16Bwb,
-                                                 absl::nullopt, factory);
+  const DecoderDatabase::DecoderInfo info_speech(
+      SdpAudioFormat("l16", 16000, 1), absl::nullopt, factory);
   EXPECT_CALL(decoder_database, GetDecoderInfo(kSpeechPt))
       .WillRepeatedly(Return(&info_speech));
 
@@ -549,7 +549,7 @@
   list.push_back(gen.NextPacket(payload_len));  // Valid packet.
   MockDecoderDatabase decoder_database;
   auto factory = CreateBuiltinAudioDecoderFactory();
-  const DecoderDatabase::DecoderInfo info(NetEqDecoder::kDecoderPCMu,
+  const DecoderDatabase::DecoderInfo info(SdpAudioFormat("pcmu", 8000, 1),
                                           absl::nullopt, factory);
   EXPECT_CALL(decoder_database, GetDecoderInfo(0))
       .WillRepeatedly(Return(&info));
diff --git a/modules/audio_coding/neteq/post_decode_vad.h b/modules/audio_coding/neteq/post_decode_vad.h
index 27d69a6..ca7cabf 100644
--- a/modules/audio_coding/neteq/post_decode_vad.h
+++ b/modules/audio_coding/neteq/post_decode_vad.h
@@ -16,7 +16,7 @@
 
 #include "api/audio_codecs/audio_decoder.h"
 #include "common_audio/vad/include/webrtc_vad.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
diff --git a/modules/audio_coding/neteq/preemptive_expand.h b/modules/audio_coding/neteq/preemptive_expand.h
index 0f7b3bc..e7d2bad 100644
--- a/modules/audio_coding/neteq/preemptive_expand.h
+++ b/modules/audio_coding/neteq/preemptive_expand.h
@@ -15,7 +15,7 @@
 #include <stdint.h>
 
 #include "modules/audio_coding/neteq/time_stretch.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
diff --git a/modules/audio_coding/neteq/random_vector.h b/modules/audio_coding/neteq/random_vector.h
index e8c7ba8..1d37600 100644
--- a/modules/audio_coding/neteq/random_vector.h
+++ b/modules/audio_coding/neteq/random_vector.h
@@ -14,7 +14,7 @@
 #include <stddef.h>
 #include <stdint.h>
 
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
diff --git a/modules/audio_coding/neteq/red_payload_splitter.h b/modules/audio_coding/neteq/red_payload_splitter.h
index 55063e7..c2e0a44 100644
--- a/modules/audio_coding/neteq/red_payload_splitter.h
+++ b/modules/audio_coding/neteq/red_payload_splitter.h
@@ -12,7 +12,7 @@
 #define MODULES_AUDIO_CODING_NETEQ_RED_PAYLOAD_SPLITTER_H_
 
 #include "modules/audio_coding/neteq/packet.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
diff --git a/modules/audio_coding/neteq/red_payload_splitter_unittest.cc b/modules/audio_coding/neteq/red_payload_splitter_unittest.cc
index 52fc1ba..b4cd8d7 100644
--- a/modules/audio_coding/neteq/red_payload_splitter_unittest.cc
+++ b/modules/audio_coding/neteq/red_payload_splitter_unittest.cc
@@ -18,7 +18,7 @@
 #include <utility>  // pair
 
 #include "api/audio_codecs/builtin_audio_decoder_factory.h"
-#include "modules/audio_coding/neteq/mock/mock_decoder_database.h"
+#include "modules/audio_coding/neteq/decoder_database.h"
 #include "modules/audio_coding/neteq/packet.h"
 #include "rtc_base/numerics/safe_conversions.h"
 #include "test/gtest.h"
@@ -300,10 +300,11 @@
   // do its job.
   DecoderDatabase decoder_database(
       new rtc::RefCountedObject<MockAudioDecoderFactory>, absl::nullopt);
-  decoder_database.RegisterPayload(0, NetEqDecoder::kDecoderCNGnb, "cng-nb");
-  decoder_database.RegisterPayload(1, NetEqDecoder::kDecoderPCMu, "pcmu");
-  decoder_database.RegisterPayload(2, NetEqDecoder::kDecoderAVT, "avt");
-  decoder_database.RegisterPayload(3, NetEqDecoder::kDecoderILBC, "ilbc");
+  decoder_database.RegisterPayload(0, SdpAudioFormat("cn", 8000, 1));
+  decoder_database.RegisterPayload(1, SdpAudioFormat("pcmu", 8000, 1));
+  decoder_database.RegisterPayload(2,
+                                   SdpAudioFormat("telephone-event", 8000, 1));
+  decoder_database.RegisterPayload(3, SdpAudioFormat("ilbc", 8000, 1));
 
   RedPayloadSplitter splitter;
   splitter.CheckRedPayloads(&packet_list, decoder_database);
@@ -334,8 +335,8 @@
   // do its job.
   DecoderDatabase decoder_database(
       new rtc::RefCountedObject<MockAudioDecoderFactory>, absl::nullopt);
-  decoder_database.RegisterPayload(kRedPayloadType, NetEqDecoder::kDecoderRED,
-                                   "red");
+  decoder_database.RegisterPayload(kRedPayloadType,
+                                   SdpAudioFormat("red", 8000, 1));
 
   RedPayloadSplitter splitter;
   splitter.CheckRedPayloads(&packet_list, decoder_database);
diff --git a/modules/audio_coding/neteq/statistics_calculator.cc b/modules/audio_coding/neteq/statistics_calculator.cc
index 50521fb..a0e9bca 100644
--- a/modules/audio_coding/neteq/statistics_calculator.cc
+++ b/modules/audio_coding/neteq/statistics_calculator.cc
@@ -216,7 +216,7 @@
 }
 
 void StatisticsCalculator::PacketsDiscarded(size_t num_packets) {
-  discarded_packets_ += num_packets;
+  operations_and_state_.discarded_primary_packets += num_packets;
 }
 
 void StatisticsCalculator::SecondaryPacketsDiscarded(size_t num_packets) {
@@ -246,6 +246,7 @@
 void StatisticsCalculator::JitterBufferDelay(size_t num_samples,
                                              uint64_t waiting_time_ms) {
   lifetime_stats_.jitter_buffer_delay_ms += waiting_time_ms * num_samples;
+  lifetime_stats_.jitter_buffer_emitted_count += num_samples;
 }
 
 void StatisticsCalculator::SecondaryDecodedSamples(int num_samples) {
@@ -257,6 +258,14 @@
   buffer_full_counter_.RegisterSample();
 }
 
+void StatisticsCalculator::ReceivedPacket() {
+  ++lifetime_stats_.jitter_buffer_packets_received;
+}
+
+void StatisticsCalculator::RelativePacketArrivalDelay(size_t delay_ms) {
+  lifetime_stats_.relative_packet_arrival_delay_ms += delay_ms;
+}
+
 void StatisticsCalculator::LogDelayedPacketOutageEvent(int num_samples,
                                                        int fs_hz) {
   int outage_duration_ms = num_samples / (fs_hz / 1000);
diff --git a/modules/audio_coding/neteq/statistics_calculator.h b/modules/audio_coding/neteq/statistics_calculator.h
index 49b74a0..cb92f37 100644
--- a/modules/audio_coding/neteq/statistics_calculator.h
+++ b/modules/audio_coding/neteq/statistics_calculator.h
@@ -15,7 +15,7 @@
 #include <string>
 
 #include "modules/audio_coding/neteq/include/neteq.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
@@ -83,9 +83,15 @@
   // Reports that |num_samples| samples were decoded from secondary packets.
   void SecondaryDecodedSamples(int num_samples);
 
-  // Rerport that the packet buffer was flushed.
+  // Reports that the packet buffer was flushed.
   void FlushedPacketBuffer();
 
+  // Reports that the jitter buffer received a packet.
+  void ReceivedPacket();
+
+  // Reports that a received packet was delayed by |delay_ms| milliseconds.
+  virtual void RelativePacketArrivalDelay(size_t delay_ms);
+
   // Logs a delayed packet outage event of |num_samples| expanded at a sample
   // rate of |fs_hz|. A delayed packet outage event is defined as an expand
   // period caused not by an actual packet loss, but by a delayed packet.
diff --git a/modules/audio_coding/neteq/statistics_calculator_unittest.cc b/modules/audio_coding/neteq/statistics_calculator_unittest.cc
index 0a4901d..1fb8e1c 100644
--- a/modules/audio_coding/neteq/statistics_calculator_unittest.cc
+++ b/modules/audio_coding/neteq/statistics_calculator_unittest.cc
@@ -104,4 +104,28 @@
   EXPECT_EQ((50u << 14) / k10MsSamples, stats_output.speech_expand_rate);
 }
 
+TEST(StatisticsCalculator, RelativePacketArrivalDelay) {
+  StatisticsCalculator stats;
+
+  stats.RelativePacketArrivalDelay(50);
+  NetEqLifetimeStatistics stats_output = stats.GetLifetimeStatistics();
+  EXPECT_EQ(50u, stats_output.relative_packet_arrival_delay_ms);
+
+  stats.RelativePacketArrivalDelay(20);
+  stats_output = stats.GetLifetimeStatistics();
+  EXPECT_EQ(70u, stats_output.relative_packet_arrival_delay_ms);
+}
+
+TEST(StatisticsCalculator, ReceivedPacket) {
+  StatisticsCalculator stats;
+
+  stats.ReceivedPacket();
+  NetEqLifetimeStatistics stats_output = stats.GetLifetimeStatistics();
+  EXPECT_EQ(1u, stats_output.jitter_buffer_packets_received);
+
+  stats.ReceivedPacket();
+  stats_output = stats.GetLifetimeStatistics();
+  EXPECT_EQ(2u, stats_output.jitter_buffer_packets_received);
+}
+
 }  // namespace webrtc
diff --git a/modules/audio_coding/neteq/sync_buffer.h b/modules/audio_coding/neteq/sync_buffer.h
index d645e91..7f6c111 100644
--- a/modules/audio_coding/neteq/sync_buffer.h
+++ b/modules/audio_coding/neteq/sync_buffer.h
@@ -19,7 +19,7 @@
 #include "modules/audio_coding/neteq/audio_multi_vector.h"
 #include "modules/audio_coding/neteq/audio_vector.h"
 #include "rtc_base/buffer.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
diff --git a/modules/audio_coding/neteq/tick_timer.h b/modules/audio_coding/neteq/tick_timer.h
index 02f083e..724dd12 100644
--- a/modules/audio_coding/neteq/tick_timer.h
+++ b/modules/audio_coding/neteq/tick_timer.h
@@ -15,7 +15,7 @@
 #include <memory>
 
 #include "rtc_base/checks.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
diff --git a/modules/audio_coding/neteq/time_stretch.h b/modules/audio_coding/neteq/time_stretch.h
index 13ad2c8..9f86649 100644
--- a/modules/audio_coding/neteq/time_stretch.h
+++ b/modules/audio_coding/neteq/time_stretch.h
@@ -15,7 +15,7 @@
 #include <string.h>  // memset, size_t
 
 #include "modules/audio_coding/neteq/audio_multi_vector.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
diff --git a/modules/audio_coding/neteq/time_stretch_unittest.cc b/modules/audio_coding/neteq/time_stretch_unittest.cc
index c96c7d4..6fced38 100644
--- a/modules/audio_coding/neteq/time_stretch_unittest.cc
+++ b/modules/audio_coding/neteq/time_stretch_unittest.cc
@@ -21,7 +21,7 @@
 #include "modules/audio_coding/neteq/tools/input_audio_file.h"
 #include "rtc_base/checks.h"
 #include "test/gtest.h"
-#include "test/testsupport/fileutils.h"
+#include "test/testsupport/file_utils.h"
 
 namespace webrtc {
 
diff --git a/modules/audio_coding/neteq/timestamp_scaler.h b/modules/audio_coding/neteq/timestamp_scaler.h
index 62f535c..93cb953 100644
--- a/modules/audio_coding/neteq/timestamp_scaler.h
+++ b/modules/audio_coding/neteq/timestamp_scaler.h
@@ -12,7 +12,7 @@
 #define MODULES_AUDIO_CODING_NETEQ_TIMESTAMP_SCALER_H_
 
 #include "modules/audio_coding/neteq/packet.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
diff --git a/modules/audio_coding/neteq/timestamp_scaler_unittest.cc b/modules/audio_coding/neteq/timestamp_scaler_unittest.cc
index 1f1445a..5b14189 100644
--- a/modules/audio_coding/neteq/timestamp_scaler_unittest.cc
+++ b/modules/audio_coding/neteq/timestamp_scaler_unittest.cc
@@ -25,7 +25,7 @@
   MockDecoderDatabase db;
   auto factory = CreateBuiltinAudioDecoderFactory();
   // Use PCMu, because it doesn't use scaled timestamps.
-  const DecoderDatabase::DecoderInfo info(NetEqDecoder::kDecoderPCMu,
+  const DecoderDatabase::DecoderInfo info(SdpAudioFormat("pcmu", 8000, 1),
                                           absl::nullopt, factory);
   static const uint8_t kRtpPayloadType = 0;
   EXPECT_CALL(db, GetDecoderInfo(kRtpPayloadType))
@@ -47,7 +47,7 @@
   MockDecoderDatabase db;
   auto factory = CreateBuiltinAudioDecoderFactory();
   // Use PCMu, because it doesn't use scaled timestamps.
-  const DecoderDatabase::DecoderInfo info(NetEqDecoder::kDecoderPCMu,
+  const DecoderDatabase::DecoderInfo info(SdpAudioFormat("pcmu", 8000, 1),
                                           absl::nullopt, factory);
   static const uint8_t kRtpPayloadType = 0;
   EXPECT_CALL(db, GetDecoderInfo(kRtpPayloadType))
@@ -74,7 +74,7 @@
   MockDecoderDatabase db;
   auto factory = CreateBuiltinAudioDecoderFactory();
   // Use G722, which has a factor 2 scaling.
-  const DecoderDatabase::DecoderInfo info(NetEqDecoder::kDecoderG722,
+  const DecoderDatabase::DecoderInfo info(SdpAudioFormat("g722", 8000, 1),
                                           absl::nullopt, factory);
   static const uint8_t kRtpPayloadType = 17;
   EXPECT_CALL(db, GetDecoderInfo(kRtpPayloadType))
@@ -100,7 +100,7 @@
   MockDecoderDatabase db;
   auto factory = CreateBuiltinAudioDecoderFactory();
   // Use G722, which has a factor 2 scaling.
-  const DecoderDatabase::DecoderInfo info(NetEqDecoder::kDecoderG722,
+  const DecoderDatabase::DecoderInfo info(SdpAudioFormat("g722", 8000, 1),
                                           absl::nullopt, factory);
   static const uint8_t kRtpPayloadType = 17;
   EXPECT_CALL(db, GetDecoderInfo(kRtpPayloadType))
@@ -130,9 +130,9 @@
   MockDecoderDatabase db;
   auto factory = CreateBuiltinAudioDecoderFactory();
   // Use G722, which has a factor 2 scaling.
-  const DecoderDatabase::DecoderInfo info_g722(NetEqDecoder::kDecoderG722,
+  const DecoderDatabase::DecoderInfo info_g722(SdpAudioFormat("g722", 8000, 1),
                                                absl::nullopt, factory);
-  const DecoderDatabase::DecoderInfo info_cng(NetEqDecoder::kDecoderCNGwb,
+  const DecoderDatabase::DecoderInfo info_cng(SdpAudioFormat("cn", 16000, 1),
                                               absl::nullopt, factory);
   static const uint8_t kRtpPayloadTypeG722 = 17;
   static const uint8_t kRtpPayloadTypeCng = 13;
@@ -174,7 +174,7 @@
   MockDecoderDatabase db;
   auto factory = CreateBuiltinAudioDecoderFactory();
   // Use G722, which has a factor 2 scaling.
-  const DecoderDatabase::DecoderInfo info(NetEqDecoder::kDecoderG722,
+  const DecoderDatabase::DecoderInfo info(SdpAudioFormat("g722", 8000, 1),
                                           absl::nullopt, factory);
   static const uint8_t kRtpPayloadType = 17;
   EXPECT_CALL(db, GetDecoderInfo(kRtpPayloadType))
@@ -204,7 +204,7 @@
   MockDecoderDatabase db;
   auto factory = CreateBuiltinAudioDecoderFactory();
   // Use G722, which has a factor 2 scaling.
-  const DecoderDatabase::DecoderInfo info(NetEqDecoder::kDecoderG722,
+  const DecoderDatabase::DecoderInfo info(SdpAudioFormat("g722", 8000, 1),
                                           absl::nullopt, factory);
   static const uint8_t kRtpPayloadType = 17;
   EXPECT_CALL(db, GetDecoderInfo(kRtpPayloadType))
@@ -238,7 +238,7 @@
   MockDecoderDatabase db;
   auto factory = CreateBuiltinAudioDecoderFactory();
   // Use G722, which has a factor 2 scaling.
-  const DecoderDatabase::DecoderInfo info(NetEqDecoder::kDecoderG722,
+  const DecoderDatabase::DecoderInfo info(SdpAudioFormat("g722", 8000, 1),
                                           absl::nullopt, factory);
   static const uint8_t kRtpPayloadType = 17;
   EXPECT_CALL(db, GetDecoderInfo(kRtpPayloadType))
@@ -279,7 +279,7 @@
 TEST(TimestampScaler, TestOpusLargeStep) {
   MockDecoderDatabase db;
   auto factory = CreateBuiltinAudioDecoderFactory();
-  const DecoderDatabase::DecoderInfo info(NetEqDecoder::kDecoderOpus,
+  const DecoderDatabase::DecoderInfo info(SdpAudioFormat("opus", 48000, 2),
                                           absl::nullopt, factory);
   static const uint8_t kRtpPayloadType = 17;
   EXPECT_CALL(db, GetDecoderInfo(kRtpPayloadType))
diff --git a/modules/audio_coding/neteq/tools/audio_checksum.h b/modules/audio_coding/neteq/tools/audio_checksum.h
index ee8c582..e4306fa 100644
--- a/modules/audio_coding/neteq/tools/audio_checksum.h
+++ b/modules/audio_coding/neteq/tools/audio_checksum.h
@@ -16,9 +16,9 @@
 
 #include "modules/audio_coding/neteq/tools/audio_sink.h"
 #include "rtc_base/buffer.h"
-#include "rtc_base/constructormagic.h"
-#include "rtc_base/messagedigest.h"
-#include "rtc_base/stringencode.h"
+#include "rtc_base/constructor_magic.h"
+#include "rtc_base/message_digest.h"
+#include "rtc_base/string_encode.h"
 #include "rtc_base/system/arch.h"
 
 namespace webrtc {
diff --git a/modules/audio_coding/neteq/tools/audio_loop.h b/modules/audio_coding/neteq/tools/audio_loop.h
index c7788a6..cd764cc 100644
--- a/modules/audio_coding/neteq/tools/audio_loop.h
+++ b/modules/audio_coding/neteq/tools/audio_loop.h
@@ -15,7 +15,7 @@
 #include <string>
 
 #include "api/array_view.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 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 be2a315..68825eb 100644
--- a/modules/audio_coding/neteq/tools/audio_sink.h
+++ b/modules/audio_coding/neteq/tools/audio_sink.h
@@ -12,7 +12,7 @@
 #define MODULES_AUDIO_CODING_NETEQ_TOOLS_AUDIO_SINK_H_
 
 #include "api/audio/audio_frame.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 namespace test {
diff --git a/modules/audio_coding/neteq/tools/constant_pcm_packet_source.h b/modules/audio_coding/neteq/tools/constant_pcm_packet_source.h
index 4e216e4..7adb15b 100644
--- a/modules/audio_coding/neteq/tools/constant_pcm_packet_source.h
+++ b/modules/audio_coding/neteq/tools/constant_pcm_packet_source.h
@@ -14,9 +14,8 @@
 #include <stdio.h>
 #include <string>
 
-#include "common_types.h"  // NOLINT(build/include)
 #include "modules/audio_coding/neteq/tools/packet_source.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 namespace test {
diff --git a/modules/audio_coding/neteq/tools/input_audio_file.cc b/modules/audio_coding/neteq/tools/input_audio_file.cc
index 6d11064..d5e2862 100644
--- a/modules/audio_coding/neteq/tools/input_audio_file.cc
+++ b/modules/audio_coding/neteq/tools/input_audio_file.cc
@@ -18,9 +18,11 @@
 InputAudioFile::InputAudioFile(const std::string file_name, bool loop_at_end)
     : loop_at_end_(loop_at_end) {
   fp_ = fopen(file_name.c_str(), "rb");
+  RTC_DCHECK(fp_) << file_name << " could not be opened.";
 }
 
 InputAudioFile::~InputAudioFile() {
+  RTC_DCHECK(fp_);
   fclose(fp_);
 }
 
diff --git a/modules/audio_coding/neteq/tools/input_audio_file.h b/modules/audio_coding/neteq/tools/input_audio_file.h
index b36dc24..4335a99 100644
--- a/modules/audio_coding/neteq/tools/input_audio_file.h
+++ b/modules/audio_coding/neteq/tools/input_audio_file.h
@@ -15,7 +15,7 @@
 
 #include <string>
 
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 namespace test {
diff --git a/modules/audio_coding/neteq/tools/neteq_external_decoder_test.cc b/modules/audio_coding/neteq/tools/neteq_external_decoder_test.cc
deleted file mode 100644
index 3bd218b..0000000
--- a/modules/audio_coding/neteq/tools/neteq_external_decoder_test.cc
+++ /dev/null
@@ -1,58 +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 "modules/audio_coding/neteq/tools/neteq_external_decoder_test.h"
-
-#include "api/audio/audio_frame.h"
-#include "api/audio_codecs/builtin_audio_decoder_factory.h"
-#include "rtc_base/format_macros.h"
-#include "test/gtest.h"
-
-namespace webrtc {
-namespace test {
-
-NetEqExternalDecoderTest::NetEqExternalDecoderTest(NetEqDecoder codec,
-                                                   int sample_rate_hz,
-                                                   AudioDecoder* decoder)
-    : codec_(codec),
-      decoder_(decoder),
-      sample_rate_hz_(sample_rate_hz),
-      channels_(decoder_->Channels()) {
-  NetEq::Config config;
-  config.sample_rate_hz = sample_rate_hz_;
-  neteq_.reset(NetEq::Create(config, CreateBuiltinAudioDecoderFactory()));
-}
-
-void NetEqExternalDecoderTest::Init() {
-  ASSERT_EQ(NetEq::kOK, neteq_->RegisterExternalDecoder(decoder_, codec_, name_,
-                                                        kPayloadType));
-}
-
-void NetEqExternalDecoderTest::InsertPacket(
-    RTPHeader rtp_header,
-    rtc::ArrayView<const uint8_t> payload,
-    uint32_t receive_timestamp) {
-  ASSERT_EQ(NetEq::kOK,
-            neteq_->InsertPacket(rtp_header, payload, receive_timestamp));
-}
-
-void NetEqExternalDecoderTest::GetOutputAudio(AudioFrame* output) {
-  // Get audio from regular instance.
-  bool muted;
-  EXPECT_EQ(NetEq::kOK, neteq_->GetAudio(output, &muted));
-  ASSERT_FALSE(muted);
-  EXPECT_EQ(channels_, output->num_channels_);
-  EXPECT_EQ(static_cast<size_t>(kOutputLengthMs * sample_rate_hz_ / 1000),
-            output->samples_per_channel_);
-  EXPECT_EQ(sample_rate_hz_, neteq_->last_output_sample_rate_hz());
-}
-
-}  // namespace test
-}  // namespace webrtc
diff --git a/modules/audio_coding/neteq/tools/neteq_external_decoder_test.h b/modules/audio_coding/neteq/tools/neteq_external_decoder_test.h
deleted file mode 100644
index 78f0085..0000000
--- a/modules/audio_coding/neteq/tools/neteq_external_decoder_test.h
+++ /dev/null
@@ -1,64 +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.
- */
-
-#ifndef MODULES_AUDIO_CODING_NETEQ_TOOLS_NETEQ_EXTERNAL_DECODER_TEST_H_
-#define MODULES_AUDIO_CODING_NETEQ_TOOLS_NETEQ_EXTERNAL_DECODER_TEST_H_
-
-#include <memory>
-#include <string>
-
-#include "api/audio_codecs/audio_decoder.h"
-#include "common_types.h"  // NOLINT(build/include)
-#include "modules/audio_coding/neteq/include/neteq.h"
-
-namespace webrtc {
-namespace test {
-// This test class provides a way run NetEQ with an external decoder.
-class NetEqExternalDecoderTest {
- protected:
-  static const uint8_t kPayloadType = 95;
-  static const int kOutputLengthMs = 10;
-
-  // The external decoder |decoder| is suppose to be of type |codec|.
-  NetEqExternalDecoderTest(NetEqDecoder codec,
-                           int sample_rate_hz,
-                           AudioDecoder* decoder);
-
-  virtual ~NetEqExternalDecoderTest() {}
-
-  // In Init(), we register the external decoder.
-  void Init();
-
-  // Inserts a new packet with |rtp_header| and |payload| of
-  // |payload_size_bytes| bytes. The |receive_timestamp| is an indication
-  // of the time when the packet was received, and should be measured with
-  // the same tick rate as the RTP timestamp of the current payload.
-  virtual void InsertPacket(RTPHeader rtp_header,
-                            rtc::ArrayView<const uint8_t> payload,
-                            uint32_t receive_timestamp);
-
-  // Get 10 ms of audio data.
-  void GetOutputAudio(AudioFrame* output);
-
-  NetEq* neteq() { return neteq_.get(); }
-
- private:
-  NetEqDecoder codec_;
-  std::string name_ = "dummy name";
-  AudioDecoder* decoder_;
-  int sample_rate_hz_;
-  size_t channels_;
-  std::unique_ptr<NetEq> neteq_;
-};
-
-}  // namespace test
-}  // namespace webrtc
-
-#endif  // MODULES_AUDIO_CODING_NETEQ_TOOLS_NETEQ_EXTERNAL_DECODER_TEST_H_
diff --git a/modules/audio_coding/neteq/tools/neteq_input.h b/modules/audio_coding/neteq/tools/neteq_input.h
index b9cba09..732b807 100644
--- a/modules/audio_coding/neteq/tools/neteq_input.h
+++ b/modules/audio_coding/neteq/tools/neteq_input.h
@@ -16,7 +16,6 @@
 #include <string>
 
 #include "absl/types/optional.h"
-#include "common_types.h"  // NOLINT(build/include)
 #include "modules/audio_coding/neteq/tools/packet.h"
 #include "modules/audio_coding/neteq/tools/packet_source.h"
 #include "rtc_base/buffer.h"
diff --git a/modules/audio_coding/neteq/tools/neteq_performance_test.cc b/modules/audio_coding/neteq/tools/neteq_performance_test.cc
index 52524fe..61f52bb 100644
--- a/modules/audio_coding/neteq/tools/neteq_performance_test.cc
+++ b/modules/audio_coding/neteq/tools/neteq_performance_test.cc
@@ -12,14 +12,13 @@
 
 #include "api/audio/audio_frame.h"
 #include "api/audio_codecs/builtin_audio_decoder_factory.h"
-#include "common_types.h"  // NOLINT(build/include)
 #include "modules/audio_coding/codecs/pcm16b/pcm16b.h"
 #include "modules/audio_coding/neteq/include/neteq.h"
 #include "modules/audio_coding/neteq/tools/audio_loop.h"
 #include "modules/audio_coding/neteq/tools/rtp_generator.h"
 #include "rtc_base/checks.h"
 #include "system_wrappers/include/clock.h"
-#include "test/testsupport/fileutils.h"
+#include "test/testsupport/file_utils.h"
 
 using webrtc::NetEq;
 using webrtc::test::AudioLoop;
@@ -34,8 +33,6 @@
   const std::string kInputFileName =
       webrtc::test::ResourcePath("audio_coding/testfile32kHz", "pcm");
   const int kSampRateHz = 32000;
-  const webrtc::NetEqDecoder kDecoderType =
-      webrtc::NetEqDecoder::kDecoderPCM16Bswb32kHz;
   const std::string kDecoderName = "pcm16-swb32";
   const int kPayloadType = 95;
 
@@ -44,7 +41,8 @@
   config.sample_rate_hz = kSampRateHz;
   NetEq* neteq = NetEq::Create(config, CreateBuiltinAudioDecoderFactory());
   // Register decoder in |neteq|.
-  if (neteq->RegisterPayloadType(kDecoderType, kDecoderName, kPayloadType) != 0)
+  if (!neteq->RegisterPayloadType(kPayloadType,
+                                  SdpAudioFormat("l16", kSampRateHz, 1)))
     return -1;
 
   // Set up AudioLoop object.
diff --git a/modules/audio_coding/neteq/tools/neteq_quality_test.cc b/modules/audio_coding/neteq/tools/neteq_quality_test.cc
index 2ee6779..a0e7667 100644
--- a/modules/audio_coding/neteq/tools/neteq_quality_test.cc
+++ b/modules/audio_coding/neteq/tools/neteq_quality_test.cc
@@ -17,7 +17,7 @@
 #include "modules/audio_coding/neteq/tools/output_wav_file.h"
 #include "modules/audio_coding/neteq/tools/resample_input_audio_file.h"
 #include "rtc_base/checks.h"
-#include "test/testsupport/fileutils.h"
+#include "test/testsupport/file_utils.h"
 
 namespace webrtc {
 namespace test {
@@ -135,8 +135,8 @@
 NetEqQualityTest::NetEqQualityTest(int block_duration_ms,
                                    int in_sampling_khz,
                                    int out_sampling_khz,
-                                   NetEqDecoder decoder_type)
-    : decoder_type_(decoder_type),
+                                   const SdpAudioFormat& format)
+    : audio_format_(format),
       channels_(static_cast<size_t>(FLAG_channels)),
       decoded_time_ms_(0),
       decodable_time_ms_(0),
@@ -271,8 +271,7 @@
 }
 
 void NetEqQualityTest::SetUp() {
-  ASSERT_EQ(0,
-            neteq_->RegisterPayloadType(decoder_type_, "noname", kPayloadType));
+  ASSERT_TRUE(neteq_->RegisterPayloadType(kPayloadType, audio_format_));
   rtp_generator_->set_drift_factor(drift_factor_);
 
   int units = block_duration_ms_ / kPacketLossTimeUnitMs;
diff --git a/modules/audio_coding/neteq/tools/neteq_quality_test.h b/modules/audio_coding/neteq/tools/neteq_quality_test.h
index 3d7760e..82a6a64 100644
--- a/modules/audio_coding/neteq/tools/neteq_quality_test.h
+++ b/modules/audio_coding/neteq/tools/neteq_quality_test.h
@@ -14,7 +14,6 @@
 #include <fstream>
 #include <memory>
 
-#include "common_types.h"  // NOLINT(build/include)
 #include "modules/audio_coding/neteq/include/neteq.h"
 #include "modules/audio_coding/neteq/tools/audio_sink.h"
 #include "modules/audio_coding/neteq/tools/input_audio_file.h"
@@ -35,7 +34,7 @@
 
 class LossModel {
  public:
-  virtual ~LossModel(){};
+  virtual ~LossModel() {}
   virtual bool Lost(int now_ms) = 0;
 };
 
@@ -99,7 +98,7 @@
   NetEqQualityTest(int block_duration_ms,
                    int in_sampling_khz,
                    int out_sampling_khz,
-                   NetEqDecoder decoder_type);
+                   const SdpAudioFormat& format);
   ~NetEqQualityTest() override;
 
   void SetUp() override;
@@ -133,7 +132,7 @@
   // Write to log file. Usage Log() << ...
   std::ofstream& Log();
 
-  NetEqDecoder decoder_type_;
+  SdpAudioFormat audio_format_;
   const size_t channels_;
 
  private:
diff --git a/modules/audio_coding/neteq/tools/neteq_rtpplay.cc b/modules/audio_coding/neteq/tools/neteq_rtpplay.cc
index c2726eb..36c03b8 100644
--- a/modules/audio_coding/neteq/tools/neteq_rtpplay.cc
+++ b/modules/audio_coding/neteq/tools/neteq_rtpplay.cc
@@ -17,6 +17,10 @@
 #include "system_wrappers/include/field_trial.h"
 #include "test/field_trial.h"
 
+namespace {
+
+using TestConfig = webrtc::test::NetEqTestFactory::Config;
+
 WEBRTC_DEFINE_bool(codec_map,
                    false,
                    "Prints the mapping between RTP payload type and "
@@ -28,6 +32,185 @@
     "E.g. running with --force_fieldtrials=WebRTC-FooFeature/Enable/"
     " will assign the group Enable to field trial WebRTC-FooFeature.");
 WEBRTC_DEFINE_bool(help, false, "Prints this message");
+// Define command line flags.
+WEBRTC_DEFINE_int(pcmu,
+                  TestConfig::default_pcmu(),
+                  "RTP payload type for PCM-u");
+WEBRTC_DEFINE_int(pcma,
+                  TestConfig::default_pcma(),
+                  "RTP payload type for PCM-a");
+WEBRTC_DEFINE_int(ilbc,
+                  TestConfig::default_ilbc(),
+                  "RTP payload type for iLBC");
+WEBRTC_DEFINE_int(isac,
+                  TestConfig::default_isac(),
+                  "RTP payload type for iSAC");
+WEBRTC_DEFINE_int(isac_swb,
+                  TestConfig::default_isac_swb(),
+                  "RTP payload type for iSAC-swb (32 kHz)");
+WEBRTC_DEFINE_int(opus,
+                  TestConfig::default_opus(),
+                  "RTP payload type for Opus");
+WEBRTC_DEFINE_int(pcm16b,
+                  TestConfig::default_pcm16b(),
+                  "RTP payload type for PCM16b-nb (8 kHz)");
+WEBRTC_DEFINE_int(pcm16b_wb,
+                  TestConfig::default_pcm16b_wb(),
+                  "RTP payload type for PCM16b-wb (16 kHz)");
+WEBRTC_DEFINE_int(pcm16b_swb32,
+                  TestConfig::default_pcm16b_swb32(),
+                  "RTP payload type for PCM16b-swb32 (32 kHz)");
+WEBRTC_DEFINE_int(pcm16b_swb48,
+                  TestConfig::default_pcm16b_swb48(),
+                  "RTP payload type for PCM16b-swb48 (48 kHz)");
+WEBRTC_DEFINE_int(g722,
+                  TestConfig::default_g722(),
+                  "RTP payload type for G.722");
+WEBRTC_DEFINE_int(avt,
+                  TestConfig::default_avt(),
+                  "RTP payload type for AVT/DTMF (8 kHz)");
+WEBRTC_DEFINE_int(avt_16,
+                  TestConfig::default_avt_16(),
+                  "RTP payload type for AVT/DTMF (16 kHz)");
+WEBRTC_DEFINE_int(avt_32,
+                  TestConfig::default_avt_32(),
+                  "RTP payload type for AVT/DTMF (32 kHz)");
+WEBRTC_DEFINE_int(avt_48,
+                  TestConfig::default_avt_48(),
+                  "RTP payload type for AVT/DTMF (48 kHz)");
+WEBRTC_DEFINE_int(red,
+                  TestConfig::default_red(),
+                  "RTP payload type for redundant audio (RED)");
+WEBRTC_DEFINE_int(cn_nb,
+                  TestConfig::default_cn_nb(),
+                  "RTP payload type for comfort noise (8 kHz)");
+WEBRTC_DEFINE_int(cn_wb,
+                  TestConfig::default_cn_wb(),
+                  "RTP payload type for comfort noise (16 kHz)");
+WEBRTC_DEFINE_int(cn_swb32,
+                  TestConfig::default_cn_swb32(),
+                  "RTP payload type for comfort noise (32 kHz)");
+WEBRTC_DEFINE_int(cn_swb48,
+                  TestConfig::default_cn_swb48(),
+                  "RTP payload type for comfort noise (48 kHz)");
+WEBRTC_DEFINE_string(replacement_audio_file,
+                     "",
+                     "A PCM file that will be used to populate dummy"
+                     " RTP packets");
+WEBRTC_DEFINE_string(
+    ssrc,
+    "",
+    "Only use packets with this SSRC (decimal or hex, the latter "
+    "starting with 0x)");
+WEBRTC_DEFINE_int(audio_level,
+                  TestConfig::default_audio_level(),
+                  "Extension ID for audio level (RFC 6464)");
+WEBRTC_DEFINE_int(abs_send_time,
+                  TestConfig::default_abs_send_time(),
+                  "Extension ID for absolute sender time");
+WEBRTC_DEFINE_int(transport_seq_no,
+                  TestConfig::default_transport_seq_no(),
+                  "Extension ID for transport sequence number");
+WEBRTC_DEFINE_int(video_content_type,
+                  TestConfig::default_video_content_type(),
+                  "Extension ID for video content type");
+WEBRTC_DEFINE_int(video_timing,
+                  TestConfig::default_video_timing(),
+                  "Extension ID for video timing");
+WEBRTC_DEFINE_bool(matlabplot,
+                   false,
+                   "Generates a matlab script for plotting the delay profile");
+WEBRTC_DEFINE_bool(pythonplot,
+                   false,
+                   "Generates a python script for plotting the delay profile");
+WEBRTC_DEFINE_bool(textlog,
+                   false,
+                   "Generates a text log describing the simulation on a "
+                   "step-by-step basis.");
+WEBRTC_DEFINE_bool(concealment_events, false, "Prints concealment events");
+WEBRTC_DEFINE_int(max_nr_packets_in_buffer,
+                  TestConfig::default_max_nr_packets_in_buffer(),
+                  "Maximum allowed number of packets in the buffer");
+WEBRTC_DEFINE_bool(enable_fast_accelerate,
+                   false,
+                   "Enables jitter buffer fast accelerate");
+
+// Parses the input string for a valid SSRC (at the start of the string). If a
+// valid SSRC is found, it is written to the output variable |ssrc|, and true is
+// returned. Otherwise, false is returned.
+bool ParseSsrc(const std::string& str, uint32_t* ssrc) {
+  if (str.empty())
+    return true;
+  int base = 10;
+  // Look for "0x" or "0X" at the start and change base to 16 if found.
+  if ((str.compare(0, 2, "0x") == 0) || (str.compare(0, 2, "0X") == 0))
+    base = 16;
+  errno = 0;
+  char* end_ptr;
+  unsigned long value = strtoul(str.c_str(), &end_ptr, base);  // NOLINT
+  if (value == ULONG_MAX && errno == ERANGE)
+    return false;  // Value out of range for unsigned long.
+  if (sizeof(unsigned long) > sizeof(uint32_t) && value > 0xFFFFFFFF)  // NOLINT
+    return false;  // Value out of range for uint32_t.
+  if (end_ptr - str.c_str() < static_cast<ptrdiff_t>(str.length()))
+    return false;  // Part of the string was not parsed.
+  *ssrc = static_cast<uint32_t>(value);
+  return true;
+}
+
+static bool ValidateExtensionId(int value) {
+  if (value > 0 && value <= 255)  // Value is ok.
+    return true;
+  printf("Extension ID must be between 1 and 255, not %d\n",
+         static_cast<int>(value));
+  return false;
+}
+
+// Flag validators.
+bool ValidatePayloadType(int value) {
+  if (value >= 0 && value <= 127)  // Value is ok.
+    return true;
+  printf("Payload type must be between 0 and 127, not %d\n",
+         static_cast<int>(value));
+  return false;
+}
+
+bool ValidateSsrcValue(const std::string& str) {
+  uint32_t dummy_ssrc;
+  if (ParseSsrc(str, &dummy_ssrc))  // Value is ok.
+    return true;
+  printf("Invalid SSRC: %s\n", str.c_str());
+  return false;
+}
+
+void PrintCodecMappingEntry(const char* codec, int flag) {
+  std::cout << codec << ": " << flag << std::endl;
+}
+
+void PrintCodecMapping() {
+  PrintCodecMappingEntry("PCM-u", FLAG_pcmu);
+  PrintCodecMappingEntry("PCM-a", FLAG_pcma);
+  PrintCodecMappingEntry("iLBC", FLAG_ilbc);
+  PrintCodecMappingEntry("iSAC", FLAG_isac);
+  PrintCodecMappingEntry("iSAC-swb (32 kHz)", FLAG_isac_swb);
+  PrintCodecMappingEntry("Opus", FLAG_opus);
+  PrintCodecMappingEntry("PCM16b-nb (8 kHz)", FLAG_pcm16b);
+  PrintCodecMappingEntry("PCM16b-wb (16 kHz)", FLAG_pcm16b_wb);
+  PrintCodecMappingEntry("PCM16b-swb32 (32 kHz)", FLAG_pcm16b_swb32);
+  PrintCodecMappingEntry("PCM16b-swb48 (48 kHz)", FLAG_pcm16b_swb48);
+  PrintCodecMappingEntry("G.722", FLAG_g722);
+  PrintCodecMappingEntry("AVT/DTMF (8 kHz)", FLAG_avt);
+  PrintCodecMappingEntry("AVT/DTMF (16 kHz)", FLAG_avt_16);
+  PrintCodecMappingEntry("AVT/DTMF (32 kHz)", FLAG_avt_32);
+  PrintCodecMappingEntry("AVT/DTMF (48 kHz)", FLAG_avt_48);
+  PrintCodecMappingEntry("redundant audio (RED)", FLAG_red);
+  PrintCodecMappingEntry("comfort noise (8 kHz)", FLAG_cn_nb);
+  PrintCodecMappingEntry("comfort noise (16 kHz)", FLAG_cn_wb);
+  PrintCodecMappingEntry("comfort noise (32 kHz)", FLAG_cn_swb32);
+  PrintCodecMappingEntry("comfort noise (48 kHz)", FLAG_cn_swb48);
+}
+
+}  // namespace
 
 int main(int argc, char* argv[]) {
   webrtc::test::NetEqTestFactory factory;
@@ -48,21 +231,85 @@
     exit(0);
   }
   if (FLAG_codec_map) {
-    factory.PrintCodecMap();
+    PrintCodecMapping();
+    exit(0);
   }
   if (argc != 3) {
-    if (FLAG_codec_map) {
-      // We have already printed the codec map. Just end the program.
-      exit(0);
-    }
     // Print usage information.
     std::cout << usage;
     exit(0);
   }
+  RTC_CHECK(ValidatePayloadType(FLAG_pcmu));
+  RTC_CHECK(ValidatePayloadType(FLAG_pcma));
+  RTC_CHECK(ValidatePayloadType(FLAG_ilbc));
+  RTC_CHECK(ValidatePayloadType(FLAG_isac));
+  RTC_CHECK(ValidatePayloadType(FLAG_isac_swb));
+  RTC_CHECK(ValidatePayloadType(FLAG_opus));
+  RTC_CHECK(ValidatePayloadType(FLAG_pcm16b));
+  RTC_CHECK(ValidatePayloadType(FLAG_pcm16b_wb));
+  RTC_CHECK(ValidatePayloadType(FLAG_pcm16b_swb32));
+  RTC_CHECK(ValidatePayloadType(FLAG_pcm16b_swb48));
+  RTC_CHECK(ValidatePayloadType(FLAG_g722));
+  RTC_CHECK(ValidatePayloadType(FLAG_avt));
+  RTC_CHECK(ValidatePayloadType(FLAG_avt_16));
+  RTC_CHECK(ValidatePayloadType(FLAG_avt_32));
+  RTC_CHECK(ValidatePayloadType(FLAG_avt_48));
+  RTC_CHECK(ValidatePayloadType(FLAG_red));
+  RTC_CHECK(ValidatePayloadType(FLAG_cn_nb));
+  RTC_CHECK(ValidatePayloadType(FLAG_cn_wb));
+  RTC_CHECK(ValidatePayloadType(FLAG_cn_swb32));
+  RTC_CHECK(ValidatePayloadType(FLAG_cn_swb48));
+  RTC_CHECK(ValidateSsrcValue(FLAG_ssrc));
+  RTC_CHECK(ValidateExtensionId(FLAG_audio_level));
+  RTC_CHECK(ValidateExtensionId(FLAG_abs_send_time));
+  RTC_CHECK(ValidateExtensionId(FLAG_transport_seq_no));
+  RTC_CHECK(ValidateExtensionId(FLAG_video_content_type));
+  RTC_CHECK(ValidateExtensionId(FLAG_video_timing));
+
   webrtc::test::ValidateFieldTrialsStringOrDie(FLAG_force_fieldtrials);
   webrtc::field_trial::InitFieldTrialsFromString(FLAG_force_fieldtrials);
+  webrtc::test::NetEqTestFactory::Config config;
+  config.pcmu = FLAG_pcmu;
+  config.pcma = FLAG_pcma;
+  config.ilbc = FLAG_ilbc;
+  config.isac = FLAG_isac;
+  config.isac_swb = FLAG_isac_swb;
+  config.opus = FLAG_opus;
+  config.pcm16b = FLAG_pcm16b;
+  config.pcm16b_wb = FLAG_pcm16b_wb;
+  config.pcm16b_swb32 = FLAG_pcm16b_swb32;
+  config.pcm16b_swb48 = FLAG_pcm16b_swb48;
+  config.g722 = FLAG_g722;
+  config.avt = FLAG_avt;
+  config.avt_16 = FLAG_avt_16;
+  config.avt_32 = FLAG_avt_32;
+  config.avt_48 = FLAG_avt_48;
+  config.red = FLAG_red;
+  config.cn_nb = FLAG_cn_nb;
+  config.cn_wb = FLAG_cn_wb;
+  config.cn_swb32 = FLAG_cn_swb32;
+  config.cn_swb48 = FLAG_cn_swb48;
+  config.replacement_audio_file = FLAG_replacement_audio_file;
+  config.audio_level = FLAG_audio_level;
+  config.abs_send_time = FLAG_abs_send_time;
+  config.transport_seq_no = FLAG_transport_seq_no;
+  config.video_content_type = FLAG_video_content_type;
+  config.video_timing = FLAG_video_timing;
+  config.matlabplot = FLAG_matlabplot;
+  config.pythonplot = FLAG_pythonplot;
+  config.textlog = FLAG_textlog;
+  config.concealment_events = FLAG_concealment_events;
+  config.max_nr_packets_in_buffer = FLAG_max_nr_packets_in_buffer;
+  config.enable_fast_accelerate = FLAG_enable_fast_accelerate;
+  // Check if an SSRC value was provided.
+  if (strlen(FLAG_ssrc) > 0) {
+    uint32_t ssrc;
+    RTC_CHECK(ParseSsrc(FLAG_ssrc, &ssrc)) << "Flag verification has failed.";
+    config.ssrc_filter = absl::make_optional(ssrc);
+  }
+
   std::unique_ptr<webrtc::test::NetEqTest> test =
-      factory.InitializeTest(argv[1], argv[2]);
+      factory.InitializeTest(argv[1], argv[2], config);
   test->Run();
   return 0;
 }
diff --git a/modules/audio_coding/neteq/tools/neteq_stats_getter.cc b/modules/audio_coding/neteq/tools/neteq_stats_getter.cc
index 1a52176..291fc24 100644
--- a/modules/audio_coding/neteq/tools/neteq_stats_getter.cc
+++ b/modules/audio_coding/neteq/tools/neteq_stats_getter.cc
@@ -16,7 +16,7 @@
 
 #include "rtc_base/checks.h"
 #include "rtc_base/strings/string_builder.h"
-#include "rtc_base/timeutils.h"
+#include "rtc_base/time_utils.h"
 
 namespace webrtc {
 namespace test {
diff --git a/modules/audio_coding/neteq/tools/neteq_test.cc b/modules/audio_coding/neteq/tools/neteq_test.cc
index 421f380..97e71bf 100644
--- a/modules/audio_coding/neteq/tools/neteq_test.cc
+++ b/modules/audio_coding/neteq/tools/neteq_test.cc
@@ -10,9 +10,10 @@
 
 #include "modules/audio_coding/neteq/tools/neteq_test.h"
 
+#include <iomanip>
 #include <iostream>
 
-#include "api/audio_codecs/builtin_audio_decoder_factory.h"
+#include "modules/rtp_rtcp/source/byte_io.h"
 
 namespace webrtc {
 namespace test {
@@ -50,20 +51,21 @@
 }
 
 NetEqTest::NetEqTest(const NetEq::Config& config,
+                     rtc::scoped_refptr<AudioDecoderFactory> decoder_factory,
                      const DecoderMap& codecs,
-                     const ExtDecoderMap& ext_codecs,
+                     std::unique_ptr<std::ofstream> text_log,
                      std::unique_ptr<NetEqInput> input,
                      std::unique_ptr<AudioSink> output,
                      Callbacks callbacks)
-    : neteq_(NetEq::Create(config, CreateBuiltinAudioDecoderFactory())),
+    : neteq_(NetEq::Create(config, decoder_factory)),
       input_(std::move(input)),
       output_(std::move(output)),
       callbacks_(callbacks),
-      sample_rate_hz_(config.sample_rate_hz) {
+      sample_rate_hz_(config.sample_rate_hz),
+      text_log_(std::move(text_log)) {
   RTC_CHECK(!config.enable_muted_state)
       << "The code does not handle enable_muted_state";
   RegisterDecoders(codecs);
-  RegisterExternalDecoders(ext_codecs);
 }
 
 NetEqTest::~NetEqTest() = default;
@@ -117,7 +119,36 @@
         current_state_.packet_iat_ms.push_back(time_now_ms -
                                                *last_packet_time_ms_);
       }
+      if (text_log_) {
+        const auto ops_state = neteq_->GetOperationsAndState();
+        const auto delta_wallclock =
+            last_packet_time_ms_ ? (time_now_ms - *last_packet_time_ms_) : -1;
+        const auto delta_timestamp =
+            last_packet_timestamp_
+                ? (static_cast<int64_t>(packet_data->header.timestamp) -
+                   *last_packet_timestamp_) *
+                      1000 / sample_rate_hz_
+                : -1;
+        const auto packet_size_bytes =
+            packet_data->payload.size() == 12
+                ? ByteReader<uint32_t>::ReadLittleEndian(
+                      &packet_data->payload[8])
+                : -1;
+        *text_log_ << "Packet   - wallclock: " << std::setw(5) << time_now_ms
+                   << ", delta wc: " << std::setw(4) << delta_wallclock
+                   << ", seq_no: " << packet_data->header.sequenceNumber
+                   << ", timestamp: " << std::setw(10)
+                   << packet_data->header.timestamp
+                   << ", delta ts: " << std::setw(4) << delta_timestamp
+                   << ", size: " << std::setw(5) << packet_size_bytes
+                   << ", frame size: " << std::setw(3)
+                   << ops_state.current_frame_size_ms
+                   << ", buffer size: " << std::setw(4)
+                   << ops_state.current_buffer_size_ms << std::endl;
+      }
       last_packet_time_ms_ = absl::make_optional<int>(time_now_ms);
+      last_packet_timestamp_ =
+          absl::make_optional<uint32_t>(packet_data->header.timestamp);
     }
 
     // Check if it is time to get output audio.
@@ -186,6 +217,39 @@
         // Consider the whole frame to be the result of normal playout.
         result.action_times_ms[Action::kNormal] = 10;
       }
+      auto lifetime_stats = LifetimeStats();
+      if (text_log_) {
+        const bool plc =
+            (out_frame.speech_type_ == AudioFrame::SpeechType::kPLC) ||
+            (out_frame.speech_type_ == AudioFrame::SpeechType::kPLCCNG);
+        const bool cng = out_frame.speech_type_ == AudioFrame::SpeechType::kCNG;
+        const bool voice_concealed =
+            lifetime_stats.voice_concealed_samples >
+            prev_lifetime_stats_.voice_concealed_samples;
+        *text_log_ << "GetAudio - wallclock: " << std::setw(5) << time_now_ms
+                   << ", delta wc: " << std::setw(4)
+                   << (input_->NextEventTime().value_or(time_now_ms) -
+                       start_time_ms)
+                   << ", CNG: " << cng << ", PLC: " << plc
+                   << ", voice concealed: " << voice_concealed
+                   << ", buffer size: " << std::setw(4)
+                   << current_state_.current_delay_ms << std::endl;
+        if (operations_state.discarded_primary_packets >
+            prev_ops_state_.discarded_primary_packets) {
+          *text_log_ << "Discarded "
+                     << (operations_state.discarded_primary_packets -
+                         prev_ops_state_.discarded_primary_packets)
+                     << " primary packets." << std::endl;
+        }
+        if (operations_state.packet_buffer_flushes >
+            prev_ops_state_.packet_buffer_flushes) {
+          *text_log_ << "Flushed packet buffer "
+                     << (operations_state.packet_buffer_flushes -
+                         prev_ops_state_.packet_buffer_flushes)
+                     << " times." << std::endl;
+        }
+      }
+      prev_lifetime_stats_ = lifetime_stats;
       result.is_simulation_finished = input_->ended();
       prev_ops_state_ = operations_state;
       return result;
@@ -217,53 +281,40 @@
 
 NetEqTest::DecoderMap NetEqTest::StandardDecoderMap() {
   DecoderMap codecs = {
-    {0, std::make_pair(NetEqDecoder::kDecoderPCMu, "pcmu")},
-    {8, std::make_pair(NetEqDecoder::kDecoderPCMa, "pcma")},
+    {0, SdpAudioFormat("pcmu", 8000, 1)},
+    {8, SdpAudioFormat("pcma", 8000, 1)},
 #ifdef WEBRTC_CODEC_ILBC
-    {102, std::make_pair(NetEqDecoder::kDecoderILBC, "ilbc")},
+    {102, SdpAudioFormat("ilbc", 8000, 1)},
 #endif
-    {103, std::make_pair(NetEqDecoder::kDecoderISAC, "isac")},
+    {103, SdpAudioFormat("isac", 16000, 1)},
 #if !defined(WEBRTC_ANDROID)
-    {104, std::make_pair(NetEqDecoder::kDecoderISACswb, "isac-swb")},
+    {104, SdpAudioFormat("isac", 32000, 1)},
 #endif
 #ifdef WEBRTC_CODEC_OPUS
-    {111, std::make_pair(NetEqDecoder::kDecoderOpus, "opus")},
+    {111, SdpAudioFormat("opus", 48000, 2)},
 #endif
-    {93, std::make_pair(NetEqDecoder::kDecoderPCM16B, "pcm16-nb")},
-    {94, std::make_pair(NetEqDecoder::kDecoderPCM16Bwb, "pcm16-wb")},
-    {95, std::make_pair(NetEqDecoder::kDecoderPCM16Bswb32kHz, "pcm16-swb32")},
-    {96, std::make_pair(NetEqDecoder::kDecoderPCM16Bswb48kHz, "pcm16-swb48")},
-    {9, std::make_pair(NetEqDecoder::kDecoderG722, "g722")},
-    {106, std::make_pair(NetEqDecoder::kDecoderAVT, "avt")},
-    {114, std::make_pair(NetEqDecoder::kDecoderAVT16kHz, "avt-16")},
-    {115, std::make_pair(NetEqDecoder::kDecoderAVT32kHz, "avt-32")},
-    {116, std::make_pair(NetEqDecoder::kDecoderAVT48kHz, "avt-48")},
-    {117, std::make_pair(NetEqDecoder::kDecoderRED, "red")},
-    {13, std::make_pair(NetEqDecoder::kDecoderCNGnb, "cng-nb")},
-    {98, std::make_pair(NetEqDecoder::kDecoderCNGwb, "cng-wb")},
-    {99, std::make_pair(NetEqDecoder::kDecoderCNGswb32kHz, "cng-swb32")},
-    {100, std::make_pair(NetEqDecoder::kDecoderCNGswb48kHz, "cng-swb48")}
+    {93, SdpAudioFormat("l16", 8000, 1)},
+    {94, SdpAudioFormat("l16", 16000, 1)},
+    {95, SdpAudioFormat("l16", 32000, 1)},
+    {96, SdpAudioFormat("l16", 48000, 1)},
+    {9, SdpAudioFormat("g722", 8000, 1)},
+    {106, SdpAudioFormat("telephone-event", 8000, 1)},
+    {114, SdpAudioFormat("telephone-event", 16000, 1)},
+    {115, SdpAudioFormat("telephone-event", 32000, 1)},
+    {116, SdpAudioFormat("telephone-event", 48000, 1)},
+    {117, SdpAudioFormat("red", 8000, 1)},
+    {13, SdpAudioFormat("cn", 8000, 1)},
+    {98, SdpAudioFormat("cn", 16000, 1)},
+    {99, SdpAudioFormat("cn", 32000, 1)},
+    {100, SdpAudioFormat("cn", 48000, 1)}
   };
   return codecs;
 }
 
 void NetEqTest::RegisterDecoders(const DecoderMap& codecs) {
   for (const auto& c : codecs) {
-    RTC_CHECK_EQ(
-        neteq_->RegisterPayloadType(c.second.first, c.second.second, c.first),
-        NetEq::kOK)
-        << "Cannot register " << c.second.second << " to payload type "
-        << c.first;
-  }
-}
-
-void NetEqTest::RegisterExternalDecoders(const ExtDecoderMap& codecs) {
-  for (const auto& c : codecs) {
-    RTC_CHECK_EQ(
-        neteq_->RegisterExternalDecoder(c.second.decoder, c.second.codec,
-                                        c.second.codec_name, c.first),
-        NetEq::kOK)
-        << "Cannot register " << c.second.codec_name << " to payload type "
+    RTC_CHECK(neteq_->RegisterPayloadType(c.first, c.second))
+        << "Cannot register " << c.second.name << " to payload type "
         << c.first;
   }
 }
diff --git a/modules/audio_coding/neteq/tools/neteq_test.h b/modules/audio_coding/neteq/tools/neteq_test.h
index 23d7c22..5261dd7 100644
--- a/modules/audio_coding/neteq/tools/neteq_test.h
+++ b/modules/audio_coding/neteq/tools/neteq_test.h
@@ -11,12 +11,14 @@
 #ifndef MODULES_AUDIO_CODING_NETEQ_TOOLS_NETEQ_TEST_H_
 #define MODULES_AUDIO_CODING_NETEQ_TOOLS_NETEQ_TEST_H_
 
+#include <fstream>
 #include <map>
 #include <memory>
 #include <string>
 #include <utility>
 
 #include "absl/types/optional.h"
+#include "api/audio_codecs/audio_decoder_factory.h"
 #include "api/test/neteq_simulator.h"
 #include "modules/audio_coding/neteq/include/neteq.h"
 #include "modules/audio_coding/neteq/tools/audio_sink.h"
@@ -65,15 +67,7 @@
 // directed to an AudioSink object.
 class NetEqTest : public NetEqSimulator {
  public:
-  using DecoderMap = std::map<int, std::pair<NetEqDecoder, std::string> >;
-
-  struct ExternalDecoderInfo {
-    AudioDecoder* decoder;
-    NetEqDecoder codec;
-    std::string codec_name;
-  };
-
-  using ExtDecoderMap = std::map<int, ExternalDecoderInfo>;
+  using DecoderMap = std::map<int, SdpAudioFormat>;
 
   struct Callbacks {
     NetEqTestErrorCallback* error_callback = nullptr;
@@ -85,8 +79,9 @@
   // Sets up the test with given configuration, codec mappings, input, ouput,
   // and callback objects for error reporting.
   NetEqTest(const NetEq::Config& config,
+            rtc::scoped_refptr<AudioDecoderFactory> decoder_factory,
             const DecoderMap& codecs,
-            const ExtDecoderMap& ext_codecs,
+            std::unique_ptr<std::ofstream> text_log,
             std::unique_ptr<NetEqInput> input,
             std::unique_ptr<AudioSink> output,
             Callbacks callbacks);
@@ -111,7 +106,6 @@
 
  private:
   void RegisterDecoders(const DecoderMap& codecs);
-  void RegisterExternalDecoders(const ExtDecoderMap& codecs);
   absl::optional<Action> next_action_;
   absl::optional<int> last_packet_time_ms_;
   std::unique_ptr<NetEq> neteq_;
@@ -121,6 +115,9 @@
   int sample_rate_hz_;
   NetEqState current_state_;
   NetEqOperationsAndState prev_ops_state_;
+  NetEqLifetimeStatistics prev_lifetime_stats_;
+  absl::optional<uint32_t> last_packet_timestamp_;
+  std::unique_ptr<std::ofstream> text_log_;
 };
 
 }  // namespace test
diff --git a/modules/audio_coding/neteq/tools/neteq_test_factory.cc b/modules/audio_coding/neteq/tools/neteq_test_factory.cc
index aa956ce..1d38bc4 100644
--- a/modules/audio_coding/neteq/tools/neteq_test_factory.cc
+++ b/modules/audio_coding/neteq/tools/neteq_test_factory.cc
@@ -14,6 +14,7 @@
 #include <limits.h>  // For ULONG_MAX returned by strtoul.
 #include <stdio.h>
 #include <stdlib.h>  // For strtoul.
+#include <fstream>
 #include <iostream>
 #include <memory>
 #include <set>
@@ -21,6 +22,7 @@
 #include <utility>
 
 #include "absl/memory/memory.h"
+#include "api/audio_codecs/builtin_audio_decoder_factory.h"
 #include "modules/audio_coding/neteq/include/neteq.h"
 #include "modules/audio_coding/neteq/tools/fake_decode_from_file.h"
 #include "modules/audio_coding/neteq/tools/input_audio_file.h"
@@ -36,210 +38,32 @@
 #include "modules/audio_coding/neteq/tools/rtp_file_source.h"
 #include "rtc_base/checks.h"
 #include "rtc_base/flags.h"
-#include "test/testsupport/fileutils.h"
+#include "rtc_base/ref_counted_object.h"
+#include "test/function_audio_decoder_factory.h"
+#include "test/testsupport/file_utils.h"
 
 namespace webrtc {
 namespace test {
 namespace {
 
-// Parses the input string for a valid SSRC (at the start of the string). If a
-// valid SSRC is found, it is written to the output variable |ssrc|, and true is
-// returned. Otherwise, false is returned.
-bool ParseSsrc(const std::string& str, uint32_t* ssrc) {
-  if (str.empty())
-    return true;
-  int base = 10;
-  // Look for "0x" or "0X" at the start and change base to 16 if found.
-  if ((str.compare(0, 2, "0x") == 0) || (str.compare(0, 2, "0X") == 0))
-    base = 16;
-  errno = 0;
-  char* end_ptr;
-  unsigned long value = strtoul(str.c_str(), &end_ptr, base);  // NOLINT
-  if (value == ULONG_MAX && errno == ERANGE)
-    return false;  // Value out of range for unsigned long.
-  if (sizeof(unsigned long) > sizeof(uint32_t) && value > 0xFFFFFFFF)  // NOLINT
-    return false;  // Value out of range for uint32_t.
-  if (end_ptr - str.c_str() < static_cast<ptrdiff_t>(str.length()))
-    return false;  // Part of the string was not parsed.
-  *ssrc = static_cast<uint32_t>(value);
-  return true;
-}
-
-// Flag validators.
-bool ValidatePayloadType(int value) {
-  if (value >= 0 && value <= 127)  // Value is ok.
-    return true;
-  printf("Payload type must be between 0 and 127, not %d\n",
-         static_cast<int>(value));
-  return false;
-}
-
-bool ValidateSsrcValue(const std::string& str) {
-  uint32_t dummy_ssrc;
-  if (ParseSsrc(str, &dummy_ssrc))  // Value is ok.
-    return true;
-  printf("Invalid SSRC: %s\n", str.c_str());
-  return false;
-}
-
-static bool ValidateExtensionId(int value) {
-  if (value > 0 && value <= 255)  // Value is ok.
-    return true;
-  printf("Extension ID must be between 1 and 255, not %d\n",
-         static_cast<int>(value));
-  return false;
-}
-
-// Define command line flags.
-WEBRTC_DEFINE_int(pcmu, 0, "RTP payload type for PCM-u");
-WEBRTC_DEFINE_int(pcma, 8, "RTP payload type for PCM-a");
-WEBRTC_DEFINE_int(ilbc, 102, "RTP payload type for iLBC");
-WEBRTC_DEFINE_int(isac, 103, "RTP payload type for iSAC");
-WEBRTC_DEFINE_int(isac_swb, 104, "RTP payload type for iSAC-swb (32 kHz)");
-WEBRTC_DEFINE_int(opus, 111, "RTP payload type for Opus");
-WEBRTC_DEFINE_int(pcm16b, 93, "RTP payload type for PCM16b-nb (8 kHz)");
-WEBRTC_DEFINE_int(pcm16b_wb, 94, "RTP payload type for PCM16b-wb (16 kHz)");
-WEBRTC_DEFINE_int(pcm16b_swb32,
-                  95,
-                  "RTP payload type for PCM16b-swb32 (32 kHz)");
-WEBRTC_DEFINE_int(pcm16b_swb48,
-                  96,
-                  "RTP payload type for PCM16b-swb48 (48 kHz)");
-WEBRTC_DEFINE_int(g722, 9, "RTP payload type for G.722");
-WEBRTC_DEFINE_int(avt, 106, "RTP payload type for AVT/DTMF (8 kHz)");
-WEBRTC_DEFINE_int(avt_16, 114, "RTP payload type for AVT/DTMF (16 kHz)");
-WEBRTC_DEFINE_int(avt_32, 115, "RTP payload type for AVT/DTMF (32 kHz)");
-WEBRTC_DEFINE_int(avt_48, 116, "RTP payload type for AVT/DTMF (48 kHz)");
-WEBRTC_DEFINE_int(red, 117, "RTP payload type for redundant audio (RED)");
-WEBRTC_DEFINE_int(cn_nb, 13, "RTP payload type for comfort noise (8 kHz)");
-WEBRTC_DEFINE_int(cn_wb, 98, "RTP payload type for comfort noise (16 kHz)");
-WEBRTC_DEFINE_int(cn_swb32, 99, "RTP payload type for comfort noise (32 kHz)");
-WEBRTC_DEFINE_int(cn_swb48, 100, "RTP payload type for comfort noise (48 kHz)");
-WEBRTC_DEFINE_string(replacement_audio_file,
-                     "",
-                     "A PCM file that will be used to populate "
-                     "dummy"
-                     " RTP packets");
-WEBRTC_DEFINE_string(
-    ssrc,
-    "",
-    "Only use packets with this SSRC (decimal or hex, the latter "
-    "starting with 0x)");
-WEBRTC_DEFINE_int(audio_level, 1, "Extension ID for audio level (RFC 6464)");
-WEBRTC_DEFINE_int(abs_send_time, 3, "Extension ID for absolute sender time");
-WEBRTC_DEFINE_int(transport_seq_no,
-                  5,
-                  "Extension ID for transport sequence number");
-WEBRTC_DEFINE_int(video_content_type, 7, "Extension ID for video content type");
-WEBRTC_DEFINE_int(video_timing, 8, "Extension ID for video timing");
-WEBRTC_DEFINE_bool(matlabplot,
-                   false,
-                   "Generates a matlab script for plotting the delay profile");
-WEBRTC_DEFINE_bool(pythonplot,
-                   false,
-                   "Generates a python script for plotting the delay profile");
-WEBRTC_DEFINE_bool(concealment_events, false, "Prints concealment events");
-WEBRTC_DEFINE_int(max_nr_packets_in_buffer,
-                  50,
-                  "Maximum allowed number of packets in the buffer");
-WEBRTC_DEFINE_bool(enable_fast_accelerate,
-                   false,
-                   "Enables jitter buffer fast accelerate");
-
-// Maps a codec type to a printable name string.
-std::string CodecName(NetEqDecoder codec) {
-  switch (codec) {
-    case NetEqDecoder::kDecoderPCMu:
-      return "PCM-u";
-    case NetEqDecoder::kDecoderPCMa:
-      return "PCM-a";
-    case NetEqDecoder::kDecoderILBC:
-      return "iLBC";
-    case NetEqDecoder::kDecoderISAC:
-      return "iSAC";
-    case NetEqDecoder::kDecoderISACswb:
-      return "iSAC-swb (32 kHz)";
-    case NetEqDecoder::kDecoderOpus:
-      return "Opus";
-    case NetEqDecoder::kDecoderPCM16B:
-      return "PCM16b-nb (8 kHz)";
-    case NetEqDecoder::kDecoderPCM16Bwb:
-      return "PCM16b-wb (16 kHz)";
-    case NetEqDecoder::kDecoderPCM16Bswb32kHz:
-      return "PCM16b-swb32 (32 kHz)";
-    case NetEqDecoder::kDecoderPCM16Bswb48kHz:
-      return "PCM16b-swb48 (48 kHz)";
-    case NetEqDecoder::kDecoderG722:
-      return "G.722";
-    case NetEqDecoder::kDecoderRED:
-      return "redundant audio (RED)";
-    case NetEqDecoder::kDecoderAVT:
-      return "AVT/DTMF (8 kHz)";
-    case NetEqDecoder::kDecoderAVT16kHz:
-      return "AVT/DTMF (16 kHz)";
-    case NetEqDecoder::kDecoderAVT32kHz:
-      return "AVT/DTMF (32 kHz)";
-    case NetEqDecoder::kDecoderAVT48kHz:
-      return "AVT/DTMF (48 kHz)";
-    case NetEqDecoder::kDecoderCNGnb:
-      return "comfort noise (8 kHz)";
-    case NetEqDecoder::kDecoderCNGwb:
-      return "comfort noise (16 kHz)";
-    case NetEqDecoder::kDecoderCNGswb32kHz:
-      return "comfort noise (32 kHz)";
-    case NetEqDecoder::kDecoderCNGswb48kHz:
-      return "comfort noise (48 kHz)";
-    default:
-      FATAL();
-      return "undefined";
-  }
-}
-
-void PrintCodecMappingEntry(NetEqDecoder codec, int flag) {
-  std::cout << CodecName(codec) << ": " << flag << std::endl;
-}
-
-void PrintCodecMapping() {
-  PrintCodecMappingEntry(NetEqDecoder::kDecoderPCMu, FLAG_pcmu);
-  PrintCodecMappingEntry(NetEqDecoder::kDecoderPCMa, FLAG_pcma);
-  PrintCodecMappingEntry(NetEqDecoder::kDecoderILBC, FLAG_ilbc);
-  PrintCodecMappingEntry(NetEqDecoder::kDecoderISAC, FLAG_isac);
-  PrintCodecMappingEntry(NetEqDecoder::kDecoderISACswb, FLAG_isac_swb);
-  PrintCodecMappingEntry(NetEqDecoder::kDecoderOpus, FLAG_opus);
-  PrintCodecMappingEntry(NetEqDecoder::kDecoderPCM16B, FLAG_pcm16b);
-  PrintCodecMappingEntry(NetEqDecoder::kDecoderPCM16Bwb, FLAG_pcm16b_wb);
-  PrintCodecMappingEntry(NetEqDecoder::kDecoderPCM16Bswb32kHz,
-                         FLAG_pcm16b_swb32);
-  PrintCodecMappingEntry(NetEqDecoder::kDecoderPCM16Bswb48kHz,
-                         FLAG_pcm16b_swb48);
-  PrintCodecMappingEntry(NetEqDecoder::kDecoderG722, FLAG_g722);
-  PrintCodecMappingEntry(NetEqDecoder::kDecoderAVT, FLAG_avt);
-  PrintCodecMappingEntry(NetEqDecoder::kDecoderAVT16kHz, FLAG_avt_16);
-  PrintCodecMappingEntry(NetEqDecoder::kDecoderAVT32kHz, FLAG_avt_32);
-  PrintCodecMappingEntry(NetEqDecoder::kDecoderAVT48kHz, FLAG_avt_48);
-  PrintCodecMappingEntry(NetEqDecoder::kDecoderRED, FLAG_red);
-  PrintCodecMappingEntry(NetEqDecoder::kDecoderCNGnb, FLAG_cn_nb);
-  PrintCodecMappingEntry(NetEqDecoder::kDecoderCNGwb, FLAG_cn_wb);
-  PrintCodecMappingEntry(NetEqDecoder::kDecoderCNGswb32kHz, FLAG_cn_swb32);
-  PrintCodecMappingEntry(NetEqDecoder::kDecoderCNGswb48kHz, FLAG_cn_swb48);
-}
-
-absl::optional<int> CodecSampleRate(uint8_t payload_type) {
-  if (payload_type == FLAG_pcmu || payload_type == FLAG_pcma ||
-      payload_type == FLAG_ilbc || payload_type == FLAG_pcm16b ||
-      payload_type == FLAG_cn_nb || payload_type == FLAG_avt)
+absl::optional<int> CodecSampleRate(
+    uint8_t payload_type,
+    webrtc::test::NetEqTestFactory::Config config) {
+  if (payload_type == config.pcmu || payload_type == config.pcma ||
+      payload_type == config.ilbc || payload_type == config.pcm16b ||
+      payload_type == config.cn_nb || payload_type == config.avt)
     return 8000;
-  if (payload_type == FLAG_isac || payload_type == FLAG_pcm16b_wb ||
-      payload_type == FLAG_g722 || payload_type == FLAG_cn_wb ||
-      payload_type == FLAG_avt_16)
+  if (payload_type == config.isac || payload_type == config.pcm16b_wb ||
+      payload_type == config.g722 || payload_type == config.cn_wb ||
+      payload_type == config.avt_16)
     return 16000;
-  if (payload_type == FLAG_isac_swb || payload_type == FLAG_pcm16b_swb32 ||
-      payload_type == FLAG_cn_swb32 || payload_type == FLAG_avt_32)
+  if (payload_type == config.isac_swb || payload_type == config.pcm16b_swb32 ||
+      payload_type == config.cn_swb32 || payload_type == config.avt_32)
     return 32000;
-  if (payload_type == FLAG_opus || payload_type == FLAG_pcm16b_swb48 ||
-      payload_type == FLAG_cn_swb48 || payload_type == FLAG_avt_48)
+  if (payload_type == config.opus || payload_type == config.pcm16b_swb48 ||
+      payload_type == config.cn_swb48 || payload_type == config.avt_48)
     return 48000;
-  if (payload_type == FLAG_red)
+  if (payload_type == config.red)
     return 0;
   return absl::nullopt;
 }
@@ -277,66 +101,31 @@
 };
 
 NetEqTestFactory::NetEqTestFactory() = default;
-
 NetEqTestFactory::~NetEqTestFactory() = default;
 
-void NetEqTestFactory::PrintCodecMap() {
-  PrintCodecMapping();
-}
+NetEqTestFactory::Config::Config() = default;
+NetEqTestFactory::Config::Config(const Config& other) = default;
+NetEqTestFactory::Config::~Config() = default;
 
 std::unique_ptr<NetEqTest> NetEqTestFactory::InitializeTest(
     std::string input_file_name,
-    std::string output_file_name) {
-  RTC_CHECK(ValidatePayloadType(FLAG_pcmu));
-  RTC_CHECK(ValidatePayloadType(FLAG_pcma));
-  RTC_CHECK(ValidatePayloadType(FLAG_ilbc));
-  RTC_CHECK(ValidatePayloadType(FLAG_isac));
-  RTC_CHECK(ValidatePayloadType(FLAG_isac_swb));
-  RTC_CHECK(ValidatePayloadType(FLAG_opus));
-  RTC_CHECK(ValidatePayloadType(FLAG_pcm16b));
-  RTC_CHECK(ValidatePayloadType(FLAG_pcm16b_wb));
-  RTC_CHECK(ValidatePayloadType(FLAG_pcm16b_swb32));
-  RTC_CHECK(ValidatePayloadType(FLAG_pcm16b_swb48));
-  RTC_CHECK(ValidatePayloadType(FLAG_g722));
-  RTC_CHECK(ValidatePayloadType(FLAG_avt));
-  RTC_CHECK(ValidatePayloadType(FLAG_avt_16));
-  RTC_CHECK(ValidatePayloadType(FLAG_avt_32));
-  RTC_CHECK(ValidatePayloadType(FLAG_avt_48));
-  RTC_CHECK(ValidatePayloadType(FLAG_red));
-  RTC_CHECK(ValidatePayloadType(FLAG_cn_nb));
-  RTC_CHECK(ValidatePayloadType(FLAG_cn_wb));
-  RTC_CHECK(ValidatePayloadType(FLAG_cn_swb32));
-  RTC_CHECK(ValidatePayloadType(FLAG_cn_swb48));
-  RTC_CHECK(ValidateSsrcValue(FLAG_ssrc));
-  RTC_CHECK(ValidateExtensionId(FLAG_audio_level));
-  RTC_CHECK(ValidateExtensionId(FLAG_abs_send_time));
-  RTC_CHECK(ValidateExtensionId(FLAG_transport_seq_no));
-  RTC_CHECK(ValidateExtensionId(FLAG_video_content_type));
-  RTC_CHECK(ValidateExtensionId(FLAG_video_timing));
-
+    std::string output_file_name,
+    const Config& config) {
   // Gather RTP header extensions in a map.
   NetEqPacketSourceInput::RtpHeaderExtensionMap rtp_ext_map = {
-      {FLAG_audio_level, kRtpExtensionAudioLevel},
-      {FLAG_abs_send_time, kRtpExtensionAbsoluteSendTime},
-      {FLAG_transport_seq_no, kRtpExtensionTransportSequenceNumber},
-      {FLAG_video_content_type, kRtpExtensionVideoContentType},
-      {FLAG_video_timing, kRtpExtensionVideoTiming}};
-
-  absl::optional<uint32_t> ssrc_filter;
-  // Check if an SSRC value was provided.
-  if (strlen(FLAG_ssrc) > 0) {
-    uint32_t ssrc;
-    RTC_CHECK(ParseSsrc(FLAG_ssrc, &ssrc)) << "Flag verification has failed.";
-    ssrc_filter = ssrc;
-  }
+      {config.audio_level, kRtpExtensionAudioLevel},
+      {config.abs_send_time, kRtpExtensionAbsoluteSendTime},
+      {config.transport_seq_no, kRtpExtensionTransportSequenceNumber},
+      {config.video_content_type, kRtpExtensionVideoContentType},
+      {config.video_timing, kRtpExtensionVideoTiming}};
 
   std::unique_ptr<NetEqInput> input;
   if (RtpFileSource::ValidRtpDump(input_file_name) ||
       RtpFileSource::ValidPcap(input_file_name)) {
-    input.reset(
-        new NetEqRtpDumpInput(input_file_name, rtp_ext_map, ssrc_filter));
+    input.reset(new NetEqRtpDumpInput(input_file_name, rtp_ext_map,
+                                      config.ssrc_filter));
   } else {
-    input.reset(new NetEqEventLogInput(input_file_name, ssrc_filter));
+    input.reset(new NetEqEventLogInput(input_file_name, config.ssrc_filter));
   }
 
   std::cout << "Input file: " << input_file_name << std::endl;
@@ -348,7 +137,7 @@
   std::set<std::pair<int, uint32_t>> discarded_pt_and_ssrc;
   while (absl::optional<RTPHeader> first_rtp_header = input->NextHeader()) {
     RTC_DCHECK(first_rtp_header);
-    sample_rate_hz = CodecSampleRate(first_rtp_header->payloadType);
+    sample_rate_hz = CodecSampleRate(first_rtp_header->payloadType, config);
     if (sample_rate_hz) {
       std::cout << "Found valid packet with payload type "
                 << static_cast<int>(first_rtp_header->payloadType)
@@ -391,46 +180,16 @@
 
   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")},
-#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")}
-  };
+  NetEqTest::DecoderMap codecs = NetEqTest::StandardDecoderMap();
+
+  rtc::scoped_refptr<AudioDecoderFactory> decoder_factory =
+      CreateBuiltinAudioDecoderFactory();
 
   // Check if a replacement audio file was provided.
-  if (strlen(FLAG_replacement_audio_file) > 0) {
+  if (config.replacement_audio_file.size() > 0) {
     // Find largest unused payload type.
     int replacement_pt = 127;
-    while (!(codecs.find(replacement_pt) == codecs.end() &&
-             ext_codecs_.find(replacement_pt) == ext_codecs_.end())) {
+    while (codecs.find(replacement_pt) != codecs.end()) {
       --replacement_pt;
       RTC_CHECK_GE(replacement_pt, 0);
     }
@@ -444,39 +203,59 @@
     };
 
     std::set<uint8_t> cn_types = std_set_int32_to_uint8(
-        {FLAG_cn_nb, FLAG_cn_wb, FLAG_cn_swb32, FLAG_cn_swb48});
-    std::set<uint8_t> forbidden_types = std_set_int32_to_uint8(
-        {FLAG_g722, FLAG_red, FLAG_avt, FLAG_avt_16, FLAG_avt_32, FLAG_avt_48});
+        {config.cn_nb, config.cn_wb, config.cn_swb32, config.cn_swb48});
+    std::set<uint8_t> forbidden_types =
+        std_set_int32_to_uint8({config.g722, config.red, config.avt,
+                                config.avt_16, config.avt_32, config.avt_48});
     input.reset(new NetEqReplacementInput(std::move(input), replacement_pt,
                                           cn_types, forbidden_types));
 
-    replacement_decoder_.reset(new FakeDecodeFromFile(
-        std::unique_ptr<InputAudioFile>(
-            new InputAudioFile(FLAG_replacement_audio_file)),
-        48000, false));
-    NetEqTest::ExternalDecoderInfo ext_dec_info = {
-        replacement_decoder_.get(), NetEqDecoder::kDecoderArbitrary,
-        "replacement codec"};
-    ext_codecs_[replacement_pt] = ext_dec_info;
+    // Note that capture-by-copy implies that the lambda captures the value of
+    // decoder_factory before it's reassigned on the left-hand side.
+    decoder_factory = new rtc::RefCountedObject<FunctionAudioDecoderFactory>(
+        [decoder_factory, config](
+            const SdpAudioFormat& format,
+            absl::optional<AudioCodecPairId> codec_pair_id) {
+          std::unique_ptr<AudioDecoder> decoder =
+              decoder_factory->MakeAudioDecoder(format, codec_pair_id);
+          if (!decoder && format.name == "replacement") {
+            decoder = absl::make_unique<FakeDecodeFromFile>(
+                absl::make_unique<InputAudioFile>(
+                    config.replacement_audio_file),
+                format.clockrate_hz, format.num_channels > 1);
+          }
+          return decoder;
+        });
+
+    RTC_CHECK(
+        codecs.insert({replacement_pt, SdpAudioFormat("replacement", 48000, 1)})
+            .second);
+  }
+
+  // Create a text log file if needed.
+  std::unique_ptr<std::ofstream> text_log;
+  if (config.textlog) {
+    text_log =
+        absl::make_unique<std::ofstream>(output_file_name + ".text_log.txt");
   }
 
   NetEqTest::Callbacks callbacks;
-  stats_plotter_.reset(new NetEqStatsPlotter(FLAG_matlabplot, FLAG_pythonplot,
-                                             FLAG_concealment_events,
-                                             output_file_name));
+  stats_plotter_.reset(
+      new NetEqStatsPlotter(config.matlabplot, config.pythonplot,
+                            config.concealment_events, output_file_name));
 
   ssrc_switch_detector_.reset(
       new SsrcSwitchDetector(stats_plotter_->stats_getter()->delay_analyzer()));
   callbacks.post_insert_packet = ssrc_switch_detector_.get();
   callbacks.get_audio_callback = stats_plotter_->stats_getter();
   callbacks.simulation_ended_callback = stats_plotter_.get();
-  NetEq::Config config;
-  config.sample_rate_hz = *sample_rate_hz;
-  config.max_packets_in_buffer = FLAG_max_nr_packets_in_buffer;
-  config.enable_fast_accelerate = FLAG_enable_fast_accelerate;
-  return absl::make_unique<NetEqTest>(config, codecs, ext_codecs_,
-                                      std::move(input), std::move(output),
-                                      callbacks);
+  NetEq::Config neteq_config;
+  neteq_config.sample_rate_hz = *sample_rate_hz;
+  neteq_config.max_packets_in_buffer = config.max_nr_packets_in_buffer;
+  neteq_config.enable_fast_accelerate = config.enable_fast_accelerate;
+  return absl::make_unique<NetEqTest>(neteq_config, decoder_factory, codecs,
+                                      std::move(text_log), std::move(input),
+                                      std::move(output), callbacks);
 }
 
 }  // namespace test
diff --git a/modules/audio_coding/neteq/tools/neteq_test_factory.h b/modules/audio_coding/neteq/tools/neteq_test_factory.h
index a249186..dbcdf1a 100644
--- a/modules/audio_coding/neteq/tools/neteq_test_factory.h
+++ b/modules/audio_coding/neteq/tools/neteq_test_factory.h
@@ -14,6 +14,7 @@
 #include <memory>
 #include <string>
 
+#include "absl/types/optional.h"
 #include "modules/audio_coding/neteq/tools/neteq_test.h"
 
 namespace webrtc {
@@ -29,13 +30,109 @@
  public:
   NetEqTestFactory();
   ~NetEqTestFactory();
-  void PrintCodecMap();
+  struct Config {
+    Config();
+    Config(const Config& other);
+    ~Config();
+    // RTP payload type for PCM-u.
+    static constexpr int default_pcmu() { return 0; }
+    int pcmu = default_pcmu();
+    // RTP payload type for PCM-a.
+    static constexpr int default_pcma() { return 8; }
+    int pcma = default_pcma();
+    // RTP payload type for iLBC.
+    static constexpr int default_ilbc() { return 102; }
+    int ilbc = default_ilbc();
+    // RTP payload type for iSAC.
+    static constexpr int default_isac() { return 103; }
+    int isac = default_isac();
+    // RTP payload type for iSAC-swb (32 kHz).
+    static constexpr int default_isac_swb() { return 104; }
+    int isac_swb = default_isac_swb();
+    // RTP payload type for Opus.
+    static constexpr int default_opus() { return 111; }
+    int opus = default_opus();
+    // RTP payload type for PCM16b-nb (8 kHz).
+    static constexpr int default_pcm16b() { return 93; }
+    int pcm16b = default_pcm16b();
+    // RTP payload type for PCM16b-wb (16 kHz).
+    static constexpr int default_pcm16b_wb() { return 94; }
+    int pcm16b_wb = default_pcm16b_wb();
+    // RTP payload type for PCM16b-swb32 (32 kHz).
+    static constexpr int default_pcm16b_swb32() { return 95; }
+    int pcm16b_swb32 = default_pcm16b_swb32();
+    // RTP payload type for PCM16b-swb48 (48 kHz).
+    static constexpr int default_pcm16b_swb48() { return 96; }
+    int pcm16b_swb48 = default_pcm16b_swb48();
+    // RTP payload type for G.722.
+    static constexpr int default_g722() { return 9; }
+    int g722 = default_g722();
+    // RTP payload type for AVT/DTMF (8 kHz).
+    static constexpr int default_avt() { return 106; }
+    int avt = default_avt();
+    // RTP payload type for AVT/DTMF (16 kHz).
+    static constexpr int default_avt_16() { return 114; }
+    int avt_16 = default_avt_16();
+    // RTP payload type for AVT/DTMF (32 kHz).
+    static constexpr int default_avt_32() { return 115; }
+    int avt_32 = default_avt_32();
+    // RTP payload type for AVT/DTMF (48 kHz).
+    static constexpr int default_avt_48() { return 116; }
+    int avt_48 = default_avt_48();
+    // RTP payload type for redundant audio (RED).
+    static constexpr int default_red() { return 117; }
+    int red = default_red();
+    // RTP payload type for comfort noise (8 kHz).
+    static constexpr int default_cn_nb() { return 13; }
+    int cn_nb = default_cn_nb();
+    // RTP payload type for comfort noise (16 kHz).
+    static constexpr int default_cn_wb() { return 98; }
+    int cn_wb = default_cn_wb();
+    // RTP payload type for comfort noise (32 kHz).
+    static constexpr int default_cn_swb32() { return 99; }
+    int cn_swb32 = default_cn_swb32();
+    // RTP payload type for comfort noise (48 kHz).
+    static constexpr int default_cn_swb48() { return 100; }
+    int cn_swb48 = default_cn_swb48();
+    // A PCM file that will be used to populate dummy RTP packets.
+    std::string replacement_audio_file;
+    // Only use packets with this SSRC.
+    absl::optional<uint32_t> ssrc_filter;
+    // Extension ID for audio level (RFC 6464).
+    static constexpr int default_audio_level() { return 1; }
+    int audio_level = default_audio_level();
+    // Extension ID for absolute sender time.
+    static constexpr int default_abs_send_time() { return 3; }
+    int abs_send_time = default_abs_send_time();
+    // Extension ID for transport sequence number.
+    static constexpr int default_transport_seq_no() { return 5; }
+    int transport_seq_no = default_transport_seq_no();
+    // Extension ID for video content type.
+    static constexpr int default_video_content_type() { return 7; }
+    int video_content_type = default_video_content_type();
+    // Extension ID for video timing.
+    static constexpr int default_video_timing() { return 8; }
+    int video_timing = default_video_timing();
+    // Generate a matlab script for plotting the delay profile.
+    bool matlabplot = false;
+    // Generates a python script for plotting the delay profile.
+    bool pythonplot = false;
+    // Generates a text log describing the simulation on a step-by-step basis.
+    bool textlog = false;
+    // Prints concealment events.
+    bool concealment_events = false;
+    // Maximum allowed number of packets in the buffer.
+    static constexpr int default_max_nr_packets_in_buffer() { return 50; }
+    int max_nr_packets_in_buffer = default_max_nr_packets_in_buffer();
+    // Enables jitter buffer fast accelerate.
+    bool enable_fast_accelerate = false;
+  };
+
   std::unique_ptr<NetEqTest> InitializeTest(std::string input_filename,
-                                            std::string output_filename);
+                                            std::string output_filename,
+                                            const Config& config);
 
  private:
-  std::unique_ptr<AudioDecoder> replacement_decoder_;
-  NetEqTest::ExtDecoderMap ext_codecs_;
   std::unique_ptr<SsrcSwitchDetector> ssrc_switch_detector_;
   std::unique_ptr<NetEqStatsPlotter> stats_plotter_;
 };
diff --git a/modules/audio_coding/neteq/tools/output_audio_file.h b/modules/audio_coding/neteq/tools/output_audio_file.h
index 7e65bc2..c923a1e 100644
--- a/modules/audio_coding/neteq/tools/output_audio_file.h
+++ b/modules/audio_coding/neteq/tools/output_audio_file.h
@@ -16,7 +16,7 @@
 #include <string>
 
 #include "modules/audio_coding/neteq/tools/audio_sink.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 namespace test {
diff --git a/modules/audio_coding/neteq/tools/output_wav_file.h b/modules/audio_coding/neteq/tools/output_wav_file.h
index 031a8cb..6982a76 100644
--- a/modules/audio_coding/neteq/tools/output_wav_file.h
+++ b/modules/audio_coding/neteq/tools/output_wav_file.h
@@ -15,7 +15,7 @@
 
 #include "common_audio/wav_file.h"
 #include "modules/audio_coding/neteq/tools/audio_sink.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 namespace test {
@@ -24,8 +24,10 @@
  public:
   // Creates an OutputWavFile, opening a file named |file_name| for writing.
   // The output file is a PCM encoded wav file.
-  OutputWavFile(const std::string& file_name, int sample_rate_hz)
-      : wav_writer_(file_name, sample_rate_hz, 1) {}
+  OutputWavFile(const std::string& file_name,
+                int sample_rate_hz,
+                int num_channels = 1)
+      : wav_writer_(file_name, sample_rate_hz, num_channels) {}
 
   bool WriteArray(const int16_t* audio, size_t num_samples) override {
     wav_writer_.WriteSamples(audio, num_samples);
diff --git a/modules/audio_coding/neteq/tools/packet.h b/modules/audio_coding/neteq/tools/packet.h
index 39137aa..5748ba2 100644
--- a/modules/audio_coding/neteq/tools/packet.h
+++ b/modules/audio_coding/neteq/tools/packet.h
@@ -15,8 +15,7 @@
 #include <memory>
 
 #include "api/rtp_headers.h"  // NOLINT(build/include)
-#include "common_types.h"     // NOLINT(build/include)
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
diff --git a/modules/audio_coding/neteq/tools/packet_source.h b/modules/audio_coding/neteq/tools/packet_source.h
index cb86a98..975680f 100644
--- a/modules/audio_coding/neteq/tools/packet_source.h
+++ b/modules/audio_coding/neteq/tools/packet_source.h
@@ -15,7 +15,7 @@
 #include <memory>
 
 #include "modules/audio_coding/neteq/tools/packet.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 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 4e2e9b0..d961f33 100644
--- a/modules/audio_coding/neteq/tools/resample_input_audio_file.h
+++ b/modules/audio_coding/neteq/tools/resample_input_audio_file.h
@@ -15,7 +15,7 @@
 
 #include "common_audio/resampler/include/resampler.h"
 #include "modules/audio_coding/neteq/tools/input_audio_file.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 namespace test {
diff --git a/modules/audio_coding/neteq/tools/rtc_event_log_source.cc b/modules/audio_coding/neteq/tools/rtc_event_log_source.cc
index 582c2f2..591e2b9 100644
--- a/modules/audio_coding/neteq/tools/rtc_event_log_source.cc
+++ b/modules/audio_coding/neteq/tools/rtc_event_log_source.cc
@@ -13,8 +13,10 @@
 #include <string.h>
 #include <iostream>
 #include <limits>
+#include <set>
 #include <utility>
 
+#include "absl/memory/memory.h"
 #include "logging/rtc_event_log/rtc_event_processor.h"
 #include "modules/audio_coding/neteq/tools/packet.h"
 #include "rtc_base/checks.h"
@@ -23,10 +25,10 @@
 namespace test {
 
 namespace {
-bool ShouldSkipStream(ParsedRtcEventLogNew::MediaType media_type,
+bool ShouldSkipStream(ParsedRtcEventLog::MediaType media_type,
                       uint32_t ssrc,
                       absl::optional<uint32_t> ssrc_filter) {
-  if (media_type != ParsedRtcEventLogNew::MediaType::AUDIO)
+  if (media_type != ParsedRtcEventLog::MediaType::AUDIO)
     return true;
   if (ssrc_filter.has_value() && ssrc != *ssrc_filter)
     return true;
@@ -64,7 +66,7 @@
 
 bool RtcEventLogSource::OpenFile(const std::string& file_name,
                                  absl::optional<uint32_t> ssrc_filter) {
-  ParsedRtcEventLogNew parsed_log;
+  ParsedRtcEventLog parsed_log;
   if (!parsed_log.ParseFile(file_name))
     return false;
 
@@ -73,54 +75,59 @@
           ? std::numeric_limits<int64_t>::max()
           : parsed_log.stop_log_events().front().log_time_us();
 
+  std::set<uint32_t> packet_ssrcs;
   auto handle_rtp_packet =
-      [this,
-       first_log_end_time_us](const webrtc::LoggedRtpPacketIncoming& incoming) {
+      [this, first_log_end_time_us,
+       &packet_ssrcs](const webrtc::LoggedRtpPacketIncoming& incoming) {
         if (!filter_.test(incoming.rtp.header.payloadType) &&
             incoming.log_time_us() < first_log_end_time_us) {
           rtp_packets_.emplace_back(absl::make_unique<Packet>(
               incoming.rtp.header, incoming.rtp.total_length,
               incoming.rtp.total_length - incoming.rtp.header_length,
               static_cast<double>(incoming.log_time_ms())));
+          packet_ssrcs.insert(rtp_packets_.back()->header().ssrc);
         }
       };
 
+  std::set<uint32_t> ignored_ssrcs;
   auto handle_audio_playout =
-      [this, first_log_end_time_us](
-          const webrtc::LoggedAudioPlayoutEvent& audio_playout) {
+      [this, first_log_end_time_us, &packet_ssrcs,
+       &ignored_ssrcs](const webrtc::LoggedAudioPlayoutEvent& audio_playout) {
         if (audio_playout.log_time_us() < first_log_end_time_us) {
-          audio_outputs_.emplace_back(audio_playout.log_time_ms());
+          if (packet_ssrcs.count(audio_playout.ssrc) > 0) {
+            audio_outputs_.emplace_back(audio_playout.log_time_ms());
+          } else {
+            ignored_ssrcs.insert(audio_playout.ssrc);
+          }
         }
       };
 
   // This wouldn't be needed if we knew that there was at most one audio stream.
   webrtc::RtcEventProcessor event_processor;
   for (const auto& rtp_packets : parsed_log.incoming_rtp_packets_by_ssrc()) {
-    ParsedRtcEventLogNew::MediaType media_type =
+    ParsedRtcEventLog::MediaType media_type =
         parsed_log.GetMediaType(rtp_packets.ssrc, webrtc::kIncomingPacket);
     if (ShouldSkipStream(media_type, rtp_packets.ssrc, ssrc_filter)) {
       continue;
     }
-    auto rtp_view = absl::make_unique<
-        webrtc::ProcessableEventList<webrtc::LoggedRtpPacketIncoming>>(
-        rtp_packets.incoming_packets.begin(),
-        rtp_packets.incoming_packets.end(), handle_rtp_packet);
-    event_processor.AddEvents(std::move(rtp_view));
+    event_processor.AddEvents(rtp_packets.incoming_packets, handle_rtp_packet);
   }
 
   for (const auto& audio_playouts : parsed_log.audio_playout_events()) {
     if (ssrc_filter.has_value() && audio_playouts.first != *ssrc_filter)
       continue;
-    auto audio_view = absl::make_unique<
-        webrtc::ProcessableEventList<webrtc::LoggedAudioPlayoutEvent>>(
-        audio_playouts.second.begin(), audio_playouts.second.end(),
-        handle_audio_playout);
-    event_processor.AddEvents(std::move(audio_view));
+    event_processor.AddEvents(audio_playouts.second, handle_audio_playout);
   }
 
   // Fills in rtp_packets_ and audio_outputs_.
   event_processor.ProcessEventsInOrder();
 
+  for (const auto& ssrc : ignored_ssrcs) {
+    std::cout << "Ignoring GetAudio events from SSRC 0x" << std::hex << ssrc
+              << " because no packets were found with a matching SSRC."
+              << std::endl;
+  }
+
   return true;
 }
 
diff --git a/modules/audio_coding/neteq/tools/rtc_event_log_source.h b/modules/audio_coding/neteq/tools/rtc_event_log_source.h
index 6b761f7..5238efb 100644
--- a/modules/audio_coding/neteq/tools/rtc_event_log_source.h
+++ b/modules/audio_coding/neteq/tools/rtc_event_log_source.h
@@ -16,10 +16,10 @@
 #include <vector>
 
 #include "absl/types/optional.h"
-#include "logging/rtc_event_log/rtc_event_log_parser_new.h"
+#include "logging/rtc_event_log/rtc_event_log_parser.h"
 #include "modules/audio_coding/neteq/tools/packet_source.h"
 #include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
diff --git a/modules/audio_coding/neteq/tools/rtp_file_source.h b/modules/audio_coding/neteq/tools/rtp_file_source.h
index 02ab897..77e435a 100644
--- a/modules/audio_coding/neteq/tools/rtp_file_source.h
+++ b/modules/audio_coding/neteq/tools/rtp_file_source.h
@@ -17,10 +17,9 @@
 #include <string>
 
 #include "absl/types/optional.h"
-#include "common_types.h"  // NOLINT(build/include)
 #include "modules/audio_coding/neteq/tools/packet_source.h"
 #include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
diff --git a/modules/audio_coding/neteq/tools/rtp_generator.h b/modules/audio_coding/neteq/tools/rtp_generator.h
index ca7b04f..1454c57 100644
--- a/modules/audio_coding/neteq/tools/rtp_generator.h
+++ b/modules/audio_coding/neteq/tools/rtp_generator.h
@@ -12,8 +12,7 @@
 #define MODULES_AUDIO_CODING_NETEQ_TOOLS_RTP_GENERATOR_H_
 
 #include "api/rtp_headers.h"
-#include "common_types.h"  // NOLINT(build/include)
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 namespace test {
diff --git a/modules/audio_processing/BUILD.gn b/modules/audio_processing/BUILD.gn
index 66b07df..39d492b 100644
--- a/modules/audio_processing/BUILD.gn
+++ b/modules/audio_processing/BUILD.gn
@@ -7,7 +7,7 @@
 # be found in the AUTHORS file in the root of the source tree.
 
 import("../../webrtc.gni")
-if (!build_with_mozilla) {
+if (rtc_enable_protobuf) {
   import("//third_party/protobuf/proto_library.gni")
 }
 
@@ -50,23 +50,47 @@
     ":audio_processing_statistics",
     ":config",
     ":gain_control_interface",
+    "../../api:scoped_refptr",
     "../../api/audio:aec3_config",
     "../../api/audio:echo_control",
     "../../rtc_base:deprecation",
     "../../rtc_base:macromagic",
-    "../../rtc_base:ptr_util",
     "../../rtc_base:rtc_base_approved",
     "../../rtc_base/system:rtc_export",
+    "//third_party/abseil-cpp/absl/memory:memory",
     "//third_party/abseil-cpp/absl/types:optional",
   ]
 }
 
+rtc_static_library("audio_buffer") {
+  visibility = [ "*" ]
+
+  configs += [ ":apm_debug_dump" ]
+
+  sources = [
+    "audio_buffer.cc",
+    "audio_buffer.h",
+    "splitting_filter.cc",
+    "splitting_filter.h",
+    "three_band_filter_bank.cc",
+    "three_band_filter_bank.h",
+  ]
+
+  defines = []
+
+  deps = [
+    ":api",
+    "../../api/audio:audio_frame_api",
+    "../../common_audio:common_audio",
+    "../../common_audio:common_audio_c",
+    "../../rtc_base:checks",
+  ]
+}
+
 rtc_static_library("audio_processing") {
   visibility = [ "*" ]
   configs += [ ":apm_debug_dump" ]
   sources = [
-    "audio_buffer.cc",
-    "audio_buffer.h",
     "audio_processing_impl.cc",
     "audio_processing_impl.h",
     "common.h",
@@ -101,10 +125,6 @@
     "residual_echo_detector.h",
     "rms_level.cc",
     "rms_level.h",
-    "splitting_filter.cc",
-    "splitting_filter.h",
-    "three_band_filter_bank.cc",
-    "three_band_filter_bank.h",
     "transient/common.h",
     "transient/daubechies_8_wavelet_coeffs.h",
     "transient/dyadic_decimator.h",
@@ -128,12 +148,14 @@
   deps = [
     ":api",
     ":apm_logging",
+    ":audio_buffer",
     ":audio_frame_view",
     ":audio_generator_interface",
     ":audio_processing_c",
     ":audio_processing_statistics",
     ":config",
     ":gain_control_interface",
+    ":noise_suppression_proxy",
     "../..:webrtc_common",
     "../../api:array_view",
     "../../api/audio:aec3_config",
@@ -154,6 +176,7 @@
     "../../system_wrappers:metrics",
     "aec:aec",
     "aec:aec_core",
+    "aec3:aec3",
     "aecm:aecm_core",
     "agc",
     "agc:agc_legacy_c",
@@ -161,6 +184,7 @@
     "agc2:fixed_digital",
     "agc2:gain_applier",
     "vad",
+    "//third_party/abseil-cpp/absl/memory:memory",
     "//third_party/abseil-cpp/absl/types:optional",
   ]
 
@@ -189,6 +213,17 @@
   ]
 }
 
+rtc_source_set("noise_suppression_proxy") {
+  sources = [
+    "noise_suppression_proxy.cc",
+    "noise_suppression_proxy.h",
+  ]
+  deps = [
+    ":api",
+    "../../rtc_base:macromagic",
+  ]
+}
+
 rtc_source_set("audio_processing_statistics") {
   visibility = [ "*" ]
   sources = [
@@ -331,7 +366,6 @@
     "../../common_audio:common_audio",
     "../../rtc_base:checks",
     "../../rtc_base:rtc_base_approved",
-    "../../rtc_base:stringutils",
   ]
   defines = []
 }
@@ -397,6 +431,7 @@
       ":analog_mic_simulation",
       ":api",
       ":apm_logging",
+      ":audio_buffer",
       ":audio_frame_view",
       ":audio_processing",
       ":audioproc_test_utils",
@@ -405,6 +440,7 @@
       ":mocks",
       "../..:webrtc_common",
       "../../api:array_view",
+      "../../api:scoped_refptr",
       "../../api/audio:aec3_config",
       "../../api/audio:aec3_factory",
       "../../common_audio:common_audio",
@@ -437,6 +473,7 @@
       "test/conversational_speech:unittest",
       "utility:block_mean_calculator_unittest",
       "utility:legacy_delay_estimator_unittest",
+      "utility:pffft_wrapper_unittest",
       "vad:vad_unittests",
       "//testing/gtest",
       "//third_party/abseil-cpp/absl/memory",
@@ -460,6 +497,8 @@
         ":audioproc_unittest_proto",
         ":runtime_settings_protobuf_utils",
         "../../api/audio:audio_frame_api",
+        "../../api/audio:echo_control",
+        "../../rtc_base:rtc_base_tests_utils",
         "../../rtc_base:rtc_task_queue",
         "aec_dump",
         "aec_dump:aec_dump_unittests",
@@ -486,15 +525,11 @@
         "test/echo_canceller_test_tools.cc",
         "test/echo_canceller_test_tools.h",
         "test/echo_canceller_test_tools_unittest.cc",
+        "test/echo_control_mock.h",
         "test/test_utils.h",
         "voice_detection_unittest.cc",
       ]
     }
-
-    if ((!build_with_chromium || is_win) && 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_processing_perf_tests") {
@@ -583,7 +618,6 @@
         "../../rtc_base:rtc_base_approved",
         "../../rtc_base:rtc_json",
         "../../rtc_base:rtc_task_queue",
-        "../../rtc_base:stringutils",
         "../../system_wrappers",
         "../../test:test_support",
         "aec_dump",
@@ -627,6 +661,7 @@
 
     deps = [
       ":api",
+      ":audio_buffer",
       ":audio_processing",
       "../../api:array_view",
       "../../api/audio:audio_frame_api",
diff --git a/modules/audio_processing/aec/aec_core.h b/modules/audio_processing/aec/aec_core.h
index 35a6c9b..06ae2a4 100644
--- a/modules/audio_processing/aec/aec_core.h
+++ b/modules/audio_processing/aec/aec_core.h
@@ -25,7 +25,7 @@
 #include "modules/audio_processing/aec/aec_common.h"
 #include "modules/audio_processing/utility/block_mean_calculator.h"
 #include "modules/audio_processing/utility/ooura_fft.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
diff --git a/modules/audio_processing/aec3/BUILD.gn b/modules/audio_processing/aec3/BUILD.gn
index 189bcfd..259403c 100644
--- a/modules/audio_processing/aec3/BUILD.gn
+++ b/modules/audio_processing/aec3/BUILD.gn
@@ -28,7 +28,6 @@
     "block_framer.h",
     "block_processor.cc",
     "block_processor.h",
-    "block_processor2.cc",
     "block_processor_metrics.cc",
     "block_processor_metrics.h",
     "cascaded_biquad_filter.cc",
@@ -81,10 +80,8 @@
     "render_buffer.h",
     "render_delay_buffer.cc",
     "render_delay_buffer.h",
-    "render_delay_buffer2.cc",
     "render_delay_controller.cc",
     "render_delay_controller.h",
-    "render_delay_controller2.cc",
     "render_delay_controller_metrics.cc",
     "render_delay_controller_metrics.h",
     "render_reverb_model.cc",
@@ -123,8 +120,6 @@
     "suppression_filter.h",
     "suppression_gain.cc",
     "suppression_gain.h",
-    "suppression_gain_limiter.cc",
-    "suppression_gain_limiter.h",
     "vector_buffer.cc",
     "vector_buffer.h",
     "vector_math.h",
@@ -138,7 +133,7 @@
 
   deps = [
     "..:apm_logging",
-    "..:audio_processing",
+    "..:audio_buffer",
     "../../../api:array_view",
     "../../../api/audio:aec3_config",
     "../../../api/audio:echo_control",
@@ -174,6 +169,7 @@
     deps = [
       ":aec3",
       "..:apm_logging",
+      "..:audio_buffer",
       "..:audio_processing",
       "..:audio_processing_unittests",
       "../../../api:array_view",
diff --git a/modules/audio_processing/aec3/adaptive_fir_filter.cc b/modules/audio_processing/aec3/adaptive_fir_filter.cc
index 3ab1ebc..8837c2c 100644
--- a/modules/audio_processing/aec3/adaptive_fir_filter.cc
+++ b/modules/audio_processing/aec3/adaptive_fir_filter.cc
@@ -24,7 +24,6 @@
 
 #include "modules/audio_processing/aec3/fft_data.h"
 #include "rtc_base/checks.h"
-#include "system_wrappers/include/field_trial.h"
 
 namespace webrtc {
 
@@ -417,21 +416,12 @@
 
 }  // namespace aec3
 
-namespace {
-
-bool EnablePartialFilterReset() {
-  return !field_trial::IsEnabled("WebRTC-Aec3PartialFilterResetKillSwitch");
-}
-
-}  // namespace
-
 AdaptiveFirFilter::AdaptiveFirFilter(size_t max_size_partitions,
                                      size_t initial_size_partitions,
                                      size_t size_change_duration_blocks,
                                      Aec3Optimization optimization,
                                      ApmDataDumper* data_dumper)
     : data_dumper_(data_dumper),
-      use_partial_filter_reset_(EnablePartialFilterReset()),
       fft_(),
       optimization_(optimization),
       max_size_partitions_(max_size_partitions),
@@ -464,18 +454,14 @@
 void AdaptiveFirFilter::HandleEchoPathChange() {
   size_t current_h_size = h_.size();
   h_.resize(GetTimeDomainLength(max_size_partitions_));
-  const size_t begin_coeffficient =
-      use_partial_filter_reset_ ? current_h_size : 0;
-  std::fill(h_.begin() + begin_coeffficient, h_.end(), 0.f);
+  std::fill(h_.begin() + current_h_size, h_.end(), 0.f);
   h_.resize(current_h_size);
 
   size_t current_size_partitions = H_.size();
   H_.resize(max_size_partitions_);
   H2_.resize(max_size_partitions_);
 
-  const size_t begin_partition =
-      use_partial_filter_reset_ ? current_size_partitions : 0;
-  for (size_t k = begin_partition; k < max_size_partitions_; ++k) {
+  for (size_t k = current_size_partitions; k < max_size_partitions_; ++k) {
     H_[k].Clear();
     H2_[k].fill(0.f);
   }
diff --git a/modules/audio_processing/aec3/adaptive_fir_filter.h b/modules/audio_processing/aec3/adaptive_fir_filter.h
index 7c832a6..5afb80e 100644
--- a/modules/audio_processing/aec3/adaptive_fir_filter.h
+++ b/modules/audio_processing/aec3/adaptive_fir_filter.h
@@ -21,7 +21,7 @@
 #include "modules/audio_processing/aec3/fft_data.h"
 #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/constructor_magic.h"
 #include "rtc_base/system/arch.h"
 
 namespace webrtc {
@@ -164,7 +164,6 @@
   void UpdateSize();
 
   ApmDataDumper* const data_dumper_;
-  const bool use_partial_filter_reset_;
   const Aec3Fft fft_;
   const Aec3Optimization optimization_;
   const size_t max_size_partitions_;
diff --git a/modules/audio_processing/aec3/adaptive_fir_filter_unittest.cc b/modules/audio_processing/aec3/adaptive_fir_filter_unittest.cc
index 3d583e8..3c4f5a5 100644
--- a/modules/audio_processing/aec3/adaptive_fir_filter_unittest.cc
+++ b/modules/audio_processing/aec3/adaptive_fir_filter_unittest.cc
@@ -317,7 +317,6 @@
                            config.filter.config_change_duration_blocks,
                            DetectOptimization(), &data_dumper);
   Aec3Fft fft;
-  config.delay.min_echo_path_delay_blocks = 0;
   config.delay.default_delay = 1;
   std::unique_ptr<RenderDelayBuffer> render_delay_buffer(
       RenderDelayBuffer::Create(config, 3));
diff --git a/modules/audio_processing/aec3/aec3_fft.h b/modules/audio_processing/aec3/aec3_fft.h
index 6cd649a..d5db83e 100644
--- a/modules/audio_processing/aec3/aec3_fft.h
+++ b/modules/audio_processing/aec3/aec3_fft.h
@@ -18,7 +18,7 @@
 #include "modules/audio_processing/aec3/fft_data.h"
 #include "modules/audio_processing/utility/ooura_fft.h"
 #include "rtc_base/checks.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
diff --git a/modules/audio_processing/aec3/aec_state.cc b/modules/audio_processing/aec3/aec_state.cc
index 45b361f..99791a7 100644
--- a/modules/audio_processing/aec3/aec_state.cc
+++ b/modules/audio_processing/aec3/aec_state.cc
@@ -19,33 +19,12 @@
 #include "api/array_view.h"
 #include "modules/audio_processing/aec3/aec3_common.h"
 #include "modules/audio_processing/logging/apm_data_dumper.h"
-#include "rtc_base/atomicops.h"
+#include "rtc_base/atomic_ops.h"
 #include "rtc_base/checks.h"
-#include "system_wrappers/include/field_trial.h"
 
 namespace webrtc {
 namespace {
 
-bool EnableErleResetsAtGainChanges() {
-  return !field_trial::IsEnabled("WebRTC-Aec3ResetErleAtGainChangesKillSwitch");
-}
-
-bool UseLegacyFilterQualityState() {
-  return field_trial::IsEnabled("WebRTC-Aec3FilterQualityStateKillSwitch");
-}
-
-bool EnableLegacySaturationBehavior() {
-  return field_trial::IsEnabled("WebRTC-Aec3NewSaturationBehaviorKillSwitch");
-}
-
-bool UseSuppressionGainLimiter() {
-  return field_trial::IsEnabled("WebRTC-Aec3GainLimiterDeactivationKillSwitch");
-}
-bool EnableErleUpdatesDuringReverb() {
-  return !field_trial::IsEnabled(
-      "WebRTC-Aec3EnableErleUpdatesDuringReverbKillSwitch");
-}
-
 constexpr size_t kBlocksSinceConvergencedFilterInit = 10000;
 constexpr size_t kBlocksSinceConsistentEstimateInit = 10000;
 
@@ -68,7 +47,7 @@
 }
 
 absl::optional<float> AecState::ErleUncertainty() const {
-  if (SaturatedEcho() && use_legacy_saturation_behavior_) {
+  if (SaturatedEcho()) {
     return 1.f;
   }
 
@@ -79,11 +58,6 @@
     : data_dumper_(
           new ApmDataDumper(rtc::AtomicOps::Increment(&instance_count_))),
       config_(config),
-      use_legacy_saturation_behavior_(EnableLegacySaturationBehavior()),
-      enable_erle_resets_at_gain_changes_(EnableErleResetsAtGainChanges()),
-      enable_erle_updates_during_reverb_(EnableErleUpdatesDuringReverb()),
-      use_legacy_filter_quality_(UseLegacyFilterQualityState()),
-      use_suppressor_gain_limiter_(UseSuppressionGainLimiter()),
       initial_state_(config_),
       delay_state_(config_),
       transparent_state_(config_),
@@ -92,7 +66,6 @@
       legacy_saturation_detector_(config_),
       erl_estimator_(2 * kNumBlocksPerSecond),
       erle_estimator_(2 * kNumBlocksPerSecond, config_),
-      suppression_gain_limiter_(config_),
       filter_analyzer_(config_),
       echo_audibility_(
           config_.echo_audibility.use_stationarity_properties_at_init),
@@ -107,21 +80,12 @@
     capture_signal_saturation_ = false;
     strong_not_saturated_render_blocks_ = 0;
     blocks_with_active_render_ = 0;
-    if (use_suppressor_gain_limiter_) {
-      suppression_gain_limiter_.Reset();
-    }
     initial_state_.Reset();
     transparent_state_.Reset();
-    if (use_legacy_saturation_behavior_) {
       legacy_saturation_detector_.Reset();
-    }
     erle_estimator_.Reset(true);
     erl_estimator_.Reset();
-    if (use_legacy_filter_quality_) {
-      legacy_filter_quality_state_.Reset();
-    } else {
       filter_quality_state_.Reset();
-    }
   };
 
   // TODO(peah): Refine the reset scheme according to the type of gain and
@@ -130,8 +94,7 @@
   if (echo_path_variability.delay_change !=
       EchoPathVariability::DelayAdjustment::kNone) {
     full_reset();
-  } else if (enable_erle_resets_at_gain_changes_ &&
-             echo_path_variability.gain_change) {
+  } else if (echo_path_variability.gain_change) {
     erle_estimator_.Reset(false);
   }
   subtractor_output_analyzer_.HandleEchoPathChange();
@@ -172,17 +135,6 @@
   strong_not_saturated_render_blocks_ +=
       active_render && !SaturatedCapture() ? 1 : 0;
 
-  if (use_suppressor_gain_limiter_) {
-    // Update the limit on the echo suppression after an echo path change to
-    // avoid an initial echo burst.
-    suppression_gain_limiter_.Update(render_buffer.GetRenderActivity(),
-                                     TransparentMode());
-
-    if (subtractor_output_analyzer_.ConvergedFilter()) {
-      suppression_gain_limiter_.Deactivate();
-    }
-  }
-
   std::array<float, kFftLengthBy2Plus1> X2_reverb;
   render_reverb_.Apply(
       render_buffer.GetSpectrumBuffer(), delay_state_.DirectPathFilterDelay(),
@@ -203,8 +155,7 @@
   }
 
   const auto& X2 = render_buffer.Spectrum(delay_state_.DirectPathFilterDelay());
-  const auto& X2_input_erle =
-      enable_erle_updates_during_reverb_ ? X2_reverb : X2;
+  const auto& X2_input_erle = X2_reverb;
 
   erle_estimator_.Update(render_buffer, adaptive_filter_frequency_response,
                          X2_input_erle, Y2, E2_main,
@@ -214,14 +165,9 @@
   erl_estimator_.Update(subtractor_output_analyzer_.ConvergedFilter(), X2, Y2);
 
   // Detect and flag echo saturation.
-  if (use_legacy_saturation_behavior_) {
-    legacy_saturation_detector_.Update(aligned_render_block, SaturatedCapture(),
-                                       EchoPathGain());
-  } else {
-    saturation_detector_.Update(aligned_render_block, SaturatedCapture(),
-                                UsableLinearEstimate(), subtractor_output,
-                                EchoPathGain());
-  }
+  saturation_detector_.Update(aligned_render_block, SaturatedCapture(),
+                              UsableLinearEstimate(), subtractor_output,
+                              EchoPathGain());
 
   // Update the decision on whether to use the initial state parameter set.
   initial_state_.Update(active_render, SaturatedCapture());
@@ -234,17 +180,10 @@
                             active_render, SaturatedCapture());
 
   // Analyze the quality of the filter.
-  if (use_legacy_filter_quality_) {
-    legacy_filter_quality_state_.Update(
-        SaturatedEcho(), active_render, SaturatedCapture(), TransparentMode(),
-        external_delay, subtractor_output_analyzer_.ConvergedFilter(),
-        subtractor_output_analyzer_.DivergedFilter());
-  } else {
-    filter_quality_state_.Update(active_render, TransparentMode(),
-                                 SaturatedCapture(),
-                                 filter_analyzer_.Consistent(), external_delay,
-                                 subtractor_output_analyzer_.ConvergedFilter());
-  }
+  filter_quality_state_.Update(active_render, TransparentMode(),
+                               SaturatedCapture(),
+                               filter_analyzer_.Consistent(), external_delay,
+                               subtractor_output_analyzer_.ConvergedFilter());
 
   // Update the reverb estimate.
   const bool stationary_block =
@@ -261,13 +200,13 @@
   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_erle", Erle());
   data_dumper_->DumpRaw("aec3_usable_linear_estimate", UsableLinearEstimate());
   data_dumper_->DumpRaw("aec3_transparent_mode", TransparentMode());
   data_dumper_->DumpRaw("aec3_filter_delay", filter_analyzer_.DelayBlocks());
 
   data_dumper_->DumpRaw("aec3_consistent_filter",
                         filter_analyzer_.Consistent());
-  data_dumper_->DumpRaw("aec3_suppression_gain_limit", SuppressionGainLimit());
   data_dumper_->DumpRaw("aec3_initial_state",
                         initial_state_.InitialStateActive());
   data_dumper_->DumpRaw("aec3_capture_saturation", SaturatedCapture());
@@ -279,8 +218,6 @@
 
   data_dumper_->DumpRaw("aec3_external_delay_avaliable",
                         external_delay ? 1 : 0);
-  data_dumper_->DumpRaw("aec3_suppresion_gain_limiter_running",
-                        IsSuppressionGainLimitActive());
   data_dumper_->DumpRaw("aec3_filter_tail_freq_resp_est",
                         GetReverbFrequencyResponse());
 }
@@ -314,7 +251,7 @@
 }
 
 AecState::FilterDelay::FilterDelay(const EchoCanceller3Config& config)
-    : delay_headroom_blocks_(config.delay.delay_headroom_blocks) {}
+    : delay_headroom_samples_(config.delay.delay_headroom_samples) {}
 
 void AecState::FilterDelay::Update(
     const FilterAnalyzer& filter_analyzer,
@@ -332,7 +269,7 @@
   const bool delay_estimator_may_not_have_converged =
       blocks_with_proper_filter_adaptation < 2 * kNumBlocksPerSecond;
   if (delay_estimator_may_not_have_converged && external_delay_) {
-    filter_delay_blocks_ = delay_headroom_blocks_;
+    filter_delay_blocks_ = delay_headroom_samples_ / kBlockSize;
   } else {
     filter_delay_blocks_ = filter_analyzer.DelayBlocks();
   }
diff --git a/modules/audio_processing/aec3/aec_state.h b/modules/audio_processing/aec3/aec_state.h
index c9d9cf3..e323b2c 100644
--- a/modules/audio_processing/aec3/aec_state.h
+++ b/modules/audio_processing/aec3/aec_state.h
@@ -31,7 +31,6 @@
 #include "modules/audio_processing/aec3/reverb_model_estimator.h"
 #include "modules/audio_processing/aec3/subtractor_output.h"
 #include "modules/audio_processing/aec3/subtractor_output_analyzer.h"
-#include "modules/audio_processing/aec3/suppression_gain_limiter.h"
 
 namespace webrtc {
 
@@ -46,17 +45,11 @@
   // Returns whether the echo subtractor can be used to determine the residual
   // echo.
   bool UsableLinearEstimate() const {
-    if (use_legacy_filter_quality_) {
-      return legacy_filter_quality_state_.LinearFilterUsable();
-    }
     return filter_quality_state_.LinearFilterUsable();
   }
 
   // Returns whether the echo subtractor output should be used as output.
   bool UseLinearFilterOutput() const {
-    if (use_legacy_filter_quality_) {
-      return legacy_filter_quality_state_.LinearFilterUsable();
-    }
     return filter_quality_state_.LinearFilterUsable();
   }
 
@@ -105,11 +98,7 @@
   bool SaturatedCapture() const { return capture_signal_saturation_; }
 
   // Returns whether the echo signal is saturated.
-  bool SaturatedEcho() const {
-    return use_legacy_saturation_behavior_
-               ? legacy_saturation_detector_.SaturatedEcho()
-               : saturation_detector_.SaturatedEcho();
-  }
+  bool SaturatedEcho() const { return saturation_detector_.SaturatedEcho(); }
 
   // Updates the capture signal saturation.
   void UpdateCaptureSaturation(bool capture_signal_saturation) {
@@ -130,20 +119,6 @@
     return reverb_model_estimator_.GetReverbFrequencyResponse();
   }
 
-  // Returns the upper limit for the echo suppression gain.
-  float SuppressionGainLimit() const {
-    if (use_suppressor_gain_limiter_) {
-      return suppression_gain_limiter_.Limit();
-    } else {
-      return 1.f;
-    }
-  }
-
-  // Returns whether the suppression gain limiter is active.
-  bool IsSuppressionGainLimitActive() const {
-    return suppression_gain_limiter_.IsActive();
-  }
-
   // Returns whether the transition for going out of the initial stated has
   // been triggered.
   bool TransitionTriggered() const {
@@ -170,11 +145,6 @@
   static int instance_count_;
   std::unique_ptr<ApmDataDumper> data_dumper_;
   const EchoCanceller3Config config_;
-  const bool use_legacy_saturation_behavior_;
-  const bool enable_erle_resets_at_gain_changes_;
-  const bool enable_erle_updates_during_reverb_;
-  const bool use_legacy_filter_quality_;
-  const bool use_suppressor_gain_limiter_;
 
   // Class for controlling the transition from the intial state, which in turn
   // controls when the filter parameters for the initial state should be used.
@@ -222,7 +192,7 @@
                 size_t blocks_with_proper_filter_adaptation);
 
    private:
-    const int delay_headroom_blocks_;
+    const int delay_headroom_samples_;
     bool external_delay_reported_ = false;
     int filter_delay_blocks_ = 0;
     absl::optional<DelayEstimate> external_delay_;
@@ -336,7 +306,7 @@
   class SaturationDetector {
    public:
     // Returns whether the echo is to be considered saturated.
-    bool SaturatedEcho() const { return saturated_echo_; };
+    bool SaturatedEcho() const { return saturated_echo_; }
 
     // Updates the detection decision based on new data.
     void Update(rtc::ArrayView<const float> x,
@@ -357,7 +327,7 @@
     explicit LegacySaturationDetector(const EchoCanceller3Config& config);
 
     // Returns whether the echo is to be considered saturated.
-    bool SaturatedEcho() const { return saturated_echo_; };
+    bool SaturatedEcho() const { return saturated_echo_; }
 
     // Resets the state of the detector.
     void Reset();
@@ -378,8 +348,6 @@
   size_t strong_not_saturated_render_blocks_ = 0;
   size_t blocks_with_active_render_ = 0;
   bool capture_signal_saturation_ = false;
-
-  SuppressionGainUpperLimiter suppression_gain_limiter_;
   FilterAnalyzer filter_analyzer_;
   absl::optional<DelayEstimate> external_delay_;
   EchoAudibility echo_audibility_;
diff --git a/modules/audio_processing/aec3/aec_state_unittest.cc b/modules/audio_processing/aec3/aec_state_unittest.cc
index a331006..314d05f 100644
--- a/modules/audio_processing/aec3/aec_state_unittest.cc
+++ b/modules/audio_processing/aec3/aec_state_unittest.cc
@@ -25,7 +25,7 @@
   absl::optional<DelayEstimate> delay_estimate =
       DelayEstimate(DelayEstimate::Quality::kRefined, 10);
   std::unique_ptr<RenderDelayBuffer> render_delay_buffer(
-      RenderDelayBuffer::Create2(config, 3));
+      RenderDelayBuffer::Create(config, 3));
   std::array<float, kFftLengthBy2Plus1> E2_main = {};
   std::array<float, kFftLengthBy2Plus1> Y2 = {};
   std::vector<std::vector<float>> x(3, std::vector<float>(kBlockSize, 0.f));
@@ -179,7 +179,7 @@
   EchoCanceller3Config config;
   AecState state(config);
   std::unique_ptr<RenderDelayBuffer> render_delay_buffer(
-      RenderDelayBuffer::Create2(config, 3));
+      RenderDelayBuffer::Create(config, 3));
   absl::optional<DelayEstimate> delay_estimate;
   std::array<float, kFftLengthBy2Plus1> E2_main;
   std::array<float, kFftLengthBy2Plus1> Y2;
diff --git a/modules/audio_processing/aec3/block_framer.h b/modules/audio_processing/aec3/block_framer.h
index 923e4cf..fae4b29 100644
--- a/modules/audio_processing/aec3/block_framer.h
+++ b/modules/audio_processing/aec3/block_framer.h
@@ -15,7 +15,7 @@
 
 #include "api/array_view.h"
 #include "modules/audio_processing/aec3/aec3_common.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
diff --git a/modules/audio_processing/aec3/block_processor.cc b/modules/audio_processing/aec3/block_processor.cc
index ef25e7c..b08be68 100644
--- a/modules/audio_processing/aec3/block_processor.cc
+++ b/modules/audio_processing/aec3/block_processor.cc
@@ -1,5 +1,5 @@
 /*
- *  Copyright (c) 2016 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
@@ -7,19 +7,25 @@
  *  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_processor.h"
-
+#include <stddef.h>
+#include <memory>
 #include <utility>
+#include <vector>
 
 #include "absl/types/optional.h"
+#include "api/audio/echo_canceller3_config.h"
+#include "api/audio/echo_control.h"
 #include "modules/audio_processing/aec3/aec3_common.h"
+#include "modules/audio_processing/aec3/block_processor.h"
 #include "modules/audio_processing/aec3/block_processor_metrics.h"
 #include "modules/audio_processing/aec3/delay_estimate.h"
 #include "modules/audio_processing/aec3/echo_path_variability.h"
+#include "modules/audio_processing/aec3/echo_remover.h"
+#include "modules/audio_processing/aec3/render_delay_buffer.h"
+#include "modules/audio_processing/aec3/render_delay_controller.h"
 #include "modules/audio_processing/logging/apm_data_dumper.h"
-#include "rtc_base/atomicops.h"
+#include "rtc_base/atomic_ops.h"
 #include "rtc_base/checks.h"
-#include "rtc_base/constructormagic.h"
 #include "rtc_base/logging.h"
 
 namespace webrtc {
@@ -35,6 +41,8 @@
                      std::unique_ptr<RenderDelayController> delay_controller,
                      std::unique_ptr<EchoRemover> echo_remover);
 
+  BlockProcessorImpl() = delete;
+
   ~BlockProcessorImpl() override;
 
   void ProcessCapture(bool echo_path_gain_change,
@@ -64,7 +72,6 @@
   size_t capture_call_counter_ = 0;
   absl::optional<DelayEstimate> estimated_delay_;
   absl::optional<int> echo_remover_delay_;
-  RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(BlockProcessorImpl);
 };
 
 int BlockProcessorImpl::instance_count_ = 0;
@@ -127,35 +134,16 @@
     RTC_LOG(LS_WARNING) << "Reset due to render buffer overrun at block  "
                         << capture_call_counter_;
   }
+  render_event_ = RenderDelayBuffer::BufferingEvent::kNone;
 
   // Update the render buffers with any newly arrived render blocks and prepare
   // the render buffers for reading the render data corresponding to the current
   // capture block.
-  render_event_ = render_buffer_->PrepareCaptureProcessing();
-  RTC_DCHECK(RenderDelayBuffer::BufferingEvent::kRenderOverrun !=
-             render_event_);
-  if (render_event_ == RenderDelayBuffer::BufferingEvent::kRenderUnderrun) {
-    if (estimated_delay_ &&
-        estimated_delay_->quality == DelayEstimate::Quality::kRefined) {
-      echo_path_variability.delay_change =
-          EchoPathVariability::DelayAdjustment::kDelayReset;
-      delay_controller_->Reset(true);
-      capture_properly_started_ = false;
-      render_properly_started_ = false;
-
-      RTC_LOG(LS_WARNING) << "Reset due to render buffer underrun at block "
-                          << capture_call_counter_;
-    }
-  } else if (render_event_ == RenderDelayBuffer::BufferingEvent::kApiCallSkew) {
-    // There have been too many render calls in a row. Reset to avoid noncausal
-    // echo.
-    echo_path_variability.delay_change =
-        EchoPathVariability::DelayAdjustment::kDelayReset;
-    delay_controller_->Reset(true);
-    capture_properly_started_ = false;
-    render_properly_started_ = false;
-    RTC_LOG(LS_WARNING) << "Reset due to render buffer api skew at block "
-                        << capture_call_counter_;
+  RenderDelayBuffer::BufferingEvent buffer_event =
+      render_buffer_->PrepareCaptureProcessing();
+  // Reset the delay controller at render buffer underrun.
+  if (buffer_event == RenderDelayBuffer::BufferingEvent::kRenderUnderrun) {
+    delay_controller_->Reset(false);
   }
 
   data_dumper_->DumpWav("aec3_processblock_capture_input2", kBlockSize,
@@ -169,28 +157,12 @@
       echo_remover_delay_, (*capture_block)[0]);
 
   if (estimated_delay_) {
-    if (render_buffer_->CausalDelay(estimated_delay_->delay)) {
-      bool delay_change = render_buffer_->SetDelay(estimated_delay_->delay);
-      if (delay_change) {
-        RTC_LOG(LS_WARNING) << "Delay changed to " << estimated_delay_->delay
-                            << " at block " << capture_call_counter_;
-        echo_path_variability.delay_change =
-            EchoPathVariability::DelayAdjustment::kNewDetectedDelay;
-      }
-    } else {
-      // A noncausal delay has been detected. This can only happen if there is
-      // clockdrift, an audio pipeline issue has occurred, an unreliable delay
-      // estimate is used or the specified minimum delay is too short.
-      if (estimated_delay_->quality == DelayEstimate::Quality::kRefined) {
-        echo_path_variability.delay_change =
-            EchoPathVariability::DelayAdjustment::kDelayReset;
-        delay_controller_->Reset(true);
-        render_buffer_->Reset();
-        capture_properly_started_ = false;
-        render_properly_started_ = false;
-        RTC_LOG(LS_WARNING) << "Reset due to noncausal delay at block "
-                            << capture_call_counter_;
-      }
+    bool delay_change = render_buffer_->SetDelay(estimated_delay_->delay);
+    if (delay_change) {
+      RTC_LOG(LS_WARNING) << "Delay changed to " << estimated_delay_->delay
+                          << " at block " << capture_call_counter_;
+      echo_path_variability.delay_change =
+          EchoPathVariability::DelayAdjustment::kNewDetectedDelay;
     }
   }
 
@@ -207,8 +179,6 @@
 
   // Update the metrics.
   metrics_.UpdateCapture(false);
-
-  render_event_ = RenderDelayBuffer::BufferingEvent::kNone;
 }
 
 void BlockProcessorImpl::BufferRender(
@@ -253,9 +223,7 @@
   std::unique_ptr<RenderDelayBuffer> render_buffer(
       RenderDelayBuffer::Create(config, NumBandsForRate(sample_rate_hz)));
   std::unique_ptr<RenderDelayController> delay_controller(
-      RenderDelayController::Create(
-          config, RenderDelayBuffer::DelayEstimatorOffset(config),
-          sample_rate_hz));
+      RenderDelayController::Create(config, sample_rate_hz));
   std::unique_ptr<EchoRemover> echo_remover(
       EchoRemover::Create(config, sample_rate_hz));
   return Create(config, sample_rate_hz, std::move(render_buffer),
@@ -267,9 +235,7 @@
     int sample_rate_hz,
     std::unique_ptr<RenderDelayBuffer> render_buffer) {
   std::unique_ptr<RenderDelayController> delay_controller(
-      RenderDelayController::Create(
-          config, RenderDelayBuffer::DelayEstimatorOffset(config),
-          sample_rate_hz));
+      RenderDelayController::Create(config, sample_rate_hz));
   std::unique_ptr<EchoRemover> echo_remover(
       EchoRemover::Create(config, sample_rate_hz));
   return Create(config, sample_rate_hz, std::move(render_buffer),
diff --git a/modules/audio_processing/aec3/block_processor.h b/modules/audio_processing/aec3/block_processor.h
index 5f7ec7c..bcee3b7 100644
--- a/modules/audio_processing/aec3/block_processor.h
+++ b/modules/audio_processing/aec3/block_processor.h
@@ -26,33 +26,19 @@
 // Class for performing echo cancellation on 64 sample blocks of audio data.
 class BlockProcessor {
  public:
-  // Create a block processor with the legacy render buffering.
   static BlockProcessor* Create(const EchoCanceller3Config& config,
                                 int sample_rate_hz);
-  // Create a block processor with the new render buffering.
-  static BlockProcessor* Create2(const EchoCanceller3Config& config,
-                                 int sample_rate_hz);
   // Only used for testing purposes.
   static BlockProcessor* Create(
       const EchoCanceller3Config& config,
       int sample_rate_hz,
       std::unique_ptr<RenderDelayBuffer> render_buffer);
-  static BlockProcessor* Create2(
-      const EchoCanceller3Config& config,
-      int sample_rate_hz,
-      std::unique_ptr<RenderDelayBuffer> render_buffer);
   static BlockProcessor* Create(
       const EchoCanceller3Config& config,
       int sample_rate_hz,
       std::unique_ptr<RenderDelayBuffer> render_buffer,
       std::unique_ptr<RenderDelayController> delay_controller,
       std::unique_ptr<EchoRemover> echo_remover);
-  static BlockProcessor* Create2(
-      const EchoCanceller3Config& config,
-      int sample_rate_hz,
-      std::unique_ptr<RenderDelayBuffer> render_buffer,
-      std::unique_ptr<RenderDelayController> delay_controller,
-      std::unique_ptr<EchoRemover> echo_remover);
 
   virtual ~BlockProcessor() = default;
 
diff --git a/modules/audio_processing/aec3/block_processor2.cc b/modules/audio_processing/aec3/block_processor2.cc
deleted file mode 100644
index 30bd3ee..0000000
--- a/modules/audio_processing/aec3/block_processor2.cc
+++ /dev/null
@@ -1,256 +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 <stddef.h>
-#include <memory>
-#include <utility>
-#include <vector>
-
-#include "absl/types/optional.h"
-#include "api/audio/echo_canceller3_config.h"
-#include "api/audio/echo_control.h"
-#include "modules/audio_processing/aec3/aec3_common.h"
-#include "modules/audio_processing/aec3/block_processor.h"
-#include "modules/audio_processing/aec3/block_processor_metrics.h"
-#include "modules/audio_processing/aec3/delay_estimate.h"
-#include "modules/audio_processing/aec3/echo_path_variability.h"
-#include "modules/audio_processing/aec3/echo_remover.h"
-#include "modules/audio_processing/aec3/render_delay_buffer.h"
-#include "modules/audio_processing/aec3/render_delay_controller.h"
-#include "modules/audio_processing/logging/apm_data_dumper.h"
-#include "rtc_base/atomicops.h"
-#include "rtc_base/checks.h"
-#include "rtc_base/logging.h"
-
-namespace webrtc {
-namespace {
-
-enum class BlockProcessorApiCall { kCapture, kRender };
-
-class BlockProcessorImpl2 final : public BlockProcessor {
- public:
-  BlockProcessorImpl2(const EchoCanceller3Config& config,
-                      int sample_rate_hz,
-                      std::unique_ptr<RenderDelayBuffer> render_buffer,
-                      std::unique_ptr<RenderDelayController> delay_controller,
-                      std::unique_ptr<EchoRemover> echo_remover);
-
-  BlockProcessorImpl2() = delete;
-
-  ~BlockProcessorImpl2() override;
-
-  void ProcessCapture(bool echo_path_gain_change,
-                      bool capture_signal_saturation,
-                      std::vector<std::vector<float>>* capture_block) override;
-
-  void BufferRender(const std::vector<std::vector<float>>& block) override;
-
-  void UpdateEchoLeakageStatus(bool leakage_detected) override;
-
-  void GetMetrics(EchoControl::Metrics* metrics) const override;
-
-  void SetAudioBufferDelay(size_t delay_ms) override;
-
- private:
-  static int instance_count_;
-  std::unique_ptr<ApmDataDumper> data_dumper_;
-  const EchoCanceller3Config config_;
-  bool capture_properly_started_ = false;
-  bool render_properly_started_ = false;
-  const size_t sample_rate_hz_;
-  std::unique_ptr<RenderDelayBuffer> render_buffer_;
-  std::unique_ptr<RenderDelayController> delay_controller_;
-  std::unique_ptr<EchoRemover> echo_remover_;
-  BlockProcessorMetrics metrics_;
-  RenderDelayBuffer::BufferingEvent render_event_;
-  size_t capture_call_counter_ = 0;
-  absl::optional<DelayEstimate> estimated_delay_;
-  absl::optional<int> echo_remover_delay_;
-};
-
-int BlockProcessorImpl2::instance_count_ = 0;
-
-BlockProcessorImpl2::BlockProcessorImpl2(
-    const EchoCanceller3Config& config,
-    int sample_rate_hz,
-    std::unique_ptr<RenderDelayBuffer> render_buffer,
-    std::unique_ptr<RenderDelayController> delay_controller,
-    std::unique_ptr<EchoRemover> echo_remover)
-    : data_dumper_(
-          new ApmDataDumper(rtc::AtomicOps::Increment(&instance_count_))),
-      config_(config),
-      sample_rate_hz_(sample_rate_hz),
-      render_buffer_(std::move(render_buffer)),
-      delay_controller_(std::move(delay_controller)),
-      echo_remover_(std::move(echo_remover)),
-      render_event_(RenderDelayBuffer::BufferingEvent::kNone) {
-  RTC_DCHECK(ValidFullBandRate(sample_rate_hz_));
-}
-
-BlockProcessorImpl2::~BlockProcessorImpl2() = default;
-
-void BlockProcessorImpl2::ProcessCapture(
-    bool echo_path_gain_change,
-    bool capture_signal_saturation,
-    std::vector<std::vector<float>>* capture_block) {
-  RTC_DCHECK(capture_block);
-  RTC_DCHECK_EQ(NumBandsForRate(sample_rate_hz_), capture_block->size());
-  RTC_DCHECK_EQ(kBlockSize, (*capture_block)[0].size());
-
-  capture_call_counter_++;
-
-  data_dumper_->DumpRaw("aec3_processblock_call_order",
-                        static_cast<int>(BlockProcessorApiCall::kCapture));
-  data_dumper_->DumpWav("aec3_processblock_capture_input", kBlockSize,
-                        &(*capture_block)[0][0],
-                        LowestBandRate(sample_rate_hz_), 1);
-
-  if (render_properly_started_) {
-    if (!capture_properly_started_) {
-      capture_properly_started_ = true;
-      render_buffer_->Reset();
-      delay_controller_->Reset(true);
-    }
-  } else {
-    // If no render data has yet arrived, do not process the capture signal.
-    return;
-  }
-
-  EchoPathVariability echo_path_variability(
-      echo_path_gain_change, EchoPathVariability::DelayAdjustment::kNone,
-      false);
-
-  if (render_event_ == RenderDelayBuffer::BufferingEvent::kRenderOverrun &&
-      render_properly_started_) {
-    echo_path_variability.delay_change =
-        EchoPathVariability::DelayAdjustment::kBufferFlush;
-    delay_controller_->Reset(true);
-    RTC_LOG(LS_WARNING) << "Reset due to render buffer overrun at block  "
-                        << capture_call_counter_;
-  }
-  render_event_ = RenderDelayBuffer::BufferingEvent::kNone;
-
-  // Update the render buffers with any newly arrived render blocks and prepare
-  // the render buffers for reading the render data corresponding to the current
-  // capture block.
-  RenderDelayBuffer::BufferingEvent buffer_event =
-      render_buffer_->PrepareCaptureProcessing();
-  // Reset the delay controller at render buffer underrun.
-  if (buffer_event == RenderDelayBuffer::BufferingEvent::kRenderUnderrun) {
-    delay_controller_->Reset(false);
-  }
-
-  data_dumper_->DumpWav("aec3_processblock_capture_input2", kBlockSize,
-                        &(*capture_block)[0][0],
-                        LowestBandRate(sample_rate_hz_), 1);
-
-  // Compute and and apply the render delay required to achieve proper signal
-  // alignment.
-  estimated_delay_ = delay_controller_->GetDelay(
-      render_buffer_->GetDownsampledRenderBuffer(), render_buffer_->Delay(),
-      echo_remover_delay_, (*capture_block)[0]);
-
-  if (estimated_delay_) {
-    bool delay_change = render_buffer_->SetDelay(estimated_delay_->delay);
-    if (delay_change) {
-      RTC_LOG(LS_WARNING) << "Delay changed to " << estimated_delay_->delay
-                          << " at block " << capture_call_counter_;
-      echo_path_variability.delay_change =
-          EchoPathVariability::DelayAdjustment::kNewDetectedDelay;
-    }
-  }
-
-  echo_path_variability.clock_drift = delay_controller_->HasClockdrift();
-
-  // Remove the echo from the capture signal.
-  echo_remover_->ProcessCapture(
-      echo_path_variability, capture_signal_saturation, estimated_delay_,
-      render_buffer_->GetRenderBuffer(), capture_block);
-
-  // Check to see if a refined delay estimate has been obtained from the echo
-  // remover.
-  echo_remover_delay_ = echo_remover_->Delay();
-
-  // Update the metrics.
-  metrics_.UpdateCapture(false);
-}
-
-void BlockProcessorImpl2::BufferRender(
-    const std::vector<std::vector<float>>& block) {
-  RTC_DCHECK_EQ(NumBandsForRate(sample_rate_hz_), block.size());
-  RTC_DCHECK_EQ(kBlockSize, block[0].size());
-  data_dumper_->DumpRaw("aec3_processblock_call_order",
-                        static_cast<int>(BlockProcessorApiCall::kRender));
-  data_dumper_->DumpWav("aec3_processblock_render_input", kBlockSize,
-                        &block[0][0], LowestBandRate(sample_rate_hz_), 1);
-  data_dumper_->DumpWav("aec3_processblock_render_input2", kBlockSize,
-                        &block[0][0], LowestBandRate(sample_rate_hz_), 1);
-
-  render_event_ = render_buffer_->Insert(block);
-
-  metrics_.UpdateRender(render_event_ !=
-                        RenderDelayBuffer::BufferingEvent::kNone);
-
-  render_properly_started_ = true;
-  delay_controller_->LogRenderCall();
-}
-
-void BlockProcessorImpl2::UpdateEchoLeakageStatus(bool leakage_detected) {
-  echo_remover_->UpdateEchoLeakageStatus(leakage_detected);
-}
-
-void BlockProcessorImpl2::GetMetrics(EchoControl::Metrics* metrics) const {
-  echo_remover_->GetMetrics(metrics);
-  const int block_size_ms = sample_rate_hz_ == 8000 ? 8 : 4;
-  absl::optional<size_t> delay = render_buffer_->Delay();
-  metrics->delay_ms = delay ? static_cast<int>(*delay) * block_size_ms : 0;
-}
-
-void BlockProcessorImpl2::SetAudioBufferDelay(size_t delay_ms) {
-  render_buffer_->SetAudioBufferDelay(delay_ms);
-}
-
-}  // namespace
-
-BlockProcessor* BlockProcessor::Create2(const EchoCanceller3Config& config,
-                                        int sample_rate_hz) {
-  std::unique_ptr<RenderDelayBuffer> render_buffer(
-      RenderDelayBuffer::Create2(config, NumBandsForRate(sample_rate_hz)));
-  std::unique_ptr<RenderDelayController> delay_controller(
-      RenderDelayController::Create2(config, sample_rate_hz));
-  std::unique_ptr<EchoRemover> echo_remover(
-      EchoRemover::Create(config, sample_rate_hz));
-  return Create2(config, sample_rate_hz, std::move(render_buffer),
-                 std::move(delay_controller), std::move(echo_remover));
-}
-
-BlockProcessor* BlockProcessor::Create2(
-    const EchoCanceller3Config& config,
-    int sample_rate_hz,
-    std::unique_ptr<RenderDelayBuffer> render_buffer) {
-  std::unique_ptr<RenderDelayController> delay_controller(
-      RenderDelayController::Create2(config, sample_rate_hz));
-  std::unique_ptr<EchoRemover> echo_remover(
-      EchoRemover::Create(config, sample_rate_hz));
-  return Create2(config, sample_rate_hz, std::move(render_buffer),
-                 std::move(delay_controller), std::move(echo_remover));
-}
-
-BlockProcessor* BlockProcessor::Create2(
-    const EchoCanceller3Config& config,
-    int sample_rate_hz,
-    std::unique_ptr<RenderDelayBuffer> render_buffer,
-    std::unique_ptr<RenderDelayController> delay_controller,
-    std::unique_ptr<EchoRemover> echo_remover) {
-  return new BlockProcessorImpl2(
-      config, sample_rate_hz, std::move(render_buffer),
-      std::move(delay_controller), std::move(echo_remover));
-}
-
-}  // namespace webrtc
diff --git a/modules/audio_processing/aec3/block_processor_metrics.h b/modules/audio_processing/aec3/block_processor_metrics.h
index 9b437c0..4ba0536 100644
--- a/modules/audio_processing/aec3/block_processor_metrics.h
+++ b/modules/audio_processing/aec3/block_processor_metrics.h
@@ -11,7 +11,7 @@
 #ifndef MODULES_AUDIO_PROCESSING_AEC3_BLOCK_PROCESSOR_METRICS_H_
 #define MODULES_AUDIO_PROCESSING_AEC3_BLOCK_PROCESSOR_METRICS_H_
 
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
diff --git a/modules/audio_processing/aec3/block_processor_unittest.cc b/modules/audio_processing/aec3/block_processor_unittest.cc
index 8aba5b5..7145786 100644
--- a/modules/audio_processing/aec3/block_processor_unittest.cc
+++ b/modules/audio_processing/aec3/block_processor_unittest.cc
@@ -37,7 +37,7 @@
 // methods are callable.
 void RunBasicSetupAndApiCallTest(int sample_rate_hz, int num_iterations) {
   std::unique_ptr<BlockProcessor> block_processor(
-      BlockProcessor::Create2(EchoCanceller3Config(), sample_rate_hz));
+      BlockProcessor::Create(EchoCanceller3Config(), sample_rate_hz));
   std::vector<std::vector<float>> block(NumBandsForRate(sample_rate_hz),
                                         std::vector<float>(kBlockSize, 1000.f));
 
@@ -51,7 +51,7 @@
 #if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
 void RunRenderBlockSizeVerificationTest(int sample_rate_hz) {
   std::unique_ptr<BlockProcessor> block_processor(
-      BlockProcessor::Create2(EchoCanceller3Config(), sample_rate_hz));
+      BlockProcessor::Create(EchoCanceller3Config(), sample_rate_hz));
   std::vector<std::vector<float>> block(
       NumBandsForRate(sample_rate_hz), std::vector<float>(kBlockSize - 1, 0.f));
 
@@ -60,7 +60,7 @@
 
 void RunCaptureBlockSizeVerificationTest(int sample_rate_hz) {
   std::unique_ptr<BlockProcessor> block_processor(
-      BlockProcessor::Create2(EchoCanceller3Config(), sample_rate_hz));
+      BlockProcessor::Create(EchoCanceller3Config(), sample_rate_hz));
   std::vector<std::vector<float>> block(
       NumBandsForRate(sample_rate_hz), std::vector<float>(kBlockSize - 1, 0.f));
 
@@ -72,7 +72,7 @@
                                      ? NumBandsForRate(sample_rate_hz) + 1
                                      : 1;
   std::unique_ptr<BlockProcessor> block_processor(
-      BlockProcessor::Create2(EchoCanceller3Config(), sample_rate_hz));
+      BlockProcessor::Create(EchoCanceller3Config(), sample_rate_hz));
   std::vector<std::vector<float>> block(wrong_num_bands,
                                         std::vector<float>(kBlockSize, 0.f));
 
@@ -84,7 +84,7 @@
                                      ? NumBandsForRate(sample_rate_hz) + 1
                                      : 1;
   std::unique_ptr<BlockProcessor> block_processor(
-      BlockProcessor::Create2(EchoCanceller3Config(), sample_rate_hz));
+      BlockProcessor::Create(EchoCanceller3Config(), sample_rate_hz));
   std::vector<std::vector<float>> block(wrong_num_bands,
                                         std::vector<float>(kBlockSize, 0.f));
 
@@ -124,7 +124,7 @@
     EXPECT_CALL(*render_delay_buffer_mock, Delay())
         .Times(kNumBlocks + 1)
         .WillRepeatedly(Return(0));
-    std::unique_ptr<BlockProcessor> block_processor(BlockProcessor::Create2(
+    std::unique_ptr<BlockProcessor> block_processor(BlockProcessor::Create(
         EchoCanceller3Config(), rate, std::move(render_delay_buffer_mock)));
 
     std::vector<std::vector<float>> render_block(
@@ -173,7 +173,7 @@
     EXPECT_CALL(*echo_remover_mock, UpdateEchoLeakageStatus(_))
         .Times(kNumBlocks);
 
-    std::unique_ptr<BlockProcessor> block_processor(BlockProcessor::Create2(
+    std::unique_ptr<BlockProcessor> block_processor(BlockProcessor::Create(
         EchoCanceller3Config(), rate, std::move(render_delay_buffer_mock),
         std::move(render_delay_controller_mock), std::move(echo_remover_mock)));
 
@@ -239,7 +239,7 @@
 // Verifiers that the verification for null ProcessCapture input works.
 TEST(BlockProcessor, NullProcessCaptureParameter) {
   EXPECT_DEATH(std::unique_ptr<BlockProcessor>(
-                   BlockProcessor::Create2(EchoCanceller3Config(), 8000))
+                   BlockProcessor::Create(EchoCanceller3Config(), 8000))
                    ->ProcessCapture(false, false, nullptr),
                "");
 }
@@ -249,7 +249,7 @@
 // tests on test bots has been fixed.
 TEST(BlockProcessor, DISABLED_WrongSampleRate) {
   EXPECT_DEATH(std::unique_ptr<BlockProcessor>(
-                   BlockProcessor::Create2(EchoCanceller3Config(), 8001)),
+                   BlockProcessor::Create(EchoCanceller3Config(), 8001)),
                "");
 }
 
diff --git a/modules/audio_processing/aec3/cascaded_biquad_filter.h b/modules/audio_processing/aec3/cascaded_biquad_filter.h
index 2a3b6d6..3d9b14b 100644
--- a/modules/audio_processing/aec3/cascaded_biquad_filter.h
+++ b/modules/audio_processing/aec3/cascaded_biquad_filter.h
@@ -16,7 +16,7 @@
 #include <vector>
 
 #include "api/array_view.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
diff --git a/modules/audio_processing/aec3/comfort_noise_generator.cc b/modules/audio_processing/aec3/comfort_noise_generator.cc
index 766e658..1e3cdf2 100644
--- a/modules/audio_processing/aec3/comfort_noise_generator.cc
+++ b/modules/audio_processing/aec3/comfort_noise_generator.cc
@@ -31,17 +31,15 @@
 
 namespace {
 
-// Creates an array of uniformly distributed variables.
-void TableRandomValue(int16_t* vector, int16_t vector_length, uint32_t* seed) {
-  for (int i = 0; i < vector_length; i++) {
-    seed[0] = (seed[0] * ((int32_t)69069) + 1) & (0x80000000 - 1);
-    vector[i] = (int16_t)(seed[0] >> 16);
-  }
-}
-
-}  // namespace
-
-namespace {
+// Table of sqrt(2) * sin(2*pi*i/32).
+constexpr float kSqrt2Sin[32] = {
+    +0.0000000f, +0.2758994f, +0.5411961f, +0.7856950f, +1.0000000f,
+    +1.1758756f, +1.3065630f, +1.3870398f, +1.4142136f, +1.3870398f,
+    +1.3065630f, +1.1758756f, +1.0000000f, +0.7856950f, +0.5411961f,
+    +0.2758994f, +0.0000000f, -0.2758994f, -0.5411961f, -0.7856950f,
+    -1.0000000f, -1.1758756f, -1.3065630f, -1.3870398f, -1.4142136f,
+    -1.3870398f, -1.3065630f, -1.1758756f, -1.0000000f, -0.7856950f,
+    -0.5411961f, -0.2758994f};
 
 void GenerateComfortNoise(Aec3Optimization optimization,
                           const std::array<float, kFftLengthBy2Plus1>& N2,
@@ -63,39 +61,33 @@
       std::accumulate(N.begin() + kFftLengthBy2Plus1By2, N.end(), 0.f) *
       kOneByNumBands;
 
-  // Generate complex noise.
-  std::array<int16_t, kFftLengthBy2 - 1> random_values_int;
-  TableRandomValue(random_values_int.data(), random_values_int.size(), seed);
-
   // The analysis and synthesis windowing cause loss of power when
   // cross-fading the noise where frames are completely uncorrelated
   // (generated with random phase), hence the factor sqrt(2).
   // This is not the case for the speech signal where the input is overlapping
   // (strong correlation).
-  std::array<float, kFftLengthBy2 - 1> sin;
-  std::array<float, kFftLengthBy2 - 1> cos;
-  constexpr float kScale = 6.28318530717959f / 32768.0f;
-  constexpr float kSqrt2 = 1.4142135623f;
-  std::transform(random_values_int.begin(), random_values_int.end(),
-                 sin.begin(),
-                 [&](int16_t a) { return -sinf(kScale * a) * kSqrt2; });
-  std::transform(random_values_int.begin(), random_values_int.end(),
-                 cos.begin(),
-                 [&](int16_t a) { return cosf(kScale * a) * kSqrt2; });
-
-  // Form low-frequency noise via spectral shaping.
   N_low->re[0] = N_low->re[kFftLengthBy2] = N_high->re[0] =
       N_high->re[kFftLengthBy2] = 0.f;
-  std::transform(cos.begin(), cos.end(), N.begin() + 1, N_low->re.begin() + 1,
-                 std::multiplies<float>());
-  std::transform(sin.begin(), sin.end(), N.begin() + 1, N_low->im.begin() + 1,
-                 std::multiplies<float>());
+  for (size_t k = 1; k < kFftLengthBy2; k++) {
+    constexpr int kIndexMask = 32 - 1;
+    // Generate a random 31-bit integer.
+    seed[0] = (seed[0] * 69069 + 1) & (0x80000000 - 1);
+    // Convert to a 5-bit index.
+    int i = seed[0] >> 26;
 
-  // Form the high-frequency noise via simple levelling.
-  std::transform(cos.begin(), cos.end(), N_high->re.begin() + 1,
-                 [&](float a) { return high_band_noise_level * a; });
-  std::transform(sin.begin(), sin.end(), N_high->im.begin() + 1,
-                 [&](float a) { return high_band_noise_level * a; });
+    // y = sqrt(2) * sin(a)
+    const float x = kSqrt2Sin[i];
+    // x = sqrt(2) * cos(a) = sqrt(2) * sin(a + pi/2)
+    const float y = kSqrt2Sin[(i + 8) & kIndexMask];
+
+    // Form low-frequency noise via spectral shaping.
+    N_low->re[k] = N[k] * x;
+    N_low->im[k] = N[k] * y;
+
+    // Form the high-frequency noise via simple levelling.
+    N_high->re[k] = high_band_noise_level * x;
+    N_high->im[k] = high_band_noise_level * y;
+  }
 }
 
 }  // namespace
diff --git a/modules/audio_processing/aec3/comfort_noise_generator.h b/modules/audio_processing/aec3/comfort_noise_generator.h
index 3be386b..f78fda2 100644
--- a/modules/audio_processing/aec3/comfort_noise_generator.h
+++ b/modules/audio_processing/aec3/comfort_noise_generator.h
@@ -18,7 +18,7 @@
 #include "modules/audio_processing/aec3/aec3_common.h"
 #include "modules/audio_processing/aec3/aec_state.h"
 #include "modules/audio_processing/aec3/fft_data.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 #include "rtc_base/system/arch.h"
 
 namespace webrtc {
diff --git a/modules/audio_processing/aec3/decimator.h b/modules/audio_processing/aec3/decimator.h
index 2bb60a4..a505014 100644
--- a/modules/audio_processing/aec3/decimator.h
+++ b/modules/audio_processing/aec3/decimator.h
@@ -16,7 +16,7 @@
 #include "api/array_view.h"
 #include "modules/audio_processing/aec3/aec3_common.h"
 #include "modules/audio_processing/aec3/cascaded_biquad_filter.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
diff --git a/modules/audio_processing/aec3/echo_audibility.h b/modules/audio_processing/aec3/echo_audibility.h
index b903ca0..7b85321 100644
--- a/modules/audio_processing/aec3/echo_audibility.h
+++ b/modules/audio_processing/aec3/echo_audibility.h
@@ -19,7 +19,7 @@
 #include "modules/audio_processing/aec3/render_buffer.h"
 #include "modules/audio_processing/aec3/stationarity_estimator.h"
 #include "modules/audio_processing/aec3/vector_buffer.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
diff --git a/modules/audio_processing/aec3/echo_canceller3.cc b/modules/audio_processing/aec3/echo_canceller3.cc
index f05edb1..8a4d8c2 100644
--- a/modules/audio_processing/aec3/echo_canceller3.cc
+++ b/modules/audio_processing/aec3/echo_canceller3.cc
@@ -14,7 +14,7 @@
 
 #include "modules/audio_processing/aec3/aec3_common.h"
 #include "modules/audio_processing/logging/apm_data_dumper.h"
-#include "rtc_base/atomicops.h"
+#include "rtc_base/atomic_ops.h"
 #include "system_wrappers/include/field_trial.h"
 
 namespace webrtc {
@@ -32,136 +32,13 @@
   return false;
 }
 
-bool UseShortDelayEstimatorWindow() {
-  return field_trial::IsEnabled("WebRTC-Aec3UseShortDelayEstimatorWindow");
-}
-
-bool EnableReverbBasedOnRender() {
-  return !field_trial::IsEnabled("WebRTC-Aec3ReverbBasedOnRenderKillSwitch");
-}
-
-bool EnableReverbModelling() {
-  return !field_trial::IsEnabled("WebRTC-Aec3ReverbModellingKillSwitch");
-}
-
-bool EnableUnityInitialRampupGain() {
-  return field_trial::IsEnabled("WebRTC-Aec3EnableUnityInitialRampupGain");
-}
-
-bool EnableUnityNonZeroRampupGain() {
-  return field_trial::IsEnabled("WebRTC-Aec3EnableUnityNonZeroRampupGain");
-}
-
-bool EnableLongReverb() {
-  return field_trial::IsEnabled("WebRTC-Aec3ShortReverbKillSwitch");
-}
-
-bool EnableNewFilterParams() {
-  return !field_trial::IsEnabled("WebRTC-Aec3NewFilterParamsKillSwitch");
-}
-
-bool EnableLegacyDominantNearend() {
-  return field_trial::IsEnabled("WebRTC-Aec3EnableLegacyDominantNearend");
-}
-
-bool UseLegacyNormalSuppressorTuning() {
-  return field_trial::IsEnabled("WebRTC-Aec3UseLegacyNormalSuppressorTuning");
-}
-
-bool ActivateStationarityProperties() {
-  return field_trial::IsEnabled("WebRTC-Aec3UseStationarityProperties");
-}
-
-bool ActivateStationarityPropertiesAtInit() {
-  return field_trial::IsEnabled("WebRTC-Aec3UseStationarityPropertiesAtInit");
-}
-
-bool EnableNewRenderBuffering() {
-  return !field_trial::IsEnabled("WebRTC-Aec3NewRenderBufferingKillSwitch");
-}
-
-bool UseEarlyDelayDetection() {
-  return !field_trial::IsEnabled("WebRTC-Aec3EarlyDelayDetectionKillSwitch");
-}
-
 // Method for adjusting config parameter dependencies..
 EchoCanceller3Config AdjustConfig(const EchoCanceller3Config& config) {
   EchoCanceller3Config adjusted_cfg = config;
-  const EchoCanceller3Config default_cfg;
 
-  if (!EnableReverbModelling()) {
-    adjusted_cfg.ep_strength.default_len = 0.f;
-  }
-
-  if (UseShortDelayEstimatorWindow()) {
-    adjusted_cfg.delay.num_filters =
-        std::min(adjusted_cfg.delay.num_filters, static_cast<size_t>(5));
-  }
-
-  bool use_new_render_buffering =
-      EnableNewRenderBuffering() && config.buffering.use_new_render_buffering;
-  // Old render buffering needs one more filter to cover the same delay.
-  if (!use_new_render_buffering) {
-    adjusted_cfg.delay.num_filters += 1;
-  }
-
-  if (EnableReverbBasedOnRender() == false) {
-    adjusted_cfg.ep_strength.reverb_based_on_render = false;
-  }
-
-  if (!EnableNewFilterParams()) {
-    adjusted_cfg.filter.main.leakage_diverged = 0.01f;
-    adjusted_cfg.filter.main.error_floor = 0.1f;
-    adjusted_cfg.filter.main.error_ceil = 1E10f;
-    adjusted_cfg.filter.main_initial.error_ceil = 1E10f;
-  }
-
-  if (EnableUnityInitialRampupGain() &&
-      adjusted_cfg.echo_removal_control.gain_rampup.initial_gain ==
-          default_cfg.echo_removal_control.gain_rampup.initial_gain) {
-    adjusted_cfg.echo_removal_control.gain_rampup.initial_gain = 1.f;
-  }
-
-  if (EnableUnityNonZeroRampupGain() &&
-      adjusted_cfg.echo_removal_control.gain_rampup.first_non_zero_gain ==
-          default_cfg.echo_removal_control.gain_rampup.first_non_zero_gain) {
-    adjusted_cfg.echo_removal_control.gain_rampup.first_non_zero_gain = 1.f;
-  }
-
-  if (EnableLongReverb()) {
-    adjusted_cfg.ep_strength.default_len = 0.88f;
-  }
-
-  if (EnableLegacyDominantNearend()) {
-    adjusted_cfg.suppressor.nearend_tuning =
-        EchoCanceller3Config::Suppressor::Tuning(
-            EchoCanceller3Config::Suppressor::MaskingThresholds(.2f, .3f, .3f),
-            EchoCanceller3Config::Suppressor::MaskingThresholds(.07f, .1f, .3f),
-            2.0f, 0.25f);
-  }
-
-  if (UseLegacyNormalSuppressorTuning()) {
-    adjusted_cfg.suppressor.normal_tuning =
-        EchoCanceller3Config::Suppressor::Tuning(
-            EchoCanceller3Config::Suppressor::MaskingThresholds(.2f, .3f, .3f),
-            EchoCanceller3Config::Suppressor::MaskingThresholds(.07f, .1f, .3f),
-            2.0f, 0.25f);
-
-    adjusted_cfg.suppressor.dominant_nearend_detection.enr_threshold = 10.f;
-    adjusted_cfg.suppressor.dominant_nearend_detection.snr_threshold = 10.f;
-    adjusted_cfg.suppressor.dominant_nearend_detection.hold_duration = 25;
-  }
-
-  if (ActivateStationarityProperties()) {
-    adjusted_cfg.echo_audibility.use_stationary_properties = true;
-  }
-
-  if (ActivateStationarityPropertiesAtInit()) {
-    adjusted_cfg.echo_audibility.use_stationarity_properties_at_init = true;
-  }
-
-  if (!UseEarlyDelayDetection()) {
-    adjusted_cfg.delay.delay_selection_thresholds = {25, 25};
+  if (field_trial::IsEnabled("WebRTC-Aec3ShortHeadroomKillSwitch")) {
+    // Two blocks headroom.
+    adjusted_cfg.delay.delay_headroom_samples = kBlockSize * 2;
   }
 
   return adjusted_cfg;
@@ -347,16 +224,12 @@
 EchoCanceller3::EchoCanceller3(const EchoCanceller3Config& config,
                                int sample_rate_hz,
                                bool use_highpass_filter)
-    : EchoCanceller3(AdjustConfig(config),
-                     sample_rate_hz,
-                     use_highpass_filter,
-                     std::unique_ptr<BlockProcessor>(
-                         EnableNewRenderBuffering() &&
-                                 config.buffering.use_new_render_buffering
-                             ? BlockProcessor::Create2(AdjustConfig(config),
-                                                       sample_rate_hz)
-                             : BlockProcessor::Create(AdjustConfig(config),
-                                                      sample_rate_hz))) {}
+    : EchoCanceller3(
+          AdjustConfig(config),
+          sample_rate_hz,
+          use_highpass_filter,
+          std::unique_ptr<BlockProcessor>(
+              BlockProcessor::Create(AdjustConfig(config), sample_rate_hz))) {}
 EchoCanceller3::EchoCanceller3(const EchoCanceller3Config& config,
                                int sample_rate_hz,
                                bool use_highpass_filter,
diff --git a/modules/audio_processing/aec3/echo_canceller3.h b/modules/audio_processing/aec3/echo_canceller3.h
index 671d271..c1298d2 100644
--- a/modules/audio_processing/aec3/echo_canceller3.h
+++ b/modules/audio_processing/aec3/echo_canceller3.h
@@ -27,7 +27,7 @@
 #include "modules/audio_processing/audio_buffer.h"
 #include "modules/audio_processing/logging/apm_data_dumper.h"
 #include "rtc_base/checks.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 #include "rtc_base/race_checker.h"
 #include "rtc_base/swap_queue.h"
 #include "rtc_base/thread_annotations.h"
diff --git a/modules/audio_processing/aec3/echo_canceller3_unittest.cc b/modules/audio_processing/aec3/echo_canceller3_unittest.cc
index 3f1e059..267213e 100644
--- a/modules/audio_processing/aec3/echo_canceller3_unittest.cc
+++ b/modules/audio_processing/aec3/echo_canceller3_unittest.cc
@@ -104,7 +104,7 @@
 
   void GetMetrics(EchoControl::Metrics* metrics) const override {}
 
-  void SetAudioBufferDelay(size_t delay_ms) override{};
+  void SetAudioBufferDelay(size_t delay_ms) override {}
 
  private:
   RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(CaptureTransportVerificationProcessor);
@@ -134,7 +134,7 @@
 
   void GetMetrics(EchoControl::Metrics* metrics) const override {}
 
-  void SetAudioBufferDelay(size_t delay_ms) override{};
+  void SetAudioBufferDelay(size_t delay_ms) override {}
 
  private:
   std::deque<std::vector<std::vector<float>>> received_render_blocks_;
diff --git a/modules/audio_processing/aec3/echo_path_delay_estimator.h b/modules/audio_processing/aec3/echo_path_delay_estimator.h
index 1f14735..11255a4 100644
--- a/modules/audio_processing/aec3/echo_path_delay_estimator.h
+++ b/modules/audio_processing/aec3/echo_path_delay_estimator.h
@@ -20,7 +20,7 @@
 #include "modules/audio_processing/aec3/delay_estimate.h"
 #include "modules/audio_processing/aec3/matched_filter.h"
 #include "modules/audio_processing/aec3/matched_filter_lag_aggregator.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
diff --git a/modules/audio_processing/aec3/echo_path_delay_estimator_unittest.cc b/modules/audio_processing/aec3/echo_path_delay_estimator_unittest.cc
index a4e3133..3be8260 100644
--- a/modules/audio_processing/aec3/echo_path_delay_estimator_unittest.cc
+++ b/modules/audio_processing/aec3/echo_path_delay_estimator_unittest.cc
@@ -39,7 +39,7 @@
   ApmDataDumper data_dumper(0);
   EchoCanceller3Config config;
   std::unique_ptr<RenderDelayBuffer> render_delay_buffer(
-      RenderDelayBuffer::Create2(config, 3));
+      RenderDelayBuffer::Create(config, 3));
   EchoPathDelayEstimator estimator(&data_dumper, config);
   std::vector<std::vector<float>> render(3, std::vector<float>(kBlockSize));
   std::vector<float> capture(kBlockSize);
@@ -65,7 +65,7 @@
     for (size_t delay_samples : {30, 64, 150, 200, 800, 4000}) {
       SCOPED_TRACE(ProduceDebugText(delay_samples, down_sampling_factor));
       std::unique_ptr<RenderDelayBuffer> render_delay_buffer(
-          RenderDelayBuffer::Create2(config, 3));
+          RenderDelayBuffer::Create(config, 3));
       DelayBuffer<float> signal_delay_buffer(delay_samples);
       EchoPathDelayEstimator estimator(&data_dumper, config);
 
@@ -113,7 +113,7 @@
   ApmDataDumper data_dumper(0);
   EchoPathDelayEstimator estimator(&data_dumper, config);
   std::unique_ptr<RenderDelayBuffer> render_delay_buffer(
-      RenderDelayBuffer::Create2(EchoCanceller3Config(), 3));
+      RenderDelayBuffer::Create(EchoCanceller3Config(), 3));
   for (size_t k = 0; k < 100; ++k) {
     RandomizeSampleVector(&random_generator, render[0]);
     for (auto& render_k : render[0]) {
@@ -137,7 +137,7 @@
   EchoCanceller3Config config;
   EchoPathDelayEstimator estimator(&data_dumper, config);
   std::unique_ptr<RenderDelayBuffer> render_delay_buffer(
-      RenderDelayBuffer::Create2(config, 3));
+      RenderDelayBuffer::Create(config, 3));
   std::vector<float> capture(kBlockSize);
   EXPECT_DEATH(estimator.EstimateDelay(
                    render_delay_buffer->GetDownsampledRenderBuffer(), capture),
@@ -152,7 +152,7 @@
   EchoCanceller3Config config;
   EchoPathDelayEstimator estimator(&data_dumper, config);
   std::unique_ptr<RenderDelayBuffer> render_delay_buffer(
-      RenderDelayBuffer::Create2(config, 3));
+      RenderDelayBuffer::Create(config, 3));
   std::vector<float> capture(std::vector<float>(kBlockSize - 1));
   EXPECT_DEATH(estimator.EstimateDelay(
                    render_delay_buffer->GetDownsampledRenderBuffer(), capture),
diff --git a/modules/audio_processing/aec3/echo_remover.cc b/modules/audio_processing/aec3/echo_remover.cc
index cfb7395..b010152 100644
--- a/modules/audio_processing/aec3/echo_remover.cc
+++ b/modules/audio_processing/aec3/echo_remover.cc
@@ -31,30 +31,15 @@
 #include "modules/audio_processing/aec3/suppression_filter.h"
 #include "modules/audio_processing/aec3/suppression_gain.h"
 #include "modules/audio_processing/logging/apm_data_dumper.h"
-#include "rtc_base/atomicops.h"
+#include "rtc_base/atomic_ops.h"
 #include "rtc_base/checks.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 #include "rtc_base/logging.h"
-#include "system_wrappers/include/field_trial.h"
 
 namespace webrtc {
 
 namespace {
 
-bool UseShadowFilterOutput() {
-  return !field_trial::IsEnabled(
-      "WebRTC-Aec3UtilizeShadowFilterOutputKillSwitch");
-}
-
-bool UseSmoothSignalTransitions() {
-  return !field_trial::IsEnabled(
-      "WebRTC-Aec3SmoothSignalTransitionsKillSwitch");
-}
-
-bool EnableBoundedNearend() {
-  return !field_trial::IsEnabled("WebRTC-Aec3BoundedNearendKillSwitch");
-}
-
 void LinearEchoPower(const FftData& E,
                      const FftData& Y,
                      std::array<float, kFftLengthBy2Plus1>* S2) {
@@ -127,8 +112,7 @@
   // Selects which of the shadow and main linear filter outputs that is most
   // appropriate to pass to the suppressor and forms the linear filter output by
   // smoothly transition between those.
-  void FormLinearFilterOutput(bool smooth_transition,
-                              const SubtractorOutput& subtractor_output,
+  void FormLinearFilterOutput(const SubtractorOutput& subtractor_output,
                               rtc::ArrayView<float> output);
 
   static int instance_count_;
@@ -138,8 +122,6 @@
   const Aec3Optimization optimization_;
   const int sample_rate_hz_;
   const bool use_shadow_filter_output_;
-  const bool use_smooth_signal_transitions_;
-  const bool enable_bounded_nearend_;
   Subtractor subtractor_;
   SuppressionGain suppression_gain_;
   ComfortNoiseGenerator cng_;
@@ -171,10 +153,7 @@
       optimization_(DetectOptimization()),
       sample_rate_hz_(sample_rate_hz),
       use_shadow_filter_output_(
-          UseShadowFilterOutput() &&
           config_.filter.enable_shadow_filter_output_usage),
-      use_smooth_signal_transitions_(UseSmoothSignalTransitions()),
-      enable_bounded_nearend_(EnableBoundedNearend()),
       subtractor_(config, data_dumper_.get(), optimization_),
       suppression_gain_(config_, optimization_, sample_rate_hz),
       cng_(optimization_),
@@ -275,7 +254,7 @@
   subtractor_.Process(*render_buffer, y0, render_signal_analyzer_, aec_state_,
                       &subtractor_output);
   std::array<float, kBlockSize> e;
-  FormLinearFilterOutput(use_smooth_signal_transitions_, subtractor_output, e);
+  FormLinearFilterOutput(subtractor_output, e);
 
   // Compute spectra.
   WindowedPaddedFft(fft_, y0, y_old_, &Y);
@@ -293,14 +272,13 @@
   data_dumper_->DumpWav("aec3_output_linear2", kBlockSize, &e[0],
                         LowestBandRate(sample_rate_hz_), 1);
   if (aec_state_.UseLinearFilterOutput()) {
-    if (!linear_filter_output_last_selected_ &&
-        use_smooth_signal_transitions_) {
+    if (!linear_filter_output_last_selected_) {
       SignalTransition(y0, e, y0);
     } else {
       std::copy(e.begin(), e.end(), y0.begin());
     }
   } else {
-    if (linear_filter_output_last_selected_ && use_smooth_signal_transitions_) {
+    if (linear_filter_output_last_selected_) {
       SignalTransition(e, y0, y0);
     }
   }
@@ -322,12 +300,8 @@
       aec_state_.UsableLinearEstimate() ? S2_linear : R2;
 
   std::array<float, kFftLengthBy2Plus1> E2_bounded;
-  if (enable_bounded_nearend_) {
-    std::transform(E2.begin(), E2.end(), Y2.begin(), E2_bounded.begin(),
-                   [](float a, float b) { return std::min(a, b); });
-  } else {
-    std::copy(E2.begin(), E2.end(), E2_bounded.begin());
-  }
+  std::transform(E2.begin(), E2.end(), Y2.begin(), E2_bounded.begin(),
+                 [](float a, float b) { return std::min(a, b); });
 
   suppression_gain_.GetGain(E2, E2_bounded, echo_spectrum, R2,
                             cng_.NoiseSpectrum(), E, Y, render_signal_analyzer_,
@@ -367,7 +341,6 @@
 }
 
 void EchoRemoverImpl::FormLinearFilterOutput(
-    bool smooth_transition,
     const SubtractorOutput& subtractor_output,
     rtc::ArrayView<float> output) {
   RTC_DCHECK_EQ(subtractor_output.e_main.size(), output.size());
@@ -393,7 +366,7 @@
   }
 
   if (use_main_output) {
-    if (!main_filter_output_last_selected_ && smooth_transition) {
+    if (!main_filter_output_last_selected_) {
       SignalTransition(subtractor_output.e_shadow, subtractor_output.e_main,
                        output);
     } else {
@@ -401,7 +374,7 @@
                 subtractor_output.e_main.end(), output.begin());
     }
   } else {
-    if (main_filter_output_last_selected_ && smooth_transition) {
+    if (main_filter_output_last_selected_) {
       SignalTransition(subtractor_output.e_main, subtractor_output.e_shadow,
                        output);
     } else {
diff --git a/modules/audio_processing/aec3/echo_remover_metrics.h b/modules/audio_processing/aec3/echo_remover_metrics.h
index 0707a5f..da740fb 100644
--- a/modules/audio_processing/aec3/echo_remover_metrics.h
+++ b/modules/audio_processing/aec3/echo_remover_metrics.h
@@ -15,7 +15,7 @@
 
 #include "modules/audio_processing/aec3/aec3_common.h"
 #include "modules/audio_processing/aec3/aec_state.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
diff --git a/modules/audio_processing/aec3/echo_remover_unittest.cc b/modules/audio_processing/aec3/echo_remover_unittest.cc
index 8bf76c4..82d149a 100644
--- a/modules/audio_processing/aec3/echo_remover_unittest.cc
+++ b/modules/audio_processing/aec3/echo_remover_unittest.cc
@@ -48,7 +48,7 @@
     SCOPED_TRACE(ProduceDebugText(rate));
     std::unique_ptr<EchoRemover> remover(
         EchoRemover::Create(EchoCanceller3Config(), rate));
-    std::unique_ptr<RenderDelayBuffer> render_buffer(RenderDelayBuffer::Create2(
+    std::unique_ptr<RenderDelayBuffer> render_buffer(RenderDelayBuffer::Create(
         EchoCanceller3Config(), NumBandsForRate(rate)));
 
     std::vector<std::vector<float>> render(NumBandsForRate(rate),
@@ -89,7 +89,7 @@
     SCOPED_TRACE(ProduceDebugText(rate));
     std::unique_ptr<EchoRemover> remover(
         EchoRemover::Create(EchoCanceller3Config(), rate));
-    std::unique_ptr<RenderDelayBuffer> render_buffer(RenderDelayBuffer::Create2(
+    std::unique_ptr<RenderDelayBuffer> render_buffer(RenderDelayBuffer::Create(
         EchoCanceller3Config(), NumBandsForRate(rate)));
     std::vector<std::vector<float>> capture(
         NumBandsForRate(rate), std::vector<float>(kBlockSize - 1, 0.f));
@@ -111,7 +111,7 @@
     SCOPED_TRACE(ProduceDebugText(rate));
     std::unique_ptr<EchoRemover> remover(
         EchoRemover::Create(EchoCanceller3Config(), rate));
-    std::unique_ptr<RenderDelayBuffer> render_buffer(RenderDelayBuffer::Create2(
+    std::unique_ptr<RenderDelayBuffer> render_buffer(RenderDelayBuffer::Create(
         EchoCanceller3Config(), NumBandsForRate(rate)));
     std::vector<std::vector<float>> capture(
         NumBandsForRate(rate == 48000 ? 16000 : rate + 16000),
@@ -131,7 +131,7 @@
   std::unique_ptr<EchoRemover> remover(
       EchoRemover::Create(EchoCanceller3Config(), 8000));
   std::unique_ptr<RenderDelayBuffer> render_buffer(
-      RenderDelayBuffer::Create2(EchoCanceller3Config(), 3));
+      RenderDelayBuffer::Create(EchoCanceller3Config(), 3));
   EchoPathVariability echo_path_variability(
       false, EchoPathVariability::DelayAdjustment::kNone, false);
   EXPECT_DEATH(
@@ -158,10 +158,9 @@
     for (size_t delay_samples : {0, 64, 150, 200, 301}) {
       SCOPED_TRACE(ProduceDebugText(rate, delay_samples));
       EchoCanceller3Config config;
-      config.delay.min_echo_path_delay_blocks = 0;
       std::unique_ptr<EchoRemover> remover(EchoRemover::Create(config, rate));
       std::unique_ptr<RenderDelayBuffer> render_buffer(
-          RenderDelayBuffer::Create2(config, NumBandsForRate(rate)));
+          RenderDelayBuffer::Create(config, NumBandsForRate(rate)));
       render_buffer->SetDelay(delay_samples / kBlockSize);
 
       std::vector<std::unique_ptr<DelayBuffer<float>>> delay_buffers(x.size());
diff --git a/modules/audio_processing/aec3/erl_estimator.h b/modules/audio_processing/aec3/erl_estimator.h
index 29718c3..060fb91 100644
--- a/modules/audio_processing/aec3/erl_estimator.h
+++ b/modules/audio_processing/aec3/erl_estimator.h
@@ -16,7 +16,7 @@
 
 #include "api/array_view.h"
 #include "modules/audio_processing/aec3/aec3_common.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
diff --git a/modules/audio_processing/aec3/erle_estimator_unittest.cc b/modules/audio_processing/aec3/erle_estimator_unittest.cc
index 59a7471..5ef4f24 100644
--- a/modules/audio_processing/aec3/erle_estimator_unittest.cc
+++ b/modules/audio_processing/aec3/erle_estimator_unittest.cc
@@ -86,8 +86,8 @@
 
 void GetFilterFreq(std::vector<std::array<float, kFftLengthBy2Plus1>>&
                        filter_frequency_response,
-                   size_t delay_headroom_blocks) {
-  RTC_DCHECK_GE(filter_frequency_response.size(), delay_headroom_blocks);
+                   size_t delay_headroom_samples) {
+  const size_t delay_headroom_blocks = delay_headroom_samples / kBlockSize;
   for (auto& block_freq_resp : filter_frequency_response) {
     block_freq_resp.fill(0.f);
   }
@@ -108,9 +108,9 @@
   std::vector<std::array<float, kFftLengthBy2Plus1>> filter_frequency_response(
       config.filter.main.length_blocks);
   std::unique_ptr<RenderDelayBuffer> render_delay_buffer(
-      RenderDelayBuffer::Create2(config, 3));
+      RenderDelayBuffer::Create(config, 3));
 
-  GetFilterFreq(filter_frequency_response, config.delay.delay_headroom_blocks);
+  GetFilterFreq(filter_frequency_response, config.delay.delay_headroom_samples);
 
   ErleEstimator estimator(0, config);
 
@@ -152,9 +152,9 @@
       config.filter.main.length_blocks);
 
   std::unique_ptr<RenderDelayBuffer> render_delay_buffer(
-      RenderDelayBuffer::Create2(config, 3));
+      RenderDelayBuffer::Create(config, 3));
 
-  GetFilterFreq(filter_frequency_response, config.delay.delay_headroom_blocks);
+  GetFilterFreq(filter_frequency_response, config.delay.delay_headroom_samples);
 
   ErleEstimator estimator(0, config);
 
diff --git a/modules/audio_processing/aec3/filter_analyzer.cc b/modules/audio_processing/aec3/filter_analyzer.cc
index 3e69be6..7a6471a 100644
--- a/modules/audio_processing/aec3/filter_analyzer.cc
+++ b/modules/audio_processing/aec3/filter_analyzer.cc
@@ -18,9 +18,8 @@
 #include "modules/audio_processing/aec3/aec3_common.h"
 #include "modules/audio_processing/aec3/render_buffer.h"
 #include "modules/audio_processing/logging/apm_data_dumper.h"
-#include "rtc_base/atomicops.h"
+#include "rtc_base/atomic_ops.h"
 #include "rtc_base/checks.h"
-#include "system_wrappers/include/field_trial.h"
 
 namespace webrtc {
 namespace {
@@ -43,16 +42,6 @@
   return peak_index_out;
 }
 
-bool EnableFilterPreprocessing() {
-  return !field_trial::IsEnabled(
-      "WebRTC-Aec3FilterAnalyzerPreprocessorKillSwitch");
-}
-
-bool EnableIncrementalAnalysis() {
-  return !field_trial::IsEnabled(
-      "WebRTC-Aec3FilterAnalyzerIncrementalAnalysisKillSwitch");
-}
-
 }  // namespace
 
 int FilterAnalyzer::instance_count_ = 0;
@@ -60,10 +49,8 @@
 FilterAnalyzer::FilterAnalyzer(const EchoCanceller3Config& config)
     : data_dumper_(
           new ApmDataDumper(rtc::AtomicOps::Increment(&instance_count_))),
-      use_preprocessed_filter_(EnableFilterPreprocessing()),
       bounded_erl_(config.ep_strength.bounded_erl),
-      default_gain_(config.ep_strength.lf),
-      use_incremental_analysis_(EnableIncrementalAnalysis()),
+      default_gain_(config.ep_strength.default_gain),
       h_highpass_(GetTimeDomainLength(config.filter.main.length_blocks), 0.f),
       filter_length_blocks_(config.filter.main_initial.length_blocks),
       consistent_filter_detector_(config) {
@@ -99,19 +86,17 @@
   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());
+  RTC_DCHECK_EQ(h_highpass_.size(), filter_time_domain.size());
 
-  peak_index_ = FindPeakIndex(filter_to_analyze, peak_index_,
-                              region_.start_sample_, region_.end_sample_);
+  peak_index_ = FindPeakIndex(h_highpass_, peak_index_, region_.start_sample_,
+                              region_.end_sample_);
   delay_blocks_ = peak_index_ >> kBlockSizeLog2;
-  UpdateFilterGain(filter_to_analyze, peak_index_);
+  UpdateFilterGain(h_highpass_, peak_index_);
   filter_length_blocks_ = filter_time_domain.size() * (1.f / kBlockSize);
 
   consistent_estimate_ = consistent_filter_detector_.Detect(
-      filter_to_analyze, region_, render_buffer.Block(-delay_blocks_)[0],
-      peak_index_, delay_blocks_);
+      h_highpass_, region_, render_buffer.Block(-delay_blocks_)[0], peak_index_,
+      delay_blocks_);
 }
 
 void FilterAnalyzer::UpdateFilterGain(
@@ -159,17 +144,11 @@
     rtc::ArrayView<const float> filter_time_domain) {
   constexpr size_t kNumberBlocksToUpdate = 1;
   auto& r = region_;
-  if (use_incremental_analysis_) {
     r.start_sample_ =
         r.end_sample_ == filter_time_domain.size() - 1 ? 0 : r.end_sample_ + 1;
     r.end_sample_ =
         std::min(r.start_sample_ + kNumberBlocksToUpdate * kBlockSize - 1,
                  filter_time_domain.size() - 1);
-
-  } else {
-    r.start_sample_ = 0;
-    r.end_sample_ = filter_time_domain.size() - 1;
-  }
 }
 
 FilterAnalyzer::ConsistentFilterDetector::ConsistentFilterDetector(
diff --git a/modules/audio_processing/aec3/filter_analyzer.h b/modules/audio_processing/aec3/filter_analyzer.h
index e0fd069..37d8efd 100644
--- a/modules/audio_processing/aec3/filter_analyzer.h
+++ b/modules/audio_processing/aec3/filter_analyzer.h
@@ -19,7 +19,7 @@
 #include "api/array_view.h"
 #include "api/audio/echo_canceller3_config.h"
 #include "modules/audio_processing/aec3/aec3_common.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
@@ -97,10 +97,8 @@
 
   static int instance_count_;
   std::unique_ptr<ApmDataDumper> data_dumper_;
-  const bool use_preprocessed_filter_;
   const bool bounded_erl_;
   const float default_gain_;
-  const bool use_incremental_analysis_;
   std::vector<float> h_highpass_;
   int delay_blocks_ = 0;
   size_t blocks_since_reset_ = 0;
diff --git a/modules/audio_processing/aec3/frame_blocker.h b/modules/audio_processing/aec3/frame_blocker.h
index 08e1e1d..68cee97 100644
--- a/modules/audio_processing/aec3/frame_blocker.h
+++ b/modules/audio_processing/aec3/frame_blocker.h
@@ -16,7 +16,7 @@
 
 #include "api/array_view.h"
 #include "modules/audio_processing/aec3/aec3_common.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
diff --git a/modules/audio_processing/aec3/main_filter_update_gain.cc b/modules/audio_processing/aec3/main_filter_update_gain.cc
index ef87d14..11a97e2 100644
--- a/modules/audio_processing/aec3/main_filter_update_gain.cc
+++ b/modules/audio_processing/aec3/main_filter_update_gain.cc
@@ -20,7 +20,7 @@
 #include "modules/audio_processing/aec3/render_signal_analyzer.h"
 #include "modules/audio_processing/aec3/subtractor_output.h"
 #include "modules/audio_processing/logging/apm_data_dumper.h"
-#include "rtc_base/atomicops.h"
+#include "rtc_base/atomic_ops.h"
 #include "rtc_base/checks.h"
 
 namespace webrtc {
diff --git a/modules/audio_processing/aec3/main_filter_update_gain.h b/modules/audio_processing/aec3/main_filter_update_gain.h
index 892ff68..5c817cd 100644
--- a/modules/audio_processing/aec3/main_filter_update_gain.h
+++ b/modules/audio_processing/aec3/main_filter_update_gain.h
@@ -17,7 +17,7 @@
 
 #include "api/audio/echo_canceller3_config.h"
 #include "modules/audio_processing/aec3/aec3_common.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
diff --git a/modules/audio_processing/aec3/main_filter_update_gain_unittest.cc b/modules/audio_processing/aec3/main_filter_update_gain_unittest.cc
index 093b194..46165e5 100644
--- a/modules/audio_processing/aec3/main_filter_update_gain_unittest.cc
+++ b/modules/audio_processing/aec3/main_filter_update_gain_unittest.cc
@@ -63,10 +63,9 @@
   Random random_generator(42U);
   std::vector<std::vector<float>> x(3, std::vector<float>(kBlockSize, 0.f));
   std::vector<float> y(kBlockSize, 0.f);
-  config.delay.min_echo_path_delay_blocks = 0;
   config.delay.default_delay = 1;
   std::unique_ptr<RenderDelayBuffer> render_delay_buffer(
-      RenderDelayBuffer::Create2(config, 3));
+      RenderDelayBuffer::Create(config, 3));
   AecState aec_state(config);
   RenderSignalAnalyzer render_signal_analyzer(config);
   absl::optional<DelayEstimate> delay_estimate;
diff --git a/modules/audio_processing/aec3/matched_filter.h b/modules/audio_processing/aec3/matched_filter.h
index 2a65339..084267f 100644
--- a/modules/audio_processing/aec3/matched_filter.h
+++ b/modules/audio_processing/aec3/matched_filter.h
@@ -16,7 +16,7 @@
 
 #include "api/array_view.h"
 #include "modules/audio_processing/aec3/aec3_common.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 #include "rtc_base/system/arch.h"
 
 namespace webrtc {
diff --git a/modules/audio_processing/aec3/matched_filter_lag_aggregator.cc b/modules/audio_processing/aec3/matched_filter_lag_aggregator.cc
index f59525e..603a864 100644
--- a/modules/audio_processing/aec3/matched_filter_lag_aggregator.cc
+++ b/modules/audio_processing/aec3/matched_filter_lag_aggregator.cc
@@ -57,6 +57,7 @@
   // TODO(peah): Remove this logging once all development is done.
   data_dumper_->DumpRaw("aec3_echo_path_delay_estimator_best_index",
                         best_lag_estimate_index);
+  data_dumper_->DumpRaw("aec3_echo_path_delay_estimator_histogram", histogram_);
 
   if (best_lag_estimate_index != -1) {
     RTC_DCHECK_GT(histogram_.size(), histogram_data_[histogram_data_index_]);
diff --git a/modules/audio_processing/aec3/matched_filter_lag_aggregator.h b/modules/audio_processing/aec3/matched_filter_lag_aggregator.h
index d7f34ae..0cc7789 100644
--- a/modules/audio_processing/aec3/matched_filter_lag_aggregator.h
+++ b/modules/audio_processing/aec3/matched_filter_lag_aggregator.h
@@ -17,7 +17,7 @@
 #include "api/audio/echo_canceller3_config.h"
 #include "modules/audio_processing/aec3/delay_estimate.h"
 #include "modules/audio_processing/aec3/matched_filter.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
diff --git a/modules/audio_processing/aec3/matched_filter_unittest.cc b/modules/audio_processing/aec3/matched_filter_unittest.cc
index 0c17118..bf650bc 100644
--- a/modules/audio_processing/aec3/matched_filter_unittest.cc
+++ b/modules/audio_processing/aec3/matched_filter_unittest.cc
@@ -153,8 +153,6 @@
       EchoCanceller3Config config;
       config.delay.down_sampling_factor = down_sampling_factor;
       config.delay.num_filters = kNumMatchedFilters;
-      config.delay.min_echo_path_delay_blocks = 0;
-      config.delay.api_call_jitter_blocks = 0;
       Decimator capture_decimator(down_sampling_factor);
       DelayBuffer<float> signal_delay_buffer(down_sampling_factor *
                                              delay_samples);
@@ -165,7 +163,7 @@
                            config.delay.delay_candidate_detection_threshold);
 
       std::unique_ptr<RenderDelayBuffer> render_delay_buffer(
-          RenderDelayBuffer::Create2(config, 3));
+          RenderDelayBuffer::Create(config, 3));
 
       // Analyze the correlation between render and capture.
       for (size_t k = 0; k < (600 + delay_samples / sub_block_size); ++k) {
@@ -261,7 +259,7 @@
     std::fill(capture.begin(), capture.end(), 0.f);
     ApmDataDumper data_dumper(0);
     std::unique_ptr<RenderDelayBuffer> render_delay_buffer(
-        RenderDelayBuffer::Create2(config, 3));
+        RenderDelayBuffer::Create(config, 3));
     MatchedFilter filter(&data_dumper, DetectOptimization(), sub_block_size,
                          kWindowSizeSubBlocks, kNumMatchedFilters,
                          kAlignmentShiftSubBlocks, 150,
@@ -306,7 +304,7 @@
                          config.delay.delay_estimate_smoothing,
                          config.delay.delay_candidate_detection_threshold);
     std::unique_ptr<RenderDelayBuffer> render_delay_buffer(
-        RenderDelayBuffer::Create2(EchoCanceller3Config(), 3));
+        RenderDelayBuffer::Create(EchoCanceller3Config(), 3));
     Decimator capture_decimator(down_sampling_factor);
 
     // Analyze the correlation between render and capture.
diff --git a/modules/audio_processing/aec3/render_buffer.h b/modules/audio_processing/aec3/render_buffer.h
index 4c7c60c..cc6cd1c 100644
--- a/modules/audio_processing/aec3/render_buffer.h
+++ b/modules/audio_processing/aec3/render_buffer.h
@@ -22,7 +22,7 @@
 #include "modules/audio_processing/aec3/matrix_buffer.h"
 #include "modules/audio_processing/aec3/vector_buffer.h"
 #include "rtc_base/checks.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
diff --git a/modules/audio_processing/aec3/render_delay_buffer.cc b/modules/audio_processing/aec3/render_delay_buffer.cc
index 1ec2779..fea2d6e 100644
--- a/modules/audio_processing/aec3/render_delay_buffer.cc
+++ b/modules/audio_processing/aec3/render_delay_buffer.cc
@@ -1,5 +1,5 @@
 /*
- *  Copyright (c) 2017 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
@@ -8,47 +8,44 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#include "modules/audio_processing/aec3/render_delay_buffer.h"
-
-#include <stdlib.h>
+#include <string.h>
 #include <algorithm>
 #include <memory>
 #include <numeric>
+#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/aec3/aec3_fft.h"
 #include "modules/audio_processing/aec3/decimator.h"
+#include "modules/audio_processing/aec3/downsampled_render_buffer.h"
 #include "modules/audio_processing/aec3/fft_buffer.h"
 #include "modules/audio_processing/aec3/fft_data.h"
 #include "modules/audio_processing/aec3/matrix_buffer.h"
+#include "modules/audio_processing/aec3/render_buffer.h"
+#include "modules/audio_processing/aec3/render_delay_buffer.h"
 #include "modules/audio_processing/aec3/vector_buffer.h"
 #include "modules/audio_processing/logging/apm_data_dumper.h"
-#include "rtc_base/atomicops.h"
+#include "rtc_base/atomic_ops.h"
 #include "rtc_base/checks.h"
-#include "rtc_base/constructormagic.h"
 #include "rtc_base/logging.h"
-#include "system_wrappers/include/field_trial.h"
 
 namespace webrtc {
 namespace {
 
-bool EnableZeroExternalDelayHeadroom() {
-  return !field_trial::IsEnabled(
-      "WebRTC-Aec3ZeroExternalDelayHeadroomKillSwitch");
-}
-
 class RenderDelayBufferImpl final : public RenderDelayBuffer {
  public:
   RenderDelayBufferImpl(const EchoCanceller3Config& config, size_t num_bands);
+  RenderDelayBufferImpl() = delete;
   ~RenderDelayBufferImpl() override;
 
   void Reset() override;
   BufferingEvent Insert(const std::vector<std::vector<float>>& block) override;
   BufferingEvent PrepareCaptureProcessing() override;
   bool SetDelay(size_t delay) override;
-  size_t Delay() const override { return MapInternalDelayToExternalDelay(); }
+  size_t Delay() const override { return ComputeDelay(); }
   size_t MaxDelay() const override {
     return blocks_.buffer.size() - 1 - buffer_headroom_;
   }
@@ -58,8 +55,7 @@
     return low_rate_;
   }
 
-  bool CausalDelay(size_t delay) const override;
-
+  int BufferLatency() const;
   void SetAudioBufferDelay(size_t delay_ms) override;
 
  private:
@@ -68,17 +64,14 @@
   const Aec3Optimization optimization_;
   const EchoCanceller3Config config_;
   size_t down_sampling_factor_;
-  const bool use_zero_external_delay_headroom_;
   const int sub_block_size_;
   MatrixBuffer blocks_;
   VectorBuffer spectra_;
   FftBuffer ffts_;
   absl::optional<size_t> delay_;
-  absl::optional<int> internal_delay_;
   RenderBuffer echo_remover_buffer_;
   DownsampledRenderBuffer low_rate_;
   Decimator render_decimator_;
-  const std::vector<std::vector<float>> zero_block_;
   const Aec3Fft fft_;
   std::vector<float> render_ds_;
   const int buffer_headroom_;
@@ -90,81 +83,25 @@
   bool render_activity_ = false;
   size_t render_activity_counter_ = 0;
   absl::optional<size_t> external_audio_buffer_delay_;
-  bool external_delay_verified_after_reset_ = false;
+  bool external_audio_buffer_delay_verified_after_reset_ = false;
+  size_t min_latency_blocks_ = 0;
+  size_t excess_render_detection_counter_ = 0;
+  size_t num_bands_;
 
-  int LowRateBufferOffset() const { return DelayEstimatorOffset(config_) >> 1; }
-  int MapExternalDelayToInternalDelay(size_t external_delay_blocks) const;
-  int MapInternalDelayToExternalDelay() const;
-  void ApplyDelay(int delay);
+  int MapDelayToTotalDelay(size_t delay) const;
+  int ComputeDelay() const;
+  void ApplyTotalDelay(int delay);
   void InsertBlock(const std::vector<std::vector<float>>& block,
                    int previous_write);
   bool DetectActiveRender(rtc::ArrayView<const float> x) const;
-
-  RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(RenderDelayBufferImpl);
+  bool DetectExcessRenderBlocks();
+  void IncrementWriteIndices();
+  void IncrementLowRateReadIndices();
+  void IncrementReadIndices();
+  bool RenderOverrun();
+  bool RenderUnderrun();
 };
 
-// Increases the write indices for the render buffers.
-void IncreaseWriteIndices(int sub_block_size,
-                          MatrixBuffer* blocks,
-                          VectorBuffer* spectra,
-                          FftBuffer* ffts,
-                          DownsampledRenderBuffer* low_rate) {
-  low_rate->UpdateWriteIndex(-sub_block_size);
-  blocks->IncWriteIndex();
-  spectra->DecWriteIndex();
-  ffts->DecWriteIndex();
-}
-
-// Increases the read indices for the render buffers.
-void IncreaseReadIndices(const absl::optional<int>& delay,
-                         int sub_block_size,
-                         MatrixBuffer* blocks,
-                         VectorBuffer* spectra,
-                         FftBuffer* ffts,
-                         DownsampledRenderBuffer* low_rate) {
-  RTC_DCHECK_NE(low_rate->read, low_rate->write);
-  low_rate->UpdateReadIndex(-sub_block_size);
-
-  if (blocks->read != blocks->write) {
-    blocks->IncReadIndex();
-    spectra->DecReadIndex();
-    ffts->DecReadIndex();
-  } else {
-    // Only allow underrun for blocks_ when the delay is not set.
-    RTC_DCHECK(!delay);
-  }
-}
-
-// Checks for a render buffer overrun.
-bool RenderOverrun(const MatrixBuffer& b, const DownsampledRenderBuffer& l) {
-  return l.read == l.write || b.read == b.write;
-}
-
-// Checks for a render buffer underrun. If the delay is not specified, only the
-// low rate buffer underrun is counted as the delay offset for the other buffers
-// is unknown.
-bool RenderUnderrun(const absl::optional<int>& delay,
-                    const MatrixBuffer& b,
-                    const DownsampledRenderBuffer& l) {
-  return l.read == l.write || (delay && b.read == b.write);
-}
-
-// Computes the latency in the buffer (the number of unread elements).
-int BufferLatency(const DownsampledRenderBuffer& l) {
-  return (l.buffer.size() + l.read - l.write) % l.buffer.size();
-}
-
-// Computes the mismatch between the number of render and capture calls based on
-// the known offset (achieved during reset) of the low rate buffer.
-bool ApiCallSkew(const DownsampledRenderBuffer& low_rate_buffer,
-                 int sub_block_size,
-                 int low_rate_buffer_offset_sub_blocks) {
-  int latency = BufferLatency(low_rate_buffer);
-  int skew = abs(low_rate_buffer_offset_sub_blocks * sub_block_size - latency);
-  int skew_limit = low_rate_buffer_offset_sub_blocks * sub_block_size;
-  return skew >= skew_limit;
-}
-
 int RenderDelayBufferImpl::instance_count_ = 0;
 
 RenderDelayBufferImpl::RenderDelayBufferImpl(const EchoCanceller3Config& config,
@@ -174,7 +111,6 @@
       optimization_(DetectOptimization()),
       config_(config),
       down_sampling_factor_(config.delay.down_sampling_factor),
-      use_zero_external_delay_headroom_(EnableZeroExternalDelayHeadroom()),
       sub_block_size_(static_cast<int>(down_sampling_factor_ > 0
                                            ? kBlockSize / down_sampling_factor_
                                            : kBlockSize)),
@@ -190,15 +126,13 @@
       low_rate_(GetDownSampledBufferSize(down_sampling_factor_,
                                          config.delay.num_filters)),
       render_decimator_(down_sampling_factor_),
-      zero_block_(num_bands, std::vector<float>(kBlockSize, 0.f)),
       fft_(),
       render_ds_(sub_block_size_, 0.f),
-      buffer_headroom_(config.filter.main.length_blocks) {
+      buffer_headroom_(config.filter.main.length_blocks),
+      num_bands_(num_bands) {
   RTC_DCHECK_EQ(blocks_.buffer.size(), ffts_.buffer.size());
   RTC_DCHECK_EQ(spectra_.buffer.size(), ffts_.buffer.size());
 
-  // Necessary condition to avoid unrecoverable echp due to noncausal alignment.
-  RTC_DCHECK_EQ(DelayEstimatorOffset(config_), LowRateBufferOffset() * 2);
   Reset();
 }
 
@@ -208,39 +142,38 @@
 void RenderDelayBufferImpl::Reset() {
   last_call_was_render_ = false;
   num_api_calls_in_a_row_ = 1;
+  min_latency_blocks_ = 0;
+  excess_render_detection_counter_ = 0;
 
-  // Pre-fill the low rate buffer (which is used for delay estimation) to add
-  // headroom for the allowed api call jitter.
-  low_rate_.read = low_rate_.OffsetIndex(
-      low_rate_.write, LowRateBufferOffset() * sub_block_size_);
+  // Initialize the read index to one sub-block before the write index.
+  low_rate_.read = low_rate_.OffsetIndex(low_rate_.write, sub_block_size_);
 
   // Check for any external audio buffer delay and whether it is feasible.
   if (external_audio_buffer_delay_) {
-    const size_t headroom = use_zero_external_delay_headroom_ ? 0 : 2;
-    size_t external_delay_to_set = 0;
-    if (*external_audio_buffer_delay_ < headroom) {
-      external_delay_to_set = 0;
+    const size_t headroom = 2;
+    size_t audio_buffer_delay_to_set;
+    // Minimum delay is 1 (like the low-rate render buffer).
+    if (*external_audio_buffer_delay_ <= headroom) {
+      audio_buffer_delay_to_set = 1;
     } else {
-      external_delay_to_set = *external_audio_buffer_delay_ - headroom;
+      audio_buffer_delay_to_set = *external_audio_buffer_delay_ - headroom;
     }
 
-    external_delay_to_set = std::min(external_delay_to_set, MaxDelay());
+    audio_buffer_delay_to_set = std::min(audio_buffer_delay_to_set, MaxDelay());
 
     // When an external delay estimate is available, use that delay as the
     // initial render buffer delay.
-    internal_delay_ = external_delay_to_set;
-    ApplyDelay(*internal_delay_);
-    delay_ = MapInternalDelayToExternalDelay();
+    ApplyTotalDelay(audio_buffer_delay_to_set);
+    delay_ = ComputeDelay();
 
-    external_delay_verified_after_reset_ = false;
+    external_audio_buffer_delay_verified_after_reset_ = false;
   } else {
     // If an external delay estimate is not available, use that delay as the
     // initial delay. Set the render buffer delays to the default delay.
-    ApplyDelay(config_.delay.default_delay);
+    ApplyTotalDelay(config_.delay.default_delay);
 
     // Unset the delays which are set by SetDelay.
     delay_ = absl::nullopt;
-    internal_delay_ = absl::nullopt;
   }
 }
 
@@ -265,14 +198,12 @@
 
   // Increase the write indices to where the new blocks should be written.
   const int previous_write = blocks_.write;
-  IncreaseWriteIndices(sub_block_size_, &blocks_, &spectra_, &ffts_,
-                       &low_rate_);
+  IncrementWriteIndices();
 
   // Allow overrun and do a reset when render overrun occurrs due to more render
   // data being inserted than capture data is received.
-  BufferingEvent event = RenderOverrun(blocks_, low_rate_)
-                             ? BufferingEvent::kRenderOverrun
-                             : BufferingEvent::kNone;
+  BufferingEvent event =
+      RenderOverrun() ? BufferingEvent::kRenderOverrun : BufferingEvent::kNone;
 
   // Detect and update render activity.
   if (!render_activity_) {
@@ -293,7 +224,7 @@
 // Prepares the render buffers for processing another capture block.
 RenderDelayBuffer::BufferingEvent
 RenderDelayBufferImpl::PrepareCaptureProcessing() {
-  BufferingEvent event = BufferingEvent::kNone;
+  RenderDelayBuffer::BufferingEvent event = BufferingEvent::kNone;
   ++capture_call_counter_;
 
   if (delay_) {
@@ -311,26 +242,29 @@
     }
   }
 
-  if (RenderUnderrun(internal_delay_, blocks_, low_rate_)) {
-    // Don't increase the read indices if there is a render underrun.
+  if (DetectExcessRenderBlocks()) {
+    // Too many render blocks compared to capture blocks. Risk of delay ending
+    // up before the filter used by the delay estimator.
+    RTC_LOG(LS_WARNING) << "Excess render blocks detected at block "
+                        << capture_call_counter_;
+    Reset();
+    event = BufferingEvent::kRenderOverrun;
+  } else if (RenderUnderrun()) {
+    // Don't increment the read indices of the low rate buffer if there is a
+    // render underrun.
+    RTC_LOG(LS_WARNING) << "Render buffer underrun detected at block "
+                        << capture_call_counter_;
+    IncrementReadIndices();
+    // Incrementing the buffer index without increasing the low rate buffer
+    // index means that the delay is reduced by one.
+    if (delay_ && *delay_ > 0)
+      delay_ = *delay_ - 1;
     event = BufferingEvent::kRenderUnderrun;
   } else {
-    // Increase the read indices in the render buffers to point to the most
+    // Increment the read indices in the render buffers to point to the most
     // recent block to use in the capture processing.
-    IncreaseReadIndices(internal_delay_, sub_block_size_, &blocks_, &spectra_,
-                        &ffts_, &low_rate_);
-
-    // Check for skew in the API calls which, if too large, causes the delay
-    // estimation to be noncausal. Doing this check after the render indice
-    // increase saves one unit of allowed skew. Note that the skew check only
-    // should need to be one-sided as one of the skew directions results in an
-    // underrun.
-    bool skew = ApiCallSkew(low_rate_, sub_block_size_, LowRateBufferOffset());
-    event = skew ? BufferingEvent::kApiCallSkew : BufferingEvent::kNone;
-  }
-
-  if (event != BufferingEvent::kNone) {
-    Reset();
+    IncrementLowRateReadIndices();
+    IncrementReadIndices();
   }
 
   echo_remover_buffer_.SetRenderActivity(render_activity_);
@@ -344,76 +278,60 @@
 
 // Sets the delay and returns a bool indicating whether the delay was changed.
 bool RenderDelayBufferImpl::SetDelay(size_t delay) {
-  if (!external_delay_verified_after_reset_ && external_audio_buffer_delay_ &&
-      delay_) {
+  if (!external_audio_buffer_delay_verified_after_reset_ &&
+      external_audio_buffer_delay_ && delay_) {
     int difference = static_cast<int>(delay) - static_cast<int>(*delay_);
     RTC_LOG(LS_WARNING) << "Mismatch between first estimated delay after reset "
-                           "and external delay: "
+                           "and externally reported audio buffer delay: "
                         << difference << " blocks";
-    external_delay_verified_after_reset_ = true;
+    external_audio_buffer_delay_verified_after_reset_ = true;
   }
   if (delay_ && *delay_ == delay) {
     return false;
   }
   delay_ = delay;
 
-  // Compute the internal delay and limit the delay to the allowed range.
-  int internal_delay = MapExternalDelayToInternalDelay(*delay_);
-  internal_delay_ =
-      std::min(MaxDelay(), static_cast<size_t>(std::max(internal_delay, 0)));
+  // Compute the total delay and limit the delay to the allowed range.
+  int total_delay = MapDelayToTotalDelay(*delay_);
+  total_delay =
+      std::min(MaxDelay(), static_cast<size_t>(std::max(total_delay, 0)));
 
   // Apply the delay to the buffers.
-  ApplyDelay(*internal_delay_);
+  ApplyTotalDelay(total_delay);
   return true;
 }
 
-// Returns whether the specified delay is causal.
-bool RenderDelayBufferImpl::CausalDelay(size_t delay) const {
-  // Compute the internal delay and limit the delay to the allowed range.
-  int internal_delay = MapExternalDelayToInternalDelay(delay);
-  internal_delay =
-      std::min(MaxDelay(), static_cast<size_t>(std::max(internal_delay, 0)));
-
-  return internal_delay >=
-         static_cast<int>(config_.delay.min_echo_path_delay_blocks);
-}
-
 void RenderDelayBufferImpl::SetAudioBufferDelay(size_t delay_ms) {
   if (!external_audio_buffer_delay_) {
     RTC_LOG(LS_WARNING)
-        << "Receiving a first reported externally buffer delay of " << delay_ms
-        << " ms.";
+        << "Receiving a first externally reported audio buffer delay of "
+        << delay_ms << " ms.";
   }
 
   // Convert delay from milliseconds to blocks (rounded down).
-  external_audio_buffer_delay_ = delay_ms / 4;
+  external_audio_buffer_delay_ = delay_ms >> ((num_bands_ == 1) ? 1 : 2);
 }
 
 // Maps the externally computed delay to the delay used internally.
-int RenderDelayBufferImpl::MapExternalDelayToInternalDelay(
+int RenderDelayBufferImpl::MapDelayToTotalDelay(
     size_t external_delay_blocks) const {
-  const int latency = BufferLatency(low_rate_);
-  RTC_DCHECK_LT(0, sub_block_size_);
-  RTC_DCHECK_EQ(0, latency % sub_block_size_);
-  int latency_blocks = latency / sub_block_size_;
-  return latency_blocks + static_cast<int>(external_delay_blocks) -
-         DelayEstimatorOffset(config_);
+  const int latency_blocks = BufferLatency();
+  return latency_blocks + static_cast<int>(external_delay_blocks);
 }
 
-// Maps the internally used delay to the delay used externally.
-int RenderDelayBufferImpl::MapInternalDelayToExternalDelay() const {
-  const int latency = BufferLatency(low_rate_);
-  int latency_blocks = latency / sub_block_size_;
+// Returns the delay (not including call jitter).
+int RenderDelayBufferImpl::ComputeDelay() const {
+  const int latency_blocks = BufferLatency();
   int internal_delay = spectra_.read >= spectra_.write
                            ? spectra_.read - spectra_.write
                            : spectra_.size + spectra_.read - spectra_.write;
 
-  return internal_delay - latency_blocks + DelayEstimatorOffset(config_);
+  return internal_delay - latency_blocks;
 }
 
 // Set the read indices according to the delay.
-void RenderDelayBufferImpl::ApplyDelay(int delay) {
-  RTC_LOG(LS_WARNING) << "Applying internal delay of " << delay << " blocks.";
+void RenderDelayBufferImpl::ApplyTotalDelay(int delay) {
+  RTC_LOG(LS_WARNING) << "Applying total delay of " << delay << " blocks.";
   blocks_.read = blocks_.OffsetIndex(blocks_.write, -delay);
   spectra_.read = spectra_.OffsetIndex(spectra_.write, delay);
   ffts_.read = ffts_.OffsetIndex(ffts_.write, delay);
@@ -452,13 +370,72 @@
                         kFftLengthBy2;
 }
 
-}  // namespace
+bool RenderDelayBufferImpl::DetectExcessRenderBlocks() {
+  bool excess_render_detected = false;
+  const size_t latency_blocks = static_cast<size_t>(BufferLatency());
+  // The recently seen minimum latency in blocks. Should be close to 0.
+  min_latency_blocks_ = std::min(min_latency_blocks_, latency_blocks);
+  // After processing a configurable number of blocks the minimum latency is
+  // checked.
+  if (++excess_render_detection_counter_ >=
+      config_.buffering.excess_render_detection_interval_blocks) {
+    // If the minimum latency is not lower than the threshold there have been
+    // more render than capture frames.
+    excess_render_detected = min_latency_blocks_ >
+                             config_.buffering.max_allowed_excess_render_blocks;
+    // Reset the counter and let the minimum latency be the current latency.
+    min_latency_blocks_ = latency_blocks;
+    excess_render_detection_counter_ = 0;
+  }
 
-int RenderDelayBuffer::RenderDelayBuffer::DelayEstimatorOffset(
-    const EchoCanceller3Config& config) {
-  return config.delay.api_call_jitter_blocks * 2;
+  data_dumper_->DumpRaw("aec3_latency_blocks", latency_blocks);
+  data_dumper_->DumpRaw("aec3_min_latency_blocks", min_latency_blocks_);
+  data_dumper_->DumpRaw("aec3_excess_render_detected", excess_render_detected);
+  return excess_render_detected;
 }
 
+// Computes the latency in the buffer (the number of unread sub-blocks).
+int RenderDelayBufferImpl::BufferLatency() const {
+  const DownsampledRenderBuffer& l = low_rate_;
+  int latency_samples = (l.buffer.size() + l.read - l.write) % l.buffer.size();
+  int latency_blocks = latency_samples / sub_block_size_;
+  return latency_blocks;
+}
+
+// Increments the write indices for the render buffers.
+void RenderDelayBufferImpl::IncrementWriteIndices() {
+  low_rate_.UpdateWriteIndex(-sub_block_size_);
+  blocks_.IncWriteIndex();
+  spectra_.DecWriteIndex();
+  ffts_.DecWriteIndex();
+}
+
+// Increments the read indices of the low rate render buffers.
+void RenderDelayBufferImpl::IncrementLowRateReadIndices() {
+  low_rate_.UpdateReadIndex(-sub_block_size_);
+}
+
+// Increments the read indices for the render buffers.
+void RenderDelayBufferImpl::IncrementReadIndices() {
+  if (blocks_.read != blocks_.write) {
+    blocks_.IncReadIndex();
+    spectra_.DecReadIndex();
+    ffts_.DecReadIndex();
+  }
+}
+
+// Checks for a render buffer overrun.
+bool RenderDelayBufferImpl::RenderOverrun() {
+  return low_rate_.read == low_rate_.write || blocks_.read == blocks_.write;
+}
+
+// Checks for a render buffer underrun.
+bool RenderDelayBufferImpl::RenderUnderrun() {
+  return low_rate_.read == low_rate_.write;
+}
+
+}  // namespace
+
 RenderDelayBuffer* RenderDelayBuffer::Create(const EchoCanceller3Config& config,
                                              size_t num_bands) {
   return new RenderDelayBufferImpl(config, num_bands);
diff --git a/modules/audio_processing/aec3/render_delay_buffer.h b/modules/audio_processing/aec3/render_delay_buffer.h
index bd242f7..6926c67 100644
--- a/modules/audio_processing/aec3/render_delay_buffer.h
+++ b/modules/audio_processing/aec3/render_delay_buffer.h
@@ -33,8 +33,6 @@
 
   static RenderDelayBuffer* Create(const EchoCanceller3Config& config,
                                    size_t num_bands);
-  static RenderDelayBuffer* Create2(const EchoCanceller3Config& config,
-                                    size_t num_bands);
   virtual ~RenderDelayBuffer() = default;
 
   // Resets the buffer alignment.
@@ -64,9 +62,6 @@
   // Returns the downsampled render buffer.
   virtual const DownsampledRenderBuffer& GetDownsampledRenderBuffer() const = 0;
 
-  // Returns whether the current delay is noncausal.
-  virtual bool CausalDelay(size_t delay) const = 0;
-
   // Returns the maximum non calusal offset that can occur in the delay buffer.
   static int DelayEstimatorOffset(const EchoCanceller3Config& config);
 
diff --git a/modules/audio_processing/aec3/render_delay_buffer2.cc b/modules/audio_processing/aec3/render_delay_buffer2.cc
deleted file mode 100644
index 6992c5b..0000000
--- a/modules/audio_processing/aec3/render_delay_buffer2.cc
+++ /dev/null
@@ -1,453 +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 <string.h>
-#include <algorithm>
-#include <memory>
-#include <numeric>
-#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/aec3/aec3_fft.h"
-#include "modules/audio_processing/aec3/decimator.h"
-#include "modules/audio_processing/aec3/downsampled_render_buffer.h"
-#include "modules/audio_processing/aec3/fft_buffer.h"
-#include "modules/audio_processing/aec3/fft_data.h"
-#include "modules/audio_processing/aec3/matrix_buffer.h"
-#include "modules/audio_processing/aec3/render_buffer.h"
-#include "modules/audio_processing/aec3/render_delay_buffer.h"
-#include "modules/audio_processing/aec3/vector_buffer.h"
-#include "modules/audio_processing/logging/apm_data_dumper.h"
-#include "rtc_base/atomicops.h"
-#include "rtc_base/checks.h"
-#include "rtc_base/logging.h"
-
-namespace webrtc {
-namespace {
-
-class RenderDelayBufferImpl2 final : public RenderDelayBuffer {
- public:
-  RenderDelayBufferImpl2(const EchoCanceller3Config& config, size_t num_bands);
-  RenderDelayBufferImpl2() = delete;
-  ~RenderDelayBufferImpl2() override;
-
-  void Reset() override;
-  BufferingEvent Insert(const std::vector<std::vector<float>>& block) override;
-  BufferingEvent PrepareCaptureProcessing() override;
-  bool SetDelay(size_t delay) override;
-  size_t Delay() const override { return ComputeDelay(); }
-  size_t MaxDelay() const override {
-    return blocks_.buffer.size() - 1 - buffer_headroom_;
-  }
-  RenderBuffer* GetRenderBuffer() override { return &echo_remover_buffer_; }
-
-  const DownsampledRenderBuffer& GetDownsampledRenderBuffer() const override {
-    return low_rate_;
-  }
-
-  int BufferLatency() const;
-  bool CausalDelay(size_t delay) const override;
-  void SetAudioBufferDelay(size_t delay_ms) override;
-
- private:
-  static int instance_count_;
-  std::unique_ptr<ApmDataDumper> data_dumper_;
-  const Aec3Optimization optimization_;
-  const EchoCanceller3Config config_;
-  size_t down_sampling_factor_;
-  const int sub_block_size_;
-  MatrixBuffer blocks_;
-  VectorBuffer spectra_;
-  FftBuffer ffts_;
-  absl::optional<size_t> delay_;
-  RenderBuffer echo_remover_buffer_;
-  DownsampledRenderBuffer low_rate_;
-  Decimator render_decimator_;
-  const Aec3Fft fft_;
-  std::vector<float> render_ds_;
-  const int buffer_headroom_;
-  bool last_call_was_render_ = false;
-  int num_api_calls_in_a_row_ = 0;
-  int max_observed_jitter_ = 1;
-  size_t capture_call_counter_ = 0;
-  size_t render_call_counter_ = 0;
-  bool render_activity_ = false;
-  size_t render_activity_counter_ = 0;
-  absl::optional<size_t> external_audio_buffer_delay_;
-  bool external_audio_buffer_delay_verified_after_reset_ = false;
-  size_t min_latency_blocks_ = 0;
-  size_t excess_render_detection_counter_ = 0;
-  size_t num_bands_;
-
-  int MapDelayToTotalDelay(size_t delay) const;
-  int ComputeDelay() const;
-  void ApplyTotalDelay(int delay);
-  void InsertBlock(const std::vector<std::vector<float>>& block,
-                   int previous_write);
-  bool DetectActiveRender(rtc::ArrayView<const float> x) const;
-  bool DetectExcessRenderBlocks();
-  void IncrementWriteIndices();
-  void IncrementLowRateReadIndices();
-  void IncrementReadIndices();
-  bool RenderOverrun();
-  bool RenderUnderrun();
-};
-
-int RenderDelayBufferImpl2::instance_count_ = 0;
-
-RenderDelayBufferImpl2::RenderDelayBufferImpl2(
-    const EchoCanceller3Config& config,
-    size_t num_bands)
-    : data_dumper_(
-          new ApmDataDumper(rtc::AtomicOps::Increment(&instance_count_))),
-      optimization_(DetectOptimization()),
-      config_(config),
-      down_sampling_factor_(config.delay.down_sampling_factor),
-      sub_block_size_(static_cast<int>(down_sampling_factor_ > 0
-                                           ? kBlockSize / down_sampling_factor_
-                                           : kBlockSize)),
-      blocks_(GetRenderDelayBufferSize(down_sampling_factor_,
-                                       config.delay.num_filters,
-                                       config.filter.main.length_blocks),
-              num_bands,
-              kBlockSize),
-      spectra_(blocks_.buffer.size(), kFftLengthBy2Plus1),
-      ffts_(blocks_.buffer.size()),
-      delay_(config_.delay.default_delay),
-      echo_remover_buffer_(&blocks_, &spectra_, &ffts_),
-      low_rate_(GetDownSampledBufferSize(down_sampling_factor_,
-                                         config.delay.num_filters)),
-      render_decimator_(down_sampling_factor_),
-      fft_(),
-      render_ds_(sub_block_size_, 0.f),
-      buffer_headroom_(config.filter.main.length_blocks),
-      num_bands_(num_bands) {
-  RTC_DCHECK_EQ(blocks_.buffer.size(), ffts_.buffer.size());
-  RTC_DCHECK_EQ(spectra_.buffer.size(), ffts_.buffer.size());
-
-  Reset();
-}
-
-RenderDelayBufferImpl2::~RenderDelayBufferImpl2() = default;
-
-// Resets the buffer delays and clears the reported delays.
-void RenderDelayBufferImpl2::Reset() {
-  last_call_was_render_ = false;
-  num_api_calls_in_a_row_ = 1;
-  min_latency_blocks_ = 0;
-  excess_render_detection_counter_ = 0;
-
-  // Initialize the read index to one sub-block before the write index.
-  low_rate_.read = low_rate_.OffsetIndex(low_rate_.write, sub_block_size_);
-
-  // Check for any external audio buffer delay and whether it is feasible.
-  if (external_audio_buffer_delay_) {
-    const size_t headroom = 2;
-    size_t audio_buffer_delay_to_set;
-    // Minimum delay is 1 (like the low-rate render buffer).
-    if (*external_audio_buffer_delay_ <= headroom) {
-      audio_buffer_delay_to_set = 1;
-    } else {
-      audio_buffer_delay_to_set = *external_audio_buffer_delay_ - headroom;
-    }
-
-    audio_buffer_delay_to_set = std::min(audio_buffer_delay_to_set, MaxDelay());
-
-    // When an external delay estimate is available, use that delay as the
-    // initial render buffer delay.
-    ApplyTotalDelay(audio_buffer_delay_to_set);
-    delay_ = ComputeDelay();
-
-    external_audio_buffer_delay_verified_after_reset_ = false;
-  } else {
-    // If an external delay estimate is not available, use that delay as the
-    // initial delay. Set the render buffer delays to the default delay.
-    ApplyTotalDelay(config_.delay.default_delay);
-
-    // Unset the delays which are set by SetDelay.
-    delay_ = absl::nullopt;
-  }
-}
-
-// Inserts a new block into the render buffers.
-RenderDelayBuffer::BufferingEvent RenderDelayBufferImpl2::Insert(
-    const std::vector<std::vector<float>>& block) {
-  ++render_call_counter_;
-  if (delay_) {
-    if (!last_call_was_render_) {
-      last_call_was_render_ = true;
-      num_api_calls_in_a_row_ = 1;
-    } else {
-      if (++num_api_calls_in_a_row_ > max_observed_jitter_) {
-        max_observed_jitter_ = num_api_calls_in_a_row_;
-        RTC_LOG(LS_WARNING)
-            << "New max number api jitter observed at render block "
-            << render_call_counter_ << ":  " << num_api_calls_in_a_row_
-            << " blocks";
-      }
-    }
-  }
-
-  // Increase the write indices to where the new blocks should be written.
-  const int previous_write = blocks_.write;
-  IncrementWriteIndices();
-
-  // Allow overrun and do a reset when render overrun occurrs due to more render
-  // data being inserted than capture data is received.
-  BufferingEvent event =
-      RenderOverrun() ? BufferingEvent::kRenderOverrun : BufferingEvent::kNone;
-
-  // Detect and update render activity.
-  if (!render_activity_) {
-    render_activity_counter_ += DetectActiveRender(block[0]) ? 1 : 0;
-    render_activity_ = render_activity_counter_ >= 20;
-  }
-
-  // Insert the new render block into the specified position.
-  InsertBlock(block, previous_write);
-
-  if (event != BufferingEvent::kNone) {
-    Reset();
-  }
-
-  return event;
-}
-
-// Prepares the render buffers for processing another capture block.
-RenderDelayBuffer::BufferingEvent
-RenderDelayBufferImpl2::PrepareCaptureProcessing() {
-  RenderDelayBuffer::BufferingEvent event = BufferingEvent::kNone;
-  ++capture_call_counter_;
-
-  if (delay_) {
-    if (last_call_was_render_) {
-      last_call_was_render_ = false;
-      num_api_calls_in_a_row_ = 1;
-    } else {
-      if (++num_api_calls_in_a_row_ > max_observed_jitter_) {
-        max_observed_jitter_ = num_api_calls_in_a_row_;
-        RTC_LOG(LS_WARNING)
-            << "New max number api jitter observed at capture block "
-            << capture_call_counter_ << ":  " << num_api_calls_in_a_row_
-            << " blocks";
-      }
-    }
-  }
-
-  if (DetectExcessRenderBlocks()) {
-    // Too many render blocks compared to capture blocks. Risk of delay ending
-    // up before the filter used by the delay estimator.
-    RTC_LOG(LS_WARNING) << "Excess render blocks detected at block "
-                        << capture_call_counter_;
-    Reset();
-    event = BufferingEvent::kRenderOverrun;
-  } else if (RenderUnderrun()) {
-    // Don't increment the read indices of the low rate buffer if there is a
-    // render underrun.
-    RTC_LOG(LS_WARNING) << "Render buffer underrun detected at block "
-                        << capture_call_counter_;
-    IncrementReadIndices();
-    // Incrementing the buffer index without increasing the low rate buffer
-    // index means that the delay is reduced by one.
-    if (delay_ && *delay_ > 0)
-      delay_ = *delay_ - 1;
-    event = BufferingEvent::kRenderUnderrun;
-  } else {
-    // Increment the read indices in the render buffers to point to the most
-    // recent block to use in the capture processing.
-    IncrementLowRateReadIndices();
-    IncrementReadIndices();
-  }
-
-  echo_remover_buffer_.SetRenderActivity(render_activity_);
-  if (render_activity_) {
-    render_activity_counter_ = 0;
-    render_activity_ = false;
-  }
-
-  return event;
-}
-
-// Sets the delay and returns a bool indicating whether the delay was changed.
-bool RenderDelayBufferImpl2::SetDelay(size_t delay) {
-  if (!external_audio_buffer_delay_verified_after_reset_ &&
-      external_audio_buffer_delay_ && delay_) {
-    int difference = static_cast<int>(delay) - static_cast<int>(*delay_);
-    RTC_LOG(LS_WARNING) << "Mismatch between first estimated delay after reset "
-                           "and externally reported audio buffer delay: "
-                        << difference << " blocks";
-    external_audio_buffer_delay_verified_after_reset_ = true;
-  }
-  if (delay_ && *delay_ == delay) {
-    return false;
-  }
-  delay_ = delay;
-
-  // Compute the total delay and limit the delay to the allowed range.
-  int total_delay = MapDelayToTotalDelay(*delay_);
-  total_delay =
-      std::min(MaxDelay(), static_cast<size_t>(std::max(total_delay, 0)));
-
-  // Apply the delay to the buffers.
-  ApplyTotalDelay(total_delay);
-  return true;
-}
-
-// Returns whether the specified delay is causal.
-bool RenderDelayBufferImpl2::CausalDelay(size_t delay) const {
-  // TODO(gustaf): Remove this from RenderDelayBuffer.
-  return true;
-}
-
-void RenderDelayBufferImpl2::SetAudioBufferDelay(size_t delay_ms) {
-  if (!external_audio_buffer_delay_) {
-    RTC_LOG(LS_WARNING)
-        << "Receiving a first externally reported audio buffer delay of "
-        << delay_ms << " ms.";
-  }
-
-  // Convert delay from milliseconds to blocks (rounded down).
-  external_audio_buffer_delay_ = delay_ms >> ((num_bands_ == 1) ? 1 : 2);
-}
-
-// Maps the externally computed delay to the delay used internally.
-int RenderDelayBufferImpl2::MapDelayToTotalDelay(
-    size_t external_delay_blocks) const {
-  const int latency_blocks = BufferLatency();
-  return latency_blocks + static_cast<int>(external_delay_blocks);
-}
-
-// Returns the delay (not including call jitter).
-int RenderDelayBufferImpl2::ComputeDelay() const {
-  const int latency_blocks = BufferLatency();
-  int internal_delay = spectra_.read >= spectra_.write
-                           ? spectra_.read - spectra_.write
-                           : spectra_.size + spectra_.read - spectra_.write;
-
-  return internal_delay - latency_blocks;
-}
-
-// Set the read indices according to the delay.
-void RenderDelayBufferImpl2::ApplyTotalDelay(int delay) {
-  RTC_LOG(LS_WARNING) << "Applying total delay of " << delay << " blocks.";
-  blocks_.read = blocks_.OffsetIndex(blocks_.write, -delay);
-  spectra_.read = spectra_.OffsetIndex(spectra_.write, delay);
-  ffts_.read = ffts_.OffsetIndex(ffts_.write, delay);
-}
-
-// Inserts a block into the render buffers.
-void RenderDelayBufferImpl2::InsertBlock(
-    const std::vector<std::vector<float>>& block,
-    int previous_write) {
-  auto& b = blocks_;
-  auto& lr = low_rate_;
-  auto& ds = render_ds_;
-  auto& f = ffts_;
-  auto& s = spectra_;
-  RTC_DCHECK_EQ(block.size(), b.buffer[b.write].size());
-  for (size_t k = 0; k < block.size(); ++k) {
-    RTC_DCHECK_EQ(block[k].size(), b.buffer[b.write][k].size());
-    std::copy(block[k].begin(), block[k].end(), b.buffer[b.write][k].begin());
-  }
-
-  data_dumper_->DumpWav("aec3_render_decimator_input", block[0].size(),
-                        block[0].data(), 16000, 1);
-  render_decimator_.Decimate(block[0], ds);
-  data_dumper_->DumpWav("aec3_render_decimator_output", ds.size(), ds.data(),
-                        16000 / down_sampling_factor_, 1);
-  std::copy(ds.rbegin(), ds.rend(), lr.buffer.begin() + lr.write);
-  fft_.PaddedFft(block[0], b.buffer[previous_write][0], &f.buffer[f.write]);
-  f.buffer[f.write].Spectrum(optimization_, s.buffer[s.write]);
-}
-
-bool RenderDelayBufferImpl2::DetectActiveRender(
-    rtc::ArrayView<const float> x) const {
-  const float x_energy = std::inner_product(x.begin(), x.end(), x.begin(), 0.f);
-  return x_energy > (config_.render_levels.active_render_limit *
-                     config_.render_levels.active_render_limit) *
-                        kFftLengthBy2;
-}
-
-bool RenderDelayBufferImpl2::DetectExcessRenderBlocks() {
-  bool excess_render_detected = false;
-  const size_t latency_blocks = static_cast<size_t>(BufferLatency());
-  // The recently seen minimum latency in blocks. Should be close to 0.
-  min_latency_blocks_ = std::min(min_latency_blocks_, latency_blocks);
-  // After processing a configurable number of blocks the minimum latency is
-  // checked.
-  if (++excess_render_detection_counter_ >=
-      config_.buffering.excess_render_detection_interval_blocks) {
-    // If the minimum latency is not lower than the threshold there have been
-    // more render than capture frames.
-    excess_render_detected = min_latency_blocks_ >
-                             config_.buffering.max_allowed_excess_render_blocks;
-    // Reset the counter and let the minimum latency be the current latency.
-    min_latency_blocks_ = latency_blocks;
-    excess_render_detection_counter_ = 0;
-  }
-
-  data_dumper_->DumpRaw("aec3_latency_blocks", latency_blocks);
-  data_dumper_->DumpRaw("aec3_min_latency_blocks", min_latency_blocks_);
-  data_dumper_->DumpRaw("aec3_excess_render_detected", excess_render_detected);
-  return excess_render_detected;
-}
-
-// Computes the latency in the buffer (the number of unread sub-blocks).
-int RenderDelayBufferImpl2::BufferLatency() const {
-  const DownsampledRenderBuffer& l = low_rate_;
-  int latency_samples = (l.buffer.size() + l.read - l.write) % l.buffer.size();
-  int latency_blocks = latency_samples / sub_block_size_;
-  return latency_blocks;
-}
-
-// Increments the write indices for the render buffers.
-void RenderDelayBufferImpl2::IncrementWriteIndices() {
-  low_rate_.UpdateWriteIndex(-sub_block_size_);
-  blocks_.IncWriteIndex();
-  spectra_.DecWriteIndex();
-  ffts_.DecWriteIndex();
-}
-
-// Increments the read indices of the low rate render buffers.
-void RenderDelayBufferImpl2::IncrementLowRateReadIndices() {
-  low_rate_.UpdateReadIndex(-sub_block_size_);
-}
-
-// Increments the read indices for the render buffers.
-void RenderDelayBufferImpl2::IncrementReadIndices() {
-  if (blocks_.read != blocks_.write) {
-    blocks_.IncReadIndex();
-    spectra_.DecReadIndex();
-    ffts_.DecReadIndex();
-  }
-}
-
-// Checks for a render buffer overrun.
-bool RenderDelayBufferImpl2::RenderOverrun() {
-  return low_rate_.read == low_rate_.write || blocks_.read == blocks_.write;
-}
-
-// Checks for a render buffer underrun.
-bool RenderDelayBufferImpl2::RenderUnderrun() {
-  return low_rate_.read == low_rate_.write;
-}
-
-}  // namespace
-
-RenderDelayBuffer* RenderDelayBuffer::Create2(
-    const EchoCanceller3Config& config,
-    size_t num_bands) {
-  return new RenderDelayBufferImpl2(config, num_bands);
-}
-
-}  // namespace webrtc
diff --git a/modules/audio_processing/aec3/render_delay_buffer_unittest.cc b/modules/audio_processing/aec3/render_delay_buffer_unittest.cc
index d1530c6..641a081 100644
--- a/modules/audio_processing/aec3/render_delay_buffer_unittest.cc
+++ b/modules/audio_processing/aec3/render_delay_buffer_unittest.cc
@@ -38,7 +38,7 @@
   for (auto rate : {8000, 16000, 32000, 48000}) {
     SCOPED_TRACE(ProduceDebugText(rate));
     std::unique_ptr<RenderDelayBuffer> delay_buffer(
-        RenderDelayBuffer::Create2(config, NumBandsForRate(rate)));
+        RenderDelayBuffer::Create(config, NumBandsForRate(rate)));
     std::vector<std::vector<float>> block_to_insert(
         NumBandsForRate(rate), std::vector<float>(kBlockSize, 0.f));
     for (size_t k = 0; k < 10; ++k) {
@@ -62,7 +62,7 @@
 TEST(RenderDelayBuffer, AvailableBlock) {
   constexpr size_t kNumBands = 1;
   std::unique_ptr<RenderDelayBuffer> delay_buffer(
-      RenderDelayBuffer::Create2(EchoCanceller3Config(), kNumBands));
+      RenderDelayBuffer::Create(EchoCanceller3Config(), kNumBands));
   std::vector<std::vector<float>> input_block(
       kNumBands, std::vector<float>(kBlockSize, 1.f));
   EXPECT_EQ(RenderDelayBuffer::BufferingEvent::kNone,
@@ -74,11 +74,10 @@
 TEST(RenderDelayBuffer, SetDelay) {
   EchoCanceller3Config config;
   std::unique_ptr<RenderDelayBuffer> delay_buffer(
-      RenderDelayBuffer::Create2(config, 1));
+      RenderDelayBuffer::Create(config, 1));
   ASSERT_TRUE(delay_buffer->Delay());
   delay_buffer->Reset();
-  size_t initial_internal_delay = config.delay.min_echo_path_delay_blocks +
-                                  config.delay.api_call_jitter_blocks;
+  size_t initial_internal_delay = 0;
   for (size_t delay = initial_internal_delay;
        delay < initial_internal_delay + 20; ++delay) {
     ASSERT_TRUE(delay_buffer->SetDelay(delay));
@@ -93,7 +92,7 @@
 // tests on test bots has been fixed.
 TEST(RenderDelayBuffer, DISABLED_WrongDelay) {
   std::unique_ptr<RenderDelayBuffer> delay_buffer(
-      RenderDelayBuffer::Create2(EchoCanceller3Config(), 3));
+      RenderDelayBuffer::Create(EchoCanceller3Config(), 3));
   EXPECT_DEATH(delay_buffer->SetDelay(21), "");
 }
 
@@ -101,7 +100,7 @@
 TEST(RenderDelayBuffer, WrongNumberOfBands) {
   for (auto rate : {16000, 32000, 48000}) {
     SCOPED_TRACE(ProduceDebugText(rate));
-    std::unique_ptr<RenderDelayBuffer> delay_buffer(RenderDelayBuffer::Create2(
+    std::unique_ptr<RenderDelayBuffer> delay_buffer(RenderDelayBuffer::Create(
         EchoCanceller3Config(), NumBandsForRate(rate)));
     std::vector<std::vector<float>> block_to_insert(
         NumBandsForRate(rate < 48000 ? rate + 16000 : 16000),
@@ -115,7 +114,7 @@
   for (auto rate : {8000, 16000, 32000, 48000}) {
     SCOPED_TRACE(ProduceDebugText(rate));
     std::unique_ptr<RenderDelayBuffer> delay_buffer(
-        RenderDelayBuffer::Create2(EchoCanceller3Config(), 3));
+        RenderDelayBuffer::Create(EchoCanceller3Config(), 3));
     std::vector<std::vector<float>> block_to_insert(
         NumBandsForRate(rate), std::vector<float>(kBlockSize - 1, 0.f));
     EXPECT_DEATH(delay_buffer->Insert(block_to_insert), "");
diff --git a/modules/audio_processing/aec3/render_delay_controller.cc b/modules/audio_processing/aec3/render_delay_controller.cc
index c4665ea..4f9fa8e 100644
--- a/modules/audio_processing/aec3/render_delay_controller.cc
+++ b/modules/audio_processing/aec3/render_delay_controller.cc
@@ -1,5 +1,5 @@
 /*
- *  Copyright (c) 2017 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
@@ -7,54 +7,31 @@
  *  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/render_delay_controller.h"
-
-#include <stdlib.h>
+#include <stddef.h>
 #include <algorithm>
 #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/aec3/delay_estimate.h"
+#include "modules/audio_processing/aec3/downsampled_render_buffer.h"
 #include "modules/audio_processing/aec3/echo_path_delay_estimator.h"
+#include "modules/audio_processing/aec3/render_delay_controller.h"
 #include "modules/audio_processing/aec3/render_delay_controller_metrics.h"
-#include "modules/audio_processing/aec3/skew_estimator.h"
 #include "modules/audio_processing/logging/apm_data_dumper.h"
-#include "rtc_base/atomicops.h"
+#include "rtc_base/atomic_ops.h"
 #include "rtc_base/checks.h"
-#include "rtc_base/constructormagic.h"
-#include "rtc_base/logging.h"
-#include "system_wrappers/include/field_trial.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
 namespace {
 
-int GetSkewHysteresis(const EchoCanceller3Config& config) {
-  if (field_trial::IsEnabled("WebRTC-Aec3EnforceSkewHysteresis1")) {
-    return 1;
-  }
-  if (field_trial::IsEnabled("WebRTC-Aec3EnforceSkewHysteresis2")) {
-    return 2;
-  }
-
-  return static_cast<int>(config.delay.skew_hysteresis_blocks);
-}
-
-bool UseOffsetBlocks() {
-  return field_trial::IsEnabled("WebRTC-Aec3UseOffsetBlocks");
-}
-
-bool UseEarlyDelayDetection() {
-  return !field_trial::IsEnabled("WebRTC-Aec3EarlyDelayDetectionKillSwitch");
-}
-
-constexpr int kSkewHistorySizeLog2 = 8;
-
 class RenderDelayControllerImpl final : public RenderDelayController {
  public:
   RenderDelayControllerImpl(const EchoCanceller3Config& config,
-                            int non_causal_offset,
                             int sample_rate_hz);
   ~RenderDelayControllerImpl() override;
   void Reset(bool reset_delay_confidence) override;
@@ -69,58 +46,36 @@
  private:
   static int instance_count_;
   std::unique_ptr<ApmDataDumper> data_dumper_;
-  const bool use_early_delay_detection_;
-  const int delay_headroom_blocks_;
-  const int hysteresis_limit_1_blocks_;
-  const int hysteresis_limit_2_blocks_;
-  const int skew_hysteresis_blocks_;
-  const bool use_offset_blocks_;
+  const int hysteresis_limit_blocks_;
+  const int delay_headroom_samples_;
   absl::optional<DelayEstimate> delay_;
   EchoPathDelayEstimator delay_estimator_;
-  std::vector<float> delay_buf_;
-  int delay_buf_index_ = 0;
   RenderDelayControllerMetrics metrics_;
-  SkewEstimator skew_estimator_;
   absl::optional<DelayEstimate> delay_samples_;
-  absl::optional<int> skew_;
-  int previous_offset_blocks_ = 0;
-  int skew_shift_reporting_counter_ = 0;
   size_t capture_call_counter_ = 0;
   int delay_change_counter_ = 0;
-  size_t soft_reset_counter_ = 0;
   DelayEstimate::Quality last_delay_estimate_quality_;
   RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(RenderDelayControllerImpl);
 };
 
 DelayEstimate ComputeBufferDelay(
     const absl::optional<DelayEstimate>& current_delay,
-    int delay_headroom_blocks,
-    int hysteresis_limit_1_blocks,
-    int hysteresis_limit_2_blocks,
-    int offset_blocks,
+    int hysteresis_limit_blocks,
+    int delay_headroom_samples,
     DelayEstimate estimated_delay) {
-  // The below division is not exact and the truncation is intended.
-  const int echo_path_delay_blocks = estimated_delay.delay >> kBlockSizeLog2;
+  // Subtract delay headroom.
+  const int delay_with_headroom_samples = std::max(
+      static_cast<int>(estimated_delay.delay) - delay_headroom_samples, 0);
 
   // Compute the buffer delay increase required to achieve the desired latency.
-  size_t new_delay_blocks = std::max(
-      echo_path_delay_blocks + offset_blocks - delay_headroom_blocks, 0);
+  size_t new_delay_blocks = delay_with_headroom_samples >> kBlockSizeLog2;
 
   // Add hysteresis.
   if (current_delay) {
     size_t current_delay_blocks = current_delay->delay;
-    if (new_delay_blocks > current_delay_blocks) {
-      if (new_delay_blocks <=
-          current_delay_blocks + hysteresis_limit_1_blocks) {
-        new_delay_blocks = current_delay_blocks;
-      }
-    } else if (new_delay_blocks < current_delay_blocks) {
-      size_t hysteresis_limit = std::max(
-          static_cast<int>(current_delay_blocks) - hysteresis_limit_2_blocks,
-          0);
-      if (new_delay_blocks >= hysteresis_limit) {
-        new_delay_blocks = current_delay_blocks;
-      }
+    if (new_delay_blocks > current_delay_blocks &&
+        new_delay_blocks <= current_delay_blocks + hysteresis_limit_blocks) {
+      new_delay_blocks = current_delay_blocks;
     }
   }
 
@@ -133,26 +88,16 @@
 
 RenderDelayControllerImpl::RenderDelayControllerImpl(
     const EchoCanceller3Config& config,
-    int non_causal_offset,
     int sample_rate_hz)
     : data_dumper_(
           new ApmDataDumper(rtc::AtomicOps::Increment(&instance_count_))),
-      use_early_delay_detection_(UseEarlyDelayDetection()),
-      delay_headroom_blocks_(
-          static_cast<int>(config.delay.delay_headroom_blocks)),
-      hysteresis_limit_1_blocks_(
-          static_cast<int>(config.delay.hysteresis_limit_1_blocks)),
-      hysteresis_limit_2_blocks_(
-          static_cast<int>(config.delay.hysteresis_limit_2_blocks)),
-      skew_hysteresis_blocks_(GetSkewHysteresis(config)),
-      use_offset_blocks_(UseOffsetBlocks()),
+      hysteresis_limit_blocks_(
+          static_cast<int>(config.delay.hysteresis_limit_blocks)),
+      delay_headroom_samples_(config.delay.delay_headroom_samples),
       delay_estimator_(data_dumper_.get(), config),
-      delay_buf_(kBlockSize * non_causal_offset, 0.f),
-      skew_estimator_(kSkewHistorySizeLog2),
       last_delay_estimate_quality_(DelayEstimate::Quality::kCoarse) {
   RTC_DCHECK(ValidFullBandRate(sample_rate_hz));
-  delay_estimator_.LogDelayEstimationProperties(sample_rate_hz,
-                                                delay_buf_.size());
+  delay_estimator_.LogDelayEstimationProperties(sample_rate_hz, 0);
 }
 
 RenderDelayControllerImpl::~RenderDelayControllerImpl() = default;
@@ -160,21 +105,14 @@
 void RenderDelayControllerImpl::Reset(bool reset_delay_confidence) {
   delay_ = absl::nullopt;
   delay_samples_ = absl::nullopt;
-  skew_ = absl::nullopt;
-  previous_offset_blocks_ = 0;
-  std::fill(delay_buf_.begin(), delay_buf_.end(), 0.f);
   delay_estimator_.Reset(reset_delay_confidence);
-  skew_estimator_.Reset();
   delay_change_counter_ = 0;
-  soft_reset_counter_ = 0;
   if (reset_delay_confidence) {
     last_delay_estimate_quality_ = DelayEstimate::Quality::kCoarse;
   }
 }
 
-void RenderDelayControllerImpl::LogRenderCall() {
-  skew_estimator_.LogRenderCall();
-}
+void RenderDelayControllerImpl::LogRenderCall() {}
 
 absl::optional<DelayEstimate> RenderDelayControllerImpl::GetDelay(
     const DownsampledRenderBuffer& render_buffer,
@@ -184,12 +122,7 @@
   RTC_DCHECK_EQ(kBlockSize, capture.size());
   ++capture_call_counter_;
 
-  // Estimate the delay with a delayed capture.
-  RTC_DCHECK_LT(delay_buf_index_ + kBlockSize - 1, delay_buf_.size());
-  rtc::ArrayView<const float> capture_delayed(&delay_buf_[delay_buf_index_],
-                                              kBlockSize);
-  auto delay_samples =
-      delay_estimator_.EstimateDelay(render_buffer, capture_delayed);
+  auto delay_samples = delay_estimator_.EstimateDelay(render_buffer, capture);
 
   // Overrule the delay estimator delay if the echo remover reports a delay.
   if (echo_remover_delay) {
@@ -199,13 +132,6 @@
                                   total_echo_remover_delay_samples);
   }
 
-  std::copy(capture.begin(), capture.end(),
-            delay_buf_.begin() + delay_buf_index_);
-  delay_buf_index_ = (delay_buf_index_ + kBlockSize) % delay_buf_.size();
-
-  // Compute the latest skew update.
-  absl::optional<int> skew = skew_estimator_.GetSkewFromCapture();
-
   if (delay_samples) {
     if (!delay_samples_ || delay_samples->delay != delay_samples_->delay) {
       delay_change_counter_ = 0;
@@ -230,46 +156,6 @@
 
   if (delay_change_counter_ < 2 * kNumBlocksPerSecond) {
     ++delay_change_counter_;
-    // If a new delay estimate is recently obtained, store the skew for that.
-    skew_ = skew;
-  } else {
-    // A reliable skew should have been obtained after 2 seconds.
-    RTC_DCHECK(skew_);
-    RTC_DCHECK(skew);
-  }
-
-  ++soft_reset_counter_;
-  int offset_blocks = 0;
-  if (skew_ && skew && delay_samples_ &&
-      delay_samples_->quality == DelayEstimate::Quality::kRefined) {
-    // Compute the skew offset and add a margin.
-    offset_blocks = *skew_ - *skew;
-    if (abs(offset_blocks) <= skew_hysteresis_blocks_) {
-      offset_blocks = 0;
-    } else if (soft_reset_counter_ > 10 * kNumBlocksPerSecond) {
-      // Soft reset the delay estimator if there is a significant offset
-      // detected.
-      delay_estimator_.Reset(false);
-      soft_reset_counter_ = 0;
-    }
-  }
-  if (!use_offset_blocks_)
-    offset_blocks = 0;
-
-  // Log any changes in the skew.
-  skew_shift_reporting_counter_ =
-      std::max(0, skew_shift_reporting_counter_ - 1);
-  absl::optional<int> skew_shift =
-      skew_shift_reporting_counter_ == 0 &&
-              previous_offset_blocks_ != offset_blocks
-          ? absl::optional<int>(offset_blocks - previous_offset_blocks_)
-          : absl::nullopt;
-  previous_offset_blocks_ = offset_blocks;
-  if (skew_shift) {
-    RTC_LOG(LS_WARNING) << "API call skew shift of " << *skew_shift
-                        << " blocks detected at capture block "
-                        << capture_call_counter_;
-    skew_shift_reporting_counter_ = 3 * kNumBlocksPerSecond;
   }
 
   if (delay_samples_) {
@@ -277,29 +163,21 @@
     const bool use_hysteresis =
         last_delay_estimate_quality_ == DelayEstimate::Quality::kRefined &&
         delay_samples_->quality == DelayEstimate::Quality::kRefined;
-    delay_ = ComputeBufferDelay(delay_, delay_headroom_blocks_,
-                                use_hysteresis ? hysteresis_limit_1_blocks_ : 0,
-                                use_hysteresis ? hysteresis_limit_2_blocks_ : 0,
-                                offset_blocks, *delay_samples_);
+    delay_ = ComputeBufferDelay(delay_,
+                                use_hysteresis ? hysteresis_limit_blocks_ : 0,
+                                delay_headroom_samples_, *delay_samples_);
     last_delay_estimate_quality_ = delay_samples_->quality;
   }
 
   metrics_.Update(delay_samples_ ? absl::optional<size_t>(delay_samples_->delay)
                                  : absl::nullopt,
-                  delay_ ? delay_->delay : 0, skew_shift,
-                  delay_estimator_.Clockdrift());
+                  delay_ ? delay_->delay : 0, 0, delay_estimator_.Clockdrift());
 
   data_dumper_->DumpRaw("aec3_render_delay_controller_delay",
                         delay_samples ? delay_samples->delay : 0);
   data_dumper_->DumpRaw("aec3_render_delay_controller_buffer_delay",
                         delay_ ? delay_->delay : 0);
 
-  data_dumper_->DumpRaw("aec3_render_delay_controller_new_skew",
-                        skew ? *skew : 0);
-  data_dumper_->DumpRaw("aec3_render_delay_controller_old_skew",
-                        skew_ ? *skew_ : 0);
-  data_dumper_->DumpRaw("aec3_render_delay_controller_offset", offset_blocks);
-
   return delay_;
 }
 
@@ -311,10 +189,8 @@
 
 RenderDelayController* RenderDelayController::Create(
     const EchoCanceller3Config& config,
-    int non_causal_offset,
     int sample_rate_hz) {
-  return new RenderDelayControllerImpl(config, non_causal_offset,
-                                       sample_rate_hz);
+  return new RenderDelayControllerImpl(config, sample_rate_hz);
 }
 
 }  // namespace webrtc
diff --git a/modules/audio_processing/aec3/render_delay_controller.h b/modules/audio_processing/aec3/render_delay_controller.h
index b46ed89..fb86529 100644
--- a/modules/audio_processing/aec3/render_delay_controller.h
+++ b/modules/audio_processing/aec3/render_delay_controller.h
@@ -25,10 +25,7 @@
 class RenderDelayController {
  public:
   static RenderDelayController* Create(const EchoCanceller3Config& config,
-                                       int non_causal_offset,
                                        int sample_rate_hz);
-  static RenderDelayController* Create2(const EchoCanceller3Config& config,
-                                        int sample_rate_hz);
   virtual ~RenderDelayController() = default;
 
   // Resets the delay controller. If the delay confidence is reset, the reset
diff --git a/modules/audio_processing/aec3/render_delay_controller2.cc b/modules/audio_processing/aec3/render_delay_controller2.cc
deleted file mode 100644
index 00daf8f..0000000
--- a/modules/audio_processing/aec3/render_delay_controller2.cc
+++ /dev/null
@@ -1,218 +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 <stddef.h>
-#include <algorithm>
-#include <memory>
-
-#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/aec3/delay_estimate.h"
-#include "modules/audio_processing/aec3/downsampled_render_buffer.h"
-#include "modules/audio_processing/aec3/echo_path_delay_estimator.h"
-#include "modules/audio_processing/aec3/render_delay_controller.h"
-#include "modules/audio_processing/aec3/render_delay_controller_metrics.h"
-#include "modules/audio_processing/logging/apm_data_dumper.h"
-#include "rtc_base/atomicops.h"
-#include "rtc_base/checks.h"
-#include "rtc_base/constructormagic.h"
-#include "system_wrappers/include/field_trial.h"
-
-namespace webrtc {
-
-namespace {
-
-bool UseEarlyDelayDetection() {
-  return !field_trial::IsEnabled("WebRTC-Aec3EarlyDelayDetectionKillSwitch");
-}
-
-class RenderDelayControllerImpl2 final : public RenderDelayController {
- public:
-  RenderDelayControllerImpl2(const EchoCanceller3Config& config,
-                             int sample_rate_hz);
-  ~RenderDelayControllerImpl2() override;
-  void Reset(bool reset_delay_confidence) override;
-  void LogRenderCall() override;
-  absl::optional<DelayEstimate> GetDelay(
-      const DownsampledRenderBuffer& render_buffer,
-      size_t render_delay_buffer_delay,
-      const absl::optional<int>& echo_remover_delay,
-      rtc::ArrayView<const float> capture) override;
-  bool HasClockdrift() const override;
-
- private:
-  static int instance_count_;
-  std::unique_ptr<ApmDataDumper> data_dumper_;
-  const bool use_early_delay_detection_;
-  const int delay_headroom_blocks_;
-  const int hysteresis_limit_1_blocks_;
-  const int hysteresis_limit_2_blocks_;
-  absl::optional<DelayEstimate> delay_;
-  EchoPathDelayEstimator delay_estimator_;
-  RenderDelayControllerMetrics metrics_;
-  absl::optional<DelayEstimate> delay_samples_;
-  size_t capture_call_counter_ = 0;
-  int delay_change_counter_ = 0;
-  DelayEstimate::Quality last_delay_estimate_quality_;
-  RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(RenderDelayControllerImpl2);
-};
-
-DelayEstimate ComputeBufferDelay(
-    const absl::optional<DelayEstimate>& current_delay,
-    int delay_headroom_blocks,
-    int hysteresis_limit_1_blocks,
-    int hysteresis_limit_2_blocks,
-    DelayEstimate estimated_delay) {
-  // The below division is not exact and the truncation is intended.
-  const int echo_path_delay_blocks = estimated_delay.delay >> kBlockSizeLog2;
-
-  // Compute the buffer delay increase required to achieve the desired latency.
-  size_t new_delay_blocks =
-      std::max(echo_path_delay_blocks - delay_headroom_blocks, 0);
-
-  // Add hysteresis.
-  if (current_delay) {
-    size_t current_delay_blocks = current_delay->delay;
-    if (new_delay_blocks > current_delay_blocks) {
-      if (new_delay_blocks <=
-          current_delay_blocks + hysteresis_limit_1_blocks) {
-        new_delay_blocks = current_delay_blocks;
-      }
-    } else if (new_delay_blocks < current_delay_blocks) {
-      size_t hysteresis_limit = std::max(
-          static_cast<int>(current_delay_blocks) - hysteresis_limit_2_blocks,
-          0);
-      if (new_delay_blocks >= hysteresis_limit) {
-        new_delay_blocks = current_delay_blocks;
-      }
-    }
-  }
-
-  DelayEstimate new_delay = estimated_delay;
-  new_delay.delay = new_delay_blocks;
-  return new_delay;
-}
-
-int RenderDelayControllerImpl2::instance_count_ = 0;
-
-RenderDelayControllerImpl2::RenderDelayControllerImpl2(
-    const EchoCanceller3Config& config,
-    int sample_rate_hz)
-    : data_dumper_(
-          new ApmDataDumper(rtc::AtomicOps::Increment(&instance_count_))),
-      use_early_delay_detection_(UseEarlyDelayDetection()),
-      delay_headroom_blocks_(
-          static_cast<int>(config.delay.delay_headroom_blocks)),
-      hysteresis_limit_1_blocks_(
-          static_cast<int>(config.delay.hysteresis_limit_1_blocks)),
-      hysteresis_limit_2_blocks_(
-          static_cast<int>(config.delay.hysteresis_limit_2_blocks)),
-      delay_estimator_(data_dumper_.get(), config),
-      last_delay_estimate_quality_(DelayEstimate::Quality::kCoarse) {
-  RTC_DCHECK(ValidFullBandRate(sample_rate_hz));
-  delay_estimator_.LogDelayEstimationProperties(sample_rate_hz, 0);
-}
-
-RenderDelayControllerImpl2::~RenderDelayControllerImpl2() = default;
-
-void RenderDelayControllerImpl2::Reset(bool reset_delay_confidence) {
-  delay_ = absl::nullopt;
-  delay_samples_ = absl::nullopt;
-  delay_estimator_.Reset(reset_delay_confidence);
-  delay_change_counter_ = 0;
-  if (reset_delay_confidence) {
-    last_delay_estimate_quality_ = DelayEstimate::Quality::kCoarse;
-  }
-}
-
-void RenderDelayControllerImpl2::LogRenderCall() {}
-
-absl::optional<DelayEstimate> RenderDelayControllerImpl2::GetDelay(
-    const DownsampledRenderBuffer& render_buffer,
-    size_t render_delay_buffer_delay,
-    const absl::optional<int>& echo_remover_delay,
-    rtc::ArrayView<const float> capture) {
-  RTC_DCHECK_EQ(kBlockSize, capture.size());
-  ++capture_call_counter_;
-
-  auto delay_samples = delay_estimator_.EstimateDelay(render_buffer, capture);
-
-  // Overrule the delay estimator delay if the echo remover reports a delay.
-  if (echo_remover_delay) {
-    int total_echo_remover_delay_samples =
-        (render_delay_buffer_delay + *echo_remover_delay) * kBlockSize;
-    delay_samples = DelayEstimate(DelayEstimate::Quality::kRefined,
-                                  total_echo_remover_delay_samples);
-  }
-
-  if (delay_samples) {
-    if (!delay_samples_ || delay_samples->delay != delay_samples_->delay) {
-      delay_change_counter_ = 0;
-    }
-    if (delay_samples_) {
-      delay_samples_->blocks_since_last_change =
-          delay_samples_->delay == delay_samples->delay
-              ? delay_samples_->blocks_since_last_change + 1
-              : 0;
-      delay_samples_->blocks_since_last_update = 0;
-      delay_samples_->delay = delay_samples->delay;
-      delay_samples_->quality = delay_samples->quality;
-    } else {
-      delay_samples_ = delay_samples;
-    }
-  } else {
-    if (delay_samples_) {
-      ++delay_samples_->blocks_since_last_change;
-      ++delay_samples_->blocks_since_last_update;
-    }
-  }
-
-  if (delay_change_counter_ < 2 * kNumBlocksPerSecond) {
-    ++delay_change_counter_;
-  }
-
-  if (delay_samples_) {
-    // Compute the render delay buffer delay.
-    const bool use_hysteresis =
-        last_delay_estimate_quality_ == DelayEstimate::Quality::kRefined &&
-        delay_samples_->quality == DelayEstimate::Quality::kRefined;
-    delay_ = ComputeBufferDelay(delay_, delay_headroom_blocks_,
-                                use_hysteresis ? hysteresis_limit_1_blocks_ : 0,
-                                use_hysteresis ? hysteresis_limit_2_blocks_ : 0,
-                                *delay_samples_);
-    last_delay_estimate_quality_ = delay_samples_->quality;
-  }
-
-  metrics_.Update(delay_samples_ ? absl::optional<size_t>(delay_samples_->delay)
-                                 : absl::nullopt,
-                  delay_ ? delay_->delay : 0, 0, delay_estimator_.Clockdrift());
-
-  data_dumper_->DumpRaw("aec3_render_delay_controller_delay",
-                        delay_samples ? delay_samples->delay : 0);
-  data_dumper_->DumpRaw("aec3_render_delay_controller_buffer_delay",
-                        delay_ ? delay_->delay : 0);
-
-  return delay_;
-}
-
-bool RenderDelayControllerImpl2::HasClockdrift() const {
-  return delay_estimator_.Clockdrift() != ClockdriftDetector::Level::kNone;
-}
-
-}  // namespace
-
-RenderDelayController* RenderDelayController::Create2(
-    const EchoCanceller3Config& config,
-    int sample_rate_hz) {
-  return new RenderDelayControllerImpl2(config, sample_rate_hz);
-}
-
-}  // namespace webrtc
diff --git a/modules/audio_processing/aec3/render_delay_controller_metrics.h b/modules/audio_processing/aec3/render_delay_controller_metrics.h
index 22cc202..8c527a1 100644
--- a/modules/audio_processing/aec3/render_delay_controller_metrics.h
+++ b/modules/audio_processing/aec3/render_delay_controller_metrics.h
@@ -15,7 +15,7 @@
 
 #include "absl/types/optional.h"
 #include "modules/audio_processing/aec3/clockdrift_detector.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
diff --git a/modules/audio_processing/aec3/render_delay_controller_unittest.cc b/modules/audio_processing/aec3/render_delay_controller_unittest.cc
index e9f02d3..c8405d8 100644
--- a/modules/audio_processing/aec3/render_delay_controller_unittest.cc
+++ b/modules/audio_processing/aec3/render_delay_controller_unittest.cc
@@ -57,14 +57,14 @@
       for (auto rate : {8000, 16000, 32000, 48000}) {
         SCOPED_TRACE(ProduceDebugText(rate));
         std::unique_ptr<RenderDelayBuffer> delay_buffer(
-            RenderDelayBuffer::Create2(config, NumBandsForRate(rate)));
+            RenderDelayBuffer::Create(config, NumBandsForRate(rate)));
         std::unique_ptr<RenderDelayController> delay_controller(
-            RenderDelayController::Create2(config, rate));
+            RenderDelayController::Create(config, rate));
         for (size_t k = 0; k < 100; ++k) {
           auto delay = delay_controller->GetDelay(
               delay_buffer->GetDownsampledRenderBuffer(), delay_buffer->Delay(),
               echo_remover_delay_, block);
-          EXPECT_EQ(config.delay.min_echo_path_delay_blocks, delay->delay);
+          EXPECT_FALSE(delay->delay);
         }
       }
     }
@@ -86,9 +86,9 @@
         std::vector<std::vector<float>> render_block(
             NumBandsForRate(rate), std::vector<float>(kBlockSize, 0.f));
         std::unique_ptr<RenderDelayBuffer> render_delay_buffer(
-            RenderDelayBuffer::Create2(config, NumBandsForRate(rate)));
+            RenderDelayBuffer::Create(config, NumBandsForRate(rate)));
         std::unique_ptr<RenderDelayController> delay_controller(
-            RenderDelayController::Create2(EchoCanceller3Config(), rate));
+            RenderDelayController::Create(EchoCanceller3Config(), rate));
         for (size_t k = 0; k < 10; ++k) {
           render_delay_buffer->Insert(render_block);
           render_delay_buffer->PrepareCaptureProcessing();
@@ -98,7 +98,7 @@
               render_delay_buffer->Delay(), echo_remover_delay, capture_block);
         }
         EXPECT_TRUE(delay_blocks);
-        EXPECT_EQ(config.delay.min_echo_path_delay_blocks, delay_blocks->delay);
+        EXPECT_FALSE(delay_blocks->delay);
       }
     }
   }
@@ -125,9 +125,9 @@
           absl::optional<DelayEstimate> delay_blocks;
           SCOPED_TRACE(ProduceDebugText(rate, delay_samples));
           std::unique_ptr<RenderDelayBuffer> render_delay_buffer(
-              RenderDelayBuffer::Create2(config, NumBandsForRate(rate)));
+              RenderDelayBuffer::Create(config, NumBandsForRate(rate)));
           std::unique_ptr<RenderDelayController> delay_controller(
-              RenderDelayController::Create2(config, rate));
+              RenderDelayController::Create(config, rate));
           DelayBuffer<float> signal_delay_buffer(delay_samples);
           for (size_t k = 0; k < (400 + delay_samples / kBlockSize); ++k) {
             RandomizeSampleVector(&random_generator, render_block[0]);
@@ -174,9 +174,9 @@
           absl::optional<DelayEstimate> delay_blocks;
           SCOPED_TRACE(ProduceDebugText(rate, -delay_samples));
           std::unique_ptr<RenderDelayBuffer> render_delay_buffer(
-              RenderDelayBuffer::Create2(config, NumBandsForRate(rate)));
+              RenderDelayBuffer::Create(config, NumBandsForRate(rate)));
           std::unique_ptr<RenderDelayController> delay_controller(
-              RenderDelayController::Create2(EchoCanceller3Config(), rate));
+              RenderDelayController::Create(EchoCanceller3Config(), rate));
           DelayBuffer<float> signal_delay_buffer(-delay_samples);
           for (int k = 0;
                k < (400 - delay_samples / static_cast<int>(kBlockSize)); ++k) {
@@ -216,24 +216,23 @@
           absl::optional<DelayEstimate> delay_blocks;
           SCOPED_TRACE(ProduceDebugText(rate, delay_samples));
           std::unique_ptr<RenderDelayBuffer> render_delay_buffer(
-              RenderDelayBuffer::Create2(config, NumBandsForRate(rate)));
+              RenderDelayBuffer::Create(config, NumBandsForRate(rate)));
           std::unique_ptr<RenderDelayController> delay_controller(
-              RenderDelayController::Create2(config, rate));
+              RenderDelayController::Create(config, rate));
           DelayBuffer<float> signal_delay_buffer(delay_samples);
-          for (size_t j = 0; j < (1000 + delay_samples / kBlockSize) /
-                                         config.delay.api_call_jitter_blocks +
-                                     1;
+          constexpr size_t kMaxTestJitterBlocks = 26;
+          for (size_t j = 0;
+               j <
+               (1000 + delay_samples / kBlockSize) / kMaxTestJitterBlocks + 1;
                ++j) {
             std::vector<std::vector<float>> capture_block_buffer;
-            for (size_t k = 0; k < (config.delay.api_call_jitter_blocks - 1);
-                 ++k) {
+            for (size_t k = 0; k < (kMaxTestJitterBlocks - 1); ++k) {
               RandomizeSampleVector(&random_generator, render_block[0]);
               signal_delay_buffer.Delay(render_block[0], capture_block);
               capture_block_buffer.push_back(capture_block);
               render_delay_buffer->Insert(render_block);
             }
-            for (size_t k = 0; k < (config.delay.api_call_jitter_blocks - 1);
-                 ++k) {
+            for (size_t k = 0; k < (kMaxTestJitterBlocks - 1); ++k) {
               render_delay_buffer->PrepareCaptureProcessing();
               delay_blocks = delay_controller->GetDelay(
                   render_delay_buffer->GetDownsampledRenderBuffer(),
@@ -271,10 +270,10 @@
       for (auto rate : {8000, 16000, 32000, 48000}) {
         SCOPED_TRACE(ProduceDebugText(rate));
         std::unique_ptr<RenderDelayBuffer> render_delay_buffer(
-            RenderDelayBuffer::Create2(config, NumBandsForRate(rate)));
+            RenderDelayBuffer::Create(config, NumBandsForRate(rate)));
 
         std::unique_ptr<RenderDelayController> delay_controller(
-            RenderDelayController::Create2(config, rate));
+            RenderDelayController::Create(config, rate));
       }
     }
   }
@@ -290,10 +289,10 @@
   for (auto rate : {8000, 16000, 32000, 48000}) {
     SCOPED_TRACE(ProduceDebugText(rate));
     std::unique_ptr<RenderDelayBuffer> render_delay_buffer(
-        RenderDelayBuffer::Create2(config, NumBandsForRate(rate)));
+        RenderDelayBuffer::Create(config, NumBandsForRate(rate)));
     EXPECT_DEATH(
         std::unique_ptr<RenderDelayController>(
-            RenderDelayController::Create2(EchoCanceller3Config(), rate))
+            RenderDelayController::Create(EchoCanceller3Config(), rate))
             ->GetDelay(render_delay_buffer->GetDownsampledRenderBuffer(),
                        render_delay_buffer->Delay(), echo_remover_delay, block),
         "");
@@ -308,10 +307,10 @@
     SCOPED_TRACE(ProduceDebugText(rate));
     EchoCanceller3Config config;
     std::unique_ptr<RenderDelayBuffer> render_delay_buffer(
-        RenderDelayBuffer::Create2(config, NumBandsForRate(rate)));
+        RenderDelayBuffer::Create(config, NumBandsForRate(rate)));
     EXPECT_DEATH(
         std::unique_ptr<RenderDelayController>(
-            RenderDelayController::Create2(EchoCanceller3Config(), rate)),
+            RenderDelayController::Create(EchoCanceller3Config(), rate)),
         "");
   }
 }
diff --git a/modules/audio_processing/aec3/render_signal_analyzer.h b/modules/audio_processing/aec3/render_signal_analyzer.h
index 8a44232..c7a3d8b 100644
--- a/modules/audio_processing/aec3/render_signal_analyzer.h
+++ b/modules/audio_processing/aec3/render_signal_analyzer.h
@@ -20,7 +20,7 @@
 #include "modules/audio_processing/aec3/aec3_common.h"
 #include "modules/audio_processing/aec3/render_buffer.h"
 #include "rtc_base/checks.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
diff --git a/modules/audio_processing/aec3/render_signal_analyzer_unittest.cc b/modules/audio_processing/aec3/render_signal_analyzer_unittest.cc
index a993f8f..a15cd9a 100644
--- a/modules/audio_processing/aec3/render_signal_analyzer_unittest.cc
+++ b/modules/audio_processing/aec3/render_signal_analyzer_unittest.cc
@@ -59,7 +59,7 @@
   std::vector<std::vector<float>> x(3, std::vector<float>(kBlockSize, 0.f));
   std::array<float, kBlockSize> x_old;
   std::unique_ptr<RenderDelayBuffer> render_delay_buffer(
-      RenderDelayBuffer::Create2(EchoCanceller3Config(), 3));
+      RenderDelayBuffer::Create(EchoCanceller3Config(), 3));
   std::array<float, kFftLengthBy2Plus1> mask;
   x_old.fill(0.f);
 
@@ -91,9 +91,8 @@
   std::array<float, kBlockSize> x_old;
   Aec3Fft fft;
   EchoCanceller3Config config;
-  config.delay.min_echo_path_delay_blocks = 0;
   std::unique_ptr<RenderDelayBuffer> render_delay_buffer(
-      RenderDelayBuffer::Create2(config, 3));
+      RenderDelayBuffer::Create(config, 3));
 
   std::array<float, kFftLengthBy2Plus1> mask;
   x_old.fill(0.f);
diff --git a/modules/audio_processing/aec3/residual_echo_estimator.cc b/modules/audio_processing/aec3/residual_echo_estimator.cc
index 627dd90..d47fa4c 100644
--- a/modules/audio_processing/aec3/residual_echo_estimator.cc
+++ b/modules/audio_processing/aec3/residual_echo_estimator.cc
@@ -1,4 +1,3 @@
-
 /*
  *  Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
  *
@@ -19,70 +18,36 @@
 #include "modules/audio_processing/aec3/reverb_model.h"
 #include "modules/audio_processing/aec3/reverb_model_fallback.h"
 #include "rtc_base/checks.h"
-#include "system_wrappers/include/field_trial.h"
 
 namespace webrtc {
 namespace {
 
-bool EnableSoftTransparentMode() {
-  return !field_trial::IsEnabled("WebRTC-Aec3SoftTransparentModeKillSwitch");
-}
-
-bool OverrideEstimatedEchoPathGain() {
-  return !field_trial::IsEnabled("WebRTC-Aec3OverrideEchoPathGainKillSwitch");
-}
-
-bool UseFixedNonLinearReverbModel() {
-  return field_trial::IsEnabled(
-      "WebRTC-Aec3StandardNonlinearReverbModelKillSwitch");
-}
-
 // Computes the indexes that will be used for computing spectral power over
 // the blocks surrounding the delay.
 void GetRenderIndexesToAnalyze(
     const VectorBuffer& spectrum_buffer,
     const EchoCanceller3Config::EchoModel& echo_model,
     int filter_delay_blocks,
-    bool gain_limiter_running,
     int headroom,
     int* idx_start,
     int* idx_stop) {
   RTC_DCHECK(idx_start);
   RTC_DCHECK(idx_stop);
-  if (gain_limiter_running) {
-    if (static_cast<size_t>(headroom) >
-        echo_model.render_post_window_size_init) {
-      *idx_start = spectrum_buffer.OffsetIndex(
-          spectrum_buffer.read,
-          -static_cast<int>(echo_model.render_post_window_size_init));
-    } else {
-      *idx_start = spectrum_buffer.IncIndex(spectrum_buffer.write);
-    }
-
-    *idx_stop = spectrum_buffer.OffsetIndex(
-        spectrum_buffer.read, echo_model.render_pre_window_size_init);
-  } else {
-    size_t window_start;
-    size_t window_end;
-    window_start =
-        std::max(0, filter_delay_blocks -
-                        static_cast<int>(echo_model.render_pre_window_size));
-    window_end = filter_delay_blocks +
-                 static_cast<int>(echo_model.render_post_window_size);
-    *idx_start =
-        spectrum_buffer.OffsetIndex(spectrum_buffer.read, window_start);
-    *idx_stop =
-        spectrum_buffer.OffsetIndex(spectrum_buffer.read, window_end + 1);
-  }
+  size_t window_start;
+  size_t window_end;
+  window_start =
+      std::max(0, filter_delay_blocks -
+                      static_cast<int>(echo_model.render_pre_window_size));
+  window_end = filter_delay_blocks +
+               static_cast<int>(echo_model.render_post_window_size);
+  *idx_start = spectrum_buffer.OffsetIndex(spectrum_buffer.read, window_start);
+  *idx_stop = spectrum_buffer.OffsetIndex(spectrum_buffer.read, window_end + 1);
 }
 
 }  // namespace
 
 ResidualEchoEstimator::ResidualEchoEstimator(const EchoCanceller3Config& config)
-    : config_(config),
-      soft_transparent_mode_(EnableSoftTransparentMode()),
-      override_estimated_echo_path_gain_(OverrideEstimatedEchoPathGain()),
-      use_fixed_nonlinear_reverb_model_(UseFixedNonLinearReverbModel()) {
+    : config_(config) {
   if (config_.ep_strength.reverb_based_on_render) {
     echo_reverb_.reset(new ReverbModel());
   } else {
@@ -136,7 +101,6 @@
 
     EchoGeneratingPower(render_buffer.GetSpectrumBuffer(), config_.echo_model,
                         render_buffer.Headroom(), aec_state.FilterDelayBlocks(),
-                        aec_state.IsSuppressionGainLimitActive(),
                         !aec_state.UseStationaryProperties(), &X2);
 
     // Subtract the stationary noise power to avoid stationary noise causing
@@ -148,15 +112,8 @@
                    });
 
     float echo_path_gain;
-    if (override_estimated_echo_path_gain_) {
-      echo_path_gain = aec_state.TransparentMode() && soft_transparent_mode_
-                           ? 0.01f
-                           : config_.ep_strength.lf;
-    } else {
-      echo_path_gain = aec_state.TransparentMode() && soft_transparent_mode_
-                           ? 0.01f
-                           : aec_state.EchoPathGain();
-    }
+    echo_path_gain =
+        aec_state.TransparentMode() ? 0.01f : config_.ep_strength.default_gain;
     NonLinearEstimate(echo_path_gain, X2, Y2, R2);
 
     // When there is saturated echo, assume the same spectral content as is
@@ -165,7 +122,7 @@
       std::copy(Y2.begin(), Y2.end(), R2->begin());
     }
 
-    if (!(aec_state.TransparentMode() && soft_transparent_mode_)) {
+    if (!(aec_state.TransparentMode())) {
       if (echo_reverb_) {
         echo_reverb_->AddReverbNoFreqShaping(
             render_buffer.Spectrum(aec_state.FilterDelayBlocks() + 1),
@@ -190,14 +147,6 @@
       }
     }
   }
-  if (!soft_transparent_mode_) {
-    // If the echo is deemed inaudible, set the residual echo to zero.
-    if (aec_state.TransparentMode()) {
-      R2->fill(0.f);
-      R2_old_.fill(0.f);
-      R2_hold_counter_.fill(0.f);
-    }
-  }
 
   std::copy(R2->begin(), R2->end(), R2_old_.begin());
 }
@@ -243,22 +192,6 @@
   std::transform(X2.begin(), X2.end(), R2->begin(), [echo_path_gain](float a) {
     return a * echo_path_gain * echo_path_gain;
   });
-
-  if (use_fixed_nonlinear_reverb_model_) {
-    for (size_t k = 0; k < R2->size(); ++k) {
-      // Update hold counter.
-      R2_hold_counter_[k] = R2_old_[k] < (*R2)[k] ? 0 : R2_hold_counter_[k] + 1;
-
-      // Compute the residual echo by holding a maximum echo powers and an echo
-      // fading corresponding to a room with an RT60 value of about 50 ms.
-      (*R2)[k] =
-          R2_hold_counter_[k] < config_.echo_model.nonlinear_hold
-              ? std::max((*R2)[k], R2_old_[k])
-              : std::min((*R2)[k] +
-                             R2_old_[k] * config_.echo_model.nonlinear_release,
-                         Y2[k]);
-    }
-  }
 }
 
 void ResidualEchoEstimator::EchoGeneratingPower(
@@ -266,15 +199,14 @@
     const EchoCanceller3Config::EchoModel& echo_model,
     int headroom_spectrum_buffer,
     int filter_delay_blocks,
-    bool gain_limiter_running,
     bool apply_noise_gating,
     std::array<float, kFftLengthBy2Plus1>* X2) const {
   int idx_stop, idx_start;
 
   RTC_DCHECK(X2);
   GetRenderIndexesToAnalyze(spectrum_buffer, config_.echo_model,
-                            filter_delay_blocks, gain_limiter_running,
-                            headroom_spectrum_buffer, &idx_start, &idx_stop);
+                            filter_delay_blocks, headroom_spectrum_buffer,
+                            &idx_start, &idx_stop);
 
   X2->fill(0.f);
   for (int k = idx_start; k != idx_stop; k = spectrum_buffer.IncIndex(k)) {
diff --git a/modules/audio_processing/aec3/residual_echo_estimator.h b/modules/audio_processing/aec3/residual_echo_estimator.h
index 52885a5..3909054 100644
--- a/modules/audio_processing/aec3/residual_echo_estimator.h
+++ b/modules/audio_processing/aec3/residual_echo_estimator.h
@@ -23,7 +23,7 @@
 #include "modules/audio_processing/aec3/reverb_model_fallback.h"
 #include "modules/audio_processing/aec3/vector_buffer.h"
 #include "rtc_base/checks.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
@@ -72,7 +72,6 @@
                            const EchoCanceller3Config::EchoModel& echo_model,
                            int headroom_spectrum_buffer,
                            int filter_delay_blocks,
-                           bool gain_limiter_running,
                            bool apply_noise_gating,
                            std::array<float, kFftLengthBy2Plus1>* X2) const;
 
@@ -88,9 +87,6 @@
   std::array<int, kFftLengthBy2Plus1> R2_hold_counter_;
   std::array<float, kFftLengthBy2Plus1> X2_noise_floor_;
   std::array<int, kFftLengthBy2Plus1> X2_noise_floor_counter_;
-  const bool soft_transparent_mode_;
-  const bool override_estimated_echo_path_gain_;
-  const bool use_fixed_nonlinear_reverb_model_;
   std::unique_ptr<ReverbModel> echo_reverb_;
   std::unique_ptr<ReverbModelFallback> echo_reverb_fallback;
   RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(ResidualEchoEstimator);
diff --git a/modules/audio_processing/aec3/residual_echo_estimator_unittest.cc b/modules/audio_processing/aec3/residual_echo_estimator_unittest.cc
index 2e73a7e..6214025 100644
--- a/modules/audio_processing/aec3/residual_echo_estimator_unittest.cc
+++ b/modules/audio_processing/aec3/residual_echo_estimator_unittest.cc
@@ -27,7 +27,7 @@
   EchoCanceller3Config config;
   AecState aec_state(config);
   std::unique_ptr<RenderDelayBuffer> render_delay_buffer(
-      RenderDelayBuffer::Create2(config, 3));
+      RenderDelayBuffer::Create(config, 3));
   std::vector<std::array<float, kFftLengthBy2Plus1>> H2;
   std::array<float, kFftLengthBy2Plus1> S2_linear;
   std::array<float, kFftLengthBy2Plus1> Y2;
@@ -44,11 +44,10 @@
 TEST(ResidualEchoEstimator, DISABLED_BasicTest) {
   EchoCanceller3Config config;
   config.ep_strength.default_len = 0.f;
-  config.delay.min_echo_path_delay_blocks = 0;
   ResidualEchoEstimator estimator(config);
   AecState aec_state(config);
   std::unique_ptr<RenderDelayBuffer> render_delay_buffer(
-      RenderDelayBuffer::Create2(config, 3));
+      RenderDelayBuffer::Create(config, 3));
 
   std::array<float, kFftLengthBy2Plus1> E2_main;
   std::array<float, kFftLengthBy2Plus1> E2_shadow;
diff --git a/modules/audio_processing/aec3/reverb_decay_estimator.cc b/modules/audio_processing/aec3/reverb_decay_estimator.cc
index 95fd13a..cdcbee5 100644
--- a/modules/audio_processing/aec3/reverb_decay_estimator.cc
+++ b/modules/audio_processing/aec3/reverb_decay_estimator.cc
@@ -19,17 +19,11 @@
 #include "api/audio/echo_canceller3_config.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.
@@ -92,8 +86,7 @@
 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()),
+      use_adaptive_echo_decay_(config.ep_strength.default_len < 0.f),
       early_reverb_estimator_(config.filter.main.length_blocks -
                               kEarlyReverbMinSizeBlocks),
       late_reverb_start_(kEarlyReverbMinSizeBlocks),
@@ -287,7 +280,7 @@
   // 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;
+  count_ = N > 0 ? -N * 0.5f + 0.5f : 0.f;
   N_ = N;
   n_ = 0;
 }
diff --git a/modules/audio_processing/aec3/reverb_frequency_response.cc b/modules/audio_processing/aec3/reverb_frequency_response.cc
index d2103d4..98eeca6 100644
--- a/modules/audio_processing/aec3/reverb_frequency_response.cc
+++ b/modules/audio_processing/aec3/reverb_frequency_response.cc
@@ -18,17 +18,11 @@
 #include "api/array_view.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.
@@ -54,8 +48,7 @@
 
 }  // namespace
 
-ReverbFrequencyResponse::ReverbFrequencyResponse()
-    : enable_smooth_tail_response_updates_(EnableSmoothUpdatesTailFreqResp()) {
+ReverbFrequencyResponse::ReverbFrequencyResponse() {
   tail_response_.fill(0.f);
 }
 ReverbFrequencyResponse::~ReverbFrequencyResponse() = default;
@@ -66,10 +59,6 @@
     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;
diff --git a/modules/audio_processing/aec3/reverb_frequency_response.h b/modules/audio_processing/aec3/reverb_frequency_response.h
index eb63b8e..b164186 100644
--- a/modules/audio_processing/aec3/reverb_frequency_response.h
+++ b/modules/audio_processing/aec3/reverb_frequency_response.h
@@ -44,7 +44,6 @@
               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_;
 };
diff --git a/modules/audio_processing/aec3/shadow_filter_update_gain_unittest.cc b/modules/audio_processing/aec3/shadow_filter_update_gain_unittest.cc
index 017c679..9d87cc8 100644
--- a/modules/audio_processing/aec3/shadow_filter_update_gain_unittest.cc
+++ b/modules/audio_processing/aec3/shadow_filter_update_gain_unittest.cc
@@ -50,10 +50,9 @@
                                   DetectOptimization(), &data_dumper);
   Aec3Fft fft;
 
-  config.delay.min_echo_path_delay_blocks = 0;
   config.delay.default_delay = 1;
   std::unique_ptr<RenderDelayBuffer> render_delay_buffer(
-      RenderDelayBuffer::Create2(config, 3));
+      RenderDelayBuffer::Create(config, 3));
 
   std::array<float, kBlockSize> x_old;
   x_old.fill(0.f);
diff --git a/modules/audio_processing/aec3/signal_dependent_erle_estimator.cc b/modules/audio_processing/aec3/signal_dependent_erle_estimator.cc
index 32b36ab..6a8d7e3 100644
--- a/modules/audio_processing/aec3/signal_dependent_erle_estimator.cc
+++ b/modules/audio_processing/aec3/signal_dependent_erle_estimator.cc
@@ -122,7 +122,7 @@
     : min_erle_(config.erle.min),
       num_sections_(config.erle.num_sections),
       num_blocks_(config.filter.main.length_blocks),
-      delay_headroom_blocks_(config.delay.delay_headroom_blocks),
+      delay_headroom_blocks_(config.delay.delay_headroom_samples / kBlockSize),
       band_to_subband_(FormSubbandMap()),
       max_erle_(SetMaxErleSubbands(config.erle.max_l,
                                    config.erle.max_h,
@@ -201,7 +201,6 @@
   for (auto& factor : correction_factors_) {
     data_dumper->DumpRaw("aec3_erle_correction_factor", factor);
   }
-  data_dumper->DumpRaw("aec3_erle", erle_);
 }
 
 // Estimates for each band the smallest number of sections in the filter that
diff --git a/modules/audio_processing/aec3/signal_dependent_erle_estimator_unittest.cc b/modules/audio_processing/aec3/signal_dependent_erle_estimator_unittest.cc
index aec605f..4e62c94 100644
--- a/modules/audio_processing/aec3/signal_dependent_erle_estimator_unittest.cc
+++ b/modules/audio_processing/aec3/signal_dependent_erle_estimator_unittest.cc
@@ -62,7 +62,7 @@
 };
 
 TestInputs::TestInputs(const EchoCanceller3Config& cfg)
-    : render_delay_buffer_(RenderDelayBuffer::Create2(cfg, 1)),
+    : render_delay_buffer_(RenderDelayBuffer::Create(cfg, 1)),
       H2_(cfg.filter.main.length_blocks),
       x_(1, std::vector<float>(kBlockSize, 0.f)) {
   render_delay_buffer_->SetDelay(4);
@@ -115,7 +115,7 @@
         cfg.filter.main.length_blocks = blocks;
         cfg.filter.main_initial.length_blocks =
             std::min(cfg.filter.main_initial.length_blocks, blocks);
-        cfg.delay.delay_headroom_blocks = delay_headroom;
+        cfg.delay.delay_headroom_samples = delay_headroom * kBlockSize;
         cfg.erle.num_sections = num_sections;
         if (EchoCanceller3Config::Validate(&cfg)) {
           SignalDependentErleEstimator s(cfg);
@@ -137,8 +137,8 @@
   EchoCanceller3Config cfg;
   cfg.filter.main.length_blocks = 2;
   cfg.filter.main_initial.length_blocks = 1;
-  cfg.delay.delay_headroom_blocks = 0;
-  cfg.delay.hysteresis_limit_1_blocks = 0;
+  cfg.delay.delay_headroom_samples = 0;
+  cfg.delay.hysteresis_limit_blocks = 0;
   cfg.erle.num_sections = 2;
   EXPECT_EQ(EchoCanceller3Config::Validate(&cfg), true);
   std::array<float, kFftLengthBy2Plus1> average_erle;
diff --git a/modules/audio_processing/aec3/skew_estimator.h b/modules/audio_processing/aec3/skew_estimator.h
index b0946d8..8a457cb 100644
--- a/modules/audio_processing/aec3/skew_estimator.h
+++ b/modules/audio_processing/aec3/skew_estimator.h
@@ -15,7 +15,7 @@
 #include <vector>
 
 #include "absl/types/optional.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
diff --git a/modules/audio_processing/aec3/stationarity_estimator.cc b/modules/audio_processing/aec3/stationarity_estimator.cc
index 25100bf..47f04bf 100644
--- a/modules/audio_processing/aec3/stationarity_estimator.cc
+++ b/modules/audio_processing/aec3/stationarity_estimator.cc
@@ -18,7 +18,7 @@
 #include "modules/audio_processing/aec3/aec3_common.h"
 #include "modules/audio_processing/aec3/vector_buffer.h"
 #include "modules/audio_processing/logging/apm_data_dumper.h"
-#include "rtc_base/atomicops.h"
+#include "rtc_base/atomic_ops.h"
 
 namespace webrtc {
 
diff --git a/modules/audio_processing/aec3/subband_erle_estimator.cc b/modules/audio_processing/aec3/subband_erle_estimator.cc
index 9453e57..82f3dab 100644
--- a/modules/audio_processing/aec3/subband_erle_estimator.cc
+++ b/modules/audio_processing/aec3/subband_erle_estimator.cc
@@ -26,10 +26,6 @@
 constexpr int kBlocksForOnsetDetection = kBlocksToHoldErle + 150;
 constexpr int kPointsToAccumulate = 6;
 
-bool EnableAdaptErleOnLowRender() {
-  return !field_trial::IsEnabled("WebRTC-Aec3AdaptErleOnLowRenderKillSwitch");
-}
-
 std::array<float, kFftLengthBy2Plus1> SetMaxErleBands(float max_erle_l,
                                                       float max_erle_h) {
   std::array<float, kFftLengthBy2Plus1> max_erle;
@@ -38,12 +34,16 @@
   return max_erle;
 }
 
+bool EnableMinErleDuringOnsets() {
+  return !field_trial::IsEnabled("WebRTC-Aec3MinErleDuringOnsetsKillSwitch");
+}
+
 }  // namespace
 
 SubbandErleEstimator::SubbandErleEstimator(const EchoCanceller3Config& config)
     : min_erle_(config.erle.min),
       max_erle_(SetMaxErleBands(config.erle.max_l, config.erle.max_h)),
-      adapt_on_low_render_(EnableAdaptErleOnLowRender()) {
+      use_min_erle_during_onsets_(EnableMinErleDuringOnsets()) {
   Reset();
 }
 
@@ -101,10 +101,12 @@
       if (is_erle_updated[k] && !accum_spectra_.low_render_energy_[k]) {
         if (coming_onset_[k]) {
           coming_onset_[k] = false;
-          float alpha = new_erle[k] < erle_onsets_[k] ? 0.3f : 0.15f;
-          erle_onsets_[k] = rtc::SafeClamp(
-              erle_onsets_[k] + alpha * (new_erle[k] - erle_onsets_[k]),
-              min_erle_, max_erle_[k]);
+          if (!use_min_erle_during_onsets_) {
+            float alpha = new_erle[k] < erle_onsets_[k] ? 0.3f : 0.15f;
+            erle_onsets_[k] = rtc::SafeClamp(
+                erle_onsets_[k] + alpha * (new_erle[k] - erle_onsets_[k]),
+                min_erle_, max_erle_[k]);
+          }
         }
         hold_counters_[k] = kBlocksForOnsetDetection;
       }
@@ -151,43 +153,23 @@
     rtc::ArrayView<const float> Y2,
     rtc::ArrayView<const float> E2) {
   auto& st = accum_spectra_;
-  if (adapt_on_low_render_) {
-    if (st.num_points_[0] == kPointsToAccumulate) {
-      st.num_points_[0] = 0;
-      st.Y2_.fill(0.f);
-      st.E2_.fill(0.f);
-      st.low_render_energy_.fill(false);
-    }
-    std::transform(Y2.begin(), Y2.end(), st.Y2_.begin(), st.Y2_.begin(),
-                   std::plus<float>());
-    std::transform(E2.begin(), E2.end(), st.E2_.begin(), st.E2_.begin(),
-                   std::plus<float>());
-
-    for (size_t k = 0; k < X2.size(); ++k) {
-      st.low_render_energy_[k] =
-          st.low_render_energy_[k] || X2[k] < kX2BandEnergyThreshold;
-    }
-    st.num_points_[0]++;
-    st.num_points_.fill(st.num_points_[0]);
-
-  } else {
-    // The update is always done using high render energy signals and
-    // therefore the field accum_spectra_.low_render_energy_ does not need to
-    // be modified.
-    for (size_t k = 0; k < X2.size(); ++k) {
-      if (X2[k] > kX2BandEnergyThreshold) {
-        if (st.num_points_[k] == kPointsToAccumulate) {
-          st.Y2_[k] = 0.f;
-          st.E2_[k] = 0.f;
-          st.num_points_[k] = 0;
-        }
-        st.Y2_[k] += Y2[k];
-        st.E2_[k] += E2[k];
-        st.num_points_[k]++;
-      }
-      RTC_DCHECK_EQ(st.low_render_energy_[k], false);
-    }
+  if (st.num_points_[0] == kPointsToAccumulate) {
+    st.num_points_[0] = 0;
+    st.Y2_.fill(0.f);
+    st.E2_.fill(0.f);
+    st.low_render_energy_.fill(false);
   }
+  std::transform(Y2.begin(), Y2.end(), st.Y2_.begin(), st.Y2_.begin(),
+                 std::plus<float>());
+  std::transform(E2.begin(), E2.end(), st.E2_.begin(), st.E2_.begin(),
+                 std::plus<float>());
+
+  for (size_t k = 0; k < X2.size(); ++k) {
+    st.low_render_energy_[k] =
+        st.low_render_energy_[k] || X2[k] < kX2BandEnergyThreshold;
+  }
+  st.num_points_[0]++;
+  st.num_points_.fill(st.num_points_[0]);
 }
 
 }  // namespace webrtc
diff --git a/modules/audio_processing/aec3/subband_erle_estimator.h b/modules/audio_processing/aec3/subband_erle_estimator.h
index b9862db..903c629 100644
--- a/modules/audio_processing/aec3/subband_erle_estimator.h
+++ b/modules/audio_processing/aec3/subband_erle_estimator.h
@@ -66,7 +66,7 @@
 
   const float min_erle_;
   const std::array<float, kFftLengthBy2Plus1> max_erle_;
-  const bool adapt_on_low_render_;
+  const bool use_min_erle_during_onsets_;
   AccumulatedSpectra accum_spectra_;
   std::array<float, kFftLengthBy2Plus1> erle_;
   std::array<float, kFftLengthBy2Plus1> erle_onsets_;
diff --git a/modules/audio_processing/aec3/subtractor.cc b/modules/audio_processing/aec3/subtractor.cc
index 90069c7..aa38a34 100644
--- a/modules/audio_processing/aec3/subtractor.cc
+++ b/modules/audio_processing/aec3/subtractor.cc
@@ -18,44 +18,16 @@
 #include "modules/audio_processing/logging/apm_data_dumper.h"
 #include "rtc_base/checks.h"
 #include "rtc_base/numerics/safe_minmax.h"
-#include "system_wrappers/include/field_trial.h"
 
 namespace webrtc {
 
 namespace {
 
-bool EnableAgcGainChangeResponse() {
-  return !field_trial::IsEnabled("WebRTC-Aec3AgcGainChangeResponseKillSwitch");
-}
-
-bool EnableAdaptationDuringSaturation() {
-  return !field_trial::IsEnabled("WebRTC-Aec3RapidAgcGainRecoveryKillSwitch");
-}
-
-bool EnableMisadjustmentEstimator() {
-  return !field_trial::IsEnabled("WebRTC-Aec3MisadjustmentEstimatorKillSwitch");
-}
-
-bool EnableShadowFilterJumpstart() {
-  return !field_trial::IsEnabled("WebRTC-Aec3ShadowFilterJumpstartKillSwitch");
-}
-
-bool EnableShadowFilterBoostedJumpstart() {
-  return !field_trial::IsEnabled(
-      "WebRTC-Aec3ShadowFilterBoostedJumpstartKillSwitch");
-}
-
-bool EnableEarlyShadowFilterJumpstart() {
-  return !field_trial::IsEnabled(
-      "WebRTC-Aec3EarlyShadowFilterJumpstartKillSwitch");
-}
-
 void PredictionError(const Aec3Fft& fft,
                      const FftData& S,
                      rtc::ArrayView<const float> y,
                      std::array<float, kBlockSize>* e,
                      std::array<float, kBlockSize>* s,
-                     bool adaptation_during_saturation,
                      bool* saturation) {
   std::array<float, kFftLength> tmp;
   fft.Ifft(S, &tmp);
@@ -77,12 +49,7 @@
     *saturation = *result.first <= -32768 || *result.first >= 32767;
   }
 
-  if (!adaptation_during_saturation) {
-    std::for_each(e->begin(), e->end(),
-                  [](float& a) { a = rtc::SafeClamp(a, -32768.f, 32767.f); });
-  } else {
-    *saturation = false;
-  }
+  *saturation = false;
 }
 
 void ScaleFilterOutput(rtc::ArrayView<const float> y,
@@ -106,13 +73,6 @@
       data_dumper_(data_dumper),
       optimization_(optimization),
       config_(config),
-      adaptation_during_saturation_(EnableAdaptationDuringSaturation()),
-      enable_misadjustment_estimator_(EnableMisadjustmentEstimator()),
-      enable_agc_gain_change_response_(EnableAgcGainChangeResponse()),
-      enable_shadow_filter_jumpstart_(EnableShadowFilterJumpstart()),
-      enable_shadow_filter_boosted_jumpstart_(
-          EnableShadowFilterBoostedJumpstart()),
-      enable_early_shadow_filter_jumpstart_(EnableEarlyShadowFilterJumpstart()),
       main_filter_(config_.filter.main.length_blocks,
                    config_.filter.main_initial.length_blocks,
                    config.filter.config_change_duration_blocks,
@@ -152,7 +112,7 @@
     full_reset();
   }
 
-  if (echo_path_variability.gain_change && enable_agc_gain_change_response_) {
+  if (echo_path_variability.gain_change) {
     G_main_.HandleEchoPathChange(echo_path_variability);
   }
 }
@@ -182,28 +142,24 @@
   // Form the outputs of the main and shadow filters.
   main_filter_.Filter(render_buffer, &S);
   bool main_saturation = false;
-  PredictionError(fft_, S, y, &e_main, &output->s_main,
-                  adaptation_during_saturation_, &main_saturation);
+  PredictionError(fft_, S, y, &e_main, &output->s_main, &main_saturation);
 
   shadow_filter_.Filter(render_buffer, &S);
   bool shadow_saturation = false;
-  PredictionError(fft_, S, y, &e_shadow, &output->s_shadow,
-                  adaptation_during_saturation_, &shadow_saturation);
+  PredictionError(fft_, S, y, &e_shadow, &output->s_shadow, &shadow_saturation);
 
   // Compute the signal powers in the subtractor output.
   output->ComputeMetrics(y);
 
   // Adjust the filter if needed.
   bool main_filter_adjusted = false;
-  if (enable_misadjustment_estimator_) {
-    filter_misadjustment_estimator_.Update(*output);
-    if (filter_misadjustment_estimator_.IsAdjustmentNeeded()) {
-      float scale = filter_misadjustment_estimator_.GetMisadjustment();
-      main_filter_.ScaleFilter(scale);
-      ScaleFilterOutput(y, scale, e_main, output->s_main);
-      filter_misadjustment_estimator_.Reset();
-      main_filter_adjusted = true;
-    }
+  filter_misadjustment_estimator_.Update(*output);
+  if (filter_misadjustment_estimator_.IsAdjustmentNeeded()) {
+    float scale = filter_misadjustment_estimator_.GetMisadjustment();
+    main_filter_.ScaleFilter(scale);
+    ScaleFilterOutput(y, scale, e_main, output->s_main);
+    filter_misadjustment_estimator_.Reset();
+    main_filter_adjusted = true;
   }
 
   // Compute the FFts of the main and shadow filter outputs.
@@ -248,40 +204,26 @@
   // Update the shadow filter.
   poor_shadow_filter_counter_ =
       output->e2_main < output->e2_shadow ? poor_shadow_filter_counter_ + 1 : 0;
-  if (((poor_shadow_filter_counter_ < 5 &&
-        enable_early_shadow_filter_jumpstart_) ||
-       (poor_shadow_filter_counter_ < 10 &&
-        !enable_early_shadow_filter_jumpstart_)) ||
-      !enable_shadow_filter_jumpstart_) {
+  if (poor_shadow_filter_counter_ < 5) {
     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_shadow, render_signal_analyzer, E_main,
-                        shadow_filter_.SizePartitions(),
-                        aec_state.SaturatedCapture() || main_saturation, &G);
-      shadow_filter_.Adapt(render_buffer, G);
-    } else {
-      G.re.fill(0.f);
-      G.im.fill(0.f);
-      shadow_filter_.Adapt(render_buffer, G);
-      shadow_filter_.SetFilter(main_filter_.GetFilter());
-    }
+    shadow_filter_.SetFilter(main_filter_.GetFilter());
+    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);
   data_dumper_->DumpRaw("aec3_subtractor_G_shadow", G.re);
   data_dumper_->DumpRaw("aec3_subtractor_G_shadow", G.im);
   filter_misadjustment_estimator_.Dump(data_dumper_);
   DumpFilters();
 
-  if (adaptation_during_saturation_) {
-    std::for_each(e_main.begin(), e_main.end(),
-                  [](float& a) { a = rtc::SafeClamp(a, -32768.f, 32767.f); });
-  }
+  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);
diff --git a/modules/audio_processing/aec3/subtractor.h b/modules/audio_processing/aec3/subtractor.h
index bec014d..910be18 100644
--- a/modules/audio_processing/aec3/subtractor.h
+++ b/modules/audio_processing/aec3/subtractor.h
@@ -30,7 +30,7 @@
 #include "modules/audio_processing/aec3/subtractor_output.h"
 #include "modules/audio_processing/logging/apm_data_dumper.h"
 #include "rtc_base/checks.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
@@ -107,12 +107,6 @@
   ApmDataDumper* data_dumper_;
   const Aec3Optimization optimization_;
   const EchoCanceller3Config config_;
-  const bool adaptation_during_saturation_;
-  const bool enable_misadjustment_estimator_;
-  const bool enable_agc_gain_change_response_;
-  const bool enable_shadow_filter_jumpstart_;
-  const bool enable_shadow_filter_boosted_jumpstart_;
-  const bool enable_early_shadow_filter_jumpstart_;
 
   AdaptiveFirFilter main_filter_;
   AdaptiveFirFilter shadow_filter_;
diff --git a/modules/audio_processing/aec3/subtractor_output_analyzer.cc b/modules/audio_processing/aec3/subtractor_output_analyzer.cc
index 9374b80..9a0e0bb 100644
--- a/modules/audio_processing/aec3/subtractor_output_analyzer.cc
+++ b/modules/audio_processing/aec3/subtractor_output_analyzer.cc
@@ -13,19 +13,10 @@
 #include <algorithm>
 
 #include "modules/audio_processing/aec3/aec3_common.h"
-#include "system_wrappers/include/field_trial.h"
 
 namespace webrtc {
-namespace {
 
-bool EnableStrictDivergenceCheck() {
-  return !field_trial::IsEnabled("WebRTC-Aec3StrictDivergenceCheckKillSwitch");
-}
-
-}  // namespace
-
-SubtractorOutputAnalyzer::SubtractorOutputAnalyzer()
-    : strict_divergence_check_(EnableStrictDivergenceCheck()) {}
+SubtractorOutputAnalyzer::SubtractorOutputAnalyzer() {}
 
 void SubtractorOutputAnalyzer::Update(
     const SubtractorOutput& subtractor_output) {
@@ -37,8 +28,7 @@
   main_filter_converged_ = e2_main < 0.5f * y2 && y2 > kConvergenceThreshold;
   shadow_filter_converged_ =
       e2_shadow < 0.05f * y2 && y2 > kConvergenceThreshold;
-  float min_e2 =
-      strict_divergence_check_ ? std::min(e2_main, e2_shadow) : e2_main;
+  float min_e2 = std::min(e2_main, e2_shadow);
   filter_diverged_ = min_e2 > 1.5f * y2 && y2 > 30.f * 30.f * kBlockSize;
 }
 
diff --git a/modules/audio_processing/aec3/subtractor_output_analyzer.h b/modules/audio_processing/aec3/subtractor_output_analyzer.h
index 0e23ad5..76a2560 100644
--- a/modules/audio_processing/aec3/subtractor_output_analyzer.h
+++ b/modules/audio_processing/aec3/subtractor_output_analyzer.h
@@ -34,7 +34,6 @@
   void HandleEchoPathChange();
 
  private:
-  const bool strict_divergence_check_;
   bool shadow_filter_converged_ = false;
   bool main_filter_converged_ = false;
   bool filter_diverged_ = false;
diff --git a/modules/audio_processing/aec3/subtractor_unittest.cc b/modules/audio_processing/aec3/subtractor_unittest.cc
index 8d14cc1..99d8e1b 100644
--- a/modules/audio_processing/aec3/subtractor_unittest.cc
+++ b/modules/audio_processing/aec3/subtractor_unittest.cc
@@ -41,10 +41,9 @@
   std::vector<float> y(kBlockSize, 0.f);
   std::array<float, kBlockSize> x_old;
   SubtractorOutput output;
-  config.delay.min_echo_path_delay_blocks = 0;
   config.delay.default_delay = 1;
   std::unique_ptr<RenderDelayBuffer> render_delay_buffer(
-      RenderDelayBuffer::Create2(config, 3));
+      RenderDelayBuffer::Create(config, 3));
   RenderSignalAnalyzer render_signal_analyzer(config);
   Random random_generator(42U);
   Aec3Fft fft;
@@ -127,7 +126,7 @@
   EchoCanceller3Config config;
   Subtractor subtractor(config, &data_dumper, DetectOptimization());
   std::unique_ptr<RenderDelayBuffer> render_delay_buffer(
-      RenderDelayBuffer::Create2(config, 3));
+      RenderDelayBuffer::Create(config, 3));
   RenderSignalAnalyzer render_signal_analyzer(config);
   std::vector<float> y(kBlockSize, 0.f);
 
@@ -143,7 +142,7 @@
   EchoCanceller3Config config;
   Subtractor subtractor(config, &data_dumper, DetectOptimization());
   std::unique_ptr<RenderDelayBuffer> render_delay_buffer(
-      RenderDelayBuffer::Create2(config, 3));
+      RenderDelayBuffer::Create(config, 3));
   RenderSignalAnalyzer render_signal_analyzer(config);
   std::vector<float> y(kBlockSize - 1, 0.f);
   SubtractorOutput output;
diff --git a/modules/audio_processing/aec3/suppression_filter.h b/modules/audio_processing/aec3/suppression_filter.h
index edd1290..63569b1 100644
--- a/modules/audio_processing/aec3/suppression_filter.h
+++ b/modules/audio_processing/aec3/suppression_filter.h
@@ -18,7 +18,7 @@
 #include "modules/audio_processing/aec3/aec3_fft.h"
 #include "modules/audio_processing/aec3/fft_data.h"
 #include "modules/audio_processing/utility/ooura_fft.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
diff --git a/modules/audio_processing/aec3/suppression_gain.cc b/modules/audio_processing/aec3/suppression_gain.cc
index c6d2bf6..e258682 100644
--- a/modules/audio_processing/aec3/suppression_gain.cc
+++ b/modules/audio_processing/aec3/suppression_gain.cc
@@ -18,7 +18,7 @@
 #include "modules/audio_processing/aec3/moving_average.h"
 #include "modules/audio_processing/aec3/vector_math.h"
 #include "modules/audio_processing/logging/apm_data_dumper.h"
-#include "rtc_base/atomicops.h"
+#include "rtc_base/atomic_ops.h"
 #include "rtc_base/checks.h"
 
 namespace webrtc {
@@ -346,14 +346,6 @@
                 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();
-  if (gain_upper_bound < 1.f) {
-    for (size_t k = 0; k < low_band_gain->size(); ++k) {
-      (*low_band_gain)[k] = std::min((*low_band_gain)[k], gain_upper_bound);
-    }
-  }
-
   // Compute the gain for the upper bands.
   const absl::optional<int> narrow_peak_band =
       render_signal_analyzer.NarrowPeakBand();
diff --git a/modules/audio_processing/aec3/suppression_gain.h b/modules/audio_processing/aec3/suppression_gain.h
index e74cd96..9e33c28 100644
--- a/modules/audio_processing/aec3/suppression_gain.h
+++ b/modules/audio_processing/aec3/suppression_gain.h
@@ -24,7 +24,7 @@
 #include "modules/audio_processing/aec3/moving_average.h"
 #include "modules/audio_processing/aec3/render_signal_analyzer.h"
 #include "modules/audio_processing/logging/apm_data_dumper.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
diff --git a/modules/audio_processing/aec3/suppression_gain_limiter.cc b/modules/audio_processing/aec3/suppression_gain_limiter.cc
deleted file mode 100644
index 6625a77..0000000
--- a/modules/audio_processing/aec3/suppression_gain_limiter.cc
+++ /dev/null
@@ -1,93 +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/suppression_gain_limiter.h"
-
-#include <math.h>
-#include <algorithm>
-
-#include "modules/audio_processing/aec3/aec3_common.h"
-#include "rtc_base/checks.h"
-
-namespace webrtc {
-namespace {
-
-// Computes the gain rampup factor to use.
-float ComputeGainRampupIncrease(
-    const EchoCanceller3Config::EchoRemovalControl::GainRampup& rampup_config) {
-  return powf(1.f / rampup_config.first_non_zero_gain,
-              1.f / rampup_config.non_zero_gain_blocks);
-}
-
-}  // namespace
-
-SuppressionGainUpperLimiter::SuppressionGainUpperLimiter(
-    const EchoCanceller3Config& config)
-    : rampup_config_(config.echo_removal_control.gain_rampup),
-      gain_rampup_increase_(ComputeGainRampupIncrease(rampup_config_)) {
-  Reset();
-}
-
-void SuppressionGainUpperLimiter::Reset() {
-  recent_reset_ = true;
-}
-
-void SuppressionGainUpperLimiter::Update(bool render_activity,
-                                         bool transparent_mode) {
-  if (transparent_mode) {
-    active_render_seen_ = true;
-    call_startup_phase_ = false;
-    recent_reset_ = false;
-    suppressor_gain_limit_ = 1.f;
-    return;
-  }
-
-  if (recent_reset_ && !call_startup_phase_) {
-    // Only enforce 250 ms full suppression after in-call resets,
-    constexpr int kMuteFramesAfterReset = kNumBlocksPerSecond / 4;
-    realignment_counter_ = kMuteFramesAfterReset;
-  } else if (!active_render_seen_ && render_activity) {
-    // Enforce a tailormade suppression limiting during call startup.
-    active_render_seen_ = true;
-    realignment_counter_ = rampup_config_.full_gain_blocks;
-  } else if (realignment_counter_ > 0) {
-    if (--realignment_counter_ == 0) {
-      call_startup_phase_ = false;
-    }
-  }
-  recent_reset_ = false;
-
-  // Do not enforce any gain limit on the suppressor.
-  if (!IsActive()) {
-    suppressor_gain_limit_ = 1.f;
-    return;
-  }
-
-  // Enforce full suppression.
-  if (realignment_counter_ > rampup_config_.non_zero_gain_blocks ||
-      (!call_startup_phase_ && realignment_counter_ > 0)) {
-    suppressor_gain_limit_ = rampup_config_.initial_gain;
-    return;
-  }
-
-  // Start increasing the gain limit.
-  if (realignment_counter_ == rampup_config_.non_zero_gain_blocks) {
-    suppressor_gain_limit_ = rampup_config_.first_non_zero_gain;
-    return;
-  }
-
-  // Increase the gain limit until it reaches 1.f.
-  RTC_DCHECK_LT(0.f, suppressor_gain_limit_);
-  suppressor_gain_limit_ =
-      std::min(1.f, suppressor_gain_limit_ * gain_rampup_increase_);
-  RTC_DCHECK_GE(1.f, suppressor_gain_limit_);
-}
-
-}  // namespace webrtc
diff --git a/modules/audio_processing/aec3/suppression_gain_limiter.h b/modules/audio_processing/aec3/suppression_gain_limiter.h
deleted file mode 100644
index eade949..0000000
--- a/modules/audio_processing/aec3/suppression_gain_limiter.h
+++ /dev/null
@@ -1,58 +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_SUPPRESSION_GAIN_LIMITER_H_
-#define MODULES_AUDIO_PROCESSING_AEC3_SUPPRESSION_GAIN_LIMITER_H_
-
-#include "api/array_view.h"
-#include "api/audio/echo_canceller3_config.h"
-#include "rtc_base/constructormagic.h"
-
-namespace webrtc {
-
-// Class for applying a smoothly increasing limit for the suppression gain
-// during call startup and after in-call resets.
-class SuppressionGainUpperLimiter {
- public:
-  explicit SuppressionGainUpperLimiter(const EchoCanceller3Config& config);
-
-  // Reset the limiting behavior.
-  void Reset();
-
-  // Updates the limiting behavior for the current capture bloc.
-  void Update(bool render_activity, bool transparent_mode);
-
-  // Returns the current suppressor gain limit.
-  float Limit() const { return suppressor_gain_limit_; }
-
-  // Return whether the suppressor gain limit is active.
-  bool IsActive() const { return (realignment_counter_ > 0); }
-
-  // Inactivate limiter.
-  void Deactivate() {
-    realignment_counter_ = 0;
-    suppressor_gain_limit_ = 1.f;
-  }
-
- private:
-  const EchoCanceller3Config::EchoRemovalControl::GainRampup rampup_config_;
-  const float gain_rampup_increase_;
-  bool call_startup_phase_ = true;
-  int realignment_counter_ = 0;
-  bool active_render_seen_ = false;
-  float suppressor_gain_limit_ = 1.f;
-  bool recent_reset_ = false;
-
-  RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(SuppressionGainUpperLimiter);
-};
-
-}  // namespace webrtc
-
-#endif  // MODULES_AUDIO_PROCESSING_AEC3_SUPPRESSION_GAIN_LIMITER_H_
diff --git a/modules/audio_processing/aec3/suppression_gain_unittest.cc b/modules/audio_processing/aec3/suppression_gain_unittest.cc
index 651fd36..1ff96ca 100644
--- a/modules/audio_processing/aec3/suppression_gain_unittest.cc
+++ b/modules/audio_processing/aec3/suppression_gain_unittest.cc
@@ -77,7 +77,7 @@
   ApmDataDumper data_dumper(42);
   Subtractor subtractor(config, &data_dumper, DetectOptimization());
   std::unique_ptr<RenderDelayBuffer> render_delay_buffer(
-      RenderDelayBuffer::Create2(config, 3));
+      RenderDelayBuffer::Create(config, 3));
   absl::optional<DelayEstimate> delay_estimate;
 
   // Ensure that a strong noise is detected to mask any echoes.
diff --git a/modules/audio_processing/aec_dump/aec_dump_impl.cc b/modules/audio_processing/aec_dump/aec_dump_impl.cc
index 9020f2b..588d24d 100644
--- a/modules/audio_processing/aec_dump/aec_dump_impl.cc
+++ b/modules/audio_processing/aec_dump/aec_dump_impl.cc
@@ -55,7 +55,7 @@
 
 }  // namespace
 
-AecDumpImpl::AecDumpImpl(std::unique_ptr<FileWrapper> debug_file,
+AecDumpImpl::AecDumpImpl(FileWrapper debug_file,
                          int64_t max_log_size_bytes,
                          rtc::TaskQueue* worker_queue)
     : debug_file_(std::move(debug_file)),
@@ -196,7 +196,7 @@
 }
 
 std::unique_ptr<WriteToFileTask> AecDumpImpl::CreateWriteToFileTask() {
-  return absl::make_unique<WriteToFileTask>(debug_file_.get(),
+  return absl::make_unique<WriteToFileTask>(&debug_file_,
                                             &num_bytes_left_for_log_);
 }
 
@@ -204,24 +204,20 @@
                                                 int64_t max_log_size_bytes,
                                                 rtc::TaskQueue* worker_queue) {
   RTC_DCHECK(worker_queue);
-  std::unique_ptr<FileWrapper> debug_file(FileWrapper::Create());
   FILE* handle = rtc::FdopenPlatformFileForWriting(file);
   if (!handle) {
     return nullptr;
   }
-  if (!debug_file->OpenFromFileHandle(handle)) {
-    return nullptr;
-  }
-  return absl::make_unique<AecDumpImpl>(std::move(debug_file),
-                                        max_log_size_bytes, worker_queue);
+  return absl::make_unique<AecDumpImpl>(FileWrapper(handle), max_log_size_bytes,
+                                        worker_queue);
 }
 
 std::unique_ptr<AecDump> AecDumpFactory::Create(std::string file_name,
                                                 int64_t max_log_size_bytes,
                                                 rtc::TaskQueue* worker_queue) {
   RTC_DCHECK(worker_queue);
-  std::unique_ptr<FileWrapper> debug_file(FileWrapper::Create());
-  if (!debug_file->OpenFile(file_name.c_str(), false)) {
+  FileWrapper debug_file = FileWrapper::OpenWriteOnly(file_name.c_str());
+  if (!debug_file.is_open()) {
     return nullptr;
   }
   return absl::make_unique<AecDumpImpl>(std::move(debug_file),
@@ -233,11 +229,7 @@
                                                 rtc::TaskQueue* worker_queue) {
   RTC_DCHECK(worker_queue);
   RTC_DCHECK(handle);
-  std::unique_ptr<FileWrapper> debug_file(FileWrapper::Create());
-  if (!debug_file->OpenFromFileHandle(handle)) {
-    return nullptr;
-  }
-  return absl::make_unique<AecDumpImpl>(std::move(debug_file),
-                                        max_log_size_bytes, worker_queue);
+  return absl::make_unique<AecDumpImpl>(FileWrapper(handle), max_log_size_bytes,
+                                        worker_queue);
 }
 }  // namespace webrtc
diff --git a/modules/audio_processing/aec_dump/aec_dump_impl.h b/modules/audio_processing/aec_dump/aec_dump_impl.h
index df949ca..c247c1b 100644
--- a/modules/audio_processing/aec_dump/aec_dump_impl.h
+++ b/modules/audio_processing/aec_dump/aec_dump_impl.h
@@ -46,7 +46,7 @@
 class AecDumpImpl : public AecDump {
  public:
   // Does member variables initialization shared across all c-tors.
-  AecDumpImpl(std::unique_ptr<FileWrapper> debug_file,
+  AecDumpImpl(FileWrapper debug_file,
               int64_t max_log_size_bytes,
               rtc::TaskQueue* worker_queue);
 
@@ -73,7 +73,7 @@
  private:
   std::unique_ptr<WriteToFileTask> CreateWriteToFileTask();
 
-  std::unique_ptr<FileWrapper> debug_file_;
+  FileWrapper debug_file_;
   int64_t num_bytes_left_for_log_ = 0;
   rtc::RaceChecker race_checker_;
   rtc::TaskQueue* worker_queue_;
diff --git a/modules/audio_processing/aec_dump/aec_dump_unittest.cc b/modules/audio_processing/aec_dump/aec_dump_unittest.cc
index 75ed529..1f9ca0a 100644
--- a/modules/audio_processing/aec_dump/aec_dump_unittest.cc
+++ b/modules/audio_processing/aec_dump/aec_dump_unittest.cc
@@ -14,7 +14,7 @@
 
 #include "rtc_base/task_queue.h"
 #include "test/gtest.h"
-#include "test/testsupport/fileutils.h"
+#include "test/testsupport/file_utils.h"
 
 TEST(AecDumper, APICallsDoNotCrash) {
   // Note order of initialization: Task queue has to be initialized
diff --git a/modules/audio_processing/aec_dump/write_to_file_task.cc b/modules/audio_processing/aec_dump/write_to_file_task.cc
index 8dddd47..4839a09 100644
--- a/modules/audio_processing/aec_dump/write_to_file_task.cc
+++ b/modules/audio_processing/aec_dump/write_to_file_task.cc
@@ -10,7 +10,7 @@
 
 #include "modules/audio_processing/aec_dump/write_to_file_task.h"
 
-#include "rtc_base/protobuf_utils.h"
+#include <string>
 
 namespace webrtc {
 
@@ -39,17 +39,15 @@
 }
 
 bool WriteToFileTask::Run() {
-  if (!debug_file_->is_open()) {
-    return true;
-  }
-
-  ProtoString event_string;
+  std::string event_string;
   event_.SerializeToString(&event_string);
 
   const size_t event_byte_size = event_.ByteSizeLong();
 
   if (!IsRoomForNextEvent(event_byte_size)) {
-    debug_file_->CloseFile();
+    // Ensure that no further events are written, even if they're smaller than
+    // the current event.
+    *num_bytes_left_for_log_ = 0;
     return true;
   }
 
diff --git a/modules/audio_processing/aec_dump/write_to_file_task.h b/modules/audio_processing/aec_dump/write_to_file_task.h
index 711afb2..4b04a45 100644
--- a/modules/audio_processing/aec_dump/write_to_file_task.h
+++ b/modules/audio_processing/aec_dump/write_to_file_task.h
@@ -48,9 +48,9 @@
 
   bool Run() override;
 
-  webrtc::FileWrapper* debug_file_;
+  webrtc::FileWrapper* const debug_file_;
   audioproc::Event event_;
-  int64_t* num_bytes_left_for_log_;
+  int64_t* const num_bytes_left_for_log_;
 };
 
 }  // namespace webrtc
diff --git a/modules/audio_processing/agc/BUILD.gn b/modules/audio_processing/agc/BUILD.gn
index a5c15ec..4c0e768 100644
--- a/modules/audio_processing/agc/BUILD.gn
+++ b/modules/audio_processing/agc/BUILD.gn
@@ -108,11 +108,6 @@
     ]
     configs += [ "..:apm_debug_dump" ]
 
-    if ((!build_with_chromium || is_win) && is_clang) {
-      # Suppress warnings from the Chromium Clang plugin (bugs.webrtc.org/163).
-      suppressed_configs += [ "//build/config/clang:find_bad_constructs" ]
-    }
-
     deps = [
       ":agc",
       ":level_estimation",
diff --git a/modules/audio_processing/agc/agc_manager_direct.h b/modules/audio_processing/agc/agc_manager_direct.h
index cbfd6a1..8c9fc4d 100644
--- a/modules/audio_processing/agc/agc_manager_direct.h
+++ b/modules/audio_processing/agc/agc_manager_direct.h
@@ -15,7 +15,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/constructor_magic.h"
 #include "rtc_base/gtest_prod_util.h"
 
 namespace webrtc {
diff --git a/modules/audio_processing/agc/agc_manager_direct_unittest.cc b/modules/audio_processing/agc/agc_manager_direct_unittest.cc
index 73ea55d..4be420a 100644
--- a/modules/audio_processing/agc/agc_manager_direct_unittest.cc
+++ b/modules/audio_processing/agc/agc_manager_direct_unittest.cc
@@ -10,7 +10,6 @@
 
 #include "modules/audio_processing/agc/agc_manager_direct.h"
 
-#include "common_types.h"  // NOLINT(build/include)
 #include "modules/audio_processing/agc/mock_agc.h"
 #include "modules/audio_processing/include/mock_audio_processing.h"
 #include "test/gmock.h"
diff --git a/modules/audio_processing/agc/loudness_histogram_unittest.cc b/modules/audio_processing/agc/loudness_histogram_unittest.cc
index 8c61710..0c291d8 100644
--- a/modules/audio_processing/agc/loudness_histogram_unittest.cc
+++ b/modules/audio_processing/agc/loudness_histogram_unittest.cc
@@ -19,7 +19,7 @@
 
 #include "modules/audio_processing/agc/utility.h"
 #include "test/gtest.h"
-#include "test/testsupport/fileutils.h"
+#include "test/testsupport/file_utils.h"
 
 namespace webrtc {
 
diff --git a/modules/audio_processing/agc2/agc2_common.cc b/modules/audio_processing/agc2/agc2_common.cc
index af943df..1107885 100644
--- a/modules/audio_processing/agc2/agc2_common.cc
+++ b/modules/audio_processing/agc2/agc2_common.cc
@@ -54,4 +54,4 @@
   constexpr float kDefaultExtraSaturationMarginDb = 2.f;
   return kDefaultExtraSaturationMarginDb;
 }
-};  // namespace webrtc
+}  // namespace webrtc
diff --git a/modules/audio_processing/agc2/agc2_common.h b/modules/audio_processing/agc2/agc2_common.h
index 55dd648..a6389f4 100644
--- a/modules/audio_processing/agc2/agc2_common.h
+++ b/modules/audio_processing/agc2/agc2_common.h
@@ -41,10 +41,10 @@
 // This is the threshold for speech. Speech frames are used for updating the
 // speech level, measuring the amount of speech, and decide when to allow target
 // gain reduction.
-constexpr float kVadConfidenceThreshold = 0.4f;
+constexpr float kVadConfidenceThreshold = 0.9f;
 
 // The amount of 'memory' of the Level Estimator. Decides leak factors.
-constexpr size_t kFullBufferSizeMs = 1600;
+constexpr size_t kFullBufferSizeMs = 1200;
 constexpr float kFullBufferLeakFactor = 1.f - 1.f / kFullBufferSizeMs;
 
 constexpr float kInitialSpeechLevelEstimateDbfs = -30.f;
diff --git a/modules/audio_processing/agc2/biquad_filter.h b/modules/audio_processing/agc2/biquad_filter.h
index 3d78c07..7bf3301 100644
--- a/modules/audio_processing/agc2/biquad_filter.h
+++ b/modules/audio_processing/agc2/biquad_filter.h
@@ -15,7 +15,7 @@
 
 #include "api/array_view.h"
 #include "rtc_base/arraysize.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
diff --git a/modules/audio_processing/agc2/down_sampler.h b/modules/audio_processing/agc2/down_sampler.h
index a609ea8..61d1b00 100644
--- a/modules/audio_processing/agc2/down_sampler.h
+++ b/modules/audio_processing/agc2/down_sampler.h
@@ -13,7 +13,7 @@
 
 #include "api/array_view.h"
 #include "modules/audio_processing/agc2/biquad_filter.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 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 84429d3..aa84a2e 100644
--- a/modules/audio_processing/agc2/fixed_digital_level_estimator.h
+++ b/modules/audio_processing/agc2/fixed_digital_level_estimator.h
@@ -16,7 +16,7 @@
 
 #include "modules/audio_processing/agc2/agc2_common.h"
 #include "modules/audio_processing/include/audio_frame_view.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
diff --git a/modules/audio_processing/agc2/gain_applier.h b/modules/audio_processing/agc2/gain_applier.h
index 7f9f00e..d9aa19d 100644
--- a/modules/audio_processing/agc2/gain_applier.h
+++ b/modules/audio_processing/agc2/gain_applier.h
@@ -22,7 +22,7 @@
 
   void ApplyGain(AudioFrameView<float> signal);
   void SetGainFactor(float gain_factor);
-  float GetGainFactor() const { return current_gain_factor_; };
+  float GetGainFactor() const { return current_gain_factor_; }
 
  private:
   void Initialize(size_t samples_per_channel);
diff --git a/modules/audio_processing/agc2/interpolated_gain_curve.h b/modules/audio_processing/agc2/interpolated_gain_curve.h
index 68d4532..1ecb94e 100644
--- a/modules/audio_processing/agc2/interpolated_gain_curve.h
+++ b/modules/audio_processing/agc2/interpolated_gain_curve.h
@@ -16,7 +16,7 @@
 
 #include "modules/audio_processing/agc2/agc2_common.h"
 
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 #include "rtc_base/gtest_prod_util.h"
 #include "system_wrappers/include/metrics.h"
 
diff --git a/modules/audio_processing/agc2/limiter.h b/modules/audio_processing/agc2/limiter.h
index 1e0ab71..599fd0f 100644
--- a/modules/audio_processing/agc2/limiter.h
+++ b/modules/audio_processing/agc2/limiter.h
@@ -17,7 +17,7 @@
 #include "modules/audio_processing/agc2/fixed_digital_level_estimator.h"
 #include "modules/audio_processing/agc2/interpolated_gain_curve.h"
 #include "modules/audio_processing/include/audio_frame_view.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 class ApmDataDumper;
diff --git a/modules/audio_processing/agc2/noise_level_estimator.h b/modules/audio_processing/agc2/noise_level_estimator.h
index 24067a1..ca2f9f2 100644
--- a/modules/audio_processing/agc2/noise_level_estimator.h
+++ b/modules/audio_processing/agc2/noise_level_estimator.h
@@ -13,7 +13,7 @@
 
 #include "modules/audio_processing/agc2/signal_classifier.h"
 #include "modules/audio_processing/include/audio_frame_view.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 class ApmDataDumper;
diff --git a/modules/audio_processing/agc2/noise_spectrum_estimator.h b/modules/audio_processing/agc2/noise_spectrum_estimator.h
index fd1cc13..b22f9bb 100644
--- a/modules/audio_processing/agc2/noise_spectrum_estimator.h
+++ b/modules/audio_processing/agc2/noise_spectrum_estimator.h
@@ -12,7 +12,7 @@
 #define MODULES_AUDIO_PROCESSING_AGC2_NOISE_SPECTRUM_ESTIMATOR_H_
 
 #include "api/array_view.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
diff --git a/modules/audio_processing/agc2/rnn_vad/BUILD.gn b/modules/audio_processing/agc2/rnn_vad/BUILD.gn
index d1edece..b26aef0 100644
--- a/modules/audio_processing/agc2/rnn_vad/BUILD.gn
+++ b/modules/audio_processing/agc2/rnn_vad/BUILD.gn
@@ -52,8 +52,8 @@
     ]
     deps = [
       "../../../../api:array_view",
+      "../../../../api:scoped_refptr",
       "../../../../rtc_base:checks",
-      "../../../../rtc_base:ptr_util",
       "../../../../test:fileutils",
       "../../../../test:test_support",
       "//third_party/abseil-cpp/absl/memory",
diff --git a/modules/audio_processing/agc2/rnn_vad/fft_util.cc b/modules/audio_processing/agc2/rnn_vad/fft_util.cc
index a1c5dac..4825e2b 100644
--- a/modules/audio_processing/agc2/rnn_vad/fft_util.cc
+++ b/modules/audio_processing/agc2/rnn_vad/fft_util.cc
@@ -11,6 +11,7 @@
 #include "modules/audio_processing/agc2/rnn_vad/fft_util.h"
 
 #include <stddef.h>
+#include <algorithm>
 #include <cmath>
 
 #include "rtc_base/checks.h"
@@ -42,8 +43,8 @@
 
 void BandAnalysisFft::ForwardFft(rtc::ArrayView<const float> samples,
                                  rtc::ArrayView<std::complex<float>> dst) {
-  RTC_DCHECK_EQ(input_buf_.size(), samples.size());
-  RTC_DCHECK_EQ(samples.size(), dst.size());
+  RTC_DCHECK_EQ(samples.size(), kFrameSize20ms24kHz);
+  RTC_DCHECK_EQ(dst.size(), kFrameSize20ms24kHz / 2 + 1);
   // Apply windowing.
   RTC_DCHECK_EQ(input_buf_.size(), 2 * half_window_.size());
   for (size_t i = 0; i < input_buf_.size() / 2; ++i) {
@@ -52,7 +53,10 @@
     input_buf_[j].real(samples[j] * half_window_[i]);
   }
   fft_.ForwardFft(kFrameSize20ms24kHz, input_buf_.data(), kFrameSize20ms24kHz,
-                  dst.data());
+                  output_buf_.data());
+  // Copy the first symmetric conjugate part.
+  RTC_DCHECK_LT(dst.size(), output_buf_.size());
+  std::copy(output_buf_.begin(), output_buf_.begin() + dst.size(), dst.begin());
 }
 
 }  // namespace rnn_vad
diff --git a/modules/audio_processing/agc2/rnn_vad/fft_util.h b/modules/audio_processing/agc2/rnn_vad/fft_util.h
index f4265f4..c744ff6 100644
--- a/modules/audio_processing/agc2/rnn_vad/fft_util.h
+++ b/modules/audio_processing/agc2/rnn_vad/fft_util.h
@@ -21,6 +21,8 @@
 namespace webrtc {
 namespace rnn_vad {
 
+// TODO(alessiob): Switch to PFFFT using its own wrapper.
+// TODO(alessiob): Delete this class when switching to PFFFT.
 // FFT implementation wrapper for the band-wise analysis step in which 20 ms
 // frames at 24 kHz are analyzed in the frequency domain. The goal of this class
 // are (i) making easy to switch to another FFT implementation, (ii) own the
@@ -34,6 +36,8 @@
   ~BandAnalysisFft();
   // Applies a windowing function to |samples|, computes the real forward FFT
   // and writes the result in |dst|.
+  // The size of |samples| must be 480 (20 ms at 24 kHz).
+  // The size of |dst| must be 241 since the complex conjugate is not written.
   void ForwardFft(rtc::ArrayView<const float> samples,
                   rtc::ArrayView<std::complex<float>> dst);
 
@@ -42,6 +46,7 @@
                 "kFrameSize20ms24kHz must be even.");
   const std::array<float, kFrameSize20ms24kHz / 2> half_window_;
   std::array<std::complex<float>, kFrameSize20ms24kHz> input_buf_{};
+  std::array<std::complex<float>, kFrameSize20ms24kHz> output_buf_{};
   rnnoise::KissFft fft_;
 };
 
diff --git a/modules/audio_processing/agc2/rnn_vad/fft_util_unittest.cc b/modules/audio_processing/agc2/rnn_vad/fft_util_unittest.cc
index 9854600..28f56bd 100644
--- a/modules/audio_processing/agc2/rnn_vad/fft_util_unittest.cc
+++ b/modules/audio_processing/agc2/rnn_vad/fft_util_unittest.cc
@@ -8,7 +8,9 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#include <array>
+#include <algorithm>
+#include <cmath>
+#include <vector>
 
 #include "modules/audio_processing/agc2/rnn_vad/common.h"
 #include "modules/audio_processing/agc2/rnn_vad/fft_util.h"
@@ -20,27 +22,40 @@
 namespace webrtc {
 namespace rnn_vad {
 namespace test {
+namespace {
 
-TEST(RnnVadTest, CheckBandAnalysisFftOutput) {
-  // Input data.
-  std::array<float, kFrameSize20ms24kHz> samples{};
-  for (int i = 0; i < static_cast<int>(kFrameSize20ms24kHz); ++i) {
-    samples[i] = i - static_cast<int>(kFrameSize20ms24kHz / 2);
+std::vector<float> CreateSine(float amplitude,
+                              float frequency_hz,
+                              float duration_s,
+                              int sample_rate_hz) {
+  size_t num_samples = static_cast<size_t>(duration_s * sample_rate_hz);
+  std::vector<float> signal(num_samples);
+  for (size_t i = 0; i < num_samples; ++i) {
+    signal[i] =
+        amplitude * std::sin(i * 2.0 * kPi * frequency_hz / sample_rate_hz);
   }
-  // TODO(bugs.webrtc.org/8948): Add when the issue is fixed.
-  // FloatingPointExceptionObserver fpe_observer;
-  BandAnalysisFft fft;
-  std::array<std::complex<float>, kFrameSize20ms24kHz> fft_coeffs;
-  fft.ForwardFft(samples, fft_coeffs);
-  // First coefficient is DC - i.e., real number.
-  EXPECT_EQ(0.f, fft_coeffs[0].imag());
-  // Check conjugated symmetry of the FFT output.
-  for (size_t i = 1; i < fft_coeffs.size() / 2; ++i) {
-    SCOPED_TRACE(i);
-    const auto& a = fft_coeffs[i];
-    const auto& b = fft_coeffs[fft_coeffs.size() - i];
-    EXPECT_NEAR(a.real(), b.real(), 2e-6f);
-    EXPECT_NEAR(a.imag(), -b.imag(), 2e-6f);
+  return signal;
+}
+
+}  // namespace
+
+TEST(RnnVadTest, BandAnalysisFftTest) {
+  for (float frequency_hz : {200.f, 450.f, 1500.f}) {
+    SCOPED_TRACE(frequency_hz);
+    auto x = CreateSine(
+        /*amplitude=*/1000.f, frequency_hz,
+        /*duration_s=*/0.02f,
+        /*sample_rate_hz=*/kSampleRate24kHz);
+    BandAnalysisFft analyzer;
+    std::vector<std::complex<float>> x_fft(x.size() / 2 + 1);
+    analyzer.ForwardFft(x, x_fft);
+    int peak_fft_bin_index = std::distance(
+        x_fft.begin(),
+        std::max_element(x_fft.begin(), x_fft.end(),
+                         [](std::complex<float> a, std::complex<float> b) {
+                           return std::abs(a) < std::abs(b);
+                         }));
+    EXPECT_EQ(frequency_hz, kSampleRate24kHz * peak_fft_bin_index / x.size());
   }
 }
 
diff --git a/modules/audio_processing/agc2/rnn_vad/pitch_info.h b/modules/audio_processing/agc2/rnn_vad/pitch_info.h
index f0998d1..c9fdd18 100644
--- a/modules/audio_processing/agc2/rnn_vad/pitch_info.h
+++ b/modules/audio_processing/agc2/rnn_vad/pitch_info.h
@@ -18,8 +18,8 @@
 // strength of the pitch (the higher, the stronger).
 struct PitchInfo {
   PitchInfo() : period(0), gain(0.f) {}
-  PitchInfo(size_t p, float g) : period(p), gain(g) {}
-  size_t period;
+  PitchInfo(int p, float g) : period(p), gain(g) {}
+  int period;
   float gain;
 };
 
diff --git a/modules/audio_processing/agc2/rnn_vad/pitch_search_internal.cc b/modules/audio_processing/agc2/rnn_vad/pitch_search_internal.cc
index 32ee8c0..7c17dfb 100644
--- a/modules/audio_processing/agc2/rnn_vad/pitch_search_internal.cc
+++ b/modules/audio_processing/agc2/rnn_vad/pitch_search_internal.cc
@@ -128,12 +128,12 @@
 //     sn = mex({n * i for i in S} | {1})
 //     S = S | {Fraction(1, n), Fraction(sn, n)}
 //     print(sn, end=', ')
-constexpr std::array<size_t, 14> kSubHarmonicMultipliers = {
+constexpr std::array<int, 14> kSubHarmonicMultipliers = {
     {3, 2, 3, 2, 5, 2, 3, 2, 3, 2, 5, 2, 3, 2}};
 
 // Initial pitch period candidate thresholds for ComputePitchGainThreshold() for
 // a sample rate of 24 kHz. Computed as [5*k*k for k in range(16)].
-constexpr std::array<size_t, 14> kInitialPitchPeriodThresholds = {
+constexpr std::array<int, 14> kInitialPitchPeriodThresholds = {
     {20, 45, 80, 125, 180, 245, 320, 405, 500, 605, 720, 845, 980, 1125}};
 
 }  // namespace
@@ -147,31 +147,34 @@
   }
 }
 
-float ComputePitchGainThreshold(size_t candidate_pitch_period,
-                                size_t pitch_period_ratio,
-                                size_t initial_pitch_period,
+float ComputePitchGainThreshold(int candidate_pitch_period,
+                                int pitch_period_ratio,
+                                int initial_pitch_period,
                                 float initial_pitch_gain,
-                                size_t prev_pitch_period,
-                                size_t prev_pitch_gain) {
+                                int prev_pitch_period,
+                                float prev_pitch_gain) {
   // Map arguments to more compact aliases.
-  const size_t& t1 = candidate_pitch_period;
-  const size_t& k = pitch_period_ratio;
-  const size_t& t0 = initial_pitch_period;
+  const int& t1 = candidate_pitch_period;
+  const int& k = pitch_period_ratio;
+  const int& t0 = initial_pitch_period;
   const float& g0 = initial_pitch_gain;
-  const size_t& t_prev = prev_pitch_period;
-  const size_t& g_prev = prev_pitch_gain;
+  const int& t_prev = prev_pitch_period;
+  const float& g_prev = prev_pitch_gain;
 
   // Validate input.
+  RTC_DCHECK_GE(t1, 0);
   RTC_DCHECK_GE(k, 2);
+  RTC_DCHECK_GE(t0, 0);
+  RTC_DCHECK_GE(t_prev, 0);
 
   // Compute a term that lowers the threshold when |t1| is close to the last
   // estimated period |t_prev| - i.e., pitch tracking.
   float lower_threshold_term = 0;
-  if (abs(static_cast<int>(t1) - static_cast<int>(t_prev)) <= 1) {
+  if (abs(t1 - t_prev) <= 1) {
     // The candidate pitch period is within 1 sample from the previous one.
     // Make the candidate at |t1| very easy to be accepted.
     lower_threshold_term = g_prev;
-  } else if (abs(static_cast<int>(t1) - static_cast<int>(t_prev)) == 2 &&
+  } else if (abs(t1 - t_prev) == 2 &&
              t0 > kInitialPitchPeriodThresholds[k - 2]) {
     // The candidate pitch period is 2 samples far from the previous one and the
     // period |t0| (from which |t1| has been derived) is greater than a
@@ -182,9 +185,11 @@
   // reduce the chance of false positives caused by a bias towards high
   // frequencies (originating from short-term correlations).
   float threshold = std::max(0.3f, 0.7f * g0 - lower_threshold_term);
-  if (t1 < 3 * kMinPitch24kHz) {  // High frequency.
+  if (static_cast<size_t>(t1) < 3 * kMinPitch24kHz) {
+    // High frequency.
     threshold = std::max(0.4f, 0.85f * g0 - lower_threshold_term);
-  } else if (t1 < 2 * kMinPitch24kHz) {  // Even higher frequency.
+  } else if (static_cast<size_t>(t1) < 2 * kMinPitch24kHz) {
+    // Even higher frequency.
     threshold = std::max(0.5f, 0.9f * g0 - lower_threshold_term);
   }
   return threshold;
@@ -350,16 +355,16 @@
 
 PitchInfo CheckLowerPitchPeriodsAndComputePitchGain(
     rtc::ArrayView<const float, kBufSize24kHz> pitch_buf,
-    size_t initial_pitch_period_48kHz,
+    int initial_pitch_period_48kHz,
     PitchInfo prev_pitch_48kHz) {
   RTC_DCHECK_LE(kMinPitch48kHz, initial_pitch_period_48kHz);
   RTC_DCHECK_LE(initial_pitch_period_48kHz, kMaxPitch48kHz);
   // Stores information for a refined pitch candidate.
   struct RefinedPitchCandidate {
     RefinedPitchCandidate() {}
-    RefinedPitchCandidate(size_t period_24kHz, float gain, float xy, float yy)
+    RefinedPitchCandidate(int period_24kHz, float gain, float xy, float yy)
         : period_24kHz(period_24kHz), gain(gain), xy(xy), yy(yy) {}
-    size_t period_24kHz;
+    int period_24kHz;
     // Pitch strength information.
     float gain;
     // Additional pitch strength information used for the final estimation of
@@ -380,8 +385,8 @@
   };
   // Initial pitch candidate gain.
   RefinedPitchCandidate best_pitch;
-  best_pitch.period_24kHz =
-      std::min(initial_pitch_period_48kHz / 2, kMaxPitch24kHz - 1);
+  best_pitch.period_24kHz = std::min(initial_pitch_period_48kHz / 2,
+                                     static_cast<int>(kMaxPitch24kHz - 1));
   best_pitch.xy = ComputeAutoCorrelationCoeff(
       pitch_buf, GetInvertedLag(best_pitch.period_24kHz), kMaxPitch24kHz);
   best_pitch.yy = yy_values[best_pitch.period_24kHz];
@@ -392,24 +397,27 @@
   const float initial_pitch_gain = best_pitch.gain;
 
   // Given the initial pitch estimation, check lower periods (i.e., harmonics).
-  const auto alternative_period = [](size_t period, size_t k,
-                                     size_t n) -> size_t {
-    RTC_DCHECK_LT(0, k);
+  const auto alternative_period = [](int period, int k, int n) -> int {
+    RTC_DCHECK_GT(k, 0);
     return (2 * n * period + k) / (2 * k);  // Same as round(n*period/k).
   };
-  for (size_t k = 2; k < kSubHarmonicMultipliers.size() + 2; ++k) {
-    size_t candidate_pitch_period =
-        alternative_period(initial_pitch_period, k, 1);
-    if (candidate_pitch_period < kMinPitch24kHz)
+  for (int k = 2; k < static_cast<int>(kSubHarmonicMultipliers.size() + 2);
+       ++k) {
+    int candidate_pitch_period = alternative_period(initial_pitch_period, k, 1);
+    if (static_cast<size_t>(candidate_pitch_period) < kMinPitch24kHz) {
       break;
+    }
     // When looking at |candidate_pitch_period|, we also look at one of its
     // sub-harmonics. |kSubHarmonicMultipliers| is used to know where to look.
     // |k| == 2 is a special case since |candidate_pitch_secondary_period| might
     // be greater than the maximum pitch period.
-    size_t candidate_pitch_secondary_period = alternative_period(
+    int candidate_pitch_secondary_period = alternative_period(
         initial_pitch_period, k, kSubHarmonicMultipliers[k - 2]);
-    if (k == 2 && candidate_pitch_secondary_period > kMaxPitch24kHz)
+    RTC_DCHECK_GT(candidate_pitch_secondary_period, 0);
+    if (k == 2 &&
+        candidate_pitch_secondary_period > static_cast<int>(kMaxPitch24kHz)) {
       candidate_pitch_secondary_period = initial_pitch_period;
+    }
     RTC_DCHECK_NE(candidate_pitch_period, candidate_pitch_secondary_period)
         << "The lower pitch period and the additional sub-harmonic must not "
         << "coincide.";
@@ -442,7 +450,7 @@
                                ? 1.f
                                : best_pitch.xy / (best_pitch.yy + 1.f);
   final_pitch_gain = std::min(best_pitch.gain, final_pitch_gain);
-  size_t final_pitch_period_48kHz = std::max(
+  int final_pitch_period_48kHz = std::max(
       kMinPitch48kHz,
       PitchPseudoInterpolationLagPitchBuf(best_pitch.period_24kHz, pitch_buf));
 
diff --git a/modules/audio_processing/agc2/rnn_vad/pitch_search_internal.h b/modules/audio_processing/agc2/rnn_vad/pitch_search_internal.h
index bb747bb..aabf713 100644
--- a/modules/audio_processing/agc2/rnn_vad/pitch_search_internal.h
+++ b/modules/audio_processing/agc2/rnn_vad/pitch_search_internal.h
@@ -41,12 +41,12 @@
 // Computes a gain threshold for a candidate pitch period given the initial and
 // the previous pitch period and gain estimates and the pitch period ratio used
 // to derive the candidate pitch period from the initial period.
-float ComputePitchGainThreshold(size_t candidate_pitch_period,
-                                size_t pitch_period_ratio,
-                                size_t initial_pitch_period,
+float ComputePitchGainThreshold(int candidate_pitch_period,
+                                int pitch_period_ratio,
+                                int initial_pitch_period,
                                 float initial_pitch_gain,
-                                size_t prev_pitch_period,
-                                size_t prev_pitch_gain);
+                                int prev_pitch_period,
+                                float prev_pitch_gain);
 
 // Computes the sum of squared samples for every sliding frame in the pitch
 // buffer. |yy_values| indexes are lags.
@@ -99,7 +99,7 @@
 // refined pitch estimation data at 48 kHz.
 PitchInfo CheckLowerPitchPeriodsAndComputePitchGain(
     rtc::ArrayView<const float, kBufSize24kHz> pitch_buf,
-    size_t initial_pitch_period_48kHz,
+    int initial_pitch_period_48kHz,
     PitchInfo prev_pitch_48kHz);
 
 }  // namespace rnn_vad
diff --git a/modules/audio_processing/agc2/rnn_vad/pitch_search_internal_unittest.cc b/modules/audio_processing/agc2/rnn_vad/pitch_search_internal_unittest.cc
index 82b4810..8ff6ac1 100644
--- a/modules/audio_processing/agc2/rnn_vad/pitch_search_internal_unittest.cc
+++ b/modules/audio_processing/agc2/rnn_vad/pitch_search_internal_unittest.cc
@@ -24,8 +24,9 @@
 namespace test {
 namespace {
 
-constexpr std::array<size_t, 2> kTestPitchPeriods = {
-    3 * kMinPitch48kHz / 2, (3 * kMinPitch48kHz + kMaxPitch48kHz) / 2,
+constexpr std::array<int, 2> kTestPitchPeriods = {
+    3 * kMinPitch48kHz / 2,
+    (3 * kMinPitch48kHz + kMaxPitch48kHz) / 2,
 };
 constexpr std::array<float, 2> kTestPitchGains = {0.35f, 0.75f};
 
@@ -87,7 +88,7 @@
   }
 }
 
-INSTANTIATE_TEST_CASE_P(
+INSTANTIATE_TEST_SUITE_P(
     RnnVadTest,
     ComputePitchGainThresholdTest,
     ::testing::Values(
@@ -197,14 +198,14 @@
 class CheckLowerPitchPeriodsAndComputePitchGainTest
     : public testing::Test,
       public ::testing::WithParamInterface<
-          std::tuple<size_t, size_t, float, size_t, float>> {};
+          std::tuple<int, int, float, int, float>> {};
 
 TEST_P(CheckLowerPitchPeriodsAndComputePitchGainTest, BitExactness) {
   const auto params = GetParam();
-  const size_t initial_pitch_period = std::get<0>(params);
-  const size_t prev_pitch_period = std::get<1>(params);
+  const int initial_pitch_period = std::get<0>(params);
+  const int prev_pitch_period = std::get<1>(params);
   const float prev_pitch_gain = std::get<2>(params);
-  const size_t expected_pitch_period = std::get<3>(params);
+  const int expected_pitch_period = std::get<3>(params);
   const float expected_pitch_gain = std::get<4>(params);
   TestData test_data;
   {
@@ -218,48 +219,48 @@
   }
 }
 
-INSTANTIATE_TEST_CASE_P(RnnVadTest,
-                        CheckLowerPitchPeriodsAndComputePitchGainTest,
-                        ::testing::Values(std::make_tuple(kTestPitchPeriods[0],
-                                                          kTestPitchPeriods[0],
-                                                          kTestPitchGains[0],
-                                                          91,
-                                                          -0.0188608f),
-                                          std::make_tuple(kTestPitchPeriods[0],
-                                                          kTestPitchPeriods[0],
-                                                          kTestPitchGains[1],
-                                                          91,
-                                                          -0.0188608f),
-                                          std::make_tuple(kTestPitchPeriods[0],
-                                                          kTestPitchPeriods[1],
-                                                          kTestPitchGains[0],
-                                                          91,
-                                                          -0.0188608f),
-                                          std::make_tuple(kTestPitchPeriods[0],
-                                                          kTestPitchPeriods[1],
-                                                          kTestPitchGains[1],
-                                                          91,
-                                                          -0.0188608f),
-                                          std::make_tuple(kTestPitchPeriods[1],
-                                                          kTestPitchPeriods[0],
-                                                          kTestPitchGains[0],
-                                                          475,
-                                                          -0.0904344f),
-                                          std::make_tuple(kTestPitchPeriods[1],
-                                                          kTestPitchPeriods[0],
-                                                          kTestPitchGains[1],
-                                                          475,
-                                                          -0.0904344f),
-                                          std::make_tuple(kTestPitchPeriods[1],
-                                                          kTestPitchPeriods[1],
-                                                          kTestPitchGains[0],
-                                                          475,
-                                                          -0.0904344f),
-                                          std::make_tuple(kTestPitchPeriods[1],
-                                                          kTestPitchPeriods[1],
-                                                          kTestPitchGains[1],
-                                                          475,
-                                                          -0.0904344f)));
+INSTANTIATE_TEST_SUITE_P(RnnVadTest,
+                         CheckLowerPitchPeriodsAndComputePitchGainTest,
+                         ::testing::Values(std::make_tuple(kTestPitchPeriods[0],
+                                                           kTestPitchPeriods[0],
+                                                           kTestPitchGains[0],
+                                                           91,
+                                                           -0.0188608f),
+                                           std::make_tuple(kTestPitchPeriods[0],
+                                                           kTestPitchPeriods[0],
+                                                           kTestPitchGains[1],
+                                                           91,
+                                                           -0.0188608f),
+                                           std::make_tuple(kTestPitchPeriods[0],
+                                                           kTestPitchPeriods[1],
+                                                           kTestPitchGains[0],
+                                                           91,
+                                                           -0.0188608f),
+                                           std::make_tuple(kTestPitchPeriods[0],
+                                                           kTestPitchPeriods[1],
+                                                           kTestPitchGains[1],
+                                                           91,
+                                                           -0.0188608f),
+                                           std::make_tuple(kTestPitchPeriods[1],
+                                                           kTestPitchPeriods[0],
+                                                           kTestPitchGains[0],
+                                                           475,
+                                                           -0.0904344f),
+                                           std::make_tuple(kTestPitchPeriods[1],
+                                                           kTestPitchPeriods[0],
+                                                           kTestPitchGains[1],
+                                                           475,
+                                                           -0.0904344f),
+                                           std::make_tuple(kTestPitchPeriods[1],
+                                                           kTestPitchPeriods[1],
+                                                           kTestPitchGains[0],
+                                                           475,
+                                                           -0.0904344f),
+                                           std::make_tuple(kTestPitchPeriods[1],
+                                                           kTestPitchPeriods[1],
+                                                           kTestPitchGains[1],
+                                                           475,
+                                                           -0.0904344f)));
 
 }  // namespace test
 }  // namespace rnn_vad
diff --git a/modules/audio_processing/agc2/rnn_vad/pitch_search_unittest.cc b/modules/audio_processing/agc2/rnn_vad/pitch_search_unittest.cc
index 4c56238..eac332e 100644
--- a/modules/audio_processing/agc2/rnn_vad/pitch_search_unittest.cc
+++ b/modules/audio_processing/agc2/rnn_vad/pitch_search_unittest.cc
@@ -39,7 +39,7 @@
       lp_residual_reader.first->ReadValue(&expected_pitch_period);
       lp_residual_reader.first->ReadValue(&expected_pitch_gain);
       PitchInfo pitch_info = pitch_estimator.Estimate(lp_residual);
-      EXPECT_EQ(static_cast<size_t>(expected_pitch_period), pitch_info.period);
+      EXPECT_EQ(static_cast<int>(expected_pitch_period), pitch_info.period);
       EXPECT_NEAR(expected_pitch_gain, pitch_info.gain, 1e-5f);
     }
   }
diff --git a/modules/audio_processing/agc2/rnn_vad/spectral_features.cc b/modules/audio_processing/agc2/rnn_vad/spectral_features.cc
index 695eed5..84db2df 100644
--- a/modules/audio_processing/agc2/rnn_vad/spectral_features.cc
+++ b/modules/audio_processing/agc2/rnn_vad/spectral_features.cc
@@ -68,8 +68,8 @@
 
 SpectralFeaturesExtractor::SpectralFeaturesExtractor()
     : fft_(),
-      reference_frame_fft_(kFrameSize20ms24kHz),
-      lagged_frame_fft_(kFrameSize20ms24kHz),
+      reference_frame_fft_(kFrameSize20ms24kHz / 2 + 1),
+      lagged_frame_fft_(kFrameSize20ms24kHz / 2 + 1),
       band_boundaries_(
           ComputeBandBoundaryIndexes(kSampleRate24kHz, kFrameSize20ms24kHz)),
       dct_table_(ComputeDctTable()) {}
diff --git a/modules/audio_processing/agc2/rnn_vad/test_utils.cc b/modules/audio_processing/agc2/rnn_vad/test_utils.cc
index db38cab..8decbd0 100644
--- a/modules/audio_processing/agc2/rnn_vad/test_utils.cc
+++ b/modules/audio_processing/agc2/rnn_vad/test_utils.cc
@@ -13,7 +13,7 @@
 #include "absl/memory/memory.h"
 #include "rtc_base/checks.h"
 #include "test/gtest.h"
-#include "test/testsupport/fileutils.h"
+#include "test/testsupport/file_utils.h"
 
 namespace webrtc {
 namespace rnn_vad {
diff --git a/modules/audio_processing/agc2/signal_classifier.h b/modules/audio_processing/agc2/signal_classifier.h
index 23fe315..e0d6771 100644
--- a/modules/audio_processing/agc2/signal_classifier.h
+++ b/modules/audio_processing/agc2/signal_classifier.h
@@ -18,7 +18,7 @@
 #include "modules/audio_processing/agc2/down_sampler.h"
 #include "modules/audio_processing/agc2/noise_spectrum_estimator.h"
 #include "modules/audio_processing/utility/ooura_fft.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
diff --git a/modules/audio_processing/audio_buffer.h b/modules/audio_processing/audio_buffer.h
index 469646e..a85144b 100644
--- a/modules/audio_processing/audio_buffer.h
+++ b/modules/audio_processing/audio_buffer.h
@@ -19,7 +19,6 @@
 #include "api/audio/audio_frame.h"
 #include "common_audio/channel_buffer.h"
 #include "modules/audio_processing/include/audio_processing.h"
-#include "rtc_base/gtest_prod_util.h"
 
 namespace webrtc {
 
diff --git a/modules/audio_processing/audio_generator/file_audio_generator.h b/modules/audio_processing/audio_generator/file_audio_generator.h
index 01979a4..f322b09 100644
--- a/modules/audio_processing/audio_generator/file_audio_generator.h
+++ b/modules/audio_processing/audio_generator/file_audio_generator.h
@@ -15,7 +15,7 @@
 
 #include "common_audio/wav_file.h"
 #include "modules/audio_processing/include/audio_generator.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
diff --git a/modules/audio_processing/audio_generator/file_audio_generator_unittest.cc b/modules/audio_processing/audio_generator/file_audio_generator_unittest.cc
index 6ed3b94..6569bfe 100644
--- a/modules/audio_processing/audio_generator/file_audio_generator_unittest.cc
+++ b/modules/audio_processing/audio_generator/file_audio_generator_unittest.cc
@@ -13,7 +13,7 @@
 #include "modules/audio_processing/include/audio_generator_factory.h"
 #include "modules/audio_processing/include/audio_processing.h"
 #include "test/gtest.h"
-#include "test/testsupport/fileutils.h"
+#include "test/testsupport/file_utils.h"
 
 namespace webrtc {
 namespace test {
diff --git a/modules/audio_processing/audio_processing_impl.cc b/modules/audio_processing/audio_processing_impl.cc
index 2937c06..504eb31 100644
--- a/modules/audio_processing/audio_processing_impl.cc
+++ b/modules/audio_processing/audio_processing_impl.cc
@@ -16,10 +16,12 @@
 #include <type_traits>
 #include <utility>
 
+#include "absl/memory/memory.h"
 #include "absl/types/optional.h"
 #include "api/array_view.h"
 #include "common_audio/audio_converter.h"
 #include "common_audio/include/audio_util.h"
+#include "modules/audio_processing/aec3/echo_canceller3.h"
 #include "modules/audio_processing/agc/agc_manager_direct.h"
 #include "modules/audio_processing/agc2/gain_applier.h"
 #include "modules/audio_processing/audio_buffer.h"
@@ -34,15 +36,16 @@
 #include "modules/audio_processing/logging/apm_data_dumper.h"
 #include "modules/audio_processing/low_cut_filter.h"
 #include "modules/audio_processing/noise_suppression_impl.h"
+#include "modules/audio_processing/noise_suppression_proxy.h"
 #include "modules/audio_processing/residual_echo_detector.h"
 #include "modules/audio_processing/transient/transient_suppressor.h"
 #include "modules/audio_processing/voice_detection_impl.h"
-#include "rtc_base/atomicops.h"
+#include "rtc_base/atomic_ops.h"
 #include "rtc_base/checks.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 #include "rtc_base/logging.h"
-#include "rtc_base/refcountedobject.h"
-#include "rtc_base/timeutils.h"
+#include "rtc_base/ref_counted_object.h"
+#include "rtc_base/time_utils.h"
 #include "rtc_base/trace_event.h"
 #include "system_wrappers/include/metrics.h"
 
@@ -107,6 +110,23 @@
   return uppermost_native_rate;
 }
 
+NoiseSuppression::Level NsConfigLevelToInterfaceLevel(
+    AudioProcessing::Config::NoiseSuppression::Level level) {
+  using NsConfig = AudioProcessing::Config::NoiseSuppression;
+  switch (level) {
+    case NsConfig::kLow:
+      return NoiseSuppression::kLow;
+    case NsConfig::kModerate:
+      return NoiseSuppression::kModerate;
+    case NsConfig::kHigh:
+      return NoiseSuppression::kHigh;
+    case NsConfig::kVeryHigh:
+      return NoiseSuppression::kVeryHigh;
+    default:
+      RTC_NOTREACHED();
+  }
+}
+
 // Maximum lengths that frame of samples being passed from the render side to
 // the capture side can have (does not apply to AEC3).
 static const size_t kMaxAllowedValuesOfSamplesPerBand = 160;
@@ -140,6 +160,7 @@
     bool pre_amplifier_enabled,
     bool echo_controller_enabled,
     bool voice_activity_detector_enabled,
+    bool private_voice_detector_enabled,
     bool level_estimator_enabled,
     bool transient_suppressor_enabled) {
   bool changed = false;
@@ -159,6 +180,8 @@
   changed |= (level_estimator_enabled != level_estimator_enabled_);
   changed |=
       (voice_activity_detector_enabled != voice_activity_detector_enabled_);
+  changed |=
+      (private_voice_detector_enabled != private_voice_detector_enabled_);
   changed |= (transient_suppressor_enabled != transient_suppressor_enabled_);
   if (changed) {
     high_pass_filter_enabled_ = high_pass_filter_enabled;
@@ -172,6 +195,7 @@
     echo_controller_enabled_ = echo_controller_enabled;
     level_estimator_enabled_ = level_estimator_enabled;
     voice_activity_detector_enabled_ = voice_activity_detector_enabled;
+    private_voice_detector_enabled_ = private_voice_detector_enabled;
     transient_suppressor_enabled_ = transient_suppressor_enabled;
   }
 
@@ -182,7 +206,8 @@
 
 bool AudioProcessingImpl::ApmSubmoduleStates::CaptureMultiBandSubModulesActive()
     const {
-  return CaptureMultiBandProcessingActive() || voice_activity_detector_enabled_;
+  return CaptureMultiBandProcessingActive() ||
+         voice_activity_detector_enabled_ || private_voice_detector_enabled_;
 }
 
 bool AudioProcessingImpl::ApmSubmoduleStates::CaptureMultiBandProcessingActive()
@@ -227,9 +252,12 @@
 struct AudioProcessingImpl::ApmPublicSubmodules {
   ApmPublicSubmodules() {}
   // Accessed externally of APM without any lock acquired.
+  // TODO(bugs.webrtc.org/9947): Move these submodules into private_submodules_
+  // when their pointer-to-submodule API functions are gone.
   std::unique_ptr<GainControlImpl> gain_control;
   std::unique_ptr<LevelEstimatorImpl> level_estimator;
   std::unique_ptr<NoiseSuppressionImpl> noise_suppression;
+  std::unique_ptr<NoiseSuppressionProxy> noise_suppression_proxy;
   std::unique_ptr<VoiceDetectionImpl> voice_detection;
   std::unique_ptr<GainControlForExperimentalAgc>
       gain_control_for_experimental_agc;
@@ -260,6 +288,7 @@
   std::unique_ptr<GainApplier> pre_amplifier;
   std::unique_ptr<CustomAudioAnalyzer> capture_analyzer;
   std::unique_ptr<LevelEstimatorImpl> output_level_estimator;
+  std::unique_ptr<VoiceDetectionImpl> voice_detector;
 };
 
 AudioProcessingBuilder::AudioProcessingBuilder() = default;
@@ -360,46 +389,42 @@
       capture_(config.Get<ExperimentalNs>().enabled),
 #endif
       capture_nonlocked_() {
-  {
-    rtc::CritScope cs_render(&crit_render_);
-    rtc::CritScope cs_capture(&crit_capture_);
+  // Mark Echo Controller enabled if a factory is injected.
+  capture_nonlocked_.echo_controller_enabled =
+      static_cast<bool>(echo_control_factory_);
 
-    // Mark Echo Controller enabled if a factory is injected.
-    capture_nonlocked_.echo_controller_enabled =
-        static_cast<bool>(echo_control_factory_);
+  public_submodules_->gain_control.reset(new GainControlImpl(&crit_capture_));
+  public_submodules_->level_estimator.reset(
+      new LevelEstimatorImpl(&crit_capture_));
+  public_submodules_->noise_suppression.reset(
+      new NoiseSuppressionImpl(&crit_capture_));
+  public_submodules_->noise_suppression_proxy.reset(new NoiseSuppressionProxy(
+      this, public_submodules_->noise_suppression.get()));
+  public_submodules_->voice_detection.reset(
+      new VoiceDetectionImpl(&crit_capture_));
+  public_submodules_->gain_control_for_experimental_agc.reset(
+      new GainControlForExperimentalAgc(public_submodules_->gain_control.get(),
+                                        &crit_capture_));
 
-    public_submodules_->gain_control.reset(
-        new GainControlImpl(&crit_render_, &crit_capture_));
-    public_submodules_->level_estimator.reset(
-        new LevelEstimatorImpl(&crit_capture_));
-    public_submodules_->noise_suppression.reset(
-        new NoiseSuppressionImpl(&crit_capture_));
-    public_submodules_->voice_detection.reset(
-        new VoiceDetectionImpl(&crit_capture_));
-    public_submodules_->gain_control_for_experimental_agc.reset(
-        new GainControlForExperimentalAgc(
-            public_submodules_->gain_control.get(), &crit_capture_));
-
-    // If no echo detector is injected, use the ResidualEchoDetector.
-    if (!private_submodules_->echo_detector) {
-      private_submodules_->echo_detector =
-          new rtc::RefCountedObject<ResidualEchoDetector>();
-    }
-
-    private_submodules_->echo_cancellation.reset(new EchoCancellationImpl());
-    private_submodules_->echo_control_mobile.reset(new EchoControlMobileImpl());
-    // TODO(alessiob): Move the injected gain controller once injection is
-    // implemented.
-    private_submodules_->gain_controller2.reset(new GainController2());
-
-    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;
+  // If no echo detector is injected, use the ResidualEchoDetector.
+  if (!private_submodules_->echo_detector) {
+    private_submodules_->echo_detector =
+        new rtc::RefCountedObject<ResidualEchoDetector>();
   }
 
+  private_submodules_->echo_cancellation.reset(new EchoCancellationImpl());
+  private_submodules_->echo_control_mobile.reset(new EchoControlMobileImpl());
+  // TODO(alessiob): Move the injected gain controller once injection is
+  // implemented.
+  private_submodules_->gain_controller2.reset(new GainController2());
+
+  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;
+
   SetExtraOptions(config);
 }
 
@@ -540,6 +565,10 @@
   public_submodules_->noise_suppression->Initialize(num_proc_channels(),
                                                     proc_sample_rate_hz());
   public_submodules_->voice_detection->Initialize(proc_split_sample_rate_hz());
+  if (private_submodules_->voice_detector) {
+    private_submodules_->voice_detector->Initialize(
+        proc_split_sample_rate_hz());
+  }
   public_submodules_->level_estimator->Initialize();
   InitializeResidualEchoDetector();
   InitializeEchoController();
@@ -642,17 +671,25 @@
   rtc::CritScope cs_render(&crit_render_);
   rtc::CritScope cs_capture(&crit_capture_);
 
+  const bool aec_config_changed =
+      config_.echo_canceller.enabled != config.echo_canceller.enabled ||
+      config_.echo_canceller.use_legacy_aec !=
+          config.echo_canceller.use_legacy_aec ||
+      config_.echo_canceller.mobile_mode != config.echo_canceller.mobile_mode ||
+      (config_.echo_canceller.enabled && config.echo_canceller.use_legacy_aec &&
+       config_.echo_canceller.legacy_moderate_suppression_level !=
+           config.echo_canceller.legacy_moderate_suppression_level);
+
   config_ = config;
 
-  private_submodules_->echo_cancellation->Enable(
-      config_.echo_canceller.enabled && !config_.echo_canceller.mobile_mode);
-  private_submodules_->echo_control_mobile->Enable(
-      config_.echo_canceller.enabled && config_.echo_canceller.mobile_mode);
+  if (aec_config_changed) {
+    InitializeEchoController();
+  }
 
-  private_submodules_->echo_cancellation->set_suppression_level(
-      config.echo_canceller.legacy_moderate_suppression_level
-          ? EchoCancellationImpl::SuppressionLevel::kModerateSuppression
-          : EchoCancellationImpl::SuppressionLevel::kHighSuppression);
+  public_submodules_->noise_suppression->Enable(
+      config.noise_suppression.enabled);
+  public_submodules_->noise_suppression->set_level(
+      NsConfigLevelToInterfaceLevel(config.noise_suppression.level));
 
   InitializeLowCutFilter();
 
@@ -681,6 +718,16 @@
         new LevelEstimatorImpl(&crit_capture_));
     private_submodules_->output_level_estimator->Enable(true);
   }
+
+  if (config_.voice_detection.enabled && !private_submodules_->voice_detector) {
+    private_submodules_->voice_detector.reset(
+        new VoiceDetectionImpl(&crit_capture_));
+    private_submodules_->voice_detector->Enable(true);
+    private_submodules_->voice_detector->set_likelihood(
+        VoiceDetection::kVeryLowLikelihood);
+    private_submodules_->voice_detector->Initialize(
+        proc_split_sample_rate_hz());
+  }
 }
 
 void AudioProcessingImpl::SetExtraOptions(const webrtc::Config& config) {
@@ -1285,6 +1332,13 @@
   }
 
   public_submodules_->voice_detection->ProcessCaptureAudio(capture_buffer);
+  if (config_.voice_detection.enabled) {
+    private_submodules_->voice_detector->ProcessCaptureAudio(capture_buffer);
+    capture_.stats.voice_detected =
+        private_submodules_->voice_detector->stream_has_voice();
+  } else {
+    capture_.stats.voice_detected = absl::nullopt;
+  }
 
   if (constants_.use_experimental_agc &&
       public_submodules_->gain_control->is_enabled() &&
@@ -1293,6 +1347,7 @@
         capture_buffer->split_bands_const(0)[kBand0To8kHz],
         capture_buffer->num_frames_per_band(), capture_nonlocked_.split_rate);
   }
+  // TODO(peah): Add reporting from AEC3 whether there is echo.
   RETURN_ON_ERR(public_submodules_->gain_control->ProcessCaptureAudio(
       capture_buffer,
       private_submodules_->echo_cancellation->stream_has_echo()));
@@ -1663,7 +1718,7 @@
 }
 
 NoiseSuppression* AudioProcessingImpl::noise_suppression() const {
-  return public_submodules_->noise_suppression.get();
+  return public_submodules_->noise_suppression_proxy.get();
 }
 
 VoiceDetection* AudioProcessingImpl::voice_detection() const {
@@ -1695,6 +1750,7 @@
       config_.gain_controller2.enabled, config_.pre_amplifier.enabled,
       capture_nonlocked_.echo_controller_enabled,
       public_submodules_->voice_detection->is_enabled(),
+      config_.voice_detection.enabled,
       public_submodules_->level_estimator->is_enabled(),
       capture_.transient_suppressor_enabled);
 }
@@ -1720,11 +1776,31 @@
 }
 
 void AudioProcessingImpl::InitializeEchoController() {
-  if (echo_control_factory_) {
-    private_submodules_->echo_controller =
-        echo_control_factory_->Create(proc_sample_rate_hz());
+  if (echo_control_factory_ ||
+      (config_.echo_canceller.enabled && !config_.echo_canceller.mobile_mode &&
+       !config_.echo_canceller.use_legacy_aec)) {
+    if (echo_control_factory_) {
+      private_submodules_->echo_controller =
+          echo_control_factory_->Create(proc_sample_rate_hz());
+    } else {
+      private_submodules_->echo_controller = absl::make_unique<EchoCanceller3>(
+          EchoCanceller3Config(), proc_sample_rate_hz(), true);
+    }
+
+    capture_nonlocked_.echo_controller_enabled = true;
   } else {
+    private_submodules_->echo_cancellation->Enable(
+        config_.echo_canceller.enabled && !config_.echo_canceller.mobile_mode);
+    private_submodules_->echo_control_mobile->Enable(
+        config_.echo_canceller.enabled && config_.echo_canceller.mobile_mode);
+
+    private_submodules_->echo_cancellation->set_suppression_level(
+        config_.echo_canceller.legacy_moderate_suppression_level
+            ? EchoCancellationImpl::SuppressionLevel::kModerateSuppression
+            : EchoCancellationImpl::SuppressionLevel::kHighSuppression);
+
     private_submodules_->echo_controller.reset();
+    capture_nonlocked_.echo_controller_enabled = false;
   }
 }
 
@@ -1865,7 +1941,7 @@
 
   InternalAPMConfig apm_config;
 
-  apm_config.aec_enabled = private_submodules_->echo_cancellation->is_enabled();
+  apm_config.aec_enabled = config_.echo_canceller.enabled;
   apm_config.aec_delay_agnostic_enabled =
       private_submodules_->echo_cancellation->is_delay_agnostic_enabled();
   apm_config.aec_drift_compensation_enabled =
diff --git a/modules/audio_processing/audio_processing_impl.h b/modules/audio_processing/audio_processing_impl.h
index 2f946c5..9b66c26 100644
--- a/modules/audio_processing/audio_processing_impl.h
+++ b/modules/audio_processing/audio_processing_impl.h
@@ -21,7 +21,7 @@
 #include "modules/audio_processing/include/audio_processing_statistics.h"
 #include "modules/audio_processing/render_queue_item_verifier.h"
 #include "modules/audio_processing/rms_level.h"
-#include "rtc_base/criticalsection.h"
+#include "rtc_base/critical_section.h"
 #include "rtc_base/function_view.h"
 #include "rtc_base/gtest_prod_util.h"
 #include "rtc_base/ignore_wundef.h"
@@ -181,6 +181,7 @@
                 bool pre_amplifier_enabled,
                 bool echo_controller_enabled,
                 bool voice_activity_detector_enabled,
+                bool private_voice_detector_enabled,
                 bool level_estimator_enabled,
                 bool transient_suppressor_enabled);
     bool CaptureMultiBandSubModulesActive() const;
@@ -207,6 +208,7 @@
     bool echo_controller_enabled_ = false;
     bool level_estimator_enabled_ = false;
     bool voice_activity_detector_enabled_ = false;
+    bool private_voice_detector_enabled_ = false;
     bool transient_suppressor_enabled_ = false;
     bool first_update_ = true;
   };
diff --git a/modules/audio_processing/audio_processing_impl_locking_unittest.cc b/modules/audio_processing/audio_processing_impl_locking_unittest.cc
index 9685ef9..828e2e7 100644
--- a/modules/audio_processing/audio_processing_impl_locking_unittest.cc
+++ b/modules/audio_processing/audio_processing_impl_locking_unittest.cc
@@ -16,7 +16,7 @@
 
 #include "api/array_view.h"
 #include "modules/audio_processing/test/test_utils.h"
-#include "rtc_base/criticalsection.h"
+#include "rtc_base/critical_section.h"
 #include "rtc_base/event.h"
 #include "rtc_base/platform_thread.h"
 #include "rtc_base/random.h"
@@ -527,21 +527,20 @@
 void AudioProcessingImplLockTest::SetUp() {
   test_config_ = static_cast<TestConfig>(GetParam());
 
-  ASSERT_EQ(apm_->kNoError, apm_->level_estimator()->Enable(true));
   ASSERT_EQ(apm_->kNoError, apm_->gain_control()->Enable(true));
 
   ASSERT_EQ(apm_->kNoError,
             apm_->gain_control()->set_mode(GainControl::kAdaptiveDigital));
   ASSERT_EQ(apm_->kNoError, apm_->gain_control()->Enable(true));
 
-  ASSERT_EQ(apm_->kNoError, apm_->noise_suppression()->Enable(true));
-  ASSERT_EQ(apm_->kNoError, apm_->voice_detection()->Enable(true));
-
-  AudioProcessing::Config apm_config;
+  AudioProcessing::Config apm_config = apm_->GetConfig();
   apm_config.echo_canceller.enabled =
       (test_config_.aec_type != AecType::AecTurnedOff);
   apm_config.echo_canceller.mobile_mode =
       (test_config_.aec_type == AecType::BasicWebRtcAecSettingsWithAecMobile);
+  apm_config.noise_suppression.enabled = true;
+  apm_config.voice_detection.enabled = true;
+  apm_config.level_estimation.enabled = true;
   apm_->ApplyConfig(apm_config);
 
   Config config;
@@ -584,12 +583,14 @@
     EXPECT_FALSE(apm_config.echo_canceller.enabled);
   }
   EXPECT_TRUE(apm_->gain_control()->is_enabled());
-  EXPECT_TRUE(apm_->noise_suppression()->is_enabled());
+  EXPECT_TRUE(apm_config.noise_suppression.enabled);
 
   // The below return values are not testable.
   apm_->noise_suppression()->speech_probability();
   apm_->voice_detection()->is_enabled();
 
+  apm_->GetStatistics(/*has_remote_tracks=*/true);
+
   return true;
 }
 
@@ -1108,12 +1109,12 @@
 }
 
 // Instantiate tests from the extreme test configuration set.
-INSTANTIATE_TEST_CASE_P(
+INSTANTIATE_TEST_SUITE_P(
     DISABLED_AudioProcessingImplLockExtensive,
     AudioProcessingImplLockTest,
     ::testing::ValuesIn(TestConfig::GenerateExtensiveTestConfigs()));
 
-INSTANTIATE_TEST_CASE_P(
+INSTANTIATE_TEST_SUITE_P(
     AudioProcessingImplLockBrief,
     AudioProcessingImplLockTest,
     ::testing::ValuesIn(TestConfig::GenerateBriefTestConfigs()));
diff --git a/modules/audio_processing/audio_processing_impl_unittest.cc b/modules/audio_processing/audio_processing_impl_unittest.cc
index 8926f02..69fc779 100644
--- a/modules/audio_processing/audio_processing_impl_unittest.cc
+++ b/modules/audio_processing/audio_processing_impl_unittest.cc
@@ -10,18 +10,24 @@
 
 #include "modules/audio_processing/audio_processing_impl.h"
 
+#include <memory>
+
+#include "absl/memory/memory.h"
+#include "api/scoped_refptr.h"
 #include "modules/audio_processing/include/audio_processing.h"
+#include "modules/audio_processing/test/echo_control_mock.h"
 #include "modules/audio_processing/test/test_utils.h"
-#include "rtc_base/refcountedobject.h"
-#include "rtc_base/scoped_ref_ptr.h"
+#include "rtc_base/checks.h"
+#include "rtc_base/ref_counted_object.h"
 #include "test/gmock.h"
 #include "test/gtest.h"
 
-using ::testing::Invoke;
-
 namespace webrtc {
 namespace {
 
+using ::testing::Invoke;
+using ::testing::NotNull;
+
 class MockInitialize : public AudioProcessingImpl {
  public:
   explicit MockInitialize(const webrtc::Config& config)
@@ -36,6 +42,28 @@
   MOCK_CONST_METHOD0(Release, rtc::RefCountReleaseStatus());
 };
 
+// Creates MockEchoControl instances and provides a raw pointer access to
+// the next created one. The raw pointer is meant to be used with gmock.
+// Returning a pointer of the next created MockEchoControl instance is necessary
+// for the following reasons: (i) gmock expectations must be set before any call
+// occurs, (ii) APM is initialized the first time that
+// AudioProcessingImpl::ProcessStream() is called and the initialization leads
+// to the creation of a new EchoControl object.
+class MockEchoControlFactory : public EchoControlFactory {
+ public:
+  MockEchoControlFactory() : next_mock_(absl::make_unique<MockEchoControl>()) {}
+  // Returns a pointer to the next MockEchoControl that this factory creates.
+  MockEchoControl* GetNext() const { return next_mock_.get(); }
+  std::unique_ptr<EchoControl> Create(int sample_rate_hz) override {
+    std::unique_ptr<EchoControl> mock = std::move(next_mock_);
+    next_mock_ = absl::make_unique<MockEchoControl>();
+    return mock;
+  }
+
+ private:
+  std::unique_ptr<MockEchoControl> next_mock_;
+};
+
 void InitializeAudioFrame(size_t input_rate,
                           size_t num_channels,
                           AudioFrame* frame) {
@@ -105,7 +133,7 @@
       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
@@ -183,6 +211,87 @@
       << "Frame should be amplified.";
 }
 
+TEST(AudioProcessingImplTest,
+     EchoControllerObservesPreAmplifierEchoPathGainChange) {
+  // Tests that the echo controller observes an echo path gain change when the
+  // pre-amplifier submodule changes the gain.
+  auto echo_control_factory = absl::make_unique<MockEchoControlFactory>();
+  const auto* echo_control_factory_ptr = echo_control_factory.get();
+
+  std::unique_ptr<AudioProcessing> apm(
+      AudioProcessingBuilder()
+          .SetEchoControlFactory(std::move(echo_control_factory))
+          .Create());
+  apm->gain_control()->Enable(false);  // Disable AGC.
+  apm->gain_control()->set_mode(GainControl::Mode::kFixedDigital);
+  webrtc::AudioProcessing::Config apm_config;
+  apm_config.gain_controller2.enabled = false;
+  apm_config.pre_amplifier.enabled = true;
+  apm_config.pre_amplifier.fixed_gain_factor = 1.f;
+  apm->ApplyConfig(apm_config);
+
+  AudioFrame frame;
+  constexpr int16_t kAudioLevel = 10000;
+  constexpr size_t kSampleRateHz = 48000;
+  constexpr size_t kNumChannels = 2;
+  InitializeAudioFrame(kSampleRateHz, kNumChannels, &frame);
+  FillFixedFrame(kAudioLevel, &frame);
+
+  MockEchoControl* echo_control_mock = echo_control_factory_ptr->GetNext();
+
+  EXPECT_CALL(*echo_control_mock, AnalyzeCapture(NotNull())).Times(1);
+  EXPECT_CALL(*echo_control_mock, ProcessCapture(NotNull(), false)).Times(1);
+  apm->ProcessStream(&frame);
+
+  EXPECT_CALL(*echo_control_mock, AnalyzeCapture(NotNull())).Times(1);
+  EXPECT_CALL(*echo_control_mock, ProcessCapture(NotNull(), true)).Times(1);
+  apm->SetRuntimeSetting(
+      AudioProcessing::RuntimeSetting::CreateCapturePreGain(2.f));
+  apm->ProcessStream(&frame);
+}
+
+TEST(AudioProcessingImplTest,
+     EchoControllerObservesAnalogAgc1EchoPathGainChange) {
+  // Tests that the echo controller observes an echo path gain change when the
+  // AGC1 analog adaptive submodule changes the analog gain.
+  auto echo_control_factory = absl::make_unique<MockEchoControlFactory>();
+  const auto* echo_control_factory_ptr = echo_control_factory.get();
+
+  std::unique_ptr<AudioProcessing> apm(
+      AudioProcessingBuilder()
+          .SetEchoControlFactory(std::move(echo_control_factory))
+          .Create());
+  apm->gain_control()->Enable(true);  // Enable AGC.
+  apm->gain_control()->set_mode(GainControl::Mode::kAdaptiveAnalog);
+  webrtc::AudioProcessing::Config apm_config;
+  apm_config.gain_controller2.enabled = false;
+  apm_config.pre_amplifier.enabled = false;
+  apm->ApplyConfig(apm_config);
+
+  AudioFrame frame;
+  constexpr int16_t kAudioLevel = 1000;
+  constexpr size_t kSampleRateHz = 48000;
+  constexpr size_t kNumChannels = 2;
+  InitializeAudioFrame(kSampleRateHz, kNumChannels, &frame);
+  FillFixedFrame(kAudioLevel, &frame);
+
+  MockEchoControl* echo_control_mock = echo_control_factory_ptr->GetNext();
+
+  const int initial_analog_gain = apm->gain_control()->stream_analog_level();
+  EXPECT_CALL(*echo_control_mock, AnalyzeCapture(NotNull())).Times(1);
+  EXPECT_CALL(*echo_control_mock, ProcessCapture(NotNull(), false)).Times(1);
+  apm->ProcessStream(&frame);
+
+  // Force an analog gain change if it did not happen.
+  if (initial_analog_gain == apm->gain_control()->stream_analog_level()) {
+    apm->gain_control()->set_stream_analog_level(initial_analog_gain + 1);
+  }
+
+  EXPECT_CALL(*echo_control_mock, AnalyzeCapture(NotNull())).Times(1);
+  EXPECT_CALL(*echo_control_mock, ProcessCapture(NotNull(), true)).Times(1);
+  apm->ProcessStream(&frame);
+}
+
 TEST(AudioProcessingImplTest, RenderPreProcessorBeforeEchoDetector) {
   // Make sure that signal changes caused by a render pre-processing sub-module
   // take place before any echo detector analysis.
diff --git a/modules/audio_processing/audio_processing_performance_unittest.cc b/modules/audio_processing/audio_processing_performance_unittest.cc
index 84cb574..70c91c4 100644
--- a/modules/audio_processing/audio_processing_performance_unittest.cc
+++ b/modules/audio_processing/audio_processing_performance_unittest.cc
@@ -17,7 +17,7 @@
 
 #include "api/array_view.h"
 #include "modules/audio_processing/test/test_utils.h"
-#include "rtc_base/atomicops.h"
+#include "rtc_base/atomic_ops.h"
 #include "rtc_base/event.h"
 #include "rtc_base/numerics/safe_conversions.h"
 #include "rtc_base/platform_thread.h"
@@ -450,10 +450,10 @@
                 apm->gain_control()->set_mode(GainControl::kAdaptiveDigital));
       ASSERT_EQ(apm->kNoError, apm->gain_control()->Enable(true));
       ASSERT_EQ(apm->kNoError, apm->noise_suppression()->Enable(true));
-      ASSERT_EQ(apm->kNoError, apm->voice_detection()->Enable(true));
       AudioProcessing::Config apm_config = apm->GetConfig();
       apm_config.echo_canceller.enabled = true;
       apm_config.echo_canceller.mobile_mode = false;
+      apm_config.voice_detection.enabled = true;
       apm->ApplyConfig(apm_config);
     };
 
@@ -465,10 +465,10 @@
                 apm->gain_control()->set_mode(GainControl::kAdaptiveDigital));
       ASSERT_EQ(apm->kNoError, apm->gain_control()->Enable(true));
       ASSERT_EQ(apm->kNoError, apm->noise_suppression()->Enable(true));
-      ASSERT_EQ(apm->kNoError, apm->voice_detection()->Enable(true));
       AudioProcessing::Config apm_config = apm->GetConfig();
       apm_config.echo_canceller.enabled = true;
       apm_config.echo_canceller.mobile_mode = true;
+      apm_config.voice_detection.enabled = true;
       apm->ApplyConfig(apm_config);
     };
 
@@ -481,9 +481,9 @@
                 apm->gain_control()->set_mode(GainControl::kAdaptiveDigital));
       ASSERT_EQ(apm->kNoError, apm->gain_control()->Enable(false));
       ASSERT_EQ(apm->kNoError, apm->noise_suppression()->Enable(false));
-      ASSERT_EQ(apm->kNoError, apm->voice_detection()->Enable(false));
       AudioProcessing::Config apm_config = apm->GetConfig();
       apm_config.echo_canceller.enabled = false;
+      apm_config.voice_detection.enabled = false;
       apm->ApplyConfig(apm_config);
     };
 
@@ -621,7 +621,7 @@
   EXPECT_TRUE(Run());
 }
 
-INSTANTIATE_TEST_CASE_P(
+INSTANTIATE_TEST_SUITE_P(
     AudioProcessingPerformanceTest,
     CallSimulator,
     ::testing::ValuesIn(SimulationConfig::GenerateSimulationConfigs()));
diff --git a/modules/audio_processing/audio_processing_unittest.cc b/modules/audio_processing/audio_processing_unittest.cc
index 6809ab9..59feb9b 100644
--- a/modules/audio_processing/audio_processing_unittest.cc
+++ b/modules/audio_processing/audio_processing_unittest.cc
@@ -28,21 +28,20 @@
 #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/fake_clock.h"
 #include "rtc_base/gtest_prod_util.h"
 #include "rtc_base/ignore_wundef.h"
 #include "rtc_base/numerics/safe_conversions.h"
 #include "rtc_base/numerics/safe_minmax.h"
 #include "rtc_base/protobuf_utils.h"
-#include "rtc_base/refcountedobject.h"
+#include "rtc_base/ref_counted_object.h"
 #include "rtc_base/strings/string_builder.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"
 #include "test/gtest.h"
-#include "test/testsupport/fileutils.h"
+#include "test/testsupport/file_utils.h"
 
 RTC_PUSH_IGNORING_WUNDEF()
 #ifdef WEBRTC_ANDROID_PLATFORM_BUILD
@@ -183,10 +182,11 @@
   apm_config.echo_canceller.enabled = true;
 #if defined(WEBRTC_AUDIOPROC_FIXED_PROFILE)
   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)
+  // TODO(peah): Update tests to instead use AEC3.
+  apm_config.echo_canceller.use_legacy_aec = true;
   apm_config.echo_canceller.mobile_mode = false;
   apm_config.echo_canceller.legacy_moderate_suppression_level = true;
 
@@ -196,6 +196,7 @@
 #endif
 
   apm_config.high_pass_filter.enabled = true;
+  apm_config.level_estimation.enabled = true;
   ap->ApplyConfig(apm_config);
 
   EXPECT_NOERR(ap->level_estimator()->Enable(true));
@@ -720,28 +721,24 @@
 
   // -- Missing delay --
   EXPECT_EQ(apm_->kNoError, ProcessStreamChooser(format));
-  EXPECT_EQ(apm_->kStreamParameterNotSetError,
-            ProcessStreamChooser(format));
+  EXPECT_EQ(apm_->kNoError, ProcessStreamChooser(format));
 
   // Resets after successful ProcessStream().
   EXPECT_EQ(apm_->kNoError, apm_->set_stream_delay_ms(100));
   EXPECT_EQ(apm_->kNoError, ProcessStreamChooser(format));
-  EXPECT_EQ(apm_->kStreamParameterNotSetError,
-            ProcessStreamChooser(format));
+  EXPECT_EQ(apm_->kNoError, ProcessStreamChooser(format));
 
   // Other stream parameters set correctly.
   EXPECT_EQ(apm_->kNoError, apm_->gain_control()->Enable(true));
   EXPECT_EQ(apm_->kNoError,
             apm_->gain_control()->set_stream_analog_level(127));
-  EXPECT_EQ(apm_->kStreamParameterNotSetError,
-            ProcessStreamChooser(format));
+  EXPECT_EQ(apm_->kNoError, ProcessStreamChooser(format));
   EXPECT_EQ(apm_->kNoError, apm_->gain_control()->Enable(false));
 
   // -- No stream parameters --
   EXPECT_EQ(apm_->kNoError,
             AnalyzeReverseStreamChooser(format));
-  EXPECT_EQ(apm_->kStreamParameterNotSetError,
-            ProcessStreamChooser(format));
+  EXPECT_EQ(apm_->kNoError, ProcessStreamChooser(format));
 
   // -- All there --
   EXPECT_EQ(apm_->kNoError, apm_->set_stream_delay_ms(100));
@@ -873,6 +870,8 @@
   // Enable AEC only.
   AudioProcessing::Config apm_config = apm_->GetConfig();
   apm_config.echo_canceller.enabled = true;
+  // TODO(peah): Update tests to instead use AEC3.
+  apm_config.echo_canceller.use_legacy_aec = true;
   apm_config.echo_canceller.mobile_mode = false;
   apm_->ApplyConfig(apm_config);
   Config config;
@@ -1277,6 +1276,8 @@
   AudioProcessing::Config config = apm_->GetConfig();
   EXPECT_FALSE(config.echo_canceller.enabled);
   EXPECT_FALSE(config.high_pass_filter.enabled);
+  EXPECT_FALSE(config.level_estimation.enabled);
+  EXPECT_FALSE(config.voice_detection.enabled);
   EXPECT_FALSE(apm_->gain_control()->is_enabled());
   EXPECT_FALSE(apm_->level_estimator()->is_enabled());
   EXPECT_FALSE(apm_->noise_suppression()->is_enabled());
@@ -1398,21 +1399,38 @@
   EXPECT_TRUE(FrameDataAreEqual(*frame_, frame_copy));
   EXPECT_EQ(apm_->kNoError, apm_->voice_detection()->Enable(false));
 
-  // 4. Both VAD and the level estimator are enabled...
+  // 4. Only GetStatistics-reporting VAD is enabled...
+  SetFrameTo(frame_, 1000);
+  frame_copy.CopyFrom(*frame_);
+  auto apm_config = apm_->GetConfig();
+  apm_config.voice_detection.enabled = true;
+  apm_->ApplyConfig(apm_config);
+  EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_));
+  EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_));
+  EXPECT_TRUE(FrameDataAreEqual(*frame_, frame_copy));
+  apm_config.voice_detection.enabled = false;
+  apm_->ApplyConfig(apm_config);
+
+  // 5. Both VADs and the level estimator are enabled...
   SetFrameTo(frame_, 1000);
   frame_copy.CopyFrom(*frame_);
   EXPECT_EQ(apm_->kNoError, apm_->level_estimator()->Enable(true));
   EXPECT_EQ(apm_->kNoError, apm_->voice_detection()->Enable(true));
+  apm_config.voice_detection.enabled = true;
+  apm_->ApplyConfig(apm_config);
   EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_));
   EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_));
   EXPECT_TRUE(FrameDataAreEqual(*frame_, frame_copy));
   EXPECT_EQ(apm_->kNoError, apm_->level_estimator()->Enable(false));
   EXPECT_EQ(apm_->kNoError, apm_->voice_detection()->Enable(false));
+  apm_config.voice_detection.enabled = false;
+  apm_->ApplyConfig(apm_config);
 
   // Check the test is valid. We should have distortion from the filter
   // when AEC is enabled (which won't affect the audio).
-  AudioProcessing::Config apm_config = apm_->GetConfig();
   apm_config.echo_canceller.enabled = true;
+  // TODO(peah): Update tests to instead use AEC3.
+  apm_config.echo_canceller.use_legacy_aec = true;
   apm_config.echo_canceller.mobile_mode = false;
   apm_->ApplyConfig(apm_config);
   frame_->samples_per_channel_ = 320;
@@ -1836,6 +1854,7 @@
     int analog_level_average = 0;
     int max_output_average = 0;
     float ns_speech_prob_average = 0.0f;
+    float rms_dbfs_average = 0.0f;
 #if defined(WEBRTC_AUDIOPROC_FLOAT_PROFILE)
   int stats_index = 0;
 #endif
@@ -1870,6 +1889,9 @@
       }
 
       ns_speech_prob_average += apm_->noise_suppression()->speech_probability();
+      AudioProcessingStats stats =
+          apm_->GetStatistics(/*has_remote_tracks=*/false);
+      rms_dbfs_average += *stats.output_rms_dbfs;
 
       size_t frame_size = frame_->samples_per_channel_ * frame_->num_channels_;
       size_t write_count = fwrite(frame_->data(),
@@ -1905,11 +1927,6 @@
         const int32_t delay_standard_deviation_ms =
             stats.delay_standard_deviation_ms.value_or(-1.0);
 
-        // Get RMS.
-        int rms_level = apm_->level_estimator()->RMS();
-        EXPECT_LE(0, rms_level);
-        EXPECT_GE(127, rms_level);
-
         if (!write_ref_data) {
           const audioproc::Test::EchoMetrics& reference =
               test->echo_metrics(stats_index);
@@ -1930,8 +1947,6 @@
           EXPECT_EQ(reference_delay.median(), delay_median_ms);
           EXPECT_EQ(reference_delay.std(), delay_standard_deviation_ms);
 
-          EXPECT_EQ(test->rms_level(stats_index), rms_level);
-
           ++stats_index;
         } else {
           audioproc::Test::EchoMetrics* message_echo = test->add_echo_metrics();
@@ -1947,8 +1962,6 @@
               test->add_delay_metrics();
           message_delay->set_median(delay_median_ms);
           message_delay->set_std(delay_standard_deviation_ms);
-
-          test->add_rms_level(rms_level);
         }
       }
 #endif  // defined(WEBRTC_AUDIOPROC_FLOAT_PROFILE).
@@ -1956,6 +1969,7 @@
     max_output_average /= frame_count;
     analog_level_average /= frame_count;
     ns_speech_prob_average /= frame_count;
+    rms_dbfs_average /= frame_count;
 
     if (!write_ref_data) {
       const int kIntNear = 1;
@@ -1990,6 +2004,7 @@
       EXPECT_NEAR(test->ns_speech_probability_average(),
                   ns_speech_prob_average,
                   kFloatNear);
+      EXPECT_NEAR(test->rms_dbfs_average(), rms_dbfs_average, kFloatNear);
 #endif
     } else {
       test->set_has_voice_count(has_voice_count);
@@ -2002,6 +2017,7 @@
       EXPECT_LE(0.0f, ns_speech_prob_average);
       EXPECT_GE(1.0f, ns_speech_prob_average);
       test->set_ns_speech_probability_average(ns_speech_prob_average);
+      test->set_rms_dbfs_average(rms_dbfs_average);
 #endif
     }
 
@@ -2398,7 +2414,7 @@
 }
 
 #if defined(WEBRTC_AUDIOPROC_FLOAT_PROFILE)
-INSTANTIATE_TEST_CASE_P(
+INSTANTIATE_TEST_SUITE_P(
     CommonFormats,
     AudioProcessingTest,
     testing::Values(std::make_tuple(48000, 48000, 48000, 48000, 0, 0),
@@ -2428,11 +2444,11 @@
                     std::make_tuple(44100, 16000, 16000, 16000, 25, 0),
 
                     std::make_tuple(32000, 48000, 48000, 48000, 30, 0),
-                    std::make_tuple(32000, 48000, 32000, 48000, 35, 30),
+                    std::make_tuple(32000, 48000, 32000, 48000, 32, 30),
                     std::make_tuple(32000, 48000, 16000, 48000, 30, 20),
-                    std::make_tuple(32000, 44100, 48000, 44100, 20, 20),
-                    std::make_tuple(32000, 44100, 32000, 44100, 20, 15),
-                    std::make_tuple(32000, 44100, 16000, 44100, 20, 15),
+                    std::make_tuple(32000, 44100, 48000, 44100, 19, 20),
+                    std::make_tuple(32000, 44100, 32000, 44100, 19, 15),
+                    std::make_tuple(32000, 44100, 16000, 44100, 19, 15),
                     std::make_tuple(32000, 32000, 48000, 32000, 40, 35),
                     std::make_tuple(32000, 32000, 32000, 32000, 0, 0),
                     std::make_tuple(32000, 32000, 16000, 32000, 40, 20),
@@ -2440,21 +2456,21 @@
                     std::make_tuple(32000, 16000, 32000, 16000, 25, 20),
                     std::make_tuple(32000, 16000, 16000, 16000, 25, 0),
 
-                    std::make_tuple(16000, 48000, 48000, 48000, 25, 0),
-                    std::make_tuple(16000, 48000, 32000, 48000, 25, 30),
-                    std::make_tuple(16000, 48000, 16000, 48000, 25, 20),
+                    std::make_tuple(16000, 48000, 48000, 48000, 24, 0),
+                    std::make_tuple(16000, 48000, 32000, 48000, 24, 30),
+                    std::make_tuple(16000, 48000, 16000, 48000, 24, 20),
                     std::make_tuple(16000, 44100, 48000, 44100, 15, 20),
                     std::make_tuple(16000, 44100, 32000, 44100, 15, 15),
                     std::make_tuple(16000, 44100, 16000, 44100, 15, 15),
                     std::make_tuple(16000, 32000, 48000, 32000, 25, 35),
                     std::make_tuple(16000, 32000, 32000, 32000, 25, 0),
                     std::make_tuple(16000, 32000, 16000, 32000, 25, 20),
-                    std::make_tuple(16000, 16000, 48000, 16000, 40, 20),
+                    std::make_tuple(16000, 16000, 48000, 16000, 39, 20),
                     std::make_tuple(16000, 16000, 32000, 16000, 40, 20),
                     std::make_tuple(16000, 16000, 16000, 16000, 0, 0)));
 
 #elif defined(WEBRTC_AUDIOPROC_FIXED_PROFILE)
-INSTANTIATE_TEST_CASE_P(
+INSTANTIATE_TEST_SUITE_P(
     CommonFormats,
     AudioProcessingTest,
     testing::Values(std::make_tuple(48000, 48000, 48000, 48000, 20, 0),
@@ -2669,12 +2685,14 @@
   }
 
   // Disable all components except for an AEC and the residual echo detector.
+  // TODO(peah): Update this to also work on AEC3.
   AudioProcessing::Config apm_config;
   apm_config.residual_echo_detector.enabled = true;
   apm_config.high_pass_filter.enabled = false;
   apm_config.gain_controller2.enabled = false;
   apm_config.echo_canceller.enabled = true;
   apm_config.echo_canceller.mobile_mode = !use_AEC2;
+  apm_config.echo_canceller.use_legacy_aec = use_AEC2;
   apm->ApplyConfig(apm_config);
   EXPECT_EQ(apm->gain_control()->Enable(false), 0);
   EXPECT_EQ(apm->level_estimator()->Enable(false), 0);
@@ -2693,11 +2711,16 @@
   // Set up APM with AEC2 and process some audio.
   std::unique_ptr<AudioProcessing> apm = CreateApm(true);
   ASSERT_TRUE(apm);
+  AudioProcessing::Config apm_config;
+  apm_config.echo_canceller.enabled = true;
+  // TODO(peah): Update tests to instead use AEC3.
+  apm_config.echo_canceller.use_legacy_aec = true;
+  apm->ApplyConfig(apm_config);
 
   // Set up an audioframe.
   AudioFrame frame;
   frame.num_channels_ = 1;
-  SetFrameSampleRate(&frame, AudioProcessing::NativeRate::kSampleRate48kHz);
+  SetFrameSampleRate(&frame, AudioProcessing::NativeRate::kSampleRate32kHz);
 
   // Fill the audio frame with a sawtooth pattern.
   int16_t* ptr = frame.mutable_data();
@@ -2756,7 +2779,7 @@
   // Set up an audioframe.
   AudioFrame frame;
   frame.num_channels_ = 1;
-  SetFrameSampleRate(&frame, AudioProcessing::NativeRate::kSampleRate48kHz);
+  SetFrameSampleRate(&frame, AudioProcessing::NativeRate::kSampleRate32kHz);
 
   // Fill the audio frame with a sawtooth pattern.
   int16_t* ptr = frame.mutable_data();
@@ -2810,7 +2833,7 @@
   // Set up an audioframe.
   AudioFrame frame;
   frame.num_channels_ = 1;
-  SetFrameSampleRate(&frame, AudioProcessing::NativeRate::kSampleRate48kHz);
+  SetFrameSampleRate(&frame, AudioProcessing::NativeRate::kSampleRate32kHz);
 
   // Fill the audio frame with a sawtooth pattern.
   int16_t* ptr = frame.mutable_data();
@@ -2839,4 +2862,41 @@
   EXPECT_EQ(apm->ProcessStream(&frame), 0);
   EXPECT_FALSE(apm->GetStatistics(false).output_rms_dbfs);
 }
+
+TEST(ApmStatistics, ReportHasVoice) {
+  ProcessingConfig processing_config = {
+      {{32000, 1}, {32000, 1}, {32000, 1}, {32000, 1}}};
+  AudioProcessing::Config config;
+
+  // Set up an audioframe.
+  AudioFrame frame;
+  frame.num_channels_ = 1;
+  SetFrameSampleRate(&frame, AudioProcessing::NativeRate::kSampleRate32kHz);
+
+  // Fill the audio frame with a sawtooth pattern.
+  int16_t* ptr = frame.mutable_data();
+  for (size_t i = 0; i < frame.kMaxDataSizeSamples; i++) {
+    ptr[i] = 10000 * ((i % 3) - 1);
+  }
+
+  std::unique_ptr<AudioProcessing> apm(AudioProcessingBuilder().Create());
+  apm->Initialize(processing_config);
+
+  // If not enabled, no metric should be reported.
+  EXPECT_EQ(apm->ProcessStream(&frame), 0);
+  EXPECT_FALSE(apm->GetStatistics(false).voice_detected);
+
+  // If enabled, metrics should be reported.
+  config.voice_detection.enabled = true;
+  apm->ApplyConfig(config);
+  EXPECT_EQ(apm->ProcessStream(&frame), 0);
+  auto stats = apm->GetStatistics(false);
+  EXPECT_TRUE(stats.voice_detected);
+
+  // If re-disabled, the value is again not reported.
+  config.voice_detection.enabled = false;
+  apm->ApplyConfig(config);
+  EXPECT_EQ(apm->ProcessStream(&frame), 0);
+  EXPECT_FALSE(apm->GetStatistics(false).voice_detected);
+}
 }  // namespace webrtc
diff --git a/modules/audio_processing/echo_cancellation_impl.cc b/modules/audio_processing/echo_cancellation_impl.cc
index 73fe51b..96b9789 100644
--- a/modules/audio_processing/echo_cancellation_impl.cc
+++ b/modules/audio_processing/echo_cancellation_impl.cc
@@ -322,7 +322,12 @@
 }
 
 std::string EchoCancellationImpl::GetExperimentsDescription() {
-  return refined_adaptive_filter_enabled_ ? "RefinedAdaptiveFilter;" : "";
+  if (enabled_) {
+    return refined_adaptive_filter_enabled_
+               ? "Legacy AEC;RefinedAdaptiveFilter;"
+               : "Legacy AEC;";
+  }
+  return "";
 }
 
 bool EchoCancellationImpl::is_refined_adaptive_filter_enabled() const {
diff --git a/modules/audio_processing/echo_cancellation_impl.h b/modules/audio_processing/echo_cancellation_impl.h
index a8b43a8..79be73b 100644
--- a/modules/audio_processing/echo_cancellation_impl.h
+++ b/modules/audio_processing/echo_cancellation_impl.h
@@ -18,8 +18,8 @@
 
 #include "api/array_view.h"
 #include "modules/audio_processing/include/audio_processing.h"
-#include "rtc_base/constructormagic.h"
-#include "rtc_base/criticalsection.h"
+#include "rtc_base/constructor_magic.h"
+#include "rtc_base/critical_section.h"
 #include "rtc_base/thread_annotations.h"
 
 namespace webrtc {
diff --git a/modules/audio_processing/echo_cancellation_impl_unittest.cc b/modules/audio_processing/echo_cancellation_impl_unittest.cc
index 9d81c1d..841ea0d 100644
--- a/modules/audio_processing/echo_cancellation_impl_unittest.cc
+++ b/modules/audio_processing/echo_cancellation_impl_unittest.cc
@@ -13,7 +13,7 @@
 #include "modules/audio_processing/aec/aec_core.h"
 #include "modules/audio_processing/echo_cancellation_impl.h"
 #include "modules/audio_processing/include/audio_processing.h"
-#include "rtc_base/criticalsection.h"
+#include "rtc_base/critical_section.h"
 #include "test/gtest.h"
 
 namespace webrtc {
diff --git a/modules/audio_processing/echo_control_mobile_impl.cc b/modules/audio_processing/echo_control_mobile_impl.cc
index b9fbf42..3655eb1 100644
--- a/modules/audio_processing/echo_control_mobile_impl.cc
+++ b/modules/audio_processing/echo_control_mobile_impl.cc
@@ -17,7 +17,7 @@
 #include "modules/audio_processing/audio_buffer.h"
 #include "modules/audio_processing/include/audio_processing.h"
 #include "rtc_base/checks.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
diff --git a/modules/audio_processing/echo_control_mobile_unittest.cc b/modules/audio_processing/echo_control_mobile_unittest.cc
index f0e6048..6b054d1 100644
--- a/modules/audio_processing/echo_control_mobile_unittest.cc
+++ b/modules/audio_processing/echo_control_mobile_unittest.cc
@@ -13,7 +13,7 @@
 
 #include "modules/audio_processing/echo_control_mobile_impl.h"
 #include "modules/audio_processing/include/audio_processing.h"
-#include "rtc_base/criticalsection.h"
+#include "rtc_base/critical_section.h"
 #include "test/gtest.h"
 
 namespace webrtc {
diff --git a/modules/audio_processing/gain_control_for_experimental_agc.cc b/modules/audio_processing/gain_control_for_experimental_agc.cc
index 1479d58..5cb22f8 100644
--- a/modules/audio_processing/gain_control_for_experimental_agc.cc
+++ b/modules/audio_processing/gain_control_for_experimental_agc.cc
@@ -12,8 +12,8 @@
 
 #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/criticalsection.h"
+#include "rtc_base/atomic_ops.h"
+#include "rtc_base/critical_section.h"
 
 namespace webrtc {
 
diff --git a/modules/audio_processing/gain_control_for_experimental_agc.h b/modules/audio_processing/gain_control_for_experimental_agc.h
index b20fbc9..8f5681f 100644
--- a/modules/audio_processing/gain_control_for_experimental_agc.h
+++ b/modules/audio_processing/gain_control_for_experimental_agc.h
@@ -13,8 +13,8 @@
 
 #include "modules/audio_processing/agc/agc_manager_direct.h"
 #include "modules/audio_processing/include/audio_processing.h"
-#include "rtc_base/constructormagic.h"
-#include "rtc_base/criticalsection.h"
+#include "rtc_base/constructor_magic.h"
+#include "rtc_base/critical_section.h"
 #include "rtc_base/thread_checker.h"
 
 namespace webrtc {
diff --git a/modules/audio_processing/gain_control_impl.cc b/modules/audio_processing/gain_control_impl.cc
index d5118ba..cd21e4c 100644
--- a/modules/audio_processing/gain_control_impl.cc
+++ b/modules/audio_processing/gain_control_impl.cc
@@ -18,7 +18,7 @@
 #include "modules/audio_processing/include/audio_processing.h"
 #include "modules/audio_processing/logging/apm_data_dumper.h"
 #include "rtc_base/checks.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
@@ -89,10 +89,8 @@
 
 int GainControlImpl::instance_counter_ = 0;
 
-GainControlImpl::GainControlImpl(rtc::CriticalSection* crit_render,
-                                 rtc::CriticalSection* crit_capture)
-    : crit_render_(crit_render),
-      crit_capture_(crit_capture),
+GainControlImpl::GainControlImpl(rtc::CriticalSection* crit_capture)
+    : crit_capture_(crit_capture),
       data_dumper_(new ApmDataDumper(instance_counter_)),
       mode_(kAdaptiveAnalog),
       minimum_capture_level_(0),
@@ -103,7 +101,6 @@
       analog_capture_level_(0),
       was_analog_level_set_(false),
       stream_is_saturated_(false) {
-  RTC_DCHECK(crit_render);
   RTC_DCHECK(crit_capture);
 }
 
@@ -267,7 +264,6 @@
 }
 
 int GainControlImpl::Enable(bool enable) {
-  rtc::CritScope cs_render(crit_render_);
   rtc::CritScope cs_capture(crit_capture_);
   if (enable && !enabled_) {
     enabled_ = enable;  // Must be set before Initialize() is called.
@@ -287,7 +283,6 @@
 }
 
 int GainControlImpl::set_mode(Mode mode) {
-  rtc::CritScope cs_render(crit_render_);
   rtc::CritScope cs_capture(crit_capture_);
   if (MapSetting(mode) == -1) {
     return AudioProcessing::kBadParameterError;
@@ -354,10 +349,8 @@
   if (level > 31 || level < 0) {
     return AudioProcessing::kBadParameterError;
   }
-  {
-    rtc::CritScope cs(crit_capture_);
-    target_level_dbfs_ = level;
-  }
+  rtc::CritScope cs(crit_capture_);
+  target_level_dbfs_ = level;
   return Configure();
 }
 
@@ -370,18 +363,14 @@
   if (gain < 0 || gain > 90) {
     return AudioProcessing::kBadParameterError;
   }
-  {
-    rtc::CritScope cs(crit_capture_);
-    compression_gain_db_ = gain;
-  }
+  rtc::CritScope cs(crit_capture_);
+  compression_gain_db_ = gain;
   return Configure();
 }
 
 int GainControlImpl::enable_limiter(bool enable) {
-  {
-    rtc::CritScope cs(crit_capture_);
-    limiter_enabled_ = enable;
-  }
+  rtc::CritScope cs(crit_capture_);
+  limiter_enabled_ = enable;
   return Configure();
 }
 
@@ -391,7 +380,6 @@
 }
 
 void GainControlImpl::Initialize(size_t num_proc_channels, int sample_rate_hz) {
-  rtc::CritScope cs_render(crit_render_);
   rtc::CritScope cs_capture(crit_capture_);
   data_dumper_->InitiateNewSetOfRecordings();
 
@@ -415,8 +403,6 @@
 }
 
 int GainControlImpl::Configure() {
-  rtc::CritScope cs_render(crit_render_);
-  rtc::CritScope cs_capture(crit_capture_);
   WebRtcAgcConfig config;
   // TODO(ajm): Flip the sign here (since AGC expects a positive value) if we
   //            change the interface.
diff --git a/modules/audio_processing/gain_control_impl.h b/modules/audio_processing/gain_control_impl.h
index c21d911..9dfe0f1 100644
--- a/modules/audio_processing/gain_control_impl.h
+++ b/modules/audio_processing/gain_control_impl.h
@@ -19,8 +19,8 @@
 #include "absl/types/optional.h"
 #include "api/array_view.h"
 #include "modules/audio_processing/include/gain_control.h"
-#include "rtc_base/constructormagic.h"
-#include "rtc_base/criticalsection.h"
+#include "rtc_base/constructor_magic.h"
+#include "rtc_base/critical_section.h"
 #include "rtc_base/thread_annotations.h"
 
 namespace webrtc {
@@ -30,8 +30,7 @@
 
 class GainControlImpl : public GainControl {
  public:
-  GainControlImpl(rtc::CriticalSection* crit_render,
-                  rtc::CriticalSection* crit_capture);
+  explicit GainControlImpl(rtc::CriticalSection* crit_capture);
   ~GainControlImpl() override;
 
   void ProcessRenderAudio(rtc::ArrayView<const int16_t> packed_render_audio);
@@ -67,9 +66,8 @@
   int analog_level_maximum() const override;
   bool stream_is_saturated() const override;
 
-  int Configure();
+  int Configure() RTC_EXCLUSIVE_LOCKS_REQUIRED(crit_capture_);
 
-  rtc::CriticalSection* const crit_render_ RTC_ACQUIRED_BEFORE(crit_capture_);
   rtc::CriticalSection* const crit_capture_;
 
   std::unique_ptr<ApmDataDumper> data_dumper_;
diff --git a/modules/audio_processing/gain_control_unittest.cc b/modules/audio_processing/gain_control_unittest.cc
index 62908c7..891e78a 100644
--- a/modules/audio_processing/gain_control_unittest.cc
+++ b/modules/audio_processing/gain_control_unittest.cc
@@ -72,9 +72,8 @@
                          int analog_level_max,
                          int achieved_stream_analog_level_reference,
                          rtc::ArrayView<const float> output_reference) {
-  rtc::CriticalSection crit_render;
   rtc::CriticalSection crit_capture;
-  GainControlImpl gain_controller(&crit_render, &crit_capture);
+  GainControlImpl gain_controller(&crit_capture);
   SetupComponent(sample_rate_hz, mode, target_level_dbfs, stream_analog_level,
                  compression_gain_db, enable_limiter, analog_level_min,
                  analog_level_max, &gain_controller);
diff --git a/modules/audio_processing/gain_controller2.cc b/modules/audio_processing/gain_controller2.cc
index 2a32744..a1bbb1b 100644
--- a/modules/audio_processing/gain_controller2.cc
+++ b/modules/audio_processing/gain_controller2.cc
@@ -14,7 +14,7 @@
 #include "modules/audio_processing/audio_buffer.h"
 #include "modules/audio_processing/include/audio_frame_view.h"
 #include "modules/audio_processing/logging/apm_data_dumper.h"
-#include "rtc_base/atomicops.h"
+#include "rtc_base/atomic_ops.h"
 #include "rtc_base/checks.h"
 #include "rtc_base/strings/string_builder.h"
 
diff --git a/modules/audio_processing/gain_controller2.h b/modules/audio_processing/gain_controller2.h
index 3a11810..7ed310e 100644
--- a/modules/audio_processing/gain_controller2.h
+++ b/modules/audio_processing/gain_controller2.h
@@ -18,7 +18,7 @@
 #include "modules/audio_processing/agc2/gain_applier.h"
 #include "modules/audio_processing/agc2/limiter.h"
 #include "modules/audio_processing/include/audio_processing.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
diff --git a/modules/audio_processing/gain_controller2_unittest.cc b/modules/audio_processing/gain_controller2_unittest.cc
index 27d540a..258832a 100644
--- a/modules/audio_processing/gain_controller2_unittest.cc
+++ b/modules/audio_processing/gain_controller2_unittest.cc
@@ -227,7 +227,7 @@
 }
 
 static_assert(test::kLimiterMaxInputLevelDbFs < 10, "");
-INSTANTIATE_TEST_CASE_P(
+INSTANTIATE_TEST_SUITE_P(
     GainController2,
     FixedDigitalTest,
     ::testing::Values(
diff --git a/modules/audio_processing/include/audio_processing.h b/modules/audio_processing/include/audio_processing.h
index df51313..6a0917a 100644
--- a/modules/audio_processing/include/audio_processing.h
+++ b/modules/audio_processing/include/audio_processing.h
@@ -25,6 +25,7 @@
 #include "absl/types/optional.h"
 #include "api/audio/echo_canceller3_config.h"
 #include "api/audio/echo_control.h"
+#include "api/scoped_refptr.h"
 #include "modules/audio_processing/include/audio_generator.h"
 #include "modules/audio_processing/include/audio_processing_statistics.h"
 #include "modules/audio_processing/include/config.h"
@@ -32,8 +33,7 @@
 #include "rtc_base/arraysize.h"
 #include "rtc_base/deprecation.h"
 #include "rtc_base/platform_file.h"
-#include "rtc_base/refcount.h"
-#include "rtc_base/scoped_ref_ptr.h"
+#include "rtc_base/ref_count.h"
 #include "rtc_base/system/rtc_export.h"
 
 namespace webrtc {
@@ -240,22 +240,6 @@
   // by changing the default values in the AudioProcessing::Config struct.
   // The config is applied by passing the struct to the ApplyConfig method.
   struct Config {
-    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;
-
-    struct HighPassFilter {
-      bool enabled = false;
-    } high_pass_filter;
-
     // Enabled the pre-amplifier. It amplifies the capture signal
     // before any other processing is done.
     struct PreAmplifier {
@@ -263,6 +247,32 @@
       float fixed_gain_factor = 1.f;
     } pre_amplifier;
 
+    struct HighPassFilter {
+      bool enabled = false;
+    } high_pass_filter;
+
+    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;
+      // Recommended not to use. Will be removed in the future.
+      bool use_legacy_aec = false;
+    } echo_canceller;
+
+    // Enables background noise suppression.
+    struct NoiseSuppression {
+      bool enabled = false;
+      enum Level { kLow, kModerate, kHigh, kVeryHigh };
+      Level level = kModerate;
+    } noise_suppression;
+
+    // Enables reporting of |has_voice| in webrtc::AudioProcessingStats.
+    struct VoiceDetection {
+      bool enabled = false;
+    } voice_detection;
+
     // 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
@@ -283,6 +293,10 @@
       } adaptive_digital;
     } gain_controller2;
 
+    struct ResidualEchoDetector {
+      bool enabled = true;
+    } residual_echo_detector;
+
     // Enables reporting of |output_rms_dbfs| in webrtc::AudioProcessingStats.
     struct LevelEstimation {
       bool enabled = false;
diff --git a/modules/audio_processing/include/audio_processing_statistics.h b/modules/audio_processing/include/audio_processing_statistics.h
index 683db05..87babee 100644
--- a/modules/audio_processing/include/audio_processing_statistics.h
+++ b/modules/audio_processing/include/audio_processing_statistics.h
@@ -32,6 +32,12 @@
   // Only reported if level estimation is enabled in AudioProcessing::Config.
   absl::optional<int> output_rms_dbfs;
 
+  // True if voice is detected in the last capture frame, after processing.
+  // It is conservative in flagging audio as speech, with low likelihood of
+  // incorrectly flagging a frame as voice.
+  // Only reported if voice detection is enabled in AudioProcessing::Config.
+  absl::optional<bool> voice_detected;
+
   // AEC Statistics.
   // ERL = 10log_10(P_far / P_echo)
   absl::optional<double> echo_return_loss;
diff --git a/modules/audio_processing/include/config.h b/modules/audio_processing/include/config.h
index e77d3fd..930cf7e 100644
--- a/modules/audio_processing/include/config.h
+++ b/modules/audio_processing/include/config.h
@@ -13,7 +13,7 @@
 
 #include <map>
 
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 #include "rtc_base/system/rtc_export.h"
 
 namespace webrtc {
diff --git a/modules/audio_processing/level_estimator_impl.h b/modules/audio_processing/level_estimator_impl.h
index 901ae4c..da217bb 100644
--- a/modules/audio_processing/level_estimator_impl.h
+++ b/modules/audio_processing/level_estimator_impl.h
@@ -14,8 +14,8 @@
 #include <memory>
 
 #include "modules/audio_processing/include/audio_processing.h"
-#include "rtc_base/constructormagic.h"
-#include "rtc_base/criticalsection.h"
+#include "rtc_base/constructor_magic.h"
+#include "rtc_base/critical_section.h"
 
 namespace webrtc {
 
diff --git a/modules/audio_processing/logging/apm_data_dumper.cc b/modules/audio_processing/logging/apm_data_dumper.cc
index cc879c8..6d84750 100644
--- a/modules/audio_processing/logging/apm_data_dumper.cc
+++ b/modules/audio_processing/logging/apm_data_dumper.cc
@@ -54,7 +54,7 @@
 ApmDataDumper::ApmDataDumper(int instance_index)
     : instance_index_(instance_index) {}
 #else
-ApmDataDumper::ApmDataDumper(int instance_index){};
+ApmDataDumper::ApmDataDumper(int instance_index) {}
 #endif
 
 ApmDataDumper::~ApmDataDumper() = default;
diff --git a/modules/audio_processing/logging/apm_data_dumper.h b/modules/audio_processing/logging/apm_data_dumper.h
index b541ae8..92adf86 100644
--- a/modules/audio_processing/logging/apm_data_dumper.h
+++ b/modules/audio_processing/logging/apm_data_dumper.h
@@ -17,6 +17,7 @@
 
 #include <string>
 #if WEBRTC_APM_DEBUG_DUMP == 1
+#include <memory>
 #include <unordered_map>
 #endif
 
@@ -25,7 +26,7 @@
 #include "common_audio/wav_file.h"
 #include "rtc_base/checks.h"
 #endif
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 // Check to verify that the define is properly set.
 #if !defined(WEBRTC_APM_DEBUG_DUMP) || \
diff --git a/modules/audio_processing/low_cut_filter.cc b/modules/audio_processing/low_cut_filter.cc
index 581d6bc..12a6e73 100644
--- a/modules/audio_processing/low_cut_filter.cc
+++ b/modules/audio_processing/low_cut_filter.cc
@@ -79,7 +79,7 @@
   }
 
  private:
-  const int16_t* const ba_ = nullptr;
+  const int16_t* const ba_;
   int16_t x_[2];
   int16_t y_[4];
 };
diff --git a/modules/audio_processing/low_cut_filter.h b/modules/audio_processing/low_cut_filter.h
index fd4c6f1..86fbddd 100644
--- a/modules/audio_processing/low_cut_filter.h
+++ b/modules/audio_processing/low_cut_filter.h
@@ -14,7 +14,7 @@
 #include <memory>
 #include <vector>
 
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
diff --git a/modules/audio_processing/module.mk b/modules/audio_processing/module.mk
index ee33c73..c12c290 100644
--- a/modules/audio_processing/module.mk
+++ b/modules/audio_processing/module.mk
@@ -27,6 +27,7 @@
 	modules/audio_processing/level_estimator_impl.o \
 	modules/audio_processing/low_cut_filter.o \
 	modules/audio_processing/noise_suppression_impl.o \
+	modules/audio_processing/noise_suppression_proxy.o \
 	modules/audio_processing/residual_echo_detector.o \
 	modules/audio_processing/rms_level.o \
 	modules/audio_processing/splitting_filter.o \
@@ -94,7 +95,6 @@
 	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_processor2.o \
 	modules/audio_processing/aec3/block_processor_metrics.o \
 	modules/audio_processing/aec3/cascaded_biquad_filter.o \
 	modules/audio_processing/aec3/clockdrift_detector.o \
@@ -120,9 +120,7 @@
 	modules/audio_processing/aec3/moving_average.o \
 	modules/audio_processing/aec3/render_buffer.o \
 	modules/audio_processing/aec3/render_delay_buffer.o \
-	modules/audio_processing/aec3/render_delay_buffer2.o \
 	modules/audio_processing/aec3/render_delay_controller.o \
-	modules/audio_processing/aec3/render_delay_controller2.o \
 	modules/audio_processing/aec3/render_delay_controller_metrics.o \
 	modules/audio_processing/aec3/render_reverb_model.o \
 	modules/audio_processing/aec3/render_signal_analyzer.o \
@@ -142,7 +140,6 @@
 	modules/audio_processing/aec3/subtractor_output_analyzer.o \
 	modules/audio_processing/aec3/suppression_filter.o \
 	modules/audio_processing/aec3/suppression_gain.o \
-	modules/audio_processing/aec3/suppression_gain_limiter.o \
 	modules/audio_processing/aec3/vector_buffer.o
 
 aec3_factory_CXX_OBJECTS = \
diff --git a/modules/audio_processing/noise_suppression_impl.cc b/modules/audio_processing/noise_suppression_impl.cc
index d8d9e32..bfaddd9 100644
--- a/modules/audio_processing/noise_suppression_impl.cc
+++ b/modules/audio_processing/noise_suppression_impl.cc
@@ -12,7 +12,7 @@
 
 #include "modules/audio_processing/audio_buffer.h"
 #include "rtc_base/checks.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 #if defined(WEBRTC_NS_FLOAT)
 #include "modules/audio_processing/ns/noise_suppression.h"
 
diff --git a/modules/audio_processing/noise_suppression_impl.h b/modules/audio_processing/noise_suppression_impl.h
index fba716e..414ca31 100644
--- a/modules/audio_processing/noise_suppression_impl.h
+++ b/modules/audio_processing/noise_suppression_impl.h
@@ -15,8 +15,8 @@
 #include <vector>
 
 #include "modules/audio_processing/include/audio_processing.h"
-#include "rtc_base/constructormagic.h"
-#include "rtc_base/criticalsection.h"
+#include "rtc_base/constructor_magic.h"
+#include "rtc_base/critical_section.h"
 
 namespace webrtc {
 
diff --git a/modules/audio_processing/noise_suppression_proxy.cc b/modules/audio_processing/noise_suppression_proxy.cc
new file mode 100644
index 0000000..a83c9b2
--- /dev/null
+++ b/modules/audio_processing/noise_suppression_proxy.cc
@@ -0,0 +1,71 @@
+/*
+ *  Copyright (c) 2019 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "modules/audio_processing/noise_suppression_proxy.h"
+
+namespace webrtc {
+NoiseSuppressionProxy::NoiseSuppressionProxy(AudioProcessing* apm,
+                                             NoiseSuppression* ns)
+    : apm_(apm), ns_(ns) {}
+
+NoiseSuppressionProxy::~NoiseSuppressionProxy() {}
+
+int NoiseSuppressionProxy::Enable(bool enable) {
+  AudioProcessing::Config config = apm_->GetConfig();
+  if (config.noise_suppression.enabled != enable) {
+    config.noise_suppression.enabled = enable;
+    apm_->ApplyConfig(config);
+  }
+  return AudioProcessing::kNoError;
+}
+
+bool NoiseSuppressionProxy::is_enabled() const {
+  return ns_->is_enabled();
+}
+
+int NoiseSuppressionProxy::set_level(Level level) {
+  AudioProcessing::Config config = apm_->GetConfig();
+  using NsConfig = AudioProcessing::Config::NoiseSuppression;
+  NsConfig::Level new_level;
+  switch (level) {
+    case NoiseSuppression::kLow:
+      new_level = NsConfig::kLow;
+      break;
+    case NoiseSuppression::kModerate:
+      new_level = NsConfig::kModerate;
+      break;
+    case NoiseSuppression::kHigh:
+      new_level = NsConfig::kHigh;
+      break;
+    case NoiseSuppression::kVeryHigh:
+      new_level = NsConfig::kVeryHigh;
+      break;
+    default:
+      RTC_NOTREACHED();
+  }
+  if (config.noise_suppression.level != new_level) {
+    config.noise_suppression.level = new_level;
+    apm_->ApplyConfig(config);
+  }
+  return AudioProcessing::kNoError;
+}
+
+NoiseSuppression::Level NoiseSuppressionProxy::level() const {
+  return ns_->level();
+}
+
+float NoiseSuppressionProxy::speech_probability() const {
+  return ns_->speech_probability();
+}
+
+std::vector<float> NoiseSuppressionProxy::NoiseEstimate() {
+  return ns_->NoiseEstimate();
+}
+}  // namespace webrtc
diff --git a/modules/audio_processing/noise_suppression_proxy.h b/modules/audio_processing/noise_suppression_proxy.h
new file mode 100644
index 0000000..959887f
--- /dev/null
+++ b/modules/audio_processing/noise_suppression_proxy.h
@@ -0,0 +1,45 @@
+/*
+ *  Copyright (c) 2019 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef MODULES_AUDIO_PROCESSING_NOISE_SUPPRESSION_PROXY_H_
+#define MODULES_AUDIO_PROCESSING_NOISE_SUPPRESSION_PROXY_H_
+
+#include <vector>
+
+#include "modules/audio_processing/include/audio_processing.h"
+#include "rtc_base/constructor_magic.h"
+
+namespace webrtc {
+// This class ensures interoperability with the pointer-to-submodule interface
+// AudioProcessing::noise_suppression() and AudioProcessing::ApplyConfig:
+// Enable(..) and set_level(..) calls are applied via
+// AudioProcessing::ApplyConfig, while all other function calls are forwarded
+// directly to a wrapped NoiseSuppression instance.
+class NoiseSuppressionProxy : public NoiseSuppression {
+ public:
+  NoiseSuppressionProxy(AudioProcessing* apm, NoiseSuppression* ns);
+  ~NoiseSuppressionProxy() override;
+
+  // NoiseSuppression implementation.
+  int Enable(bool enable) override;
+  bool is_enabled() const override;
+  int set_level(Level level) override;
+  Level level() const override;
+  float speech_probability() const override;
+  std::vector<float> NoiseEstimate() override;
+
+ private:
+  AudioProcessing* apm_;
+  NoiseSuppression* ns_;
+  RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(NoiseSuppressionProxy);
+};
+}  // namespace webrtc
+
+#endif  // MODULES_AUDIO_PROCESSING_NOISE_SUPPRESSION_PROXY_H_
diff --git a/modules/audio_processing/residual_echo_detector.cc b/modules/audio_processing/residual_echo_detector.cc
index 3454214..0b53cc2 100644
--- a/modules/audio_processing/residual_echo_detector.cc
+++ b/modules/audio_processing/residual_echo_detector.cc
@@ -16,7 +16,7 @@
 #include "absl/types/optional.h"
 #include "modules/audio_processing/audio_buffer.h"
 #include "modules/audio_processing/logging/apm_data_dumper.h"
-#include "rtc_base/atomicops.h"
+#include "rtc_base/atomic_ops.h"
 #include "rtc_base/checks.h"
 #include "rtc_base/logging.h"
 #include "system_wrappers/include/metrics.h"
diff --git a/modules/audio_processing/residual_echo_detector_unittest.cc b/modules/audio_processing/residual_echo_detector_unittest.cc
index c6fb8e4..6658999 100644
--- a/modules/audio_processing/residual_echo_detector_unittest.cc
+++ b/modules/audio_processing/residual_echo_detector_unittest.cc
@@ -11,7 +11,7 @@
 #include <vector>
 
 #include "modules/audio_processing/residual_echo_detector.h"
-#include "rtc_base/refcountedobject.h"
+#include "rtc_base/ref_counted_object.h"
 #include "test/gtest.h"
 
 namespace webrtc {
diff --git a/modules/audio_processing/rms_level_unittest.cc b/modules/audio_processing/rms_level_unittest.cc
index cf7683d..c2d6a50 100644
--- a/modules/audio_processing/rms_level_unittest.cc
+++ b/modules/audio_processing/rms_level_unittest.cc
@@ -14,7 +14,7 @@
 #include "api/array_view.h"
 #include "modules/audio_processing/rms_level.h"
 #include "rtc_base/checks.h"
-#include "rtc_base/numerics/mathutils.h"
+#include "rtc_base/numerics/math_utils.h"
 #include "rtc_base/numerics/safe_conversions.h"
 #include "test/gtest.h"
 
diff --git a/modules/audio_processing/transient/click_annotate.cc b/modules/audio_processing/transient/click_annotate.cc
index ce646b5..21641f8 100644
--- a/modules/audio_processing/transient/click_annotate.cc
+++ b/modules/audio_processing/transient/click_annotate.cc
@@ -39,16 +39,14 @@
     return 0;
   }
 
-  std::unique_ptr<FileWrapper> pcm_file(FileWrapper::Create());
-  pcm_file->OpenFile(argv[1], true);
-  if (!pcm_file->is_open()) {
+  FileWrapper pcm_file = FileWrapper::OpenReadOnly(argv[1]);
+  if (!pcm_file.is_open()) {
     printf("\nThe %s could not be opened.\n\n", argv[1]);
     return -1;
   }
 
-  std::unique_ptr<FileWrapper> dat_file(FileWrapper::Create());
-  dat_file->OpenFile(argv[2], false);
-  if (!dat_file->is_open()) {
+  FileWrapper dat_file = FileWrapper::OpenWriteOnly(argv[2]);
+  if (!dat_file.is_open()) {
     printf("\nThe %s could not be opened.\n\n", argv[2]);
     return -1;
   }
@@ -73,7 +71,7 @@
 
   // Read first buffer from the PCM test file.
   size_t file_samples_read = ReadInt16FromFileToFloatBuffer(
-      pcm_file.get(), audio_buffer_length, audio_buffer.get());
+      &pcm_file, audio_buffer_length, audio_buffer.get());
   for (int time = 0; file_samples_read > 0; time += chunk_size_ms) {
     // Pad the rest of the buffer with zeros.
     for (size_t i = file_samples_read; i < audio_buffer_length; ++i) {
@@ -91,19 +89,19 @@
 
     // Read next buffer from the PCM test file.
     file_samples_read = ReadInt16FromFileToFloatBuffer(
-        pcm_file.get(), audio_buffer_length, audio_buffer.get());
+        &pcm_file, audio_buffer_length, audio_buffer.get());
   }
 
   size_t floats_written =
-      WriteFloatBufferToFile(dat_file.get(), send_times.size(), &send_times[0]);
+      WriteFloatBufferToFile(&dat_file, send_times.size(), &send_times[0]);
 
   if (floats_written == 0) {
     printf("\nThe send times could not be written to DAT file\n\n");
     return -1;
   }
 
-  pcm_file->CloseFile();
-  dat_file->CloseFile();
+  pcm_file.Close();
+  dat_file.Close();
 
   return lost_packets;
 }
diff --git a/modules/audio_processing/transient/file_utils_unittest.cc b/modules/audio_processing/transient/file_utils_unittest.cc
index 89902ec..0bded02 100644
--- a/modules/audio_processing/transient/file_utils_unittest.cc
+++ b/modules/audio_processing/transient/file_utils_unittest.cc
@@ -17,7 +17,7 @@
 
 #include "rtc_base/system/file_wrapper.h"
 #include "test/gtest.h"
-#include "test/testsupport/fileutils.h"
+#include "test/testsupport/file_utils.h"
 
 namespace webrtc {
 
@@ -158,22 +158,20 @@
 TEST_F(TransientFileUtilsTest, MAYBE_ReadInt16BufferFromFile) {
   std::string test_filename = kTestFileName;
 
-  std::unique_ptr<FileWrapper> file(FileWrapper::Create());
-
-  file->OpenFile(test_filename.c_str(), true);  // Read only.
-  ASSERT_TRUE(file->is_open()) << "File could not be opened:\n"
-                               << kTestFileName.c_str();
+  FileWrapper file = FileWrapper::OpenReadOnly(test_filename.c_str());
+  ASSERT_TRUE(file.is_open()) << "File could not be opened:\n"
+                              << kTestFileName.c_str();
 
   const size_t kBufferLength = 12;
   std::unique_ptr<int16_t[]> buffer(new int16_t[kBufferLength]);
 
   EXPECT_EQ(kBufferLength,
-            ReadInt16BufferFromFile(file.get(), kBufferLength, buffer.get()));
+            ReadInt16BufferFromFile(&file, kBufferLength, buffer.get()));
   EXPECT_EQ(22377, buffer[4]);
   EXPECT_EQ(16389, buffer[7]);
   EXPECT_EQ(17631, buffer[kBufferLength - 1]);
 
-  file->Rewind();
+  file.Rewind();
 
   // The next test is for checking the case where there are not as much data as
   // needed in the file, but reads to the end, and it returns the number of
@@ -181,7 +179,7 @@
   const size_t kBufferLenghtLargerThanFile = kBufferLength * 2;
   buffer.reset(new int16_t[kBufferLenghtLargerThanFile]);
   EXPECT_EQ(kBufferLength,
-            ReadInt16BufferFromFile(file.get(), kBufferLenghtLargerThanFile,
+            ReadInt16BufferFromFile(&file, kBufferLenghtLargerThanFile,
                                     buffer.get()));
   EXPECT_EQ(11544, buffer[0]);
   EXPECT_EQ(22377, buffer[4]);
@@ -198,24 +196,22 @@
 TEST_F(TransientFileUtilsTest, MAYBE_ReadInt16FromFileToFloatBuffer) {
   std::string test_filename = kTestFileName;
 
-  std::unique_ptr<FileWrapper> file(FileWrapper::Create());
-
-  file->OpenFile(test_filename.c_str(), true);  // Read only.
-  ASSERT_TRUE(file->is_open()) << "File could not be opened:\n"
-                               << kTestFileName.c_str();
+  FileWrapper file = FileWrapper::OpenReadOnly(test_filename.c_str());
+  ASSERT_TRUE(file.is_open()) << "File could not be opened:\n"
+                              << kTestFileName.c_str();
 
   const size_t kBufferLength = 12;
   std::unique_ptr<float[]> buffer(new float[kBufferLength]);
 
-  EXPECT_EQ(kBufferLength, ReadInt16FromFileToFloatBuffer(
-                               file.get(), kBufferLength, buffer.get()));
+  EXPECT_EQ(kBufferLength,
+            ReadInt16FromFileToFloatBuffer(&file, kBufferLength, buffer.get()));
 
   EXPECT_DOUBLE_EQ(11544, buffer[0]);
   EXPECT_DOUBLE_EQ(22377, buffer[4]);
   EXPECT_DOUBLE_EQ(16389, buffer[7]);
   EXPECT_DOUBLE_EQ(17631, buffer[kBufferLength - 1]);
 
-  file->Rewind();
+  file.Rewind();
 
   // The next test is for checking the case where there are not as much data as
   // needed in the file, but reads to the end, and it returns the number of
@@ -223,8 +219,8 @@
   const size_t kBufferLenghtLargerThanFile = kBufferLength * 2;
   buffer.reset(new float[kBufferLenghtLargerThanFile]);
   EXPECT_EQ(kBufferLength,
-            ReadInt16FromFileToFloatBuffer(
-                file.get(), kBufferLenghtLargerThanFile, buffer.get()));
+            ReadInt16FromFileToFloatBuffer(&file, kBufferLenghtLargerThanFile,
+                                           buffer.get()));
   EXPECT_DOUBLE_EQ(11544, buffer[0]);
   EXPECT_DOUBLE_EQ(22377, buffer[4]);
   EXPECT_DOUBLE_EQ(16389, buffer[7]);
@@ -240,23 +236,21 @@
 TEST_F(TransientFileUtilsTest, MAYBE_ReadInt16FromFileToDoubleBuffer) {
   std::string test_filename = kTestFileName;
 
-  std::unique_ptr<FileWrapper> file(FileWrapper::Create());
-
-  file->OpenFile(test_filename.c_str(), true);  // Read only.
-  ASSERT_TRUE(file->is_open()) << "File could not be opened:\n"
-                               << kTestFileName.c_str();
+  FileWrapper file = FileWrapper::OpenReadOnly(test_filename.c_str());
+  ASSERT_TRUE(file.is_open()) << "File could not be opened:\n"
+                              << kTestFileName.c_str();
 
   const size_t kBufferLength = 12;
   std::unique_ptr<double[]> buffer(new double[kBufferLength]);
 
-  EXPECT_EQ(kBufferLength, ReadInt16FromFileToDoubleBuffer(
-                               file.get(), kBufferLength, buffer.get()));
+  EXPECT_EQ(kBufferLength, ReadInt16FromFileToDoubleBuffer(&file, kBufferLength,
+                                                           buffer.get()));
   EXPECT_DOUBLE_EQ(11544, buffer[0]);
   EXPECT_DOUBLE_EQ(22377, buffer[4]);
   EXPECT_DOUBLE_EQ(16389, buffer[7]);
   EXPECT_DOUBLE_EQ(17631, buffer[kBufferLength - 1]);
 
-  file->Rewind();
+  file.Rewind();
 
   // The next test is for checking the case where there are not as much data as
   // needed in the file, but reads to the end, and it returns the number of
@@ -264,8 +258,8 @@
   const size_t kBufferLenghtLargerThanFile = kBufferLength * 2;
   buffer.reset(new double[kBufferLenghtLargerThanFile]);
   EXPECT_EQ(kBufferLength,
-            ReadInt16FromFileToDoubleBuffer(
-                file.get(), kBufferLenghtLargerThanFile, buffer.get()));
+            ReadInt16FromFileToDoubleBuffer(&file, kBufferLenghtLargerThanFile,
+                                            buffer.get()));
   EXPECT_DOUBLE_EQ(11544, buffer[0]);
   EXPECT_DOUBLE_EQ(22377, buffer[4]);
   EXPECT_DOUBLE_EQ(16389, buffer[7]);
@@ -280,22 +274,20 @@
 TEST_F(TransientFileUtilsTest, MAYBE_ReadFloatBufferFromFile) {
   std::string test_filename = kTestFileNamef;
 
-  std::unique_ptr<FileWrapper> file(FileWrapper::Create());
-
-  file->OpenFile(test_filename.c_str(), true);  // Read only.
-  ASSERT_TRUE(file->is_open()) << "File could not be opened:\n"
-                               << kTestFileNamef.c_str();
+  FileWrapper file = FileWrapper::OpenReadOnly(test_filename.c_str());
+  ASSERT_TRUE(file.is_open()) << "File could not be opened:\n"
+                              << kTestFileNamef.c_str();
 
   const size_t kBufferLength = 3;
   std::unique_ptr<float[]> buffer(new float[kBufferLength]);
 
   EXPECT_EQ(kBufferLength,
-            ReadFloatBufferFromFile(file.get(), kBufferLength, buffer.get()));
+            ReadFloatBufferFromFile(&file, kBufferLength, buffer.get()));
   EXPECT_FLOAT_EQ(kPi, buffer[0]);
   EXPECT_FLOAT_EQ(kE, buffer[1]);
   EXPECT_FLOAT_EQ(kAvogadro, buffer[2]);
 
-  file->Rewind();
+  file.Rewind();
 
   // The next test is for checking the case where there are not as much data as
   // needed in the file, but reads to the end, and it returns the number of
@@ -303,7 +295,7 @@
   const size_t kBufferLenghtLargerThanFile = kBufferLength * 2;
   buffer.reset(new float[kBufferLenghtLargerThanFile]);
   EXPECT_EQ(kBufferLength,
-            ReadFloatBufferFromFile(file.get(), kBufferLenghtLargerThanFile,
+            ReadFloatBufferFromFile(&file, kBufferLenghtLargerThanFile,
                                     buffer.get()));
   EXPECT_FLOAT_EQ(kPi, buffer[0]);
   EXPECT_FLOAT_EQ(kE, buffer[1]);
@@ -318,22 +310,20 @@
 TEST_F(TransientFileUtilsTest, MAYBE_ReadDoubleBufferFromFile) {
   std::string test_filename = kTestFileName;
 
-  std::unique_ptr<FileWrapper> file(FileWrapper::Create());
-
-  file->OpenFile(test_filename.c_str(), true);  // Read only.
-  ASSERT_TRUE(file->is_open()) << "File could not be opened:\n"
-                               << kTestFileName.c_str();
+  FileWrapper file = FileWrapper::OpenReadOnly(test_filename.c_str());
+  ASSERT_TRUE(file.is_open()) << "File could not be opened:\n"
+                              << kTestFileName.c_str();
 
   const size_t kBufferLength = 3;
   std::unique_ptr<double[]> buffer(new double[kBufferLength]);
 
   EXPECT_EQ(kBufferLength,
-            ReadDoubleBufferFromFile(file.get(), kBufferLength, buffer.get()));
+            ReadDoubleBufferFromFile(&file, kBufferLength, buffer.get()));
   EXPECT_DOUBLE_EQ(kPi, buffer[0]);
   EXPECT_DOUBLE_EQ(kE, buffer[1]);
   EXPECT_DOUBLE_EQ(kAvogadro, buffer[2]);
 
-  file->Rewind();
+  file.Rewind();
 
   // The next test is for checking the case where there are not as much data as
   // needed in the file, but reads to the end, and it returns the number of
@@ -341,7 +331,7 @@
   const size_t kBufferLenghtLargerThanFile = kBufferLength * 2;
   buffer.reset(new double[kBufferLenghtLargerThanFile]);
   EXPECT_EQ(kBufferLength,
-            ReadDoubleBufferFromFile(file.get(), kBufferLenghtLargerThanFile,
+            ReadDoubleBufferFromFile(&file, kBufferLenghtLargerThanFile,
                                      buffer.get()));
   EXPECT_DOUBLE_EQ(kPi, buffer[0]);
   EXPECT_DOUBLE_EQ(kE, buffer[1]);
@@ -354,14 +344,12 @@
 #define MAYBE_WriteInt16BufferToFile WriteInt16BufferToFile
 #endif
 TEST_F(TransientFileUtilsTest, MAYBE_WriteInt16BufferToFile) {
-  std::unique_ptr<FileWrapper> file(FileWrapper::Create());
-
   std::string kOutFileName =
       CreateTempFilename(test::OutputPath(), "utils_test");
 
-  file->OpenFile(kOutFileName.c_str(), false);  // Write mode.
-  ASSERT_TRUE(file->is_open()) << "File could not be opened:\n"
-                               << kOutFileName.c_str();
+  FileWrapper file = FileWrapper::OpenWriteOnly(kOutFileName.c_str());
+  ASSERT_TRUE(file.is_open()) << "File could not be opened:\n"
+                              << kOutFileName.c_str();
 
   const size_t kBufferLength = 3;
   std::unique_ptr<int16_t[]> written_buffer(new int16_t[kBufferLength]);
@@ -371,17 +359,17 @@
   written_buffer[1] = 2;
   written_buffer[2] = 3;
 
-  EXPECT_EQ(kBufferLength, WriteInt16BufferToFile(file.get(), kBufferLength,
-                                                  written_buffer.get()));
+  EXPECT_EQ(kBufferLength,
+            WriteInt16BufferToFile(&file, kBufferLength, written_buffer.get()));
 
-  file->CloseFile();
+  file.Close();
 
-  file->OpenFile(kOutFileName.c_str(), true);  // Read only.
-  ASSERT_TRUE(file->is_open()) << "File could not be opened:\n"
-                               << kOutFileName.c_str();
+  file = FileWrapper::OpenReadOnly(kOutFileName.c_str());
+  ASSERT_TRUE(file.is_open()) << "File could not be opened:\n"
+                              << kOutFileName.c_str();
 
-  EXPECT_EQ(kBufferLength, ReadInt16BufferFromFile(file.get(), kBufferLength,
-                                                   read_buffer.get()));
+  EXPECT_EQ(kBufferLength,
+            ReadInt16BufferFromFile(&file, kBufferLength, read_buffer.get()));
   EXPECT_EQ(0, memcmp(written_buffer.get(), read_buffer.get(),
                       kBufferLength * sizeof(written_buffer[0])));
 }
@@ -392,14 +380,12 @@
 #define MAYBE_WriteFloatBufferToFile WriteFloatBufferToFile
 #endif
 TEST_F(TransientFileUtilsTest, MAYBE_WriteFloatBufferToFile) {
-  std::unique_ptr<FileWrapper> file(FileWrapper::Create());
-
   std::string kOutFileName =
       CreateTempFilename(test::OutputPath(), "utils_test");
 
-  file->OpenFile(kOutFileName.c_str(), false);  // Write mode.
-  ASSERT_TRUE(file->is_open()) << "File could not be opened:\n"
-                               << kOutFileName.c_str();
+  FileWrapper file = FileWrapper::OpenWriteOnly(kOutFileName.c_str());
+  ASSERT_TRUE(file.is_open()) << "File could not be opened:\n"
+                              << kOutFileName.c_str();
 
   const size_t kBufferLength = 3;
   std::unique_ptr<float[]> written_buffer(new float[kBufferLength]);
@@ -409,17 +395,17 @@
   written_buffer[1] = static_cast<float>(kE);
   written_buffer[2] = static_cast<float>(kAvogadro);
 
-  EXPECT_EQ(kBufferLength, WriteFloatBufferToFile(file.get(), kBufferLength,
-                                                  written_buffer.get()));
+  EXPECT_EQ(kBufferLength,
+            WriteFloatBufferToFile(&file, kBufferLength, written_buffer.get()));
 
-  file->CloseFile();
+  file.Close();
 
-  file->OpenFile(kOutFileName.c_str(), true);  // Read only.
-  ASSERT_TRUE(file->is_open()) << "File could not be opened:\n"
-                               << kOutFileName.c_str();
+  file = FileWrapper::OpenReadOnly(kOutFileName.c_str());
+  ASSERT_TRUE(file.is_open()) << "File could not be opened:\n"
+                              << kOutFileName.c_str();
 
-  EXPECT_EQ(kBufferLength, ReadFloatBufferFromFile(file.get(), kBufferLength,
-                                                   read_buffer.get()));
+  EXPECT_EQ(kBufferLength,
+            ReadFloatBufferFromFile(&file, kBufferLength, read_buffer.get()));
   EXPECT_EQ(0, memcmp(written_buffer.get(), read_buffer.get(),
                       kBufferLength * sizeof(written_buffer[0])));
 }
@@ -430,14 +416,12 @@
 #define MAYBE_WriteDoubleBufferToFile WriteDoubleBufferToFile
 #endif
 TEST_F(TransientFileUtilsTest, MAYBE_WriteDoubleBufferToFile) {
-  std::unique_ptr<FileWrapper> file(FileWrapper::Create());
-
   std::string kOutFileName =
       CreateTempFilename(test::OutputPath(), "utils_test");
 
-  file->OpenFile(kOutFileName.c_str(), false);  // Write mode.
-  ASSERT_TRUE(file->is_open()) << "File could not be opened:\n"
-                               << kOutFileName.c_str();
+  FileWrapper file = FileWrapper::OpenWriteOnly(kOutFileName.c_str());
+  ASSERT_TRUE(file.is_open()) << "File could not be opened:\n"
+                              << kOutFileName.c_str();
 
   const size_t kBufferLength = 3;
   std::unique_ptr<double[]> written_buffer(new double[kBufferLength]);
@@ -447,17 +431,17 @@
   written_buffer[1] = kE;
   written_buffer[2] = kAvogadro;
 
-  EXPECT_EQ(kBufferLength, WriteDoubleBufferToFile(file.get(), kBufferLength,
+  EXPECT_EQ(kBufferLength, WriteDoubleBufferToFile(&file, kBufferLength,
                                                    written_buffer.get()));
 
-  file->CloseFile();
+  file.Close();
 
-  file->OpenFile(kOutFileName.c_str(), true);  // Read only.
-  ASSERT_TRUE(file->is_open()) << "File could not be opened:\n"
-                               << kOutFileName.c_str();
+  file = FileWrapper::OpenReadOnly(kOutFileName.c_str());
+  ASSERT_TRUE(file.is_open()) << "File could not be opened:\n"
+                              << kOutFileName.c_str();
 
-  EXPECT_EQ(kBufferLength, ReadDoubleBufferFromFile(file.get(), kBufferLength,
-                                                    read_buffer.get()));
+  EXPECT_EQ(kBufferLength,
+            ReadDoubleBufferFromFile(&file, kBufferLength, read_buffer.get()));
   EXPECT_EQ(0, memcmp(written_buffer.get(), read_buffer.get(),
                       kBufferLength * sizeof(written_buffer[0])));
 }
@@ -473,7 +457,7 @@
   double value;
   std::unique_ptr<int16_t[]> int16_buffer(new int16_t[1]);
   std::unique_ptr<double[]> double_buffer(new double[1]);
-  std::unique_ptr<FileWrapper> file(FileWrapper::Create());
+  FileWrapper file;
 
   EXPECT_EQ(-1, ConvertByteArrayToDouble(NULL, &value));
   EXPECT_EQ(-1, ConvertByteArrayToDouble(kPiBytes, NULL));
@@ -481,37 +465,35 @@
   EXPECT_EQ(-1, ConvertDoubleToByteArray(kPi, NULL));
 
   // Tests with file not opened.
-  EXPECT_EQ(0u, ReadInt16BufferFromFile(file.get(), 1, int16_buffer.get()));
-  EXPECT_EQ(
-      0u, ReadInt16FromFileToDoubleBuffer(file.get(), 1, double_buffer.get()));
-  EXPECT_EQ(0u, ReadDoubleBufferFromFile(file.get(), 1, double_buffer.get()));
-  EXPECT_EQ(0u, WriteInt16BufferToFile(file.get(), 1, int16_buffer.get()));
-  EXPECT_EQ(0u, WriteDoubleBufferToFile(file.get(), 1, double_buffer.get()));
+  EXPECT_EQ(0u, ReadInt16BufferFromFile(&file, 1, int16_buffer.get()));
+  EXPECT_EQ(0u, ReadInt16FromFileToDoubleBuffer(&file, 1, double_buffer.get()));
+  EXPECT_EQ(0u, ReadDoubleBufferFromFile(&file, 1, double_buffer.get()));
+  EXPECT_EQ(0u, WriteInt16BufferToFile(&file, 1, int16_buffer.get()));
+  EXPECT_EQ(0u, WriteDoubleBufferToFile(&file, 1, double_buffer.get()));
 
-  file->OpenFile(test_filename.c_str(), true);  // Read only.
-  ASSERT_TRUE(file->is_open()) << "File could not be opened:\n"
-                               << kTestFileName.c_str();
+  file = FileWrapper::OpenReadOnly(test_filename.c_str());
+  ASSERT_TRUE(file.is_open()) << "File could not be opened:\n"
+                              << kTestFileName.c_str();
 
   EXPECT_EQ(0u, ReadInt16BufferFromFile(NULL, 1, int16_buffer.get()));
-  EXPECT_EQ(0u, ReadInt16BufferFromFile(file.get(), 1, NULL));
-  EXPECT_EQ(0u, ReadInt16BufferFromFile(file.get(), 0, int16_buffer.get()));
+  EXPECT_EQ(0u, ReadInt16BufferFromFile(&file, 1, NULL));
+  EXPECT_EQ(0u, ReadInt16BufferFromFile(&file, 0, int16_buffer.get()));
 
   EXPECT_EQ(0u, ReadInt16FromFileToDoubleBuffer(NULL, 1, double_buffer.get()));
-  EXPECT_EQ(0u, ReadInt16FromFileToDoubleBuffer(file.get(), 1, NULL));
-  EXPECT_EQ(
-      0u, ReadInt16FromFileToDoubleBuffer(file.get(), 0, double_buffer.get()));
+  EXPECT_EQ(0u, ReadInt16FromFileToDoubleBuffer(&file, 1, NULL));
+  EXPECT_EQ(0u, ReadInt16FromFileToDoubleBuffer(&file, 0, double_buffer.get()));
 
   EXPECT_EQ(0u, ReadDoubleBufferFromFile(NULL, 1, double_buffer.get()));
-  EXPECT_EQ(0u, ReadDoubleBufferFromFile(file.get(), 1, NULL));
-  EXPECT_EQ(0u, ReadDoubleBufferFromFile(file.get(), 0, double_buffer.get()));
+  EXPECT_EQ(0u, ReadDoubleBufferFromFile(&file, 1, NULL));
+  EXPECT_EQ(0u, ReadDoubleBufferFromFile(&file, 0, double_buffer.get()));
 
   EXPECT_EQ(0u, WriteInt16BufferToFile(NULL, 1, int16_buffer.get()));
-  EXPECT_EQ(0u, WriteInt16BufferToFile(file.get(), 1, NULL));
-  EXPECT_EQ(0u, WriteInt16BufferToFile(file.get(), 0, int16_buffer.get()));
+  EXPECT_EQ(0u, WriteInt16BufferToFile(&file, 1, NULL));
+  EXPECT_EQ(0u, WriteInt16BufferToFile(&file, 0, int16_buffer.get()));
 
   EXPECT_EQ(0u, WriteDoubleBufferToFile(NULL, 1, double_buffer.get()));
-  EXPECT_EQ(0u, WriteDoubleBufferToFile(file.get(), 1, NULL));
-  EXPECT_EQ(0u, WriteDoubleBufferToFile(file.get(), 0, double_buffer.get()));
+  EXPECT_EQ(0u, WriteDoubleBufferToFile(&file, 1, NULL));
+  EXPECT_EQ(0u, WriteDoubleBufferToFile(&file, 0, double_buffer.get()));
 }
 
 }  // namespace webrtc
diff --git a/modules/audio_processing/transient/transient_detector_unittest.cc b/modules/audio_processing/transient/transient_detector_unittest.cc
index 091a573..0425133 100644
--- a/modules/audio_processing/transient/transient_detector_unittest.cc
+++ b/modules/audio_processing/transient/transient_detector_unittest.cc
@@ -18,7 +18,7 @@
 #include "rtc_base/strings/string_builder.h"
 #include "rtc_base/system/file_wrapper.h"
 #include "test/gtest.h"
-#include "test/testsupport/fileutils.h"
+#include "test/testsupport/file_utils.h"
 
 namespace webrtc {
 
@@ -47,13 +47,10 @@
     detect_file_name << "audio_processing/transient/detect"
                      << (sample_rate_hz / 1000) << "kHz";
 
-    std::unique_ptr<FileWrapper> detect_file(FileWrapper::Create());
+    FileWrapper detect_file = FileWrapper::OpenReadOnly(
+        test::ResourcePath(detect_file_name.str(), "dat").c_str());
 
-    detect_file->OpenFile(
-        test::ResourcePath(detect_file_name.str(), "dat").c_str(),
-        true);  // Read only.
-
-    bool file_opened = detect_file->is_open();
+    bool file_opened = detect_file.is_open();
     ASSERT_TRUE(file_opened) << "File could not be opened.\n"
                              << detect_file_name.str().c_str();
 
@@ -62,11 +59,8 @@
     audio_file_name << "audio_processing/transient/audio"
                     << (sample_rate_hz / 1000) << "kHz";
 
-    std::unique_ptr<FileWrapper> audio_file(FileWrapper::Create());
-
-    audio_file->OpenFile(
-        test::ResourcePath(audio_file_name.str(), "pcm").c_str(),
-        true);  // Read only.
+    FileWrapper audio_file = FileWrapper::OpenReadOnly(
+        test::ResourcePath(audio_file_name.str(), "pcm").c_str());
 
     // Create detector.
     TransientDetector detector(sample_rate_hz);
@@ -78,14 +72,14 @@
 
     size_t frames_read = 0;
 
-    while (ReadInt16FromFileToFloatBuffer(audio_file.get(), buffer_length,
+    while (ReadInt16FromFileToFloatBuffer(&audio_file, buffer_length,
                                           buffer.get()) == buffer_length) {
       ++frames_read;
 
       float detector_value =
           detector.Detect(buffer.get(), buffer_length, NULL, 0);
       double file_value;
-      ASSERT_EQ(1u, ReadDoubleBufferFromFile(detect_file.get(), 1, &file_value))
+      ASSERT_EQ(1u, ReadDoubleBufferFromFile(&detect_file, 1, &file_value))
           << "Detect test file is malformed.\n";
 
       // Compare results with data from the matlab test file.
@@ -93,8 +87,8 @@
           << "Frame: " << frames_read;
     }
 
-    detect_file->CloseFile();
-    audio_file->CloseFile();
+    detect_file.Close();
+    audio_file.Close();
   }
 }
 
diff --git a/modules/audio_processing/transient/transient_suppression_test.cc b/modules/audio_processing/transient/transient_suppression_test.cc
index e15f69c..57bddb6 100644
--- a/modules/audio_processing/transient/transient_suppression_test.cc
+++ b/modules/audio_processing/transient/transient_suppression_test.cc
@@ -21,7 +21,7 @@
 #include "modules/audio_processing/agc/agc.h"
 #include "rtc_base/flags.h"
 #include "test/gtest.h"
-#include "test/testsupport/fileutils.h"
+#include "test/testsupport/file_utils.h"
 
 WEBRTC_DEFINE_string(in_file_name, "", "PCM file that contains the signal.");
 WEBRTC_DEFINE_string(detection_file_name,
diff --git a/modules/audio_processing/transient/wpd_tree_unittest.cc b/modules/audio_processing/transient/wpd_tree_unittest.cc
index 830a5df..11f75e6 100644
--- a/modules/audio_processing/transient/wpd_tree_unittest.cc
+++ b/modules/audio_processing/transient/wpd_tree_unittest.cc
@@ -18,7 +18,7 @@
 #include "rtc_base/strings/string_builder.h"
 #include "rtc_base/system/file_wrapper.h"
 #include "test/gtest.h"
-#include "test/testsupport/fileutils.h"
+#include "test/testsupport/file_utils.h"
 
 namespace webrtc {
 
@@ -80,31 +80,27 @@
                kDaubechies8LowPassCoefficients, kDaubechies8CoefficientsLength,
                kLevels);
   // Allocate and open all matlab and out files.
-  std::unique_ptr<FileWrapper> matlab_files_data[kLeaves];
-  std::unique_ptr<FileWrapper> out_files_data[kLeaves];
+  FileWrapper matlab_files_data[kLeaves];
+  FileWrapper out_files_data[kLeaves];
 
   for (int i = 0; i < kLeaves; ++i) {
     // Matlab files.
-    matlab_files_data[i].reset(FileWrapper::Create());
-
     rtc::StringBuilder matlab_stream;
     matlab_stream << "audio_processing/transient/wpd" << i;
     std::string matlab_string = test::ResourcePath(matlab_stream.str(), "dat");
-    matlab_files_data[i]->OpenFile(matlab_string.c_str(), true);  // Read only.
+    matlab_files_data[i] = FileWrapper::OpenReadOnly(matlab_string.c_str());
 
-    bool file_opened = matlab_files_data[i]->is_open();
+    bool file_opened = matlab_files_data[i].is_open();
     ASSERT_TRUE(file_opened) << "File could not be opened.\n" << matlab_string;
 
     // Out files.
-    out_files_data[i].reset(FileWrapper::Create());
-
     rtc::StringBuilder out_stream;
     out_stream << test::OutputPath() << "wpd_" << i << ".out";
     std::string out_string = out_stream.str();
 
-    out_files_data[i]->OpenFile(out_string.c_str(), false);  // Write mode.
+    out_files_data[i] = FileWrapper::OpenWriteOnly(out_string.c_str());
 
-    file_opened = out_files_data[i]->is_open();
+    file_opened = out_files_data[i].is_open();
     ASSERT_TRUE(file_opened) << "File could not be opened.\n" << out_string;
   }
 
@@ -112,11 +108,9 @@
   std::string test_file_name = test::ResourcePath(
       "audio_processing/transient/ajm-macbook-1-spke16m", "pcm");
 
-  std::unique_ptr<FileWrapper> test_file(FileWrapper::Create());
+  FileWrapper test_file = FileWrapper::OpenReadOnly(test_file_name.c_str());
 
-  test_file->OpenFile(test_file_name.c_str(), true);  // Read only.
-
-  bool file_opened = test_file->is_open();
+  bool file_opened = test_file.is_open();
   ASSERT_TRUE(file_opened) << "File could not be opened.\n" << test_file_name;
 
   float test_buffer[kTestBufferSize];
@@ -129,8 +123,8 @@
   size_t frames_read = 0;
 
   // Read first buffer from the PCM test file.
-  size_t file_samples_read = ReadInt16FromFileToFloatBuffer(
-      test_file.get(), kTestBufferSize, test_buffer);
+  size_t file_samples_read =
+      ReadInt16FromFileToFloatBuffer(&test_file, kTestBufferSize, test_buffer);
   while (file_samples_read > 0 && frames_read < kMaxFramesToTest) {
     ++frames_read;
 
@@ -147,7 +141,7 @@
     for (int i = 0; i < kLeaves; ++i) {
       // Compare data values
       size_t matlab_samples_read = ReadDoubleBufferFromFile(
-          matlab_files_data[i].get(), kLeavesSamples, matlab_buffer);
+          &matlab_files_data[i], kLeavesSamples, matlab_buffer);
 
       ASSERT_EQ(kLeavesSamples, matlab_samples_read)
           << "Matlab test files are malformed.\n"
@@ -162,22 +156,21 @@
       }
 
       // Write results to out files.
-      WriteFloatBufferToFile(out_files_data[i].get(), kLeavesSamples,
-                             node_data);
+      WriteFloatBufferToFile(&out_files_data[i], kLeavesSamples, node_data);
     }
 
     // Read next buffer from the PCM test file.
     file_samples_read = ReadInt16FromFileToFloatBuffer(
-        test_file.get(), kTestBufferSize, test_buffer);
+        &test_file, kTestBufferSize, test_buffer);
   }
 
   // Close all matlab and out files.
   for (int i = 0; i < kLeaves; ++i) {
-    matlab_files_data[i]->CloseFile();
-    out_files_data[i]->CloseFile();
+    matlab_files_data[i].Close();
+    out_files_data[i].Close();
   }
 
-  test_file->CloseFile();
+  test_file.Close();
 }
 
 }  // namespace webrtc
diff --git a/modules/audio_processing/utility/BUILD.gn b/modules/audio_processing/utility/BUILD.gn
index 6a4304d..f469cd4 100644
--- a/modules/audio_processing/utility/BUILD.gn
+++ b/modules/audio_processing/utility/BUILD.gn
@@ -83,6 +83,18 @@
   }
 }
 
+rtc_source_set("pffft_wrapper") {
+  sources = [
+    "pffft_wrapper.cc",
+    "pffft_wrapper.h",
+  ]
+  deps = [
+    "../../../api:array_view",
+    "../../../rtc_base:checks",
+    "//third_party/pffft",
+  ]
+}
+
 if (rtc_include_tests) {
   rtc_source_set("block_mean_calculator_unittest") {
     testonly = true
@@ -111,4 +123,17 @@
       "//testing/gtest",
     ]
   }
+
+  rtc_source_set("pffft_wrapper_unittest") {
+    testonly = true
+    sources = [
+      "pffft_wrapper_unittest.cc",
+    ]
+    deps = [
+      ":pffft_wrapper",
+      "../../../test:test_support",
+      "//testing/gtest",
+      "//third_party/pffft",
+    ]
+  }
 }
diff --git a/modules/audio_processing/utility/DEPS b/modules/audio_processing/utility/DEPS
new file mode 100644
index 0000000..c72d810
--- /dev/null
+++ b/modules/audio_processing/utility/DEPS
@@ -0,0 +1,3 @@
+include_rules = [
+  "+third_party/pffft",
+]
diff --git a/modules/audio_processing/utility/block_mean_calculator.h b/modules/audio_processing/utility/block_mean_calculator.h
index cfa7cfb..5ccdbef 100644
--- a/modules/audio_processing/utility/block_mean_calculator.h
+++ b/modules/audio_processing/utility/block_mean_calculator.h
@@ -13,7 +13,7 @@
 
 #include <stddef.h>
 
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
diff --git a/modules/audio_processing/utility/pffft_wrapper.cc b/modules/audio_processing/utility/pffft_wrapper.cc
new file mode 100644
index 0000000..eb0bff7
--- /dev/null
+++ b/modules/audio_processing/utility/pffft_wrapper.cc
@@ -0,0 +1,110 @@
+/*
+ *  Copyright (c) 2019 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "modules/audio_processing/utility/pffft_wrapper.h"
+
+#include "rtc_base/checks.h"
+#include "third_party/pffft/src/pffft.h"
+
+namespace webrtc {
+namespace {
+
+size_t GetBufferSize(size_t fft_size, Pffft::FftType fft_type) {
+  return fft_size * (fft_type == Pffft::FftType::kReal ? 1 : 2);
+}
+
+float* AllocatePffftBuffer(size_t size) {
+  return static_cast<float*>(pffft_aligned_malloc(size * sizeof(float)));
+}
+
+}  // namespace
+
+Pffft::FloatBuffer::FloatBuffer(size_t fft_size, FftType fft_type)
+    : size_(GetBufferSize(fft_size, fft_type)),
+      data_(AllocatePffftBuffer(size_)) {}
+
+Pffft::FloatBuffer::~FloatBuffer() {
+  pffft_aligned_free(data_);
+}
+
+rtc::ArrayView<const float> Pffft::FloatBuffer::GetConstView() const {
+  return {data_, size_};
+}
+
+rtc::ArrayView<float> Pffft::FloatBuffer::GetView() {
+  return {data_, size_};
+}
+
+Pffft::Pffft(size_t fft_size, FftType fft_type)
+    : fft_size_(fft_size),
+      fft_type_(fft_type),
+      pffft_status_(pffft_new_setup(
+          fft_size_,
+          fft_type == Pffft::FftType::kReal ? PFFFT_REAL : PFFFT_COMPLEX)),
+      scratch_buffer_(
+          AllocatePffftBuffer(GetBufferSize(fft_size_, fft_type_))) {
+  RTC_DCHECK(pffft_status_);
+  RTC_DCHECK(scratch_buffer_);
+}
+
+Pffft::~Pffft() {
+  pffft_destroy_setup(pffft_status_);
+  pffft_aligned_free(scratch_buffer_);
+}
+
+bool Pffft::IsValidFftSize(size_t fft_size, FftType fft_type) {
+  if (fft_size == 0) {
+    return false;
+  }
+  // PFFFT only supports transforms for inputs of length N of the form
+  // N = (2^a)*(3^b)*(5^c) where b >=0 and c >= 0 and a >= 5 for the real FFT
+  // and a >= 4 for the complex FFT.
+  constexpr int kFactors[] = {2, 3, 5};
+  int factorization[] = {0, 0, 0};
+  int n = static_cast<int>(fft_size);
+  for (int i = 0; i < 3; ++i) {
+    while (n % kFactors[i] == 0) {
+      n = n / kFactors[i];
+      factorization[i]++;
+    }
+  }
+  int a_min = (fft_type == Pffft::FftType::kReal) ? 5 : 4;
+  return factorization[0] >= a_min && n == 1;
+}
+
+bool Pffft::IsSimdEnabled() {
+  return pffft_simd_size() > 1;
+}
+
+std::unique_ptr<Pffft::FloatBuffer> Pffft::CreateBuffer() const {
+  // Cannot use make_unique from absl because Pffft is the only friend of
+  // Pffft::FloatBuffer.
+  std::unique_ptr<Pffft::FloatBuffer> buffer(
+      new Pffft::FloatBuffer(fft_size_, fft_type_));
+  return buffer;
+}
+
+void Pffft::ForwardTransform(const FloatBuffer& in, FloatBuffer* out) {
+  RTC_DCHECK_EQ(in.size(), GetBufferSize(fft_size_, fft_type_));
+  RTC_DCHECK_EQ(in.size(), out->size());
+  RTC_DCHECK(scratch_buffer_);
+  pffft_transform(pffft_status_, in.const_data(), out->data(), scratch_buffer_,
+                  PFFFT_FORWARD);
+}
+
+void Pffft::BackwardTransform(const FloatBuffer& in, FloatBuffer* out) {
+  RTC_DCHECK_EQ(in.size(), GetBufferSize(fft_size_, fft_type_));
+  RTC_DCHECK_EQ(in.size(), out->size());
+  RTC_DCHECK(scratch_buffer_);
+  pffft_transform(pffft_status_, in.const_data(), out->data(), scratch_buffer_,
+                  PFFFT_BACKWARD);
+}
+
+}  // namespace webrtc
diff --git a/modules/audio_processing/utility/pffft_wrapper.h b/modules/audio_processing/utility/pffft_wrapper.h
new file mode 100644
index 0000000..c190430
--- /dev/null
+++ b/modules/audio_processing/utility/pffft_wrapper.h
@@ -0,0 +1,85 @@
+/*
+ *  Copyright (c) 2019 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef MODULES_AUDIO_PROCESSING_UTILITY_PFFFT_WRAPPER_H_
+#define MODULES_AUDIO_PROCESSING_UTILITY_PFFFT_WRAPPER_H_
+
+#include <memory>
+
+#include "api/array_view.h"
+
+// Forward declaration.
+struct PFFFT_Setup;
+
+namespace webrtc {
+
+// Pretty-Fast Fast Fourier Transform (PFFFT) wrapper class.
+// Not thread safe.
+class Pffft {
+ public:
+  enum class FftType { kReal, kComplex };
+
+  // 1D floating point buffer used as input/output data type for the FFT ops.
+  // It must be constructed using Pffft::CreateBuffer().
+  class FloatBuffer {
+   public:
+    FloatBuffer(const FloatBuffer&) = delete;
+    FloatBuffer& operator=(const FloatBuffer&) = delete;
+    ~FloatBuffer();
+
+    rtc::ArrayView<const float> GetConstView() const;
+    rtc::ArrayView<float> GetView();
+
+   private:
+    friend class Pffft;
+    FloatBuffer(size_t fft_size, FftType fft_type);
+    const float* const_data() const { return data_; }
+    float* data() { return data_; }
+    size_t size() const { return size_; }
+
+    const size_t size_;
+    float* const data_;
+  };
+
+  // TODO(https://crbug.com/webrtc/9577): Consider adding a factory and making
+  // the ctor private.
+  // static std::unique_ptr<Pffft> Create(size_t fft_size,
+  // FftType fft_type); Ctor. |fft_size| must be a supported size (see
+  // Pffft::IsValidFftSize()). If not supported, the code will crash.
+  Pffft(size_t fft_size, FftType fft_type);
+  Pffft(const Pffft&) = delete;
+  Pffft& operator=(const Pffft&) = delete;
+  ~Pffft();
+
+  // Returns true if the FFT size is supported.
+  static bool IsValidFftSize(size_t fft_size, FftType fft_type);
+
+  // Returns true if SIMD code optimizations are being used.
+  static bool IsSimdEnabled();
+
+  // Creates a buffer of the right size.
+  std::unique_ptr<FloatBuffer> CreateBuffer() const;
+
+  // TODO(https://crbug.com/webrtc/9577): Overload with rtc::ArrayView args.
+  // Computes the forward fast Fourier transform.
+  void ForwardTransform(const FloatBuffer& in, FloatBuffer* out);
+  // Computes the backward fast Fourier transform.
+  void BackwardTransform(const FloatBuffer& in, FloatBuffer* out);
+
+ private:
+  const size_t fft_size_;
+  const FftType fft_type_;
+  PFFFT_Setup* pffft_status_;
+  float* const scratch_buffer_;
+};
+
+}  // namespace webrtc
+
+#endif  // MODULES_AUDIO_PROCESSING_UTILITY_PFFFT_WRAPPER_H_
diff --git a/modules/audio_processing/utility/pffft_wrapper_unittest.cc b/modules/audio_processing/utility/pffft_wrapper_unittest.cc
new file mode 100644
index 0000000..8ec2208
--- /dev/null
+++ b/modules/audio_processing/utility/pffft_wrapper_unittest.cc
@@ -0,0 +1,154 @@
+/*
+ *  Copyright (c) 2019 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "modules/audio_processing/utility/pffft_wrapper.h"
+
+#include <algorithm>
+#include <cstdlib>
+#include <memory>
+
+#include "test/gtest.h"
+#include "third_party/pffft/src/pffft.h"
+
+namespace webrtc {
+namespace test {
+namespace {
+
+constexpr size_t kMaxValidSizeCheck = 1024;
+
+static constexpr int kFftSizes[] = {
+    16,  32,      64,  96,  128,  160,  192,  256,  288,  384,   5 * 96, 512,
+    576, 5 * 128, 800, 864, 1024, 2048, 2592, 4000, 4096, 12000, 36864};
+
+void CreatePffftWrapper(size_t fft_size, Pffft::FftType fft_type) {
+  Pffft pffft_wrapper(fft_size, fft_type);
+}
+
+float* AllocateScratchBuffer(size_t fft_size, bool complex_fft) {
+  return static_cast<float*>(
+      pffft_aligned_malloc(fft_size * (complex_fft ? 2 : 1) * sizeof(float)));
+}
+
+double frand() {
+  return std::rand() / static_cast<double>(RAND_MAX);
+}
+
+void ExpectArrayViewsEquality(rtc::ArrayView<const float> a,
+                              rtc::ArrayView<const float> b) {
+  ASSERT_EQ(a.size(), b.size());
+  for (size_t i = 0; i < a.size(); ++i) {
+    SCOPED_TRACE(i);
+    EXPECT_EQ(a[i], b[i]);
+  }
+}
+
+// Compares the output of the PFFFT C++ wrapper to that of the C PFFFT.
+// Bit-exactness is expected.
+void PffftValidateWrapper(size_t fft_size, bool complex_fft) {
+  // Always use the same seed to avoid flakiness.
+  std::srand(0);
+
+  // Init PFFFT.
+  PFFFT_Setup* pffft_status =
+      pffft_new_setup(fft_size, complex_fft ? PFFFT_COMPLEX : PFFFT_REAL);
+  ASSERT_TRUE(pffft_status) << "FFT size (" << fft_size << ") not supported.";
+  size_t num_floats = fft_size * (complex_fft ? 2 : 1);
+  int num_bytes = static_cast<int>(num_floats) * sizeof(float);
+  float* in = static_cast<float*>(pffft_aligned_malloc(num_bytes));
+  float* out = static_cast<float*>(pffft_aligned_malloc(num_bytes));
+  float* scratch = AllocateScratchBuffer(fft_size, complex_fft);
+
+  // Init PFFFT C++ wrapper.
+  Pffft::FftType fft_type =
+      complex_fft ? Pffft::FftType::kComplex : Pffft::FftType::kReal;
+  ASSERT_TRUE(Pffft::IsValidFftSize(fft_size, fft_type));
+  Pffft pffft_wrapper(fft_size, fft_type);
+  auto in_wrapper = pffft_wrapper.CreateBuffer();
+  auto out_wrapper = pffft_wrapper.CreateBuffer();
+
+  // Input and output buffers views.
+  rtc::ArrayView<float> in_view(in, num_floats);
+  rtc::ArrayView<float> out_view(out, num_floats);
+  auto in_wrapper_view = in_wrapper->GetView();
+  EXPECT_EQ(in_wrapper_view.size(), num_floats);
+  auto out_wrapper_view = out_wrapper->GetConstView();
+  EXPECT_EQ(out_wrapper_view.size(), num_floats);
+
+  // Random input data.
+  for (size_t i = 0; i < num_floats; ++i) {
+    in_wrapper_view[i] = in[i] = static_cast<float>(frand() * 2.0 - 1.0);
+  }
+
+  // Forward transform.
+  pffft_transform(pffft_status, in, out, scratch, PFFFT_FORWARD);
+  pffft_wrapper.ForwardTransform(*in_wrapper, out_wrapper.get());
+  ExpectArrayViewsEquality(out_view, out_wrapper_view);
+
+  // Copy the FFT results into the input buffers to compute the backward FFT.
+  std::copy(out_view.begin(), out_view.end(), in_view.begin());
+  std::copy(out_wrapper_view.begin(), out_wrapper_view.end(),
+            in_wrapper_view.begin());
+
+  // Backward transform.
+  pffft_transform(pffft_status, in, out, scratch, PFFFT_BACKWARD);
+  pffft_wrapper.BackwardTransform(*in_wrapper, out_wrapper.get());
+  ExpectArrayViewsEquality(out_view, out_wrapper_view);
+
+  pffft_destroy_setup(pffft_status);
+  pffft_aligned_free(in);
+  pffft_aligned_free(out);
+  pffft_aligned_free(scratch);
+}
+
+}  // namespace
+
+TEST(PffftTest, CreateWrapperWithValidSize) {
+  for (size_t fft_size = 0; fft_size < kMaxValidSizeCheck; ++fft_size) {
+    SCOPED_TRACE(fft_size);
+    if (Pffft::IsValidFftSize(fft_size, Pffft::FftType::kReal)) {
+      CreatePffftWrapper(fft_size, Pffft::FftType::kReal);
+    }
+    if (Pffft::IsValidFftSize(fft_size, Pffft::FftType::kComplex)) {
+      CreatePffftWrapper(fft_size, Pffft::FftType::kComplex);
+    }
+  }
+}
+
+#if !defined(NDEBUG) && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
+TEST(PffftTest, DoNotCreateWrapperWithInvalidSize) {
+  for (size_t fft_size = 0; fft_size < kMaxValidSizeCheck; ++fft_size) {
+    SCOPED_TRACE(fft_size);
+    if (!Pffft::IsValidFftSize(fft_size, Pffft::FftType::kReal)) {
+      EXPECT_DEATH(CreatePffftWrapper(fft_size, Pffft::FftType::kReal), "");
+    }
+    if (!Pffft::IsValidFftSize(fft_size, Pffft::FftType::kComplex)) {
+      EXPECT_DEATH(CreatePffftWrapper(fft_size, Pffft::FftType::kComplex), "");
+    }
+  }
+}
+#endif
+
+// TODO(https://crbug.com/webrtc/9577): Enable once SIMD is always enabled.
+TEST(PffftTest, DISABLED_CheckSimd) {
+  EXPECT_TRUE(Pffft::IsSimdEnabled());
+}
+
+TEST(PffftTest, FftBitExactness) {
+  for (int fft_size : kFftSizes) {
+    SCOPED_TRACE(fft_size);
+    if (fft_size != 16) {
+      PffftValidateWrapper(fft_size, /*complex_fft=*/false);
+    }
+    PffftValidateWrapper(fft_size, /*complex_fft=*/true);
+  }
+}
+
+}  // namespace test
+}  // namespace webrtc
diff --git a/modules/audio_processing/vad/pitch_based_vad_unittest.cc b/modules/audio_processing/vad/pitch_based_vad_unittest.cc
index fb6daa5..4a8331a 100644
--- a/modules/audio_processing/vad/pitch_based_vad_unittest.cc
+++ b/modules/audio_processing/vad/pitch_based_vad_unittest.cc
@@ -16,7 +16,7 @@
 #include <string>
 
 #include "test/gtest.h"
-#include "test/testsupport/fileutils.h"
+#include "test/testsupport/file_utils.h"
 
 namespace webrtc {
 
diff --git a/modules/audio_processing/vad/pole_zero_filter_unittest.cc b/modules/audio_processing/vad/pole_zero_filter_unittest.cc
index 38ee10f..8088b40 100644
--- a/modules/audio_processing/vad/pole_zero_filter_unittest.cc
+++ b/modules/audio_processing/vad/pole_zero_filter_unittest.cc
@@ -17,7 +17,7 @@
 
 #include "modules/audio_processing/vad/vad_audio_proc_internal.h"
 #include "test/gtest.h"
-#include "test/testsupport/fileutils.h"
+#include "test/testsupport/file_utils.h"
 
 namespace webrtc {
 
diff --git a/modules/audio_processing/vad/standalone_vad_unittest.cc b/modules/audio_processing/vad/standalone_vad_unittest.cc
index 512276e..22b1f49 100644
--- a/modules/audio_processing/vad/standalone_vad_unittest.cc
+++ b/modules/audio_processing/vad/standalone_vad_unittest.cc
@@ -15,7 +15,7 @@
 #include <memory>
 
 #include "test/gtest.h"
-#include "test/testsupport/fileutils.h"
+#include "test/testsupport/file_utils.h"
 
 namespace webrtc {
 
diff --git a/modules/audio_processing/vad/vad_audio_proc_unittest.cc b/modules/audio_processing/vad/vad_audio_proc_unittest.cc
index 5b96be6..0afed84 100644
--- a/modules/audio_processing/vad/vad_audio_proc_unittest.cc
+++ b/modules/audio_processing/vad/vad_audio_proc_unittest.cc
@@ -21,7 +21,7 @@
 
 #include "modules/audio_processing/vad/common.h"
 #include "test/gtest.h"
-#include "test/testsupport/fileutils.h"
+#include "test/testsupport/file_utils.h"
 
 namespace webrtc {
 
diff --git a/modules/audio_processing/vad/voice_activity_detector_unittest.cc b/modules/audio_processing/vad/voice_activity_detector_unittest.cc
index 62eda2b..3214bd9 100644
--- a/modules/audio_processing/vad/voice_activity_detector_unittest.cc
+++ b/modules/audio_processing/vad/voice_activity_detector_unittest.cc
@@ -14,7 +14,7 @@
 #include <vector>
 
 #include "test/gtest.h"
-#include "test/testsupport/fileutils.h"
+#include "test/testsupport/file_utils.h"
 
 namespace webrtc {
 namespace {
diff --git a/modules/audio_processing/voice_detection_impl.cc b/modules/audio_processing/voice_detection_impl.cc
index c55ca4a..7bf6c4a 100644
--- a/modules/audio_processing/voice_detection_impl.cc
+++ b/modules/audio_processing/voice_detection_impl.cc
@@ -14,7 +14,7 @@
 #include "common_audio/vad/include/webrtc_vad.h"
 #include "modules/audio_processing/audio_buffer.h"
 #include "rtc_base/checks.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 class VoiceDetectionImpl::Vad {
diff --git a/modules/audio_processing/voice_detection_impl.h b/modules/audio_processing/voice_detection_impl.h
index c438473..6800566 100644
--- a/modules/audio_processing/voice_detection_impl.h
+++ b/modules/audio_processing/voice_detection_impl.h
@@ -15,8 +15,8 @@
 #include <memory>
 
 #include "modules/audio_processing/include/audio_processing.h"
-#include "rtc_base/constructormagic.h"
-#include "rtc_base/criticalsection.h"
+#include "rtc_base/constructor_magic.h"
+#include "rtc_base/critical_section.h"
 #include "rtc_base/thread_annotations.h"
 
 namespace webrtc {
diff --git a/modules/include/module_common_types.h b/modules/include/module_common_types.h
index e058cc8..26122b1 100644
--- a/modules/include/module_common_types.h
+++ b/modules/include/module_common_types.h
@@ -13,6 +13,7 @@
 
 #include <stddef.h>
 #include <stdint.h>
+#include <vector>
 
 #include "api/rtp_headers.h"
 #include "common_types.h"  // NOLINT(build/include)
@@ -96,6 +97,17 @@
   virtual ~KeyFrameRequestSender() {}
 };
 
+// Interface used by LossNotificationController to communicate to RtpRtcp.
+// TODO(bugs.webrtc.org/10336): Hook up to RtpRtcp.
+class LossNotificationSender {
+ public:
+  virtual ~LossNotificationSender() {}
+
+  virtual void SendLossNotification(uint16_t last_decoded_seq_num,
+                                    uint16_t last_received_seq_num,
+                                    bool decodability_flag) = 0;
+};
+
 // Used to indicate if a received packet contain a complete NALU (or equivalent)
 enum VCMNaluCompleteness {
   kNaluUnset = 0,     // Packet has not been filled.
diff --git a/modules/rtp_rtcp/BUILD.gn b/modules/rtp_rtcp/BUILD.gn
index edb981b..d66d437 100644
--- a/modules/rtp_rtcp/BUILD.gn
+++ b/modules/rtp_rtcp/BUILD.gn
@@ -25,6 +25,7 @@
     "source/rtcp_packet/extended_jitter_report.h",
     "source/rtcp_packet/extended_reports.h",
     "source/rtcp_packet/fir.h",
+    "source/rtcp_packet/loss_notification.h",
     "source/rtcp_packet/nack.h",
     "source/rtcp_packet/pli.h",
     "source/rtcp_packet/psfb.h",
@@ -59,6 +60,7 @@
     "source/rtcp_packet/extended_jitter_report.cc",
     "source/rtcp_packet/extended_reports.cc",
     "source/rtcp_packet/fir.cc",
+    "source/rtcp_packet/loss_notification.cc",
     "source/rtcp_packet/nack.cc",
     "source/rtcp_packet/pli.cc",
     "source/rtcp_packet/psfb.cc",
@@ -97,6 +99,7 @@
     "../../rtc_base:checks",
     "../../rtc_base:deprecation",
     "../../rtc_base:rtc_base_approved",
+    "../../rtc_base/system:unused",
     "../../system_wrappers",
     "../video_coding:codec_globals_headers",
     "//third_party/abseil-cpp/absl/types:optional",
@@ -196,8 +199,11 @@
     "../..:webrtc_common",
     "../../api:array_view",
     "../../api:libjingle_peerconnection_api",
+    "../../api:scoped_refptr",
     "../../api:transport_api",
     "../../api/audio_codecs:audio_codecs_api",
+    "../../api/transport:field_trial_based_config",
+    "../../api/transport:webrtc_key_value_config",
     "../../api/video:video_bitrate_allocation",
     "../../api/video:video_bitrate_allocator",
     "../../api/video:video_frame",
@@ -215,13 +221,10 @@
     "../../rtc_base:rtc_numerics",
     "../../rtc_base:safe_minmax",
     "../../rtc_base:sequenced_task_checker",
-    "../../rtc_base:stringutils",
     "../../rtc_base/system:fallthrough",
     "../../rtc_base/time:timestamp_extrapolator",
     "../../system_wrappers",
-    "../../system_wrappers:field_trial",
     "../../system_wrappers:metrics",
-    "../audio_coding:audio_format_conversion",
     "../remote_bitrate_estimator",
     "../video_coding:codec_globals_headers",
     "//third_party/abseil-cpp/absl/container:inlined_vector",
@@ -254,8 +257,9 @@
     "../../api/video:video_bitrate_allocation",
     "../../rtc_base:checks",
     "../../rtc_base:rtc_base_approved",
-    "../../rtc_base:rtc_cancelable_task",
     "../../rtc_base:rtc_task_queue",
+    "../../rtc_base/task_utils:repeating_task",
+    "../../rtc_base/task_utils:to_queued_task",
     "../../system_wrappers",
     "//third_party/abseil-cpp/absl/memory",
     "//third_party/abseil-cpp/absl/types:optional",
@@ -376,6 +380,7 @@
       "source/rtcp_packet/extended_jitter_report_unittest.cc",
       "source/rtcp_packet/extended_reports_unittest.cc",
       "source/rtcp_packet/fir_unittest.cc",
+      "source/rtcp_packet/loss_notification_unittest.cc",
       "source/rtcp_packet/nack_unittest.cc",
       "source/rtcp_packet/pli_unittest.cc",
       "source/rtcp_packet/rapid_resync_request_unittest.cc",
@@ -408,7 +413,9 @@
       "source/rtp_packet_history_unittest.cc",
       "source/rtp_packet_unittest.cc",
       "source/rtp_rtcp_impl_unittest.cc",
+      "source/rtp_sender_audio_unittest.cc",
       "source/rtp_sender_unittest.cc",
+      "source/rtp_sender_video_unittest.cc",
       "source/rtp_utility_unittest.cc",
       "source/time_util_unittest.cc",
       "source/ulpfec_generator_unittest.cc",
@@ -425,13 +432,17 @@
       "../..:webrtc_common",
       "../../api:array_view",
       "../../api:libjingle_peerconnection_api",
+      "../../api:scoped_refptr",
       "../../api:transport_api",
+      "../../api/transport:field_trial_based_config",
       "../../api/video:video_bitrate_allocation",
       "../../api/video:video_bitrate_allocator",
+      "../../api/video:video_codec_constants",
       "../../api/video:video_frame",
       "../../api/video_codecs:video_codecs_api",
       "../../call:rtp_receiver",
       "../../common_video:common_video",
+      "../../common_video/test:utilities",
       "../../logging:mocks",
       "../../logging:rtc_event_log_api",
       "../../rtc_base:checks",
@@ -444,7 +455,6 @@
       "../../test:rtp_test_utils",
       "../../test:test_common",
       "../../test:test_support",
-      "../audio_coding:audio_format_conversion",
       "../video_coding:codec_globals_headers",
       "//third_party/abseil-cpp/absl/memory",
       "//third_party/abseil-cpp/absl/types:optional",
diff --git a/modules/rtp_rtcp/DEPS b/modules/rtp_rtcp/DEPS
index 9d9f33c..dac95dd 100644
--- a/modules/rtp_rtcp/DEPS
+++ b/modules/rtp_rtcp/DEPS
@@ -3,4 +3,6 @@
   "+common_video",
   "+logging/rtc_event_log",
   "+system_wrappers",
+  # Avoid directly using field_trial. Instead use WebRtcKeyValueConfig.
+  "-system_wrappers/include/field_trial.h",
 ]
diff --git a/modules/rtp_rtcp/include/flexfec_receiver.h b/modules/rtp_rtcp/include/flexfec_receiver.h
index f0ed576..2426559 100644
--- a/modules/rtp_rtcp/include/flexfec_receiver.h
+++ b/modules/rtp_rtcp/include/flexfec_receiver.h
@@ -30,6 +30,10 @@
   FlexfecReceiver(uint32_t ssrc,
                   uint32_t protected_media_ssrc,
                   RecoveredPacketReceiver* recovered_packet_receiver);
+  FlexfecReceiver(Clock* clock,
+                  uint32_t ssrc,
+                  uint32_t protected_media_ssrc,
+                  RecoveredPacketReceiver* recovered_packet_receiver);
   ~FlexfecReceiver();
 
   // Inserts a received packet (can be either media or FlexFEC) into the
diff --git a/modules/rtp_rtcp/include/flexfec_sender.h b/modules/rtp_rtcp/include/flexfec_sender.h
index acee117..aa0e8e0 100644
--- a/modules/rtp_rtcp/include/flexfec_sender.h
+++ b/modules/rtp_rtcp/include/flexfec_sender.h
@@ -16,7 +16,7 @@
 #include <vector>
 
 #include "api/array_view.h"
-#include "api/rtpparameters.h"
+#include "api/rtp_parameters.h"
 #include "modules/include/module_common_types.h"
 #include "modules/rtp_rtcp/include/rtp_header_extension_map.h"
 #include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
diff --git a/modules/rtp_rtcp/include/remote_ntp_time_estimator.h b/modules/rtp_rtcp/include/remote_ntp_time_estimator.h
index e6d269c..dd0e0de 100644
--- a/modules/rtp_rtcp/include/remote_ntp_time_estimator.h
+++ b/modules/rtp_rtcp/include/remote_ntp_time_estimator.h
@@ -13,7 +13,7 @@
 
 #include <stdint.h>
 
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 #include "rtc_base/numerics/moving_median_filter.h"
 #include "system_wrappers/include/rtp_to_ntp_estimator.h"
 
diff --git a/modules/rtp_rtcp/include/rtp_header_extension_map.h b/modules/rtp_rtcp/include/rtp_header_extension_map.h
index 391c5be..07b31a3 100644
--- a/modules/rtp_rtcp/include/rtp_header_extension_map.h
+++ b/modules/rtp_rtcp/include/rtp_header_extension_map.h
@@ -15,7 +15,7 @@
 #include <string>
 
 #include "api/array_view.h"
-#include "api/rtpparameters.h"
+#include "api/rtp_parameters.h"
 #include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
 #include "rtc_base/checks.h"
 
diff --git a/modules/rtp_rtcp/include/rtp_header_parser.h b/modules/rtp_rtcp/include/rtp_header_parser.h
index 85eab90..1b0156b 100644
--- a/modules/rtp_rtcp/include/rtp_header_parser.h
+++ b/modules/rtp_rtcp/include/rtp_header_parser.h
@@ -10,7 +10,7 @@
 #ifndef MODULES_RTP_RTCP_INCLUDE_RTP_HEADER_PARSER_H_
 #define MODULES_RTP_RTCP_INCLUDE_RTP_HEADER_PARSER_H_
 
-#include "api/rtpparameters.h"
+#include "api/rtp_parameters.h"
 #include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
 
 namespace webrtc {
diff --git a/modules/rtp_rtcp/include/rtp_rtcp.h b/modules/rtp_rtcp/include/rtp_rtcp.h
index d136a5e..6e1b4a5 100644
--- a/modules/rtp_rtcp/include/rtp_rtcp.h
+++ b/modules/rtp_rtcp/include/rtp_rtcp.h
@@ -16,13 +16,16 @@
 #include <utility>
 #include <vector>
 
+#include "absl/strings/string_view.h"
 #include "absl/types/optional.h"
+#include "api/transport/webrtc_key_value_config.h"
 #include "api/video/video_bitrate_allocation.h"
 #include "modules/include/module.h"
 #include "modules/rtp_rtcp/include/flexfec_sender.h"
 #include "modules/rtp_rtcp/include/receive_statistics.h"
 #include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
-#include "rtc_base/constructormagic.h"
+#include "modules/rtp_rtcp/source/rtp_sender.h"
+#include "rtc_base/constructor_magic.h"
 #include "rtc_base/deprecation.h"
 
 namespace webrtc {
@@ -86,12 +89,13 @@
     TransportSequenceNumberAllocator* transport_sequence_number_allocator =
         nullptr;
     BitrateStatisticsObserver* send_bitrate_observer = nullptr;
-    FrameCountObserver* send_frame_count_observer = nullptr;
     SendSideDelayObserver* send_side_delay_observer = nullptr;
     RtcEventLog* event_log = nullptr;
     SendPacketObserver* send_packet_observer = nullptr;
     RateLimiter* retransmission_rate_limiter = nullptr;
     OverheadObserver* overhead_observer = nullptr;
+    RtcpAckObserver* ack_observer = nullptr;
+
     RtpKeepAliveConfig keepalive_config;
 
     int rtcp_report_interval_ms = 0;
@@ -107,6 +111,10 @@
     // Corresponds to extmap-allow-mixed in SDP negotiation.
     bool extmap_allow_mixed = false;
 
+    // If set, field trials are read from |field_trials|, otherwise
+    // defaults to  webrtc::FieldTrialBasedConfig.
+    const WebRtcKeyValueConfig* field_trials = nullptr;
+
    private:
     RTC_DISALLOW_COPY_AND_ASSIGN(Configuration);
   };
@@ -135,11 +143,13 @@
   // FEC/ULP/RED overhead (when FEC is enabled).
   virtual size_t MaxRtpPacketSize() const = 0;
 
-  // Sets codec name and payload type. Returns -1 on failure else 0.
-  virtual int32_t RegisterSendPayload(const CodecInst& voice_codec) = 0;
-
-  virtual void RegisterVideoSendPayload(int payload_type,
-                                        const char* payload_name) = 0;
+  virtual void RegisterAudioSendPayload(int payload_type,
+                                        absl::string_view payload_name,
+                                        int frequency,
+                                        int channels,
+                                        int rate) = 0;
+  virtual void RegisterSendPayloadFrequency(int payload_type,
+                                            int payload_frequency) = 0;
 
   // Unregisters a send payload.
   // |payload_type| - payload type of codec
@@ -183,6 +193,12 @@
   // Sets SSRC, default is a random number.
   virtual void SetSSRC(uint32_t ssrc) = 0;
 
+  // Sets the value for sending in the RID (and Repaired) RTP header extension.
+  // RIDs are used to identify an RTP stream if SSRCs are not negotiated.
+  // If the RID and Repaired RID extensions are not registered, the RID will
+  // not be sent.
+  virtual void SetRid(const std::string& rid) = 0;
+
   // Sets the value for sending in the MID RTP header extension.
   // The MID RTP header extension should be registered for this to do anything.
   // Once set, this value can not be changed or removed.
@@ -229,12 +245,15 @@
   // bitrate estimate since the stream participates in the bitrate allocation.
   virtual void SetAsPartOfAllocation(bool part_of_allocation) = 0;
 
-  // Returns current bitrate in Kbit/s.
+  // Fetches the current send bitrates in bits/s.
   virtual void BitrateSent(uint32_t* total_rate,
                            uint32_t* video_rate,
                            uint32_t* fec_rate,
                            uint32_t* nack_rate) const = 0;
 
+  virtual RTPSender* RtpSender() = 0;
+  virtual const RTPSender* RtpSender() const = 0;
+
   // Used by the codec module to deliver a video or audio frame for
   // packetization.
   // |frame_type|    - type of frame to send
@@ -256,6 +275,13 @@
                                 const RTPVideoHeader* rtp_video_header,
                                 uint32_t* transport_frame_id_out) = 0;
 
+  // Record that a frame is about to be sent. Returns true on success, and false
+  // if the module isn't ready to send.
+  virtual bool OnSendingRtpFrame(uint32_t timestamp,
+                                 int64_t capture_time_ms,
+                                 int payload_type,
+                                 bool force_sender_report) = 0;
+
   virtual bool TimeToSendPacket(uint32_t ssrc,
                                 uint16_t sequence_number,
                                 int64_t capture_time_ms,
@@ -313,6 +339,9 @@
                       int64_t* min_rtt,
                       int64_t* max_rtt) const = 0;
 
+  // Returns the estimated RTT, with fallback to a default value.
+  virtual int64_t ExpectedRetransmissionTimeMs() const = 0;
+
   // Forces a send of a RTCP packet. Periodic SR and RR are triggered via the
   // process function.
   // Returns -1 on failure else 0.
@@ -370,21 +399,6 @@
 
   // (NACK)
 
-  // TODO(holmer): Propagate this API to VideoEngine.
-  // Returns the currently configured selective retransmission settings.
-  virtual int SelectiveRetransmissions() const = 0;
-
-  // TODO(holmer): Propagate this API to VideoEngine.
-  // Sets the selective retransmission settings, which will decide which
-  // packets will be retransmitted if NACKed. Settings are constructed by
-  // combining the constants in enum RetransmissionMode with bitwise OR.
-  // All packets are retransmitted if kRetransmitAllPackets is set, while no
-  // packets are retransmitted if kRetransmitOff is set.
-  // By default all packets except FEC packets are retransmitted. For VP8
-  // with temporal scalability only base layer packets are retransmitted.
-  // Returns -1 on failure, otherwise 0.
-  virtual int SetSelectiveRetransmissions(uint8_t settings) = 0;
-
   // Sends a Negative acknowledgement packet.
   // Returns -1 on failure else 0.
   // TODO(philipel): Deprecate this and start using SendNack instead, mostly
@@ -435,23 +449,6 @@
   // Video
   // **************************************************************************
 
-  // Set RED and ULPFEC payload types. A payload type of -1 means that the
-  // corresponding feature is turned off. Note that we DO NOT support enabling
-  // ULPFEC without enabling RED, and RED is only ever used when ULPFEC is
-  // enabled.
-  virtual void SetUlpfecConfig(int red_payload_type,
-                               int ulpfec_payload_type) = 0;
-
-  // Set FEC rates, max frames before FEC is sent, and type of FEC masks.
-  // Returns false on failure.
-  virtual bool SetFecParameters(const FecProtectionParams& delta_params,
-                                const FecProtectionParams& key_params) = 0;
-
-  // Deprecated version of member function above.
-  RTC_DEPRECATED
-  int32_t SetFecParameters(const FecProtectionParams* delta_params,
-                           const FecProtectionParams* key_params);
-
   // Set method for requestion a new key frame.
   // Returns -1 on failure else 0.
   virtual int32_t SetKeyFrameRequestMethod(KeyFrameRequestMethod method) = 0;
@@ -459,6 +456,12 @@
   // Sends a request for a keyframe.
   // Returns -1 on failure else 0.
   virtual int32_t RequestKeyFrame() = 0;
+
+  // Sends a LossNotification RTCP message.
+  // Returns -1 on failure else 0.
+  virtual int32_t SendLossNotification(uint16_t last_decoded_seq_num,
+                                       uint16_t last_received_seq_num,
+                                       bool decodability_flag) = 0;
 };
 
 }  // namespace webrtc
diff --git a/modules/rtp_rtcp/include/rtp_rtcp_defines.cc b/modules/rtp_rtcp/include/rtp_rtcp_defines.cc
index d743f52..d23d82d 100644
--- a/modules/rtp_rtcp/include/rtp_rtcp_defines.cc
+++ b/modules/rtp_rtcp/include/rtp_rtcp_defines.cc
@@ -53,15 +53,6 @@
 // and thus assume trivial destructibility.
 static_assert(std::is_trivially_destructible<StreamId>::value, "");
 
-PayloadUnion::PayloadUnion(const AudioPayload& payload) : payload_(payload) {}
-PayloadUnion::PayloadUnion(const VideoPayload& payload) : payload_(payload) {}
-PayloadUnion::PayloadUnion(const PayloadUnion&) = default;
-PayloadUnion::PayloadUnion(PayloadUnion&&) = default;
-PayloadUnion::~PayloadUnion() = default;
-
-PayloadUnion& PayloadUnion::operator=(const PayloadUnion&) = default;
-PayloadUnion& PayloadUnion::operator=(PayloadUnion&&) = default;
-
 PacketFeedback::PacketFeedback(int64_t arrival_time_ms,
                                uint16_t sequence_number)
     : PacketFeedback(-1,
diff --git a/modules/rtp_rtcp/include/rtp_rtcp_defines.h b/modules/rtp_rtcp/include/rtp_rtcp_defines.h
index ab4fcae..b648942 100644
--- a/modules/rtp_rtcp/include/rtp_rtcp_defines.h
+++ b/modules/rtp_rtcp/include/rtp_rtcp_defines.h
@@ -41,47 +41,6 @@
 // Minimum RTP header size in bytes.
 const uint8_t kRtpHeaderSize = 12;
 
-struct AudioPayload {
-  SdpAudioFormat format;
-  uint32_t rate;
-};
-
-struct VideoPayload {
-  VideoCodecType videoCodecType;
-  // The H264 profile only matters if videoCodecType == kVideoCodecH264.
-  H264::Profile h264_profile;
-};
-
-class PayloadUnion {
- public:
-  explicit PayloadUnion(const AudioPayload& payload);
-  explicit PayloadUnion(const VideoPayload& payload);
-  PayloadUnion(const PayloadUnion&);
-  PayloadUnion(PayloadUnion&&);
-  ~PayloadUnion();
-
-  PayloadUnion& operator=(const PayloadUnion&);
-  PayloadUnion& operator=(PayloadUnion&&);
-
-  bool is_audio() const {
-    return absl::holds_alternative<AudioPayload>(payload_);
-  }
-  bool is_video() const {
-    return absl::holds_alternative<VideoPayload>(payload_);
-  }
-  const AudioPayload& audio_payload() const {
-    return absl::get<AudioPayload>(payload_);
-  }
-  const VideoPayload& video_payload() const {
-    return absl::get<VideoPayload>(payload_);
-  }
-  AudioPayload& audio_payload() { return absl::get<AudioPayload>(payload_); }
-  VideoPayload& video_payload() { return absl::get<VideoPayload>(payload_); }
-
- private:
-  absl::variant<AudioPayload, VideoPayload> payload_;
-};
-
 enum ProtectionType { kUnprotectedPacket, kProtectedPacket };
 
 enum StorageType { kDontRetransmit, kAllowRetransmission };
@@ -96,6 +55,7 @@
   kRtpExtensionAbsoluteSendTime,
   kRtpExtensionVideoRotation,
   kRtpExtensionTransportSequenceNumber,
+  kRtpExtensionTransportSequenceNumber02,
   kRtpExtensionPlayoutDelay,
   kRtpExtensionVideoContentType,
   kRtpExtensionVideoTiming,
@@ -103,7 +63,9 @@
   kRtpExtensionRtpStreamId,
   kRtpExtensionRepairedRtpStreamId,
   kRtpExtensionMid,
-  kRtpExtensionGenericFrameDescriptor,
+  kRtpExtensionGenericFrameDescriptor00,
+  kRtpExtensionGenericFrameDescriptor = kRtpExtensionGenericFrameDescriptor00,
+  kRtpExtensionGenericFrameDescriptor01,
   kRtpExtensionColorSpace,
   kRtpExtensionNumberOfExtensions  // Must be the last entity in the enum.
 };
@@ -124,6 +86,7 @@
   kRtcpTmmbn = 0x0200,
   kRtcpSrReq = 0x0400,
   kRtcpApp = 0x1000,
+  kRtcpLossNotification = 0x2000,
   kRtcpRemb = 0x10000,
   kRtcpTransmissionTimeOffset = 0x20000,
   kRtcpXrReceiverReferenceTime = 0x40000,
@@ -136,19 +99,6 @@
 
 enum RtpRtcpPacketType { kPacketRtp = 0, kPacketKeepAlive = 1 };
 
-// kConditionallyRetransmitHigherLayers allows retransmission of video frames
-// in higher layers if either the last frame in that layer was too far back in
-// time, or if we estimate that a new frame will be available in a lower layer
-// in a shorter time than it would take to request and receive a retransmission.
-enum RetransmissionMode : uint8_t {
-  kRetransmitOff = 0x0,
-  kRetransmitFECPackets = 0x1,
-  kRetransmitBaseLayer = 0x2,
-  kRetransmitHigherLayers = 0x4,
-  kConditionallyRetransmitHigherLayers = 0x8,
-  kRetransmitAllPackets = 0xFF
-};
-
 enum RtxMode {
   kRtxOff = 0x0,
   kRtxRetransmitted = 0x1,     // Only send retransmissions over RTX.
@@ -509,5 +459,18 @@
                                    uint32_t ssrc) = 0;
 };
 
+class RtcpAckObserver {
+ public:
+  // This method is called on received report blocks matching the sender ssrc.
+  // TODO(nisse): Use of "extended" sequence number is a bit brittle, since the
+  // observer for this callback typically has its own sequence number unwrapper,
+  // and there's no guarantee that they are in sync. Change to pass raw sequence
+  // number, possibly augmented with timestamp (if available) to aid
+  // disambiguation.
+  virtual void OnReceivedAck(int64_t extended_highest_sequence_number) = 0;
+
+  virtual ~RtcpAckObserver() = default;
+};
+
 }  // namespace webrtc
 #endif  // MODULES_RTP_RTCP_INCLUDE_RTP_RTCP_DEFINES_H_
diff --git a/modules/rtp_rtcp/mocks/mock_rtp_rtcp.h b/modules/rtp_rtcp/mocks/mock_rtp_rtcp.h
index 3b9b943..7d4f0f1 100644
--- a/modules/rtp_rtcp/mocks/mock_rtp_rtcp.h
+++ b/modules/rtp_rtcp/mocks/mock_rtp_rtcp.h
@@ -37,9 +37,14 @@
   MOCK_METHOD1(SetRemoteSSRC, void(uint32_t ssrc));
   MOCK_METHOD1(SetMaxRtpPacketSize, void(size_t size));
   MOCK_CONST_METHOD0(MaxRtpPacketSize, size_t());
-  MOCK_METHOD1(RegisterSendPayload, int32_t(const CodecInst& voice_codec));
-  MOCK_METHOD2(RegisterVideoSendPayload,
-               void(int payload_type, const char* payload_name));
+  MOCK_METHOD5(RegisterAudioSendPayload,
+               void(int payload_type,
+                    absl::string_view payload_name,
+                    int frequency,
+                    int channels,
+                    int rate));
+  MOCK_METHOD2(RegisterSendPayloadFrequency,
+               void(int payload_type, int frequency));
   MOCK_METHOD1(DeRegisterSendPayload, int32_t(int8_t payload_type));
   MOCK_METHOD1(SetExtmapAllowMixed, void(bool extmap_allow_mixed));
   MOCK_METHOD2(RegisterSendRtpHeaderExtension,
@@ -59,6 +64,7 @@
   MOCK_CONST_METHOD0(GetRtxState, RtpState());
   MOCK_CONST_METHOD0(SSRC, uint32_t());
   MOCK_METHOD1(SetSSRC, void(uint32_t ssrc));
+  MOCK_METHOD1(SetRid, void(const std::string& rid));
   MOCK_METHOD1(SetMid, void(const std::string& mid));
   MOCK_CONST_METHOD1(CSRCs, int32_t(uint32_t csrcs[kRtpCsrcSize]));
   MOCK_METHOD1(SetCsrcs, void(const std::vector<uint32_t>& csrcs));
@@ -91,6 +97,7 @@
                     const RTPFragmentationHeader* fragmentation,
                     const RTPVideoHeader* rtp_video_header,
                     uint32_t* frame_id_out));
+  MOCK_METHOD4(OnSendingRtpFrame, bool(uint32_t, int64_t, int, bool));
   MOCK_METHOD5(TimeToSendPacket,
                bool(uint32_t ssrc,
                     uint16_t sequence_number,
@@ -123,6 +130,7 @@
                              int64_t* avg_rtt,
                              int64_t* min_rtt,
                              int64_t* max_rtt));
+  MOCK_CONST_METHOD0(ExpectedRetransmissionTimeMs, int64_t());
   MOCK_METHOD1(SendRTCP, int32_t(RTCPPacketType packet_type));
   MOCK_METHOD1(SendCompoundRTCP,
                int32_t(const std::set<RTCPPacketType>& packet_types));
@@ -146,8 +154,6 @@
   MOCK_CONST_METHOD0(TMMBR, bool());
   MOCK_METHOD1(SetTMMBRStatus, void(bool enable));
   MOCK_METHOD1(OnBandwidthEstimateUpdate, void(uint16_t bandwidth_kbit));
-  MOCK_CONST_METHOD0(SelectiveRetransmissions, int());
-  MOCK_METHOD1(SetSelectiveRetransmissions, int(uint8_t settings));
   MOCK_METHOD2(SendNACK, int32_t(const uint16_t* nack_list, uint16_t size));
   MOCK_METHOD1(SendNack, void(const std::vector<uint16_t>& sequence_numbers));
   MOCK_METHOD2(SetStorePacketsStatus,
@@ -160,19 +166,21 @@
                int32_t(uint8_t key, uint16_t time_ms, uint8_t level));
   MOCK_METHOD1(SetAudioLevel, int32_t(uint8_t level_dbov));
   MOCK_METHOD1(SetTargetSendBitrate, void(uint32_t bitrate_bps));
-  MOCK_METHOD2(SetUlpfecConfig,
-               void(int red_payload_type, int fec_payload_type));
-  MOCK_METHOD2(SetFecParameters,
-               bool(const FecProtectionParams& delta_params,
-                    const FecProtectionParams& key_params));
   MOCK_METHOD1(SetKeyFrameRequestMethod, int32_t(KeyFrameRequestMethod method));
   MOCK_METHOD0(RequestKeyFrame, int32_t());
+  MOCK_METHOD3(SendLossNotification,
+               int32_t(uint16_t last_decoded_seq_num,
+                       uint16_t last_received_seq_num,
+                       bool decodability_flag));
   MOCK_METHOD0(Process, void());
   MOCK_METHOD1(RegisterSendChannelRtpStatisticsCallback,
                void(StreamDataCountersCallback*));
   MOCK_CONST_METHOD0(GetSendChannelRtpStatisticsCallback,
                      StreamDataCountersCallback*(void));
   MOCK_METHOD1(SetVideoBitrateAllocation, void(const VideoBitrateAllocation&));
+  MOCK_METHOD0(RtpSender, RTPSender*());
+  MOCK_CONST_METHOD0(RtpSender, const RTPSender*());
+
   // Members.
   unsigned int remote_ssrc_;
 
diff --git a/modules/rtp_rtcp/source/contributing_sources.h b/modules/rtp_rtcp/source/contributing_sources.h
index 5e34539..81bf725 100644
--- a/modules/rtp_rtcp/source/contributing_sources.h
+++ b/modules/rtp_rtcp/source/contributing_sources.h
@@ -18,8 +18,8 @@
 
 #include "absl/types/optional.h"
 #include "api/array_view.h"
-#include "api/rtpreceiverinterface.h"  // For RtpSource
-#include "rtc_base/timeutils.h"        // For kNumMillisecsPerSec
+#include "api/rtp_receiver_interface.h"  // For RtpSource
+#include "rtc_base/time_utils.h"         // For kNumMillisecsPerSec
 
 namespace webrtc {
 
diff --git a/modules/rtp_rtcp/source/contributing_sources_unittest.cc b/modules/rtp_rtcp/source/contributing_sources_unittest.cc
index 5f1d8d3..38d25ce 100644
--- a/modules/rtp_rtcp/source/contributing_sources_unittest.cc
+++ b/modules/rtp_rtcp/source/contributing_sources_unittest.cc
@@ -10,7 +10,7 @@
 
 #include "modules/rtp_rtcp/source/contributing_sources.h"
 
-#include "rtc_base/timeutils.h"
+#include "rtc_base/time_utils.h"
 
 #include "test/gmock.h"
 #include "test/gtest.h"
diff --git a/modules/rtp_rtcp/source/dtmf_queue.h b/modules/rtp_rtcp/source/dtmf_queue.h
index e5955a1..28116bc 100644
--- a/modules/rtp_rtcp/source/dtmf_queue.h
+++ b/modules/rtp_rtcp/source/dtmf_queue.h
@@ -14,7 +14,7 @@
 #include <stdint.h>
 #include <list>
 
-#include "rtc_base/criticalsection.h"
+#include "rtc_base/critical_section.h"
 
 namespace webrtc {
 class DtmfQueue {
diff --git a/modules/rtp_rtcp/source/flexfec_header_reader_writer.cc b/modules/rtp_rtcp/source/flexfec_header_reader_writer.cc
index b813340..e3cb0e9 100644
--- a/modules/rtp_rtcp/source/flexfec_header_reader_writer.cc
+++ b/modules/rtp_rtcp/source/flexfec_header_reader_writer.cc
@@ -12,11 +12,11 @@
 
 #include <string.h>
 
+#include "api/scoped_refptr.h"
 #include "modules/rtp_rtcp/source/byte_io.h"
 #include "modules/rtp_rtcp/source/forward_error_correction_internal.h"
 #include "rtc_base/checks.h"
 #include "rtc_base/logging.h"
-#include "rtc_base/scoped_ref_ptr.h"
 
 namespace webrtc {
 
diff --git a/modules/rtp_rtcp/source/flexfec_header_reader_writer_unittest.cc b/modules/rtp_rtcp/source/flexfec_header_reader_writer_unittest.cc
index 5da378c..3d19eda 100644
--- a/modules/rtp_rtcp/source/flexfec_header_reader_writer_unittest.cc
+++ b/modules/rtp_rtcp/source/flexfec_header_reader_writer_unittest.cc
@@ -13,13 +13,13 @@
 #include <memory>
 #include <utility>
 
+#include "api/scoped_refptr.h"
 #include "modules/rtp_rtcp/source/byte_io.h"
 #include "modules/rtp_rtcp/source/flexfec_header_reader_writer.h"
 #include "modules/rtp_rtcp/source/forward_error_correction.h"
 #include "modules/rtp_rtcp/source/forward_error_correction_internal.h"
 #include "rtc_base/checks.h"
 #include "rtc_base/random.h"
-#include "rtc_base/scoped_ref_ptr.h"
 #include "test/gmock.h"
 #include "test/gtest.h"
 
diff --git a/modules/rtp_rtcp/source/flexfec_receiver.cc b/modules/rtp_rtcp/source/flexfec_receiver.cc
index 1a62bce..1750927 100644
--- a/modules/rtp_rtcp/source/flexfec_receiver.cc
+++ b/modules/rtp_rtcp/source/flexfec_receiver.cc
@@ -13,9 +13,9 @@
 #include <string.h>
 
 #include "api/array_view.h"
+#include "api/scoped_refptr.h"
 #include "rtc_base/checks.h"
 #include "rtc_base/logging.h"
-#include "rtc_base/scoped_ref_ptr.h"
 
 namespace webrtc {
 
@@ -36,12 +36,22 @@
     uint32_t ssrc,
     uint32_t protected_media_ssrc,
     RecoveredPacketReceiver* recovered_packet_receiver)
+    : FlexfecReceiver(Clock::GetRealTimeClock(),
+                      ssrc,
+                      protected_media_ssrc,
+                      recovered_packet_receiver) {}
+
+FlexfecReceiver::FlexfecReceiver(
+    Clock* clock,
+    uint32_t ssrc,
+    uint32_t protected_media_ssrc,
+    RecoveredPacketReceiver* recovered_packet_receiver)
     : ssrc_(ssrc),
       protected_media_ssrc_(protected_media_ssrc),
       erasure_code_(
           ForwardErrorCorrection::CreateFlexfec(ssrc, protected_media_ssrc)),
       recovered_packet_receiver_(recovered_packet_receiver),
-      clock_(Clock::GetRealTimeClock()),
+      clock_(clock),
       last_recovered_packet_ms_(-1) {
   // It's OK to create this object on a different thread/task queue than
   // the one used during main operation.
diff --git a/modules/rtp_rtcp/source/flexfec_receiver_unittest.cc b/modules/rtp_rtcp/source/flexfec_receiver_unittest.cc
index 378cf7d..d19e575 100644
--- a/modules/rtp_rtcp/source/flexfec_receiver_unittest.cc
+++ b/modules/rtp_rtcp/source/flexfec_receiver_unittest.cc
@@ -49,8 +49,10 @@
   FlexfecReceiverForTest(uint32_t ssrc,
                          uint32_t protected_media_ssrc,
                          RecoveredPacketReceiver* recovered_packet_receiver)
-      : FlexfecReceiver(ssrc, protected_media_ssrc, recovered_packet_receiver) {
-  }
+      : FlexfecReceiver(Clock::GetRealTimeClock(),
+                        ssrc,
+                        protected_media_ssrc,
+                        recovered_packet_receiver) {}
   // Expose methods for tests.
   using FlexfecReceiver::AddReceivedPacket;
   using FlexfecReceiver::ProcessReceivedPacket;
@@ -466,7 +468,7 @@
   } loopback_recovered_packet_receiver;
 
   // Feed recovered packets back into |receiver|.
-  FlexfecReceiver receiver(kFlexfecSsrc, kMediaSsrc,
+  FlexfecReceiver receiver(Clock::GetRealTimeClock(), kFlexfecSsrc, kMediaSsrc,
                            &loopback_recovered_packet_receiver);
   loopback_recovered_packet_receiver.SetReceiver(&receiver);
 
@@ -590,7 +592,7 @@
   } loopback_recovered_packet_receiver;
 
   // Feed recovered packets back into |receiver|.
-  FlexfecReceiver receiver(kFlexfecSsrc, kMediaSsrc,
+  FlexfecReceiver receiver(Clock::GetRealTimeClock(), kFlexfecSsrc, kMediaSsrc,
                            &loopback_recovered_packet_receiver);
   loopback_recovered_packet_receiver.SetReceiver(&receiver);
 
diff --git a/modules/rtp_rtcp/source/flexfec_sender.cc b/modules/rtp_rtcp/source/flexfec_sender.cc
index 1204b2d..02fee86 100644
--- a/modules/rtp_rtcp/source/flexfec_sender.cc
+++ b/modules/rtp_rtcp/source/flexfec_sender.cc
@@ -126,6 +126,7 @@
   for (const auto* fec_packet : ulpfec_generator_.generated_fec_packets_) {
     std::unique_ptr<RtpPacketToSend> fec_packet_to_send(
         new RtpPacketToSend(&rtp_header_extension_map_));
+    fec_packet_to_send->set_is_fec(true);
 
     // RTP header.
     fec_packet_to_send->SetMarker(false);
diff --git a/modules/rtp_rtcp/source/flexfec_sender_unittest.cc b/modules/rtp_rtcp/source/flexfec_sender_unittest.cc
index ddc2805..c561dbb 100644
--- a/modules/rtp_rtcp/source/flexfec_sender_unittest.cc
+++ b/modules/rtp_rtcp/source/flexfec_sender_unittest.cc
@@ -10,7 +10,7 @@
 
 #include <vector>
 
-#include "api/rtpparameters.h"
+#include "api/rtp_parameters.h"
 #include "modules/rtp_rtcp/include/flexfec_sender.h"
 #include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
 #include "modules/rtp_rtcp/source/fec_test_helper.h"
diff --git a/modules/rtp_rtcp/source/forward_error_correction.h b/modules/rtp_rtcp/source/forward_error_correction.h
index adb7572..b442273 100644
--- a/modules/rtp_rtcp/source/forward_error_correction.h
+++ b/modules/rtp_rtcp/source/forward_error_correction.h
@@ -17,10 +17,10 @@
 #include <memory>
 #include <vector>
 
+#include "api/scoped_refptr.h"
 #include "modules/include/module_fec_types.h"
 #include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
 #include "modules/rtp_rtcp/source/forward_error_correction_internal.h"
-#include "rtc_base/scoped_ref_ptr.h"
 
 namespace webrtc {
 
diff --git a/modules/rtp_rtcp/source/nack_rtx_unittest.cc b/modules/rtp_rtcp/source/nack_rtx_unittest.cc
index 7ecec76..864befe 100644
--- a/modules/rtp_rtcp/source/nack_rtx_unittest.cc
+++ b/modules/rtp_rtcp/source/nack_rtx_unittest.cc
@@ -14,14 +14,18 @@
 #include <memory>
 #include <set>
 
+#include "absl/memory/memory.h"
 #include "api/call/transport.h"
+#include "api/transport/field_trial_based_config.h"
 #include "call/rtp_stream_receiver_controller.h"
 #include "call/rtx_receive_stream.h"
 #include "common_types.h"  // NOLINT(build/include)
 #include "modules/rtp_rtcp/include/receive_statistics.h"
 #include "modules/rtp_rtcp/include/rtp_rtcp.h"
 #include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
+#include "modules/rtp_rtcp/source/playout_delay_oracle.h"
 #include "modules/rtp_rtcp/source/rtp_packet_received.h"
+#include "modules/rtp_rtcp/source/rtp_sender_video.h"
 #include "rtc_base/rate_limiter.h"
 #include "test/gtest.h"
 
@@ -132,8 +136,10 @@
     configuration.receive_statistics = receive_statistics_.get();
     configuration.outgoing_transport = &transport_;
     configuration.retransmission_rate_limiter = &retransmission_rate_limiter_;
-    rtp_rtcp_module_ = RtpRtcp::CreateRtpRtcp(configuration);
-
+    rtp_rtcp_module_ = absl::WrapUnique(RtpRtcp::CreateRtpRtcp(configuration));
+    rtp_sender_video_ = absl::make_unique<RTPSenderVideo>(
+        &fake_clock, rtp_rtcp_module_->RtpSender(), nullptr,
+        &playout_delay_oracle_, nullptr, false, FieldTrialBasedConfig());
     rtp_rtcp_module_->SetSSRC(kTestSsrc);
     rtp_rtcp_module_->SetRTCPStatus(RtcpMode::kCompound);
     rtp_rtcp_module_->SetStorePacketsStatus(true, 600);
@@ -146,9 +152,9 @@
     // single rtp_rtcp module for both send and receive side.
     rtp_rtcp_module_->SetRemoteSSRC(kTestSsrc);
 
-    rtp_rtcp_module_->RegisterVideoSendPayload(kPayloadType, "video");
+    rtp_sender_video_->RegisterPayloadType(kPayloadType, "video");
     rtp_rtcp_module_->SetRtxSendPayloadType(kRtxPayloadType, kPayloadType);
-    transport_.SetSendModule(rtp_rtcp_module_);
+    transport_.SetSendModule(rtp_rtcp_module_.get());
     media_receiver_ = transport_.stream_receiver_controller_.CreateReceiver(
         kTestSsrc, &media_stream_);
 
@@ -203,9 +209,11 @@
     uint16_t nack_list[kVideoNackListSize];
     for (int frame = 0; frame < kNumFrames; ++frame) {
       RTPVideoHeader video_header;
-      EXPECT_TRUE(rtp_rtcp_module_->SendOutgoingData(
+      EXPECT_TRUE(rtp_rtcp_module_->OnSendingRtpFrame(timestamp, timestamp / 90,
+                                                      kPayloadType, false));
+      EXPECT_TRUE(rtp_sender_video_->SendVideo(
           webrtc::kVideoFrameDelta, kPayloadType, timestamp, timestamp / 90,
-          payload_data, payload_data_length, nullptr, &video_header, nullptr));
+          payload_data, payload_data_length, nullptr, &video_header, 0));
       // Min required delay until retransmit = 5 + RTT ms (RTT = 0).
       fake_clock.AdvanceTimeMilliseconds(5);
       int length = BuildNackList(nack_list);
@@ -219,10 +227,10 @@
     media_stream_.sequence_numbers_.sort();
   }
 
-  void TearDown() override { delete rtp_rtcp_module_; }
-
   std::unique_ptr<ReceiveStatistics> receive_statistics_;
-  RtpRtcp* rtp_rtcp_module_;
+  std::unique_ptr<RtpRtcp> rtp_rtcp_module_;
+  PlayoutDelayOracle playout_delay_oracle_;
+  std::unique_ptr<RTPSenderVideo> rtp_sender_video_;
   RtxLoopBackTransport transport_;
   const std::map<int, int> rtx_associated_payload_types_ = {
       {kRtxPayloadType, kPayloadType}};
@@ -252,9 +260,11 @@
   // enough packets.
   for (int frame = 0; frame < kNumFrames; ++frame) {
     RTPVideoHeader video_header;
-    EXPECT_TRUE(rtp_rtcp_module_->SendOutgoingData(
+    EXPECT_TRUE(rtp_rtcp_module_->OnSendingRtpFrame(timestamp, timestamp / 90,
+                                                    kPayloadType, false));
+    EXPECT_TRUE(rtp_sender_video_->SendVideo(
         webrtc::kVideoFrameDelta, kPayloadType, timestamp, timestamp / 90,
-        payload_data, payload_data_length, nullptr, &video_header, nullptr));
+        payload_data, payload_data_length, nullptr, &video_header, 0));
     // Prepare next frame.
     timestamp += 3000;
     fake_clock.AdvanceTimeMilliseconds(33);
diff --git a/modules/rtp_rtcp/source/playout_delay_oracle.cc b/modules/rtp_rtcp/source/playout_delay_oracle.cc
index dc33fad..e3e13fd 100644
--- a/modules/rtp_rtcp/source/playout_delay_oracle.cc
+++ b/modules/rtp_rtcp/source/playout_delay_oracle.cc
@@ -8,57 +8,82 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
+#include <algorithm>
+
 #include "modules/rtp_rtcp/source/playout_delay_oracle.h"
 
-#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
 #include "modules/rtp_rtcp/source/rtp_header_extensions.h"
 #include "rtc_base/checks.h"
+#include "rtc_base/logging.h"
 
 namespace webrtc {
 
-PlayoutDelayOracle::PlayoutDelayOracle()
-    : high_sequence_number_(0),
-      send_playout_delay_(false),
-      ssrc_(0),
-      playout_delay_{-1, -1} {}
+PlayoutDelayOracle::PlayoutDelayOracle() = default;
 
-PlayoutDelayOracle::~PlayoutDelayOracle() {}
+PlayoutDelayOracle::~PlayoutDelayOracle() = default;
 
-void PlayoutDelayOracle::UpdateRequest(uint32_t ssrc,
-                                       PlayoutDelay playout_delay,
-                                       uint16_t seq_num) {
+absl::optional<PlayoutDelay> PlayoutDelayOracle::PlayoutDelayToSend(
+    PlayoutDelay requested_delay) const {
   rtc::CritScope lock(&crit_sect_);
-  RTC_DCHECK_LE(playout_delay.min_ms, PlayoutDelayLimits::kMaxMs);
-  RTC_DCHECK_LE(playout_delay.max_ms, PlayoutDelayLimits::kMaxMs);
-  RTC_DCHECK_LE(playout_delay.min_ms, playout_delay.max_ms);
-  int64_t unwrapped_seq_num = unwrapper_.Unwrap(seq_num);
-  if (playout_delay.min_ms >= 0 &&
-      playout_delay.min_ms != playout_delay_.min_ms) {
-    send_playout_delay_ = true;
-    playout_delay_.min_ms = playout_delay.min_ms;
-    high_sequence_number_ = unwrapped_seq_num;
+  if (requested_delay.min_ms > PlayoutDelayLimits::kMaxMs ||
+      requested_delay.max_ms > PlayoutDelayLimits::kMaxMs) {
+    RTC_DLOG(LS_ERROR)
+        << "Requested playout delay values out of range, ignored";
+    return absl::nullopt;
+  }
+  if (requested_delay.max_ms != -1 &&
+      requested_delay.min_ms > requested_delay.max_ms) {
+    RTC_DLOG(LS_ERROR) << "Requested playout delay values out of order";
+    return absl::nullopt;
+  }
+  if ((requested_delay.min_ms == -1 ||
+       requested_delay.min_ms == latest_delay_.min_ms) &&
+      (requested_delay.max_ms == -1 ||
+       requested_delay.max_ms == latest_delay_.max_ms)) {
+    // Unchanged.
+    return unacked_sequence_number_ ? absl::make_optional(latest_delay_)
+                                    : absl::nullopt;
+  }
+  if (requested_delay.min_ms == -1) {
+    RTC_DCHECK_GE(requested_delay.max_ms, 0);
+    requested_delay.min_ms =
+        std::min(latest_delay_.min_ms, requested_delay.max_ms);
+  }
+  if (requested_delay.max_ms == -1) {
+    requested_delay.max_ms =
+        std::max(latest_delay_.max_ms, requested_delay.min_ms);
+  }
+  return requested_delay;
+}
+
+void PlayoutDelayOracle::OnSentPacket(uint16_t sequence_number,
+                                      absl::optional<PlayoutDelay> delay) {
+  rtc::CritScope lock(&crit_sect_);
+  int64_t unwrapped_sequence_number = unwrapper_.Unwrap(sequence_number);
+
+  if (!delay) {
+    return;
   }
 
-  if (playout_delay.max_ms >= 0 &&
-      playout_delay.max_ms != playout_delay_.max_ms) {
-    send_playout_delay_ = true;
-    playout_delay_.max_ms = playout_delay.max_ms;
-    high_sequence_number_ = unwrapped_seq_num;
+  RTC_DCHECK_LE(0, delay->min_ms);
+  RTC_DCHECK_LE(delay->max_ms, PlayoutDelayLimits::kMaxMs);
+  RTC_DCHECK_LE(delay->min_ms, delay->max_ms);
+
+  if (delay->min_ms != latest_delay_.min_ms ||
+      delay->max_ms != latest_delay_.max_ms) {
+    latest_delay_ = *delay;
+    unacked_sequence_number_ = unwrapped_sequence_number;
   }
-  ssrc_ = ssrc;
 }
 
 // If an ACK is received on the packet containing the playout delay extension,
 // we stop sending the extension on future packets.
-void PlayoutDelayOracle::OnReceivedRtcpReportBlocks(
-    const ReportBlockList& report_blocks) {
+void PlayoutDelayOracle::OnReceivedAck(
+    int64_t extended_highest_sequence_number) {
   rtc::CritScope lock(&crit_sect_);
-  for (const RTCPReportBlock& report_block : report_blocks) {
-    if ((ssrc_ == report_block.source_ssrc) && send_playout_delay_ &&
-        (report_block.extended_highest_sequence_number >
-         high_sequence_number_)) {
-      send_playout_delay_ = false;
-    }
+  if (unacked_sequence_number_ &&
+      extended_highest_sequence_number > *unacked_sequence_number_) {
+    unacked_sequence_number_ = absl::nullopt;
   }
 }
 
diff --git a/modules/rtp_rtcp/source/playout_delay_oracle.h b/modules/rtp_rtcp/source/playout_delay_oracle.h
index 0e3bd39..6451be4 100644
--- a/modules/rtp_rtcp/source/playout_delay_oracle.h
+++ b/modules/rtp_rtcp/source/playout_delay_oracle.h
@@ -13,11 +13,12 @@
 
 #include <stdint.h>
 
+#include "absl/types/optional.h"
 #include "common_types.h"  // NOLINT(build/include)
 #include "modules/include/module_common_types_public.h"
 #include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
-#include "rtc_base/constructormagic.h"
-#include "rtc_base/criticalsection.h"
+#include "rtc_base/constructor_magic.h"
+#include "rtc_base/critical_section.h"
 #include "rtc_base/thread_annotations.h"
 
 namespace webrtc {
@@ -33,47 +34,39 @@
 // The application specifies a minimum and maximum limit for the playout delay
 // which are both communicated to the receiver and the receiver can adapt
 // the playout delay within this range based on observed network jitter.
-class PlayoutDelayOracle {
+class PlayoutDelayOracle : public RtcpAckObserver {
  public:
   PlayoutDelayOracle();
-  ~PlayoutDelayOracle();
+  ~PlayoutDelayOracle() override;
 
-  // Returns true if the current frame should include the playout delay
-  // extension
-  bool send_playout_delay() const {
-    rtc::CritScope lock(&crit_sect_);
-    return send_playout_delay_;
-  }
+  // The playout delay to be added to a packet. The input delays are provided by
+  // the application, with -1 meaning unchanged/unspecified. The output delay
+  // are the values to be attached to packets on the wire. Presence and value
+  // depends on the current input, previous inputs, and received acks from the
+  // remote end.
+  absl::optional<PlayoutDelay> PlayoutDelayToSend(
+      PlayoutDelay requested_delay) const;
 
-  // Returns current playout delay.
-  PlayoutDelay playout_delay() const {
-    rtc::CritScope lock(&crit_sect_);
-    return playout_delay_;
-  }
+  void OnSentPacket(uint16_t sequence_number,
+                    absl::optional<PlayoutDelay> playout_delay);
 
-  // Updates the application requested playout delay, current ssrc
-  // and the current sequence number.
-  void UpdateRequest(uint32_t ssrc,
-                     PlayoutDelay playout_delay,
-                     uint16_t seq_num);
-
-  void OnReceivedRtcpReportBlocks(const ReportBlockList& report_blocks);
+  void OnReceivedAck(int64_t extended_highest_sequence_number) override;
 
  private:
   // The playout delay information is updated from the encoder thread(s).
   // The sequence number feedback is updated from the worker thread.
   // Guards access to data across multiple threads.
   rtc::CriticalSection crit_sect_;
-  // The current highest sequence number on which playout delay has been sent.
-  int64_t high_sequence_number_ RTC_GUARDED_BY(crit_sect_);
-  // Indicates whether the playout delay should go on the next frame.
-  bool send_playout_delay_ RTC_GUARDED_BY(crit_sect_);
-  // Sender ssrc.
-  uint32_t ssrc_ RTC_GUARDED_BY(crit_sect_);
-  // Sequence number unwrapper.
+  // The oldest sequence number on which the current playout delay values have
+  // been sent. When set, it means we need to attach extension to sent packets.
+  absl::optional<int64_t> unacked_sequence_number_ RTC_GUARDED_BY(crit_sect_);
+  // Sequence number unwrapper for sent packets.
+
+  // TODO(nisse): Could potentially get out of sync with the unwrapper used by
+  // the caller of OnReceivedAck.
   SequenceNumberUnwrapper unwrapper_ RTC_GUARDED_BY(crit_sect_);
   // Playout delay values on the next frame if |send_playout_delay_| is set.
-  PlayoutDelay playout_delay_ RTC_GUARDED_BY(crit_sect_);
+  PlayoutDelay latest_delay_ RTC_GUARDED_BY(crit_sect_) = {-1, -1};
 
   RTC_DISALLOW_COPY_AND_ASSIGN(PlayoutDelayOracle);
 };
diff --git a/modules/rtp_rtcp/source/playout_delay_oracle_unittest.cc b/modules/rtp_rtcp/source/playout_delay_oracle_unittest.cc
index 099339d..3857e9b 100644
--- a/modules/rtp_rtcp/source/playout_delay_oracle_unittest.cc
+++ b/modules/rtp_rtcp/source/playout_delay_oracle_unittest.cc
@@ -16,54 +16,37 @@
 namespace webrtc {
 
 namespace {
-constexpr int kSsrc = 100;
 constexpr int kSequenceNumber = 100;
 constexpr int kMinPlayoutDelay = 0;
 constexpr int kMaxPlayoutDelay = 150;
 }  // namespace
 
-class PlayoutDelayOracleTest : public ::testing::Test {
- protected:
-  void ReportRTCPFeedback(int ssrc, int seq_num) {
-    RTCPReportBlock report_block;
-    report_block.source_ssrc = ssrc;
-    report_block.extended_highest_sequence_number = seq_num;
-    report_blocks_.push_back(report_block);
-    playout_delay_oracle_.OnReceivedRtcpReportBlocks(report_blocks_);
-  }
-
-  ReportBlockList report_blocks_;
-  PlayoutDelayOracle playout_delay_oracle_;
-};
-
-TEST_F(PlayoutDelayOracleTest, DisabledByDefault) {
-  EXPECT_FALSE(playout_delay_oracle_.send_playout_delay());
-  EXPECT_EQ(-1, playout_delay_oracle_.playout_delay().min_ms);
-  EXPECT_EQ(-1, playout_delay_oracle_.playout_delay().max_ms);
+TEST(PlayoutDelayOracleTest, DisabledByDefault) {
+  PlayoutDelayOracle playout_delay_oracle;
+  EXPECT_FALSE(playout_delay_oracle.PlayoutDelayToSend({-1, -1}));
 }
 
-TEST_F(PlayoutDelayOracleTest, SendPlayoutDelayUntilSeqNumberExceeds) {
+TEST(PlayoutDelayOracleTest, SendPlayoutDelayUntilSeqNumberExceeds) {
+  PlayoutDelayOracle playout_delay_oracle;
   PlayoutDelay playout_delay = {kMinPlayoutDelay, kMaxPlayoutDelay};
-  playout_delay_oracle_.UpdateRequest(kSsrc, playout_delay, kSequenceNumber);
-  EXPECT_TRUE(playout_delay_oracle_.send_playout_delay());
-  EXPECT_EQ(kMinPlayoutDelay, playout_delay_oracle_.playout_delay().min_ms);
-  EXPECT_EQ(kMaxPlayoutDelay, playout_delay_oracle_.playout_delay().max_ms);
+  playout_delay_oracle.OnSentPacket(kSequenceNumber, playout_delay);
+  absl::optional<PlayoutDelay> delay_to_send =
+      playout_delay_oracle.PlayoutDelayToSend({-1, -1});
+  ASSERT_TRUE(delay_to_send.has_value());
+  EXPECT_EQ(kMinPlayoutDelay, delay_to_send->min_ms);
+  EXPECT_EQ(kMaxPlayoutDelay, delay_to_send->max_ms);
 
   // Oracle indicates playout delay should be sent if highest sequence number
   // acked is lower than the sequence number of the first packet containing
   // playout delay.
-  ReportRTCPFeedback(kSsrc, kSequenceNumber - 1);
-  EXPECT_TRUE(playout_delay_oracle_.send_playout_delay());
-
-  // An invalid ssrc feedback report is dropped by the oracle.
-  ReportRTCPFeedback(kSsrc + 1, kSequenceNumber + 1);
-  EXPECT_TRUE(playout_delay_oracle_.send_playout_delay());
+  playout_delay_oracle.OnReceivedAck(kSequenceNumber - 1);
+  EXPECT_TRUE(playout_delay_oracle.PlayoutDelayToSend({-1, -1}));
 
   // Oracle indicates playout delay should not be sent if sequence number
   // acked on a matching ssrc indicates the receiver has received the playout
   // delay values.
-  ReportRTCPFeedback(kSsrc, kSequenceNumber + 1);
-  EXPECT_FALSE(playout_delay_oracle_.send_playout_delay());
+  playout_delay_oracle.OnReceivedAck(kSequenceNumber + 1);
+  EXPECT_FALSE(playout_delay_oracle.PlayoutDelayToSend({-1, -1}));
 }
 
 }  // namespace webrtc
diff --git a/modules/rtp_rtcp/source/receive_statistics_impl.cc b/modules/rtp_rtcp/source/receive_statistics_impl.cc
index bc742d1..066dc4b 100644
--- a/modules/rtp_rtcp/source/receive_statistics_impl.cc
+++ b/modules/rtp_rtcp/source/receive_statistics_impl.cc
@@ -48,11 +48,10 @@
       last_receive_time_ms_(0),
       last_received_timestamp_(0),
       received_seq_first_(0),
-      received_seq_max_(0),
-      received_seq_wraps_(0),
+      received_seq_max_(-1),
       last_report_inorder_packets_(0),
       last_report_old_packets_(0),
-      last_report_seq_max_(0),
+      last_report_seq_max_(-1),
       rtcp_callback_(rtcp_callback),
       rtp_callback_(rtp_callback) {}
 
@@ -64,54 +63,75 @@
     rtp_callback_->DataCountersUpdated(counters, ssrc_);
 }
 
+bool StreamStatisticianImpl::UpdateOutOfOrder(const RtpPacketReceived& packet,
+                                              int64_t sequence_number,
+                                              int64_t now_ms) {
+  RTC_DCHECK_EQ(sequence_number,
+                seq_unwrapper_.UnwrapWithoutUpdate(packet.SequenceNumber()));
+
+  // Check if |packet| is second packet of a stream restart.
+  if (received_seq_out_of_order_) {
+    uint16_t expected_sequence_number = *received_seq_out_of_order_ + 1;
+    received_seq_out_of_order_ = absl::nullopt;
+    if (packet.SequenceNumber() == expected_sequence_number) {
+      // Ignore sequence number gap caused by stream restart for next packet
+      // loss calculation.
+      last_report_seq_max_ = sequence_number;
+      last_report_inorder_packets_ = receive_counters_.transmitted.packets -
+                                     receive_counters_.retransmitted.packets;
+      // As final part of stream restart consider |packet| is not out of order.
+      return false;
+    }
+  }
+
+  if (std::abs(sequence_number - received_seq_max_) >
+      max_reordering_threshold_) {
+    // Sequence number gap looks too large, wait until next packet to check
+    // for a stream restart.
+    received_seq_out_of_order_ = packet.SequenceNumber();
+    return true;
+  }
+
+  if (sequence_number > received_seq_max_)
+    return false;
+
+  // Old out of order packet, may be retransmit.
+  if (enable_retransmit_detection_ && IsRetransmitOfOldPacket(packet, now_ms))
+    receive_counters_.retransmitted.AddPacket(packet);
+  return true;
+}
+
 StreamDataCounters StreamStatisticianImpl::UpdateCounters(
     const RtpPacketReceived& packet) {
   rtc::CritScope cs(&stream_lock_);
   RTC_DCHECK_EQ(ssrc_, packet.Ssrc());
-  uint16_t sequence_number = packet.SequenceNumber();
-  bool in_order =
-      // First packet is always in order.
-      last_receive_time_ms_ == 0 ||
-      IsNewerSequenceNumber(sequence_number, received_seq_max_) ||
-      // If we have a restart of the remote side this packet is still in order.
-      !IsNewerSequenceNumber(sequence_number,
-                             received_seq_max_ - max_reordering_threshold_);
   int64_t now_ms = clock_->TimeInMilliseconds();
 
   incoming_bitrate_.Update(packet.size(), now_ms);
   receive_counters_.transmitted.AddPacket(packet);
-  if (!in_order && enable_retransmit_detection_ &&
-      IsRetransmitOfOldPacket(packet, now_ms)) {
-    receive_counters_.retransmitted.AddPacket(packet);
-  }
 
-  if (receive_counters_.transmitted.packets == 1) {
-    received_seq_first_ = packet.SequenceNumber();
+  int64_t sequence_number =
+      seq_unwrapper_.UnwrapWithoutUpdate(packet.SequenceNumber());
+  if (!ReceivedRtpPacket()) {
+    received_seq_first_ = sequence_number;
+    last_report_seq_max_ = sequence_number - 1;
     receive_counters_.first_packet_time_ms = now_ms;
+  } else if (UpdateOutOfOrder(packet, sequence_number, now_ms)) {
+    return receive_counters_;
   }
+  // In order packet.
+  received_seq_max_ = sequence_number;
+  seq_unwrapper_.UpdateLast(sequence_number);
 
-  // Count only the new packets received. That is, if packets 1, 2, 3, 5, 4, 6
-  // are received, 4 will be ignored.
-  if (in_order) {
-    // Wrong if we use RetransmitOfOldPacket.
-    if (receive_counters_.transmitted.packets > 1 &&
-        received_seq_max_ > packet.SequenceNumber()) {
-      // Wrap around detected.
-      received_seq_wraps_++;
-    }
-    // New max.
-    received_seq_max_ = packet.SequenceNumber();
-
-    // If new time stamp and more than one in-order packet received, calculate
-    // new jitter statistics.
-    if (packet.Timestamp() != last_received_timestamp_ &&
-        (receive_counters_.transmitted.packets -
-         receive_counters_.retransmitted.packets) > 1) {
-      UpdateJitter(packet, now_ms);
-    }
-    last_received_timestamp_ = packet.Timestamp();
-    last_receive_time_ms_ = now_ms;
+  // If new time stamp and more than one in-order packet received, calculate
+  // new jitter statistics.
+  if (packet.Timestamp() != last_received_timestamp_ &&
+      (receive_counters_.transmitted.packets -
+       receive_counters_.retransmitted.packets) > 1) {
+    UpdateJitter(packet, now_ms);
   }
+  last_received_timestamp_ = packet.Timestamp();
+  last_receive_time_ms_ = now_ms;
   return receive_counters_;
 }
 
@@ -163,9 +183,7 @@
                                            bool reset) {
   {
     rtc::CritScope cs(&stream_lock_);
-    if (received_seq_first_ == 0 &&
-        receive_counters_.transmitted.payload_bytes == 0) {
-      // We have not received anything.
+    if (!ReceivedRtpPacket()) {
       return false;
     }
 
@@ -196,9 +214,7 @@
       // Not active.
       return false;
     }
-    if (received_seq_first_ == 0 &&
-        receive_counters_.transmitted.payload_bytes == 0) {
-      // We have not received anything.
+    if (!ReceivedRtpPacket()) {
       return false;
     }
 
@@ -212,19 +228,9 @@
 
 RtcpStatistics StreamStatisticianImpl::CalculateRtcpStatistics() {
   RtcpStatistics stats;
-
-  if (last_report_inorder_packets_ == 0) {
-    // First time we send a report.
-    last_report_seq_max_ = received_seq_first_ - 1;
-  }
-
   // Calculate fraction lost.
-  uint16_t exp_since_last = (received_seq_max_ - last_report_seq_max_);
-
-  if (last_report_seq_max_ > received_seq_max_) {
-    // Can we assume that the seq_num can't go decrease over a full RTCP period?
-    exp_since_last = 0;
-  }
+  int64_t exp_since_last = received_seq_max_ - last_report_seq_max_;
+  RTC_DCHECK_GE(exp_since_last, 0);
 
   // Number of received RTP packets since last report, counts all packets but
   // not re-transmissions.
@@ -261,7 +267,7 @@
   cumulative_loss_ += missing;
   stats.packets_lost = cumulative_loss_;
   stats.extended_highest_sequence_number =
-      (received_seq_wraps_ << 16) + received_seq_max_;
+      static_cast<uint32_t>(received_seq_max_);
   // Note: internal jitter value is in Q4 and needs to be scaled by 1/16.
   stats.jitter = jitter_q4_ >> 4;
 
diff --git a/modules/rtp_rtcp/source/receive_statistics_impl.h b/modules/rtp_rtcp/source/receive_statistics_impl.h
index 8153c44..c153281 100644
--- a/modules/rtp_rtcp/source/receive_statistics_impl.h
+++ b/modules/rtp_rtcp/source/receive_statistics_impl.h
@@ -17,7 +17,9 @@
 #include <map>
 #include <vector>
 
-#include "rtc_base/criticalsection.h"
+#include "absl/types/optional.h"
+#include "modules/include/module_common_types_public.h"
+#include "rtc_base/critical_section.h"
 #include "rtc_base/rate_statistics.h"
 #include "rtc_base/thread_annotations.h"
 
@@ -58,7 +60,18 @@
       RTC_EXCLUSIVE_LOCKS_REQUIRED(stream_lock_);
   void UpdateJitter(const RtpPacketReceived& packet, int64_t receive_time_ms)
       RTC_EXCLUSIVE_LOCKS_REQUIRED(stream_lock_);
+  // Updates StreamStatistician for out of order packets.
+  // Returns true if packet considered to be out of order.
+  bool UpdateOutOfOrder(const RtpPacketReceived& packet,
+                        int64_t sequence_number,
+                        int64_t now_ms)
+      RTC_EXCLUSIVE_LOCKS_REQUIRED(stream_lock_);
+  // Updates StreamStatistician for incoming packets.
   StreamDataCounters UpdateCounters(const RtpPacketReceived& packet);
+  // Checks if this StreamStatistician received any rtp packets.
+  bool ReceivedRtpPacket() const RTC_EXCLUSIVE_LOCKS_REQUIRED(stream_lock_) {
+    return received_seq_max_ >= 0;
+  }
 
   const uint32_t ssrc_;
   Clock* const clock_;
@@ -74,9 +87,13 @@
 
   int64_t last_receive_time_ms_ 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_);
+  SequenceNumberUnwrapper seq_unwrapper_ RTC_GUARDED_BY(&stream_lock_);
+  int64_t received_seq_first_ RTC_GUARDED_BY(&stream_lock_);
+  int64_t received_seq_max_ RTC_GUARDED_BY(&stream_lock_);
+  // Assume that the other side restarted when there are two sequential packets
+  // with large jump from received_seq_max_.
+  absl::optional<uint16_t> received_seq_out_of_order_
+      RTC_GUARDED_BY(&stream_lock_);
 
   // Current counter values.
   StreamDataCounters receive_counters_ RTC_GUARDED_BY(&stream_lock_);
@@ -84,7 +101,7 @@
   // Counter values when we sent the last report.
   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_);
+  int64_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.
diff --git a/modules/rtp_rtcp/source/receive_statistics_unittest.cc b/modules/rtp_rtcp/source/receive_statistics_unittest.cc
index 2539363..1703cee 100644
--- a/modules/rtp_rtcp/source/receive_statistics_unittest.cc
+++ b/modules/rtp_rtcp/source/receive_statistics_unittest.cc
@@ -295,6 +295,217 @@
   EXPECT_EQ(177u, statistics.jitter);
 }
 
+TEST_F(ReceiveStatisticsTest, SimpleLossComputation) {
+  packet1_.SetSequenceNumber(1);
+  receive_statistics_->OnRtpPacket(packet1_);
+  packet1_.SetSequenceNumber(3);
+  receive_statistics_->OnRtpPacket(packet1_);
+  packet1_.SetSequenceNumber(4);
+  receive_statistics_->OnRtpPacket(packet1_);
+  packet1_.SetSequenceNumber(5);
+  receive_statistics_->OnRtpPacket(packet1_);
+
+  RtcpStatistics statistics;
+  receive_statistics_->GetStatistician(kSsrc1)->GetStatistics(&statistics,
+                                                              true);
+  // 20% = 51/255.
+  EXPECT_EQ(51u, statistics.fraction_lost);
+  EXPECT_EQ(1, statistics.packets_lost);
+}
+
+TEST_F(ReceiveStatisticsTest, LossComputationWithReordering) {
+  packet1_.SetSequenceNumber(1);
+  receive_statistics_->OnRtpPacket(packet1_);
+  packet1_.SetSequenceNumber(3);
+  receive_statistics_->OnRtpPacket(packet1_);
+  packet1_.SetSequenceNumber(2);
+  receive_statistics_->OnRtpPacket(packet1_);
+  packet1_.SetSequenceNumber(5);
+  receive_statistics_->OnRtpPacket(packet1_);
+
+  RtcpStatistics statistics;
+  receive_statistics_->GetStatistician(kSsrc1)->GetStatistics(&statistics,
+                                                              true);
+  // 20% = 51/255.
+  EXPECT_EQ(51u, statistics.fraction_lost);
+  EXPECT_EQ(1, statistics.packets_lost);
+}
+
+TEST_F(ReceiveStatisticsTest, LossComputationWithDuplicates) {
+  // Lose 2 packets, but also receive 1 duplicate. Should actually count as
+  // only 1 packet being lost.
+  packet1_.SetSequenceNumber(1);
+  receive_statistics_->OnRtpPacket(packet1_);
+  packet1_.SetSequenceNumber(4);
+  receive_statistics_->OnRtpPacket(packet1_);
+  packet1_.SetSequenceNumber(4);
+  receive_statistics_->OnRtpPacket(packet1_);
+  packet1_.SetSequenceNumber(5);
+  receive_statistics_->OnRtpPacket(packet1_);
+
+  RtcpStatistics statistics;
+  receive_statistics_->GetStatistician(kSsrc1)->GetStatistics(&statistics,
+                                                              true);
+  // 20% = 51/255.
+  EXPECT_EQ(51u, statistics.fraction_lost);
+  EXPECT_EQ(1, statistics.packets_lost);
+}
+
+TEST_F(ReceiveStatisticsTest, LossComputationWithSequenceNumberWrapping) {
+  // First, test loss computation over a period that included a sequence number
+  // rollover.
+  packet1_.SetSequenceNumber(0xfffd);
+  receive_statistics_->OnRtpPacket(packet1_);
+  packet1_.SetSequenceNumber(0);
+  receive_statistics_->OnRtpPacket(packet1_);
+  packet1_.SetSequenceNumber(0xfffe);
+  receive_statistics_->OnRtpPacket(packet1_);
+  packet1_.SetSequenceNumber(1);
+  receive_statistics_->OnRtpPacket(packet1_);
+
+  // Only one packet was actually lost, 0xffff.
+  RtcpStatistics statistics;
+  receive_statistics_->GetStatistician(kSsrc1)->GetStatistics(&statistics,
+                                                              true);
+  // 20% = 51/255.
+  EXPECT_EQ(51u, statistics.fraction_lost);
+  EXPECT_EQ(1, statistics.packets_lost);
+
+  // Now test losing one packet *after* the rollover.
+  packet1_.SetSequenceNumber(3);
+  receive_statistics_->OnRtpPacket(packet1_);
+  receive_statistics_->GetStatistician(kSsrc1)->GetStatistics(&statistics,
+                                                              true);
+  // 50% = 127/255.
+  EXPECT_EQ(127u, statistics.fraction_lost);
+  EXPECT_EQ(2, statistics.packets_lost);
+}
+
+TEST_F(ReceiveStatisticsTest, StreamRestartDoesntCountAsLoss) {
+  RtcpStatistics statistics;
+  receive_statistics_->SetMaxReorderingThreshold(200);
+
+  packet1_.SetSequenceNumber(0);
+  receive_statistics_->OnRtpPacket(packet1_);
+  packet1_.SetSequenceNumber(1);
+  receive_statistics_->OnRtpPacket(packet1_);
+
+  packet1_.SetSequenceNumber(400);
+  receive_statistics_->OnRtpPacket(packet1_);
+  receive_statistics_->GetStatistician(kSsrc1)->GetStatistics(&statistics,
+                                                              true);
+  EXPECT_EQ(0, statistics.fraction_lost);
+  EXPECT_EQ(0, statistics.packets_lost);
+
+  packet1_.SetSequenceNumber(401);
+  receive_statistics_->OnRtpPacket(packet1_);
+  receive_statistics_->GetStatistician(kSsrc1)->GetStatistics(&statistics,
+                                                              true);
+  EXPECT_EQ(0, statistics.fraction_lost);
+  EXPECT_EQ(0, statistics.packets_lost);
+}
+
+TEST_F(ReceiveStatisticsTest, CountsLossAfterStreamRestart) {
+  RtcpStatistics statistics;
+  receive_statistics_->SetMaxReorderingThreshold(200);
+
+  packet1_.SetSequenceNumber(0);
+  receive_statistics_->OnRtpPacket(packet1_);
+  packet1_.SetSequenceNumber(1);
+  receive_statistics_->OnRtpPacket(packet1_);
+
+  packet1_.SetSequenceNumber(400);
+  receive_statistics_->OnRtpPacket(packet1_);
+  packet1_.SetSequenceNumber(401);
+  receive_statistics_->OnRtpPacket(packet1_);
+  packet1_.SetSequenceNumber(403);
+  receive_statistics_->OnRtpPacket(packet1_);
+
+  receive_statistics_->GetStatistician(kSsrc1)->GetStatistics(&statistics,
+                                                              true);
+  EXPECT_EQ(1, statistics.packets_lost);
+}
+
+TEST_F(ReceiveStatisticsTest, StreamCanRestartAtSequenceNumberWrapAround) {
+  RtcpStatistics statistics;
+  receive_statistics_->SetMaxReorderingThreshold(200);
+
+  packet1_.SetSequenceNumber(0xffff - 401);
+  receive_statistics_->OnRtpPacket(packet1_);
+  packet1_.SetSequenceNumber(0xffff - 400);
+  receive_statistics_->OnRtpPacket(packet1_);
+
+  packet1_.SetSequenceNumber(0xffff);
+  receive_statistics_->OnRtpPacket(packet1_);
+  packet1_.SetSequenceNumber(0);
+  receive_statistics_->OnRtpPacket(packet1_);
+  packet1_.SetSequenceNumber(2);
+  receive_statistics_->OnRtpPacket(packet1_);
+
+  receive_statistics_->GetStatistician(kSsrc1)->GetStatistics(&statistics,
+                                                              true);
+  EXPECT_EQ(1, statistics.packets_lost);
+}
+
+TEST_F(ReceiveStatisticsTest, StreamRestartNeedsTwoConsecutivePackets) {
+  RtcpStatistics statistics;
+  receive_statistics_->SetMaxReorderingThreshold(200);
+
+  packet1_.SetSequenceNumber(400);
+  receive_statistics_->OnRtpPacket(packet1_);
+  packet1_.SetSequenceNumber(401);
+  receive_statistics_->OnRtpPacket(packet1_);
+
+  packet1_.SetSequenceNumber(1);
+  receive_statistics_->OnRtpPacket(packet1_);
+  packet1_.SetSequenceNumber(3);
+  receive_statistics_->OnRtpPacket(packet1_);
+  receive_statistics_->GetStatistician(kSsrc1)->GetStatistics(&statistics,
+                                                              true);
+  EXPECT_EQ(401u, statistics.extended_highest_sequence_number);
+
+  packet1_.SetSequenceNumber(4);
+  receive_statistics_->OnRtpPacket(packet1_);
+  receive_statistics_->GetStatistician(kSsrc1)->GetStatistics(&statistics,
+                                                              true);
+  EXPECT_EQ(4u, statistics.extended_highest_sequence_number);
+}
+
+TEST_F(ReceiveStatisticsTest, WrapsAroundExtendedHighestSequenceNumber) {
+  RtcpStatistics statistics;
+  packet1_.SetSequenceNumber(0xffff);
+  receive_statistics_->OnRtpPacket(packet1_);
+  receive_statistics_->GetStatistician(kSsrc1)->GetStatistics(&statistics,
+                                                              true);
+  EXPECT_EQ(0xffffu, statistics.extended_highest_sequence_number);
+
+  // Wrap around.
+  packet1_.SetSequenceNumber(1);
+  receive_statistics_->OnRtpPacket(packet1_);
+  receive_statistics_->GetStatistician(kSsrc1)->GetStatistics(&statistics,
+                                                              true);
+  EXPECT_EQ(0x10001u, statistics.extended_highest_sequence_number);
+
+  // Should be treated as out of order; shouldn't increment highest extended
+  // sequence number.
+  packet1_.SetSequenceNumber(0x10000 - 6);
+  receive_statistics_->GetStatistician(kSsrc1)->GetStatistics(&statistics,
+                                                              true);
+  EXPECT_EQ(0x10001u, statistics.extended_highest_sequence_number);
+
+  // Receive a couple packets then wrap around again.
+  receive_statistics_->SetMaxReorderingThreshold(200);
+  for (int i = 10; i < 0xffff; i += 150) {
+    packet1_.SetSequenceNumber(i);
+    receive_statistics_->OnRtpPacket(packet1_);
+  }
+  packet1_.SetSequenceNumber(1);
+  receive_statistics_->OnRtpPacket(packet1_);
+  receive_statistics_->GetStatistician(kSsrc1)->GetStatistics(&statistics,
+                                                              true);
+  EXPECT_EQ(0x20001u, statistics.extended_highest_sequence_number);
+}
+
 class RtpTestCallback : public StreamDataCountersCallback {
  public:
   RtpTestCallback()
diff --git a/modules/rtp_rtcp/source/rtcp_packet.cc b/modules/rtp_rtcp/source/rtcp_packet.cc
index 194b992..bac03e7 100644
--- a/modules/rtp_rtcp/source/rtcp_packet.cc
+++ b/modules/rtp_rtcp/source/rtcp_packet.cc
@@ -52,7 +52,8 @@
 size_t RtcpPacket::HeaderLength() const {
   size_t length_in_bytes = BlockLength();
   RTC_DCHECK_GT(length_in_bytes, 0);
-  RTC_DCHECK_EQ(length_in_bytes % 4, 0) << "Padding not supported";
+  RTC_DCHECK_EQ(length_in_bytes % 4, 0)
+      << "Padding must be handled by each subclass.";
   // Length in 32-bit words without common header.
   return (length_in_bytes - kHeaderLength) / 4;
 }
@@ -71,12 +72,23 @@
     size_t length,
     uint8_t* buffer,
     size_t* pos) {
+  CreateHeader(count_or_format, packet_type, length, /*padding=*/false, buffer,
+               pos);
+}
+
+void RtcpPacket::CreateHeader(
+    size_t count_or_format,  // Depends on packet type.
+    uint8_t packet_type,
+    size_t length,
+    bool padding,
+    uint8_t* buffer,
+    size_t* pos) {
   RTC_DCHECK_LE(length, 0xffffU);
   RTC_DCHECK_LE(count_or_format, 0x1f);
   constexpr uint8_t kVersionBits = 2 << 6;
-  constexpr uint8_t kNoPaddingBit = 0 << 5;
+  uint8_t padding_bit = padding ? 1 << 5 : 0;
   buffer[*pos + 0] =
-      kVersionBits | kNoPaddingBit | static_cast<uint8_t>(count_or_format);
+      kVersionBits | padding_bit | static_cast<uint8_t>(count_or_format);
   buffer[*pos + 1] = packet_type;
   buffer[*pos + 2] = (length >> 8) & 0xff;
   buffer[*pos + 3] = length & 0xff;
diff --git a/modules/rtp_rtcp/source/rtcp_packet.h b/modules/rtp_rtcp/source/rtcp_packet.h
index 40e51e8..94bf9f0 100644
--- a/modules/rtp_rtcp/source/rtcp_packet.h
+++ b/modules/rtp_rtcp/source/rtcp_packet.h
@@ -87,6 +87,13 @@
                            uint8_t* buffer,
                            size_t* pos);
 
+  static void CreateHeader(size_t count_or_format,
+                           uint8_t packet_type,
+                           size_t block_length,  // Payload size in 32bit words.
+                           bool padding,  // True if there are padding bytes.
+                           uint8_t* buffer,
+                           size_t* pos);
+
   bool OnBufferFull(uint8_t* packet,
                     size_t* index,
                     PacketReadyCallback callback) const;
diff --git a/modules/rtp_rtcp/source/rtcp_packet/compound_packet.h b/modules/rtp_rtcp/source/rtcp_packet/compound_packet.h
index 89b7814..f521c7f 100644
--- a/modules/rtp_rtcp/source/rtcp_packet/compound_packet.h
+++ b/modules/rtp_rtcp/source/rtcp_packet/compound_packet.h
@@ -15,7 +15,7 @@
 #include <vector>
 
 #include "modules/rtp_rtcp/source/rtcp_packet.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 namespace rtcp {
diff --git a/modules/rtp_rtcp/source/rtcp_packet/extended_reports.cc b/modules/rtp_rtcp/source/rtcp_packet/extended_reports.cc
index 2b5f9ca..561503a 100644
--- a/modules/rtp_rtcp/source/rtcp_packet/extended_reports.cc
+++ b/modules/rtp_rtcp/source/rtcp_packet/extended_reports.cc
@@ -44,7 +44,8 @@
 //  :             type-specific block contents                      :
 //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 ExtendedReports::ExtendedReports() : sender_ssrc_(0) {}
-ExtendedReports::~ExtendedReports() {}
+ExtendedReports::ExtendedReports(const ExtendedReports& xr) = default;
+ExtendedReports::~ExtendedReports() = default;
 
 bool ExtendedReports::Parse(const CommonHeader& packet) {
   RTC_DCHECK_EQ(packet.type(), kPacketType);
diff --git a/modules/rtp_rtcp/source/rtcp_packet/extended_reports.h b/modules/rtp_rtcp/source/rtcp_packet/extended_reports.h
index fd96769..4ae652c 100644
--- a/modules/rtp_rtcp/source/rtcp_packet/extended_reports.h
+++ b/modules/rtp_rtcp/source/rtcp_packet/extended_reports.h
@@ -30,6 +30,7 @@
   static constexpr size_t kMaxNumberOfDlrrItems = 50;
 
   ExtendedReports();
+  ExtendedReports(const ExtendedReports& xr);
   ~ExtendedReports() override;
 
   // Parse assumes header is already parsed and validated.
diff --git a/modules/rtp_rtcp/source/rtcp_packet/fir.cc b/modules/rtp_rtcp/source/rtcp_packet/fir.cc
index 517e991..fd4a4c9 100644
--- a/modules/rtp_rtcp/source/rtcp_packet/fir.cc
+++ b/modules/rtp_rtcp/source/rtcp_packet/fir.cc
@@ -46,6 +46,8 @@
 
 Fir::Fir() = default;
 
+Fir::Fir(const Fir& fir) = default;
+
 Fir::~Fir() = default;
 
 bool Fir::Parse(const CommonHeader& packet) {
diff --git a/modules/rtp_rtcp/source/rtcp_packet/fir.h b/modules/rtp_rtcp/source/rtcp_packet/fir.h
index 6fbc54c..383dc96 100644
--- a/modules/rtp_rtcp/source/rtcp_packet/fir.h
+++ b/modules/rtp_rtcp/source/rtcp_packet/fir.h
@@ -30,6 +30,7 @@
   };
 
   Fir();
+  Fir(const Fir& fir);
   ~Fir() override;
 
   // Parse assumes header is already parsed and validated.
diff --git a/modules/rtp_rtcp/source/rtcp_packet/loss_notification.cc b/modules/rtp_rtcp/source/rtcp_packet/loss_notification.cc
new file mode 100644
index 0000000..08c75dd
--- /dev/null
+++ b/modules/rtp_rtcp/source/rtcp_packet/loss_notification.cc
@@ -0,0 +1,133 @@
+/*
+ *  Copyright (c) 2019 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "modules/rtp_rtcp/source/rtcp_packet/loss_notification.h"
+
+#include "modules/rtp_rtcp/source/byte_io.h"
+#include "modules/rtp_rtcp/source/rtcp_packet/common_header.h"
+#include "rtc_base/checks.h"
+#include "rtc_base/logging.h"
+
+namespace webrtc {
+namespace rtcp {
+
+// Loss Notification
+// -----------------
+//     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
+//    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+//    |V=2|P| FMT=15  |   PT=206      |             length            |
+//    +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
+//  0 |                  SSRC of packet sender                        |
+//    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+//  4 |                  SSRC of media source                         |
+//    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+//  8 |  Unique identifier 'L' 'N' 'T' 'F'                            |
+//    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// 12 | Last Decoded Sequence Number  | Last Received SeqNum Delta  |D|
+//    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+LossNotification::LossNotification()
+    : last_decoded_(0), last_received_(0), decodability_flag_(false) {}
+
+LossNotification::LossNotification(uint16_t last_decoded,
+                                   uint16_t last_received,
+                                   bool decodability_flag)
+    : last_decoded_(last_decoded),
+      last_received_(last_received),
+      decodability_flag_(decodability_flag) {}
+
+LossNotification::LossNotification(const LossNotification& rhs) = default;
+
+LossNotification::~LossNotification() = default;
+
+size_t LossNotification::BlockLength() const {
+  return kHeaderLength + kCommonFeedbackLength + kLossNotificationPayloadLength;
+}
+
+bool LossNotification::Create(uint8_t* packet,
+                              size_t* index,
+                              size_t max_length,
+                              PacketReadyCallback callback) const {
+  while (*index + BlockLength() > max_length) {
+    if (!OnBufferFull(packet, index, callback))
+      return false;
+  }
+
+  const size_t index_end = *index + BlockLength();
+
+  // Note: |index| updated by the function below.
+  CreateHeader(Psfb::kAfbMessageType, kPacketType, HeaderLength(), packet,
+               index);
+
+  CreateCommonFeedback(packet + *index);
+  *index += kCommonFeedbackLength;
+
+  ByteWriter<uint32_t>::WriteBigEndian(packet + *index, kUniqueIdentifier);
+  *index += sizeof(uint32_t);
+
+  ByteWriter<uint16_t>::WriteBigEndian(packet + *index, last_decoded_);
+  *index += sizeof(uint16_t);
+
+  const uint16_t last_received_delta = last_received_ - last_decoded_;
+  RTC_DCHECK_LE(last_received_delta, 0x7fff);
+  const uint16_t last_received_delta_and_decodability =
+      (last_received_delta << 1) | (decodability_flag_ ? 0x0001 : 0x0000);
+
+  ByteWriter<uint16_t>::WriteBigEndian(packet + *index,
+                                       last_received_delta_and_decodability);
+  *index += sizeof(uint16_t);
+
+  RTC_DCHECK_EQ(index_end, *index);
+  return true;
+}
+
+bool LossNotification::Parse(const CommonHeader& packet) {
+  RTC_DCHECK_EQ(packet.type(), kPacketType);
+  RTC_DCHECK_EQ(packet.fmt(), Psfb::kAfbMessageType);
+
+  if (packet.payload_size_bytes() <
+      kCommonFeedbackLength + kLossNotificationPayloadLength) {
+    return false;
+  }
+
+  const uint8_t* const payload = packet.payload();
+
+  if (ByteReader<uint32_t>::ReadBigEndian(&payload[8]) != kUniqueIdentifier) {
+    return false;
+  }
+
+  ParseCommonFeedback(payload);
+
+  last_decoded_ = ByteReader<uint16_t>::ReadBigEndian(&payload[12]);
+
+  const uint16_t last_received_delta_and_decodability =
+      ByteReader<uint16_t>::ReadBigEndian(&payload[14]);
+  last_received_ = last_decoded_ + (last_received_delta_and_decodability >> 1);
+  decodability_flag_ = (last_received_delta_and_decodability & 0x0001);
+
+  return true;
+}
+
+bool LossNotification::Set(uint16_t last_decoded,
+                           uint16_t last_received,
+                           bool decodability_flag) {
+  const uint16_t delta = last_received - last_decoded;
+  if (delta > 0x7fff) {
+    return false;
+  }
+  last_received_ = last_received;
+  last_decoded_ = last_decoded;
+  decodability_flag_ = decodability_flag;
+  return true;
+}
+
+}  // namespace rtcp
+}  // namespace webrtc
diff --git a/modules/rtp_rtcp/source/rtcp_packet/loss_notification.h b/modules/rtp_rtcp/source/rtcp_packet/loss_notification.h
new file mode 100644
index 0000000..2603a67
--- /dev/null
+++ b/modules/rtp_rtcp/source/rtcp_packet/loss_notification.h
@@ -0,0 +1,80 @@
+/*
+ *  Copyright (c) 2019 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef MODULES_RTP_RTCP_SOURCE_RTCP_PACKET_LOSS_NOTIFICATION_H_
+#define MODULES_RTP_RTCP_SOURCE_RTCP_PACKET_LOSS_NOTIFICATION_H_
+
+#include "modules/rtp_rtcp/source/rtcp_packet/common_header.h"
+#include "modules/rtp_rtcp/source/rtcp_packet/psfb.h"
+#include "rtc_base/system/unused.h"
+
+namespace webrtc {
+namespace rtcp {
+
+class LossNotification : public Psfb {
+ public:
+  LossNotification();
+  LossNotification(uint16_t last_decoded,
+                   uint16_t last_received,
+                   bool decodability_flag);
+  LossNotification(const LossNotification& other);
+  ~LossNotification() override;
+
+  size_t BlockLength() const override;
+
+  bool Create(uint8_t* packet,
+              size_t* index,
+              size_t max_length,
+              PacketReadyCallback callback) const override
+      RTC_WARN_UNUSED_RESULT;
+
+  // Parse assumes header is already parsed and validated.
+  bool Parse(const CommonHeader& packet) RTC_WARN_UNUSED_RESULT;
+
+  // Set all of the values transmitted by the loss notification message.
+  // If the values may not be represented by a loss notification message,
+  // false is returned, and no change is made to the object; this happens
+  // when |last_recieved| is ahead of |last_decoded| by more than 0x7fff.
+  // This is because |last_recieved| is represented on the wire as a delta,
+  // and only 15 bits are available for that delta.
+  bool Set(uint16_t last_decoded,
+           uint16_t last_received,
+           bool decodability_flag) RTC_WARN_UNUSED_RESULT;
+
+  // RTP sequence number of the first packet belong to the last decoded
+  // non-discardable frame.
+  uint16_t last_decoded() const { return last_decoded_; }
+
+  // RTP sequence number of the last received packet.
+  uint16_t last_received() const { return last_received_; }
+
+  // A decodability flag, whose specific meaning depends on the last-received
+  // RTP sequence number. The decodability flag is true if and only if all of
+  // the frame's dependencies are known to be decodable, and the frame itself
+  // is not yet known to be unassemblable.
+  // * Clarification #1: In a multi-packet frame, the first packet's
+  //   dependencies are known, but it is not yet known whether all parts
+  //   of the current frame will be received.
+  // * Clarification #2: In a multi-packet frame, the dependencies would be
+  //   unknown if the first packet was not received. Then, the packet will
+  //   be known-unassemblable.
+  bool decodability_flag() const { return decodability_flag_; }
+
+ private:
+  static constexpr uint32_t kUniqueIdentifier = 0x4C4E5446;  // 'L' 'N' 'T' 'F'.
+  static constexpr size_t kLossNotificationPayloadLength = 8;
+
+  uint16_t last_decoded_;
+  uint16_t last_received_;
+  bool decodability_flag_;
+};
+}  // namespace rtcp
+}  // namespace webrtc
+#endif  // MODULES_RTP_RTCP_SOURCE_RTCP_PACKET_LOSS_NOTIFICATION_H_
diff --git a/modules/rtp_rtcp/source/rtcp_packet/loss_notification_unittest.cc b/modules/rtp_rtcp/source/rtcp_packet/loss_notification_unittest.cc
new file mode 100644
index 0000000..6d74225
--- /dev/null
+++ b/modules/rtp_rtcp/source/rtcp_packet/loss_notification_unittest.cc
@@ -0,0 +1,136 @@
+/*
+ *  Copyright (c) 2019 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "modules/rtp_rtcp/source/rtcp_packet/loss_notification.h"
+
+#include "test/gmock.h"
+#include "test/gtest.h"
+#include "test/rtcp_packet_parser.h"
+
+namespace webrtc {
+
+using ::testing::ElementsAreArray;
+using ::testing::make_tuple;
+using ::webrtc::rtcp::LossNotification;
+
+TEST(RtcpPacketLossNotificationTest, SetWithIllegalValuesFails) {
+  constexpr uint16_t kLastDecoded = 0x3c7b;
+  constexpr uint16_t kLastReceived = kLastDecoded + 0x7fff + 1;
+  constexpr bool kDecodabilityFlag = true;
+  LossNotification loss_notification;
+  EXPECT_FALSE(
+      loss_notification.Set(kLastDecoded, kLastReceived, kDecodabilityFlag));
+}
+
+TEST(RtcpPacketLossNotificationTest, SetWithLegalValuesSucceeds) {
+  constexpr uint16_t kLastDecoded = 0x3c7b;
+  constexpr uint16_t kLastReceived = kLastDecoded + 0x7fff;
+  constexpr bool kDecodabilityFlag = true;
+  LossNotification loss_notification;
+  EXPECT_TRUE(
+      loss_notification.Set(kLastDecoded, kLastReceived, kDecodabilityFlag));
+}
+
+TEST(RtcpPacketLossNotificationTest, CreateProducesExpectedWireFormat) {
+  // Note that (0x6542 >> 1) is used just to make the pattern in kPacket
+  // more apparent; there's nothing truly special about the value,
+  // it's only an implementation detail that last-received is represented
+  // as a delta from last-decoded, and that this delta is shifted before
+  // it's put on the wire.
+  constexpr uint16_t kLastDecoded = 0x3c7b;
+  constexpr uint16_t kLastReceived = kLastDecoded + (0x6542 >> 1);
+  constexpr bool kDecodabilityFlag = true;
+
+  const uint8_t kPacket[] = {0x8f, 206,  0x00, 0x04, 0x12, 0x34, 0x56, 0x78,  //
+                             0xab, 0xcd, 0xef, 0x01, 'L',  'N',  'T',  'F',   //
+                             0x3c, 0x7b, 0x65, 0x43};
+
+  LossNotification loss_notification;
+  loss_notification.SetSenderSsrc(0x12345678);
+  loss_notification.SetMediaSsrc(0xabcdef01);
+  ASSERT_TRUE(
+      loss_notification.Set(kLastDecoded, kLastReceived, kDecodabilityFlag));
+
+  rtc::Buffer packet = loss_notification.Build();
+
+  EXPECT_THAT(make_tuple(packet.data(), packet.size()),
+              ElementsAreArray(kPacket));
+}
+
+TEST(RtcpPacketLossNotificationTest,
+     ParseFailsOnTooSmallPacketToBeLossNotification) {
+  uint8_t packet[] = {0x8f, 206,  0x00, 0x04, 0x12, 0x34, 0x56, 0x78,  //
+                      0xab, 0xcd, 0xef, 0x01, 'L',  'N',  'T',  'F',   //
+                      0x3c, 0x7b, 0x65, 0x43};
+  size_t packet_length_bytes = sizeof(packet);
+
+  LossNotification loss_notification;
+
+  // First, prove that the failure we're expecting to see happens because of
+  // the length, by showing that before the modification to the length,
+  // the packet was correctly parsed.
+  ASSERT_TRUE(
+      test::ParseSinglePacket(packet, packet_length_bytes, &loss_notification));
+
+  // Show that after shaving off a word, the packet is no longer parsable.
+  packet[3] -= 1;            // Change the |length| field of the RTCP packet.
+  packet_length_bytes -= 4;  // Effectively forget the last 32-bit word.
+  EXPECT_FALSE(
+      test::ParseSinglePacket(packet, packet_length_bytes, &loss_notification));
+}
+
+TEST(RtcpPacketLossNotificationTest,
+     ParseFailsWhenUniqueIdentifierIsNotLossNotification) {
+  uint8_t packet[] = {0x8f, 206,  0x00, 0x04, 0x12, 0x34, 0x56, 0x78,  //
+                      0xab, 0xcd, 0xef, 0x01, 'L',  'N',  'T',  'F',   //
+                      0x3c, 0x7b, 0x65, 0x43};
+
+  LossNotification loss_notification;
+
+  // First, prove that the failure we're expecting to see happens because of
+  // the identifier, by showing that before the modification to the identifier,
+  // the packet was correctly parsed.
+  ASSERT_TRUE(test::ParseSinglePacket(packet, &loss_notification));
+
+  // Show that after changing the identifier, the packet is no longer parsable.
+  RTC_DCHECK_EQ(packet[12], 'L');
+  RTC_DCHECK_EQ(packet[13], 'N');
+  RTC_DCHECK_EQ(packet[14], 'T');
+  RTC_DCHECK_EQ(packet[15], 'F');
+  packet[14] = 'x';
+  EXPECT_FALSE(test::ParseSinglePacket(packet, &loss_notification));
+}
+
+TEST(RtcpPacketLossNotificationTest,
+     ParseLegalLossNotificationMessagesCorrectly) {
+  // Note that (0x6542 >> 1) is used just to make the pattern in kPacket
+  // more apparent; there's nothing truly special about the value,
+  // it's only an implementation detail that last-received is represented
+  // as a delta from last-decoded, and that this delta is shifted before
+  // it's put on the wire.
+  constexpr uint16_t kLastDecoded = 0x3c7b;
+  constexpr uint16_t kLastReceived = kLastDecoded + (0x6542 >> 1);
+  constexpr bool kDecodabilityFlag = true;
+
+  const uint8_t kPacket[] = {0x8f, 206,  0x00, 0x04, 0x12, 0x34, 0x56, 0x78,  //
+                             0xab, 0xcd, 0xef, 0x01, 'L',  'N',  'T',  'F',   //
+                             0x3c, 0x7b, 0x65, 0x43};
+
+  LossNotification loss_notification;
+  EXPECT_TRUE(test::ParseSinglePacket(kPacket, &loss_notification));
+
+  EXPECT_EQ(loss_notification.sender_ssrc(), 0x12345678u);
+  EXPECT_EQ(loss_notification.media_ssrc(), 0xabcdef01u);
+  EXPECT_EQ(loss_notification.last_decoded(), kLastDecoded);
+  EXPECT_EQ(loss_notification.last_received(), kLastReceived);
+  EXPECT_EQ(loss_notification.decodability_flag(), kDecodabilityFlag);
+}
+
+}  // namespace webrtc
diff --git a/modules/rtp_rtcp/source/rtcp_packet/pli.cc b/modules/rtp_rtcp/source/rtcp_packet/pli.cc
index 274eb6b..5b41aa5 100644
--- a/modules/rtp_rtcp/source/rtcp_packet/pli.cc
+++ b/modules/rtp_rtcp/source/rtcp_packet/pli.cc
@@ -33,6 +33,12 @@
 //  :            Feedback Control Information (FCI)                 :
 //  :                                                               :
 
+Pli::Pli() = default;
+
+Pli::Pli(const Pli& pli) = default;
+
+Pli::~Pli() = default;
+
 //
 // Picture loss indication (PLI) (RFC 4585).
 // FCI: no feedback control information.
diff --git a/modules/rtp_rtcp/source/rtcp_packet/pli.h b/modules/rtp_rtcp/source/rtcp_packet/pli.h
index fc3c20a..b9b9c45 100644
--- a/modules/rtp_rtcp/source/rtcp_packet/pli.h
+++ b/modules/rtp_rtcp/source/rtcp_packet/pli.h
@@ -20,8 +20,9 @@
  public:
   static constexpr uint8_t kFeedbackMessageType = 1;
 
-  Pli() {}
-  ~Pli() override {}
+  Pli();
+  Pli(const Pli& pli);
+  ~Pli() override;
 
   bool Parse(const CommonHeader& packet);
 
diff --git a/modules/rtp_rtcp/source/rtcp_packet/psfb.cc b/modules/rtp_rtcp/source/rtcp_packet/psfb.cc
index 074413a..bd2e7ce 100644
--- a/modules/rtp_rtcp/source/rtcp_packet/psfb.cc
+++ b/modules/rtp_rtcp/source/rtcp_packet/psfb.cc
@@ -15,6 +15,7 @@
 namespace webrtc {
 namespace rtcp {
 constexpr uint8_t Psfb::kPacketType;
+constexpr uint8_t Psfb::kAfbMessageType;
 constexpr size_t Psfb::kCommonFeedbackLength;
 // RFC 4585: Feedback format.
 //
diff --git a/modules/rtp_rtcp/source/rtcp_packet/psfb.h b/modules/rtp_rtcp/source/rtcp_packet/psfb.h
index 46ee291..dd870e3 100644
--- a/modules/rtp_rtcp/source/rtcp_packet/psfb.h
+++ b/modules/rtp_rtcp/source/rtcp_packet/psfb.h
@@ -25,6 +25,7 @@
 class Psfb : public RtcpPacket {
  public:
   static constexpr uint8_t kPacketType = 206;
+  static constexpr uint8_t kAfbMessageType = 15;
 
   Psfb() : sender_ssrc_(0), media_ssrc_(0) {}
   ~Psfb() override {}
diff --git a/modules/rtp_rtcp/source/rtcp_packet/remb.cc b/modules/rtp_rtcp/source/rtcp_packet/remb.cc
index 3ed1fbd..c4572d0 100644
--- a/modules/rtp_rtcp/source/rtcp_packet/remb.cc
+++ b/modules/rtp_rtcp/source/rtcp_packet/remb.cc
@@ -20,6 +20,7 @@
 
 namespace webrtc {
 namespace rtcp {
+// TODO(bugs.webrtc.org/10353): Remove once dependencies are updated.
 constexpr uint8_t Remb::kFeedbackMessageType;
 // Receiver Estimated Max Bitrate (REMB) (draft-alvestrand-rmcat-remb).
 //
@@ -48,7 +49,7 @@
 
 bool Remb::Parse(const CommonHeader& packet) {
   RTC_DCHECK(packet.type() == kPacketType);
-  RTC_DCHECK_EQ(packet.fmt(), kFeedbackMessageType);
+  RTC_DCHECK_EQ(packet.fmt(), Psfb::kAfbMessageType);
 
   if (packet.payload_size_bytes() < 16) {
     RTC_LOG(LS_WARNING) << "Payload length " << packet.payload_size_bytes()
@@ -57,7 +58,6 @@
   }
   const uint8_t* const payload = packet.payload();
   if (kUniqueIdentifier != ByteReader<uint32_t>::ReadBigEndian(&payload[8])) {
-    RTC_LOG(LS_WARNING) << "REMB identifier not found, not a REMB packet.";
     return false;
   }
   uint8_t number_of_ssrcs = payload[12];
@@ -113,7 +113,7 @@
       return false;
   }
   size_t index_end = *index + BlockLength();
-  CreateHeader(kFeedbackMessageType, kPacketType, HeaderLength(), packet,
+  CreateHeader(Psfb::kAfbMessageType, kPacketType, HeaderLength(), packet,
                index);
   RTC_DCHECK_EQ(0, Psfb::media_ssrc());
   CreateCommonFeedback(packet + *index);
diff --git a/modules/rtp_rtcp/source/rtcp_packet/remb.h b/modules/rtp_rtcp/source/rtcp_packet/remb.h
index 6570e59..bc19657 100644
--- a/modules/rtp_rtcp/source/rtcp_packet/remb.h
+++ b/modules/rtp_rtcp/source/rtcp_packet/remb.h
@@ -22,7 +22,7 @@
 // Receiver Estimated Max Bitrate (REMB) (draft-alvestrand-rmcat-remb).
 class Remb : public Psfb {
  public:
-  static constexpr uint8_t kFeedbackMessageType = 15;
+  static constexpr uint8_t kFeedbackMessageType = Psfb::kAfbMessageType;
   static constexpr size_t kMaxNumberOfSsrcs = 0xff;
 
   Remb();
diff --git a/modules/rtp_rtcp/source/rtcp_packet/transport_feedback.cc b/modules/rtp_rtcp/source/rtcp_packet/transport_feedback.cc
index 2816559..ee8b93a 100644
--- a/modules/rtp_rtcp/source/rtcp_packet/transport_feedback.cc
+++ b/modules/rtp_rtcp/source/rtcp_packet/transport_feedback.cc
@@ -262,10 +262,14 @@
 }
 
 TransportFeedback::TransportFeedback()
+    : TransportFeedback(/*include_timestamps=*/true) {}
+
+TransportFeedback::TransportFeedback(bool include_timestamps)
     : base_seq_no_(0),
       num_seq_no_(0),
       base_time_ticks_(0),
       feedback_seq_(0),
+      include_timestamps_(include_timestamps),
       last_timestamp_us_(0),
       size_bytes_(kTransportFeedbackHeaderSizeBytes) {}
 
@@ -276,6 +280,7 @@
       num_seq_no_(other.num_seq_no_),
       base_time_ticks_(other.base_time_ticks_),
       feedback_seq_(other.feedback_seq_),
+      include_timestamps_(other.include_timestamps_),
       last_timestamp_us_(other.last_timestamp_us_),
       packets_(std::move(other.packets_)),
       encoded_chunks_(std::move(other.encoded_chunks_)),
@@ -301,19 +306,25 @@
 
 bool TransportFeedback::AddReceivedPacket(uint16_t sequence_number,
                                           int64_t timestamp_us) {
-  // Convert to ticks and round.
-  int64_t delta_full = (timestamp_us - last_timestamp_us_) % kTimeWrapPeriodUs;
-  if (delta_full > kTimeWrapPeriodUs / 2)
-    delta_full -= kTimeWrapPeriodUs;
-  delta_full +=
-      delta_full < 0 ? -(kDeltaScaleFactor / 2) : kDeltaScaleFactor / 2;
-  delta_full /= kDeltaScaleFactor;
+  // Set delta to zero if timestamps are not included, this will simplify the
+  // encoding process.
+  int16_t delta = 0;
+  if (include_timestamps_) {
+    // Convert to ticks and round.
+    int64_t delta_full =
+        (timestamp_us - last_timestamp_us_) % kTimeWrapPeriodUs;
+    if (delta_full > kTimeWrapPeriodUs / 2)
+      delta_full -= kTimeWrapPeriodUs;
+    delta_full +=
+        delta_full < 0 ? -(kDeltaScaleFactor / 2) : kDeltaScaleFactor / 2;
+    delta_full /= kDeltaScaleFactor;
 
-  int16_t delta = static_cast<int16_t>(delta_full);
-  // If larger than 16bit signed, we can't represent it - need new fb packet.
-  if (delta != delta_full) {
-    RTC_LOG(LS_WARNING) << "Delta value too large ( >= 2^16 ticks )";
-    return false;
+    delta = static_cast<int16_t>(delta_full);
+    // If larger than 16bit signed, we can't represent it - need new fb packet.
+    if (delta != delta_full) {
+      RTC_LOG(LS_WARNING) << "Delta value too large ( >= 2^16 ticks )";
+      return false;
+    }
   }
 
   uint16_t next_seq_no = base_seq_no_ + num_seq_no_;
@@ -332,7 +343,9 @@
 
   packets_.emplace_back(sequence_number, delta);
   last_timestamp_us_ += delta * kDeltaScaleFactor;
-  size_bytes_ += delta_size;
+  if (include_timestamps_) {
+    size_bytes_ += delta_size;
+  }
   return true;
 }
 
@@ -400,38 +413,57 @@
   num_seq_no_ = status_count;
 
   uint16_t seq_no = base_seq_no_;
+  size_t recv_delta_size = 0;
   for (size_t delta_size : delta_sizes) {
-    if (index + delta_size > end_index) {
-      RTC_LOG(LS_WARNING) << "Buffer overflow while parsing packet.";
-      Clear();
-      return false;
-    }
-    switch (delta_size) {
-      case 0:
-        break;
-      case 1: {
-        int16_t delta = payload[index];
-        packets_.emplace_back(seq_no, delta);
-        last_timestamp_us_ += delta * kDeltaScaleFactor;
-        index += delta_size;
-        break;
-      }
-      case 2: {
-        int16_t delta = ByteReader<int16_t>::ReadBigEndian(&payload[index]);
-        packets_.emplace_back(seq_no, delta);
-        last_timestamp_us_ += delta * kDeltaScaleFactor;
-        index += delta_size;
-        break;
-      }
-      case 3:
+    recv_delta_size += delta_size;
+  }
+
+  // Determine if timestamps, that is, recv_delta are included in the packet.
+  if (end_index >= index + recv_delta_size) {
+    for (size_t delta_size : delta_sizes) {
+      if (index + delta_size > end_index) {
+        RTC_LOG(LS_WARNING) << "Buffer overflow while parsing packet.";
         Clear();
-        RTC_LOG(LS_WARNING) << "Invalid delta_size for seq_no " << seq_no;
         return false;
-      default:
-        RTC_NOTREACHED();
-        break;
+      }
+      switch (delta_size) {
+        case 0:
+          break;
+        case 1: {
+          int16_t delta = payload[index];
+          packets_.emplace_back(seq_no, delta);
+          last_timestamp_us_ += delta * kDeltaScaleFactor;
+          index += delta_size;
+          break;
+        }
+        case 2: {
+          int16_t delta = ByteReader<int16_t>::ReadBigEndian(&payload[index]);
+          packets_.emplace_back(seq_no, delta);
+          last_timestamp_us_ += delta * kDeltaScaleFactor;
+          index += delta_size;
+          break;
+        }
+        case 3:
+          Clear();
+          RTC_LOG(LS_WARNING) << "Invalid delta_size for seq_no " << seq_no;
+
+          return false;
+        default:
+          RTC_NOTREACHED();
+          break;
+      }
+      ++seq_no;
     }
-    ++seq_no;
+  } else {
+    // The packet does not contain receive deltas.
+    include_timestamps_ = false;
+    for (size_t delta_size : delta_sizes) {
+      // Use delta sizes to detect if packet was received.
+      if (delta_size > 0) {
+        packets_.emplace_back(seq_no, 0);
+      }
+      ++seq_no;
+    }
   }
   size_bytes_ = RtcpPacket::kHeaderLength + index;
   RTC_DCHECK_LE(index, end_index);
@@ -495,7 +527,9 @@
       timestamp_us += packet_it->delta_us();
       ++packet_it;
     }
-    packet_size += delta_size;
+    if (include_timestamps_) {
+      packet_size += delta_size;
+    }
     ++seq_no;
   }
   if (packet_it != packets_.end()) {
@@ -521,6 +555,10 @@
   return (size_bytes_ + 3) & (~static_cast<size_t>(3));
 }
 
+size_t TransportFeedback::PaddingLength() const {
+  return BlockLength() - size_bytes_;
+}
+
 // Serialize packet.
 bool TransportFeedback::Create(uint8_t* packet,
                                size_t* position,
@@ -534,9 +572,10 @@
       return false;
   }
   const size_t position_end = *position + BlockLength();
-
-  CreateHeader(kFeedbackMessageType, kPacketType, HeaderLength(), packet,
-               position);
+  const size_t padding_length = PaddingLength();
+  bool has_padding = padding_length > 0;
+  CreateHeader(kFeedbackMessageType, kPacketType, HeaderLength(), has_padding,
+               packet, position);
   CreateCommonFeedback(packet + *position);
   *position += kCommonFeedbackLength;
 
@@ -561,19 +600,24 @@
     *position += 2;
   }
 
-  for (const auto& received_packet : packets_) {
-    int16_t delta = received_packet.delta_ticks();
-    if (delta >= 0 && delta <= 0xFF) {
-      packet[(*position)++] = delta;
-    } else {
-      ByteWriter<int16_t>::WriteBigEndian(&packet[*position], delta);
-      *position += 2;
+  if (include_timestamps_) {
+    for (const auto& received_packet : packets_) {
+      int16_t delta = received_packet.delta_ticks();
+      if (delta >= 0 && delta <= 0xFF) {
+        packet[(*position)++] = delta;
+      } else {
+        ByteWriter<int16_t>::WriteBigEndian(&packet[*position], delta);
+        *position += 2;
+      }
     }
   }
 
-  while ((*position % 4) != 0)
-    packet[(*position)++] = 0;
-
+  if (padding_length > 0) {
+    for (size_t i = 0; i < padding_length - 1; ++i) {
+      packet[(*position)++] = 0;
+    }
+    packet[(*position)++] = padding_length;
+  }
   RTC_DCHECK_EQ(*position, position_end);
   return true;
 }
diff --git a/modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h b/modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h
index fbdc38e..174ef6b 100644
--- a/modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h
+++ b/modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h
@@ -45,6 +45,10 @@
   static constexpr size_t kMaxReportedPackets = 0xffff;
 
   TransportFeedback();
+  explicit TransportFeedback(
+      bool include_timestamps);  // If |include_timestamps| is set to false, the
+                                 // created packet will not contain the receive
+                                 // delta block.
   TransportFeedback(const TransportFeedback&);
   TransportFeedback(TransportFeedback&&);
 
@@ -65,6 +69,9 @@
   // Get the reference time in microseconds, including any precision loss.
   int64_t GetBaseTimeUs() const;
 
+  // Does the feedback packet contain timestamp information?
+  bool IncludeTimestamps() const { return include_timestamps_; }
+
   bool Parse(const CommonHeader& packet);
   static std::unique_ptr<TransportFeedback> ParseFrom(const uint8_t* buffer,
                                                       size_t length);
@@ -73,6 +80,7 @@
   bool IsConsistent() const;
 
   size_t BlockLength() const override;
+  size_t PaddingLength() const;
 
   bool Create(uint8_t* packet,
               size_t* position,
@@ -140,6 +148,7 @@
   uint16_t num_seq_no_;
   int32_t base_time_ticks_;
   uint8_t feedback_seq_;
+  bool include_timestamps_;
 
   int64_t last_timestamp_us_;
   std::vector<ReceivedPacket> packets_;
diff --git a/modules/rtp_rtcp/source/rtcp_packet/transport_feedback_unittest.cc b/modules/rtp_rtcp/source/rtcp_packet/transport_feedback_unittest.cc
index 0496525..0bb2d47 100644
--- a/modules/rtp_rtcp/source/rtcp_packet/transport_feedback_unittest.cc
+++ b/modules/rtp_rtcp/source/rtcp_packet/transport_feedback_unittest.cc
@@ -33,9 +33,11 @@
 
 class FeedbackTester {
  public:
-  FeedbackTester()
+  FeedbackTester() : FeedbackTester(true) {}
+  explicit FeedbackTester(bool include_timestamps)
       : expected_size_(kAnySize),
-        default_delta_(TransportFeedback::kDeltaScaleFactor * 4) {}
+        default_delta_(TransportFeedback::kDeltaScaleFactor * 4),
+        include_timestamps_(include_timestamps) {}
 
   void WithExpectedSize(size_t expected_size) {
     expected_size_ = expected_size;
@@ -46,16 +48,16 @@
   void WithInput(const uint16_t received_seq[],
                  const int64_t received_ts[],
                  uint16_t length) {
-    std::unique_ptr<int64_t[]> temp_deltas;
+    std::unique_ptr<int64_t[]> temp_timestamps;
     if (received_ts == nullptr) {
-      temp_deltas.reset(new int64_t[length]);
-      GenerateDeltas(received_seq, length, temp_deltas.get());
-      received_ts = temp_deltas.get();
+      temp_timestamps.reset(new int64_t[length]);
+      GenerateReceiveTimestamps(received_seq, length, temp_timestamps.get());
+      received_ts = temp_timestamps.get();
     }
 
     expected_seq_.clear();
     expected_deltas_.clear();
-    feedback_.reset(new TransportFeedback());
+    feedback_.reset(new TransportFeedback(include_timestamps_));
     feedback_->SetBase(received_seq[0], received_ts[0]);
     ASSERT_TRUE(feedback_->IsConsistent());
 
@@ -81,8 +83,9 @@
     VerifyInternal();
     feedback_ =
         TransportFeedback::ParseFrom(serialized_.data(), serialized_.size());
+    ASSERT_NE(nullptr, feedback_);
     ASSERT_TRUE(feedback_->IsConsistent());
-    ASSERT_NE(nullptr, feedback_.get());
+    EXPECT_EQ(include_timestamps_, feedback_->IncludeTimestamps());
     VerifyInternal();
   }
 
@@ -104,12 +107,14 @@
       actual_deltas_us.push_back(packet.delta_us());
     }
     EXPECT_THAT(actual_seq_nos, ElementsAreArray(expected_seq_));
-    EXPECT_THAT(actual_deltas_us, ElementsAreArray(expected_deltas_));
+    if (include_timestamps_) {
+      EXPECT_THAT(actual_deltas_us, ElementsAreArray(expected_deltas_));
+    }
   }
 
-  void GenerateDeltas(const uint16_t seq[],
-                      const size_t length,
-                      int64_t* deltas) {
+  void GenerateReceiveTimestamps(const uint16_t seq[],
+                                 const size_t length,
+                                 int64_t* timestamps) {
     uint16_t last_seq = seq[0];
     int64_t offset = 0;
 
@@ -118,7 +123,7 @@
         offset += 0x10000 * default_delta_;
       last_seq = seq[i];
 
-      deltas[i] = offset + (last_seq * default_delta_);
+      timestamps[i] = offset + (last_seq * default_delta_);
     }
   }
 
@@ -128,9 +133,18 @@
   int64_t default_delta_;
   std::unique_ptr<TransportFeedback> feedback_;
   rtc::Buffer serialized_;
+  bool include_timestamps_;
 };
 
-TEST(RtcpPacketTest, TransportFeedback_OneBitVector) {
+// The following tests use FeedbackTester that simulates received packets as
+// specified by the parameters |received_seq[]| and |received_ts[]| (optional).
+// The following is verified in these tests:
+// - Expected size of serialized packet.
+// - Expected sequence numbers and receive deltas.
+// - Sequence numbers and receive deltas are persistent after serialization
+//   followed by parsing.
+// - The internal state of a feedback packet is consistent.
+TEST(RtcpPacketTest, TransportFeedbackOneBitVector) {
   const uint16_t kReceived[] = {1, 2, 7, 8, 9, 10, 13};
   const size_t kLength = sizeof(kReceived) / sizeof(uint16_t);
   const size_t kExpectedSizeBytes =
@@ -142,7 +156,18 @@
   test.VerifyPacket();
 }
 
-TEST(RtcpPacketTest, TransportFeedback_FullOneBitVector) {
+TEST(RtcpPacketTest, TransportFeedbackOneBitVectorNoRecvDelta) {
+  const uint16_t kReceived[] = {1, 2, 7, 8, 9, 10, 13};
+  const size_t kLength = sizeof(kReceived) / sizeof(uint16_t);
+  const size_t kExpectedSizeBytes = kHeaderSize + kStatusChunkSize;
+
+  FeedbackTester test(/*include_timestamps=*/false);
+  test.WithExpectedSize(kExpectedSizeBytes);
+  test.WithInput(kReceived, nullptr, kLength);
+  test.VerifyPacket();
+}
+
+TEST(RtcpPacketTest, TransportFeedbackFullOneBitVector) {
   const uint16_t kReceived[] = {1, 2, 7, 8, 9, 10, 13, 14};
   const size_t kLength = sizeof(kReceived) / sizeof(uint16_t);
   const size_t kExpectedSizeBytes =
@@ -154,7 +179,7 @@
   test.VerifyPacket();
 }
 
-TEST(RtcpPacketTest, TransportFeedback_OneBitVector_WrapReceived) {
+TEST(RtcpPacketTest, TransportFeedbackOneBitVectorWrapReceived) {
   const uint16_t kMax = 0xFFFF;
   const uint16_t kReceived[] = {kMax - 2, kMax - 1, kMax, 0, 1, 2};
   const size_t kLength = sizeof(kReceived) / sizeof(uint16_t);
@@ -167,7 +192,7 @@
   test.VerifyPacket();
 }
 
-TEST(RtcpPacketTest, TransportFeedback_OneBitVector_WrapMissing) {
+TEST(RtcpPacketTest, TransportFeedbackOneBitVectorWrapMissing) {
   const uint16_t kMax = 0xFFFF;
   const uint16_t kReceived[] = {kMax - 2, kMax - 1, 1, 2};
   const size_t kLength = sizeof(kReceived) / sizeof(uint16_t);
@@ -180,7 +205,7 @@
   test.VerifyPacket();
 }
 
-TEST(RtcpPacketTest, TransportFeedback_TwoBitVector) {
+TEST(RtcpPacketTest, TransportFeedbackTwoBitVector) {
   const uint16_t kReceived[] = {1, 2, 6, 7};
   const size_t kLength = sizeof(kReceived) / sizeof(uint16_t);
   const size_t kExpectedSizeBytes =
@@ -193,7 +218,7 @@
   test.VerifyPacket();
 }
 
-TEST(RtcpPacketTest, TransportFeedback_TwoBitVectorFull) {
+TEST(RtcpPacketTest, TransportFeedbackTwoBitVectorFull) {
   const uint16_t kReceived[] = {1, 2, 6, 7, 8};
   const size_t kLength = sizeof(kReceived) / sizeof(uint16_t);
   const size_t kExpectedSizeBytes =
@@ -206,7 +231,7 @@
   test.VerifyPacket();
 }
 
-TEST(RtcpPacketTest, TransportFeedback_LargeAndNegativeDeltas) {
+TEST(RtcpPacketTest, TransportFeedbackLargeAndNegativeDeltas) {
   const uint16_t kReceived[] = {1, 2, 6, 7, 8};
   const int64_t kReceiveTimes[] = {
       2000, 1000, 4000, 3000,
@@ -221,7 +246,7 @@
   test.VerifyPacket();
 }
 
-TEST(RtcpPacketTest, TransportFeedback_MaxRle) {
+TEST(RtcpPacketTest, TransportFeedbackMaxRle) {
   // Expected chunks created:
   // * 1-bit vector chunk (1xreceived + 13xdropped)
   // * RLE chunk of max length for dropped symbol
@@ -240,7 +265,7 @@
   test.VerifyPacket();
 }
 
-TEST(RtcpPacketTest, TransportFeedback_MinRle) {
+TEST(RtcpPacketTest, TransportFeedbackMinRle) {
   // Expected chunks created:
   // * 1-bit vector chunk (1xreceived + 13xdropped)
   // * RLE chunk of length 15 for dropped symbol
@@ -258,7 +283,7 @@
   test.VerifyPacket();
 }
 
-TEST(RtcpPacketTest, TransportFeedback_OneToTwoBitVector) {
+TEST(RtcpPacketTest, TransportFeedbackOneToTwoBitVector) {
   const size_t kTwoBitVectorCapacity = 7;
   const uint16_t kReceived[] = {0, kTwoBitVectorCapacity - 1};
   const int64_t kReceiveTimes[] = {
@@ -273,7 +298,7 @@
   test.VerifyPacket();
 }
 
-TEST(RtcpPacketTest, TransportFeedback_OneToTwoBitVectorSimpleSplit) {
+TEST(RtcpPacketTest, TransportFeedbackOneToTwoBitVectorSimpleSplit) {
   const size_t kTwoBitVectorCapacity = 7;
   const uint16_t kReceived[] = {0, kTwoBitVectorCapacity};
   const int64_t kReceiveTimes[] = {
@@ -288,7 +313,7 @@
   test.VerifyPacket();
 }
 
-TEST(RtcpPacketTest, TransportFeedback_OneToTwoBitVectorSplit) {
+TEST(RtcpPacketTest, TransportFeedbackOneToTwoBitVectorSplit) {
   // With received small delta = S, received large delta = L, use input
   // SSSSSSSSLSSSSSSSSSSSS. This will cause a 1:2 split at the L.
   // After split there will be two symbols in symbol_vec: SL.
@@ -316,7 +341,7 @@
   test.VerifyPacket();
 }
 
-TEST(RtcpPacketTest, TransportFeedback_Aliasing) {
+TEST(RtcpPacketTest, TransportFeedbackAliasing) {
   TransportFeedback feedback;
   feedback.SetBase(0, 0);
 
@@ -340,7 +365,7 @@
   }
 }
 
-TEST(RtcpPacketTest, TransportFeedback_Limits) {
+TEST(RtcpPacketTest, TransportFeedbackLimits) {
   // Sequence number wrap above 0x8000.
   std::unique_ptr<TransportFeedback> packet(new TransportFeedback());
   packet->SetBase(0, 0);
@@ -404,10 +429,12 @@
   // add back test for max size in bytes.
 }
 
-TEST(RtcpPacketTest, TransportFeedback_Padding) {
+TEST(RtcpPacketTest, TransportFeedbackPadding) {
   const size_t kExpectedSizeBytes =
       kHeaderSize + kStatusChunkSize + kSmallDeltaSize;
   const size_t kExpectedSizeWords = (kExpectedSizeBytes + 3) / 4;
+  const size_t kExpectedPaddingSizeBytes =
+      4 * kExpectedSizeWords - kExpectedSizeBytes;
 
   TransportFeedback feedback;
   feedback.SetBase(0, 0);
@@ -416,8 +443,10 @@
   rtc::Buffer packet = feedback.Build();
   EXPECT_EQ(kExpectedSizeWords * 4, packet.size());
   ASSERT_GT(kExpectedSizeWords * 4, kExpectedSizeBytes);
-  for (size_t i = kExpectedSizeBytes; i < kExpectedSizeWords * 4; ++i)
-    EXPECT_EQ(0u, packet.data()[i]);
+  for (size_t i = kExpectedSizeBytes; i < (kExpectedSizeWords * 4 - 1); ++i)
+    EXPECT_EQ(0u, packet[i]);
+
+  EXPECT_EQ(kExpectedPaddingSizeBytes, packet[kExpectedSizeWords * 4 - 1]);
 
   // Modify packet by adding 4 bytes of padding at the end. Not currently used
   // when we're sending, but need to be able to handle it when receiving.
@@ -428,7 +457,8 @@
   uint8_t mod_buffer[kExpectedSizeWithPadding];
   memcpy(mod_buffer, packet.data(), kExpectedSizeWords * 4);
   memset(&mod_buffer[kExpectedSizeWords * 4], 0, kPaddingBytes - 1);
-  mod_buffer[kExpectedSizeWithPadding - 1] = kPaddingBytes;
+  mod_buffer[kExpectedSizeWithPadding - 1] =
+      kPaddingBytes + kExpectedPaddingSizeBytes;
   const uint8_t padding_flag = 1 << 5;
   mod_buffer[0] |= padding_flag;
   ByteWriter<uint16_t>::WriteBigEndian(
@@ -437,11 +467,46 @@
 
   std::unique_ptr<TransportFeedback> parsed_packet(
       TransportFeedback::ParseFrom(mod_buffer, kExpectedSizeWithPadding));
-  ASSERT_TRUE(parsed_packet.get() != nullptr);
+  ASSERT_TRUE(parsed_packet != nullptr);
   EXPECT_EQ(kExpectedSizeWords * 4, packet.size());  // Padding not included.
 }
 
-TEST(RtcpPacketTest, TransportFeedback_CorrectlySplitsVectorChunks) {
+TEST(RtcpPacketTest, TransportFeedbackPaddingBackwardsCompatibility) {
+  const size_t kExpectedSizeBytes =
+      kHeaderSize + kStatusChunkSize + kSmallDeltaSize;
+  const size_t kExpectedSizeWords = (kExpectedSizeBytes + 3) / 4;
+  const size_t kExpectedPaddingSizeBytes =
+      4 * kExpectedSizeWords - kExpectedSizeBytes;
+
+  TransportFeedback feedback;
+  feedback.SetBase(0, 0);
+  EXPECT_TRUE(feedback.AddReceivedPacket(0, 0));
+
+  rtc::Buffer packet = feedback.Build();
+  EXPECT_EQ(kExpectedSizeWords * 4, packet.size());
+  ASSERT_GT(kExpectedSizeWords * 4, kExpectedSizeBytes);
+  for (size_t i = kExpectedSizeBytes; i < (kExpectedSizeWords * 4 - 1); ++i)
+    EXPECT_EQ(0u, packet[i]);
+
+  EXPECT_GT(kExpectedPaddingSizeBytes, 0u);
+  EXPECT_EQ(kExpectedPaddingSizeBytes, packet[kExpectedSizeWords * 4 - 1]);
+
+  // Modify packet by removing padding bit and writing zero at the last padding
+  // byte to verify that we can parse packets from old clients, where zero
+  // padding of up to three bytes was used without the padding bit being set.
+  uint8_t mod_buffer[kExpectedSizeWords * 4];
+  memcpy(mod_buffer, packet.data(), kExpectedSizeWords * 4);
+  mod_buffer[kExpectedSizeWords * 4 - 1] = 0;
+  const uint8_t padding_flag = 1 << 5;
+  mod_buffer[0] &= ~padding_flag;  // Unset padding flag.
+
+  std::unique_ptr<TransportFeedback> parsed_packet(
+      TransportFeedback::ParseFrom(mod_buffer, kExpectedSizeWords * 4));
+  ASSERT_TRUE(parsed_packet != nullptr);
+  EXPECT_EQ(kExpectedSizeWords * 4, packet.size());
+}
+
+TEST(RtcpPacketTest, TransportFeedbackCorrectlySplitsVectorChunks) {
   const int kOneBitVectorCapacity = 14;
   const int64_t kLargeTimeDelta =
       TransportFeedback::kDeltaScaleFactor * (1 << 8);
@@ -460,11 +525,11 @@
     std::unique_ptr<TransportFeedback> deserialized_packet =
         TransportFeedback::ParseFrom(serialized_packet.data(),
                                      serialized_packet.size());
-    EXPECT_TRUE(deserialized_packet.get() != nullptr);
+    EXPECT_TRUE(deserialized_packet != nullptr);
   }
 }
 
-TEST(RtcpPacketTest, TransportFeedback_MoveConstructor) {
+TEST(RtcpPacketTest, TransportFeedbackMoveConstructor) {
   const int kSamples = 100;
   const int64_t kDelta = TransportFeedback::kDeltaScaleFactor;
   const uint16_t kBaseSeqNo = 7531;
diff --git a/modules/rtp_rtcp/source/rtcp_receiver.cc b/modules/rtp_rtcp/source/rtcp_receiver.cc
index 383f785..22d6433 100644
--- a/modules/rtp_rtcp/source/rtcp_receiver.cc
+++ b/modules/rtp_rtcp/source/rtcp_receiver.cc
@@ -18,6 +18,7 @@
 #include <utility>
 #include <vector>
 
+#include "absl/memory/memory.h"
 #include "api/video/video_bitrate_allocation.h"
 #include "api/video/video_bitrate_allocator.h"
 #include "common_types.h"  // NOLINT(build/include)
@@ -26,6 +27,7 @@
 #include "modules/rtp_rtcp/source/rtcp_packet/compound_packet.h"
 #include "modules/rtp_rtcp/source/rtcp_packet/extended_reports.h"
 #include "modules/rtp_rtcp/source/rtcp_packet/fir.h"
+#include "modules/rtp_rtcp/source/rtcp_packet/loss_notification.h"
 #include "modules/rtp_rtcp/source/rtcp_packet/nack.h"
 #include "modules/rtp_rtcp/source/rtcp_packet/pli.h"
 #include "modules/rtp_rtcp/source/rtcp_packet/rapid_resync_request.h"
@@ -73,6 +75,7 @@
   uint32_t receiver_estimated_max_bitrate_bps = 0;
   std::unique_ptr<rtcp::TransportFeedback> transport_feedback;
   absl::optional<VideoBitrateAllocation> target_bitrate_allocation;
+  std::unique_ptr<rtcp::LossNotification> loss_notification;
 };
 
 // Structure for handing TMMBR and TMMBN rtcp messages (RFC5104, section 3.5.4).
@@ -376,7 +379,7 @@
           case rtcp::Fir::kFeedbackMessageType:
             HandleFir(rtcp_block, packet_information);
             break;
-          case rtcp::Remb::kFeedbackMessageType:
+          case rtcp::Psfb::kAfbMessageType:
             HandlePsfbApp(rtcp_block, packet_information);
             break;
           default:
@@ -437,7 +440,7 @@
     packet_information->packet_type_flags |= kRtcpRr;
   }
 
-  for (const rtcp::ReportBlock report_block : sender_report.report_blocks())
+  for (const rtcp::ReportBlock& report_block : sender_report.report_blocks())
     HandleReportBlock(report_block, packet_information, remote_ssrc);
 }
 
@@ -869,13 +872,27 @@
 
 void RTCPReceiver::HandlePsfbApp(const CommonHeader& rtcp_block,
                                  PacketInformation* packet_information) {
-  rtcp::Remb remb;
-  if (remb.Parse(rtcp_block)) {
-    packet_information->packet_type_flags |= kRtcpRemb;
-    packet_information->receiver_estimated_max_bitrate_bps = remb.bitrate_bps();
-    return;
+  {
+    rtcp::Remb remb;
+    if (remb.Parse(rtcp_block)) {
+      packet_information->packet_type_flags |= kRtcpRemb;
+      packet_information->receiver_estimated_max_bitrate_bps =
+          remb.bitrate_bps();
+      return;
+    }
   }
 
+  {
+    auto loss_notification = absl::make_unique<rtcp::LossNotification>();
+    if (loss_notification->Parse(rtcp_block)) {
+      packet_information->packet_type_flags |= kRtcpLossNotification;
+      packet_information->loss_notification = std::move(loss_notification);
+      return;
+    }
+  }
+
+  RTC_LOG(LS_WARNING) << "Unknown PSFB-APP packet.";
+
   ++num_skipped_packets_;
 }
 
@@ -1012,6 +1029,16 @@
       rtcp_bandwidth_observer_->OnReceivedEstimatedBitrate(
           packet_information.receiver_estimated_max_bitrate_bps);
     }
+    if (packet_information.packet_type_flags & kRtcpLossNotification) {
+      rtcp::LossNotification* loss_notification =
+          packet_information.loss_notification.get();
+      RTC_DCHECK(loss_notification);
+      RTC_LOG(LS_VERBOSE) << "Incoming Loss Notification: ("
+                          << loss_notification->last_decoded() << ", "
+                          << loss_notification->last_received() << ", "
+                          << loss_notification->decodability_flag() << ").";
+      // TODO(eladalon): Notify observer.
+    }
     if ((packet_information.packet_type_flags & kRtcpSr) ||
         (packet_information.packet_type_flags & kRtcpRr)) {
       int64_t now_ms = clock_->TimeInMilliseconds();
diff --git a/modules/rtp_rtcp/source/rtcp_receiver.h b/modules/rtp_rtcp/source/rtcp_receiver.h
index be4c70e..fe6ec4c 100644
--- a/modules/rtp_rtcp/source/rtcp_receiver.h
+++ b/modules/rtp_rtcp/source/rtcp_receiver.h
@@ -21,7 +21,7 @@
 #include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
 #include "modules/rtp_rtcp/source/rtcp_nack_stats.h"
 #include "modules/rtp_rtcp/source/rtcp_packet/dlrr.h"
-#include "rtc_base/criticalsection.h"
+#include "rtc_base/critical_section.h"
 #include "rtc_base/thread_annotations.h"
 #include "system_wrappers/include/ntp_time.h"
 
diff --git a/modules/rtp_rtcp/source/rtcp_sender.cc b/modules/rtp_rtcp/source/rtcp_sender.cc
index 2581487..b2fd8b7 100644
--- a/modules/rtp_rtcp/source/rtcp_sender.cc
+++ b/modules/rtp_rtcp/source/rtcp_sender.cc
@@ -24,6 +24,7 @@
 #include "modules/rtp_rtcp/source/rtcp_packet/compound_packet.h"
 #include "modules/rtp_rtcp/source/rtcp_packet/extended_reports.h"
 #include "modules/rtp_rtcp/source/rtcp_packet/fir.h"
+#include "modules/rtp_rtcp/source/rtcp_packet/loss_notification.h"
 #include "modules/rtp_rtcp/source/rtcp_packet/nack.h"
 #include "modules/rtp_rtcp/source/rtcp_packet/pli.h"
 #include "modules/rtp_rtcp/source/rtcp_packet/receiver_report.h"
@@ -37,7 +38,7 @@
 #include "modules/rtp_rtcp/source/time_util.h"
 #include "modules/rtp_rtcp/source/tmmbr_help.h"
 #include "rtc_base/checks.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 #include "rtc_base/logging.h"
 #include "rtc_base/numerics/safe_conversions.h"
 #include "rtc_base/trace_event.h"
@@ -163,6 +164,7 @@
   builders_[kRtcpRemb] = &RTCPSender::BuildREMB;
   builders_[kRtcpBye] = &RTCPSender::BuildBYE;
   builders_[kRtcpApp] = &RTCPSender::BuildAPP;
+  builders_[kRtcpLossNotification] = &RTCPSender::BuildLossNotification;
   builders_[kRtcpTmmbr] = &RTCPSender::BuildTMMBR;
   builders_[kRtcpTmmbn] = &RTCPSender::BuildTMMBN;
   builders_[kRtcpNack] = &RTCPSender::BuildNACK;
@@ -211,6 +213,23 @@
   return 0;
 }
 
+int32_t RTCPSender::SendLossNotification(const FeedbackState& feedback_state,
+                                         uint16_t last_decoded_seq_num,
+                                         uint16_t last_received_seq_num,
+                                         bool decodability_flag) {
+  rtc::CritScope lock(&critical_section_rtcp_sender_);
+
+  loss_notification_state_.last_decoded_seq_num = last_decoded_seq_num;
+  loss_notification_state_.last_received_seq_num = last_received_seq_num;
+  loss_notification_state_.decodability_flag = decodability_flag;
+
+  SetFlag(kRtcpLossNotification, /*is_volatile=*/true);
+
+  // Send immediately.
+  return SendCompoundRTCP(feedback_state,
+                          {RTCPPacketType::kRtcpLossNotification});
+}
+
 void RTCPSender::SetRemb(int64_t bitrate_bps, std::vector<uint32_t> ssrcs) {
   RTC_CHECK_GE(bitrate_bps, 0);
   rtc::CritScope lock(&critical_section_rtcp_sender_);
@@ -583,6 +602,17 @@
   return std::unique_ptr<rtcp::RtcpPacket>(app);
 }
 
+std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildLossNotification(
+    const RtcpContext& ctx) {
+  auto loss_notification = absl::make_unique<rtcp::LossNotification>(
+      loss_notification_state_.last_decoded_seq_num,
+      loss_notification_state_.last_received_seq_num,
+      loss_notification_state_.decodability_flag);
+  loss_notification->SetSenderSsrc(ssrc_);
+  loss_notification->SetMediaSsrc(remote_ssrc_);
+  return std::move(loss_notification);
+}
+
 std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildNACK(
     const RtcpContext& ctx) {
   rtcp::Nack* nack = new rtcp::Nack();
diff --git a/modules/rtp_rtcp/source/rtcp_sender.h b/modules/rtp_rtcp/source/rtcp_sender.h
index 0845397..7a9aeac 100644
--- a/modules/rtp_rtcp/source/rtcp_sender.h
+++ b/modules/rtp_rtcp/source/rtcp_sender.h
@@ -29,8 +29,8 @@
 #include "modules/rtp_rtcp/source/rtcp_packet/dlrr.h"
 #include "modules/rtp_rtcp/source/rtcp_packet/report_block.h"
 #include "modules/rtp_rtcp/source/rtcp_packet/tmmb_item.h"
-#include "rtc_base/constructormagic.h"
-#include "rtc_base/criticalsection.h"
+#include "rtc_base/constructor_magic.h"
+#include "rtc_base/critical_section.h"
 #include "rtc_base/random.h"
 #include "rtc_base/thread_annotations.h"
 
@@ -114,6 +114,11 @@
                            int32_t nackSize = 0,
                            const uint16_t* nackList = 0);
 
+  int32_t SendLossNotification(const FeedbackState& feedback_state,
+                               uint16_t last_decoded_seq_num,
+                               uint16_t last_received_seq_num,
+                               bool decodability_flag);
+
   void SetRemb(int64_t bitrate_bps, std::vector<uint32_t> ssrcs);
 
   void UnsetRemb();
@@ -168,6 +173,9 @@
       RTC_EXCLUSIVE_LOCKS_REQUIRED(critical_section_rtcp_sender_);
   std::unique_ptr<rtcp::RtcpPacket> BuildAPP(const RtcpContext& context)
       RTC_EXCLUSIVE_LOCKS_REQUIRED(critical_section_rtcp_sender_);
+  std::unique_ptr<rtcp::RtcpPacket> BuildLossNotification(
+      const RtcpContext& context)
+      RTC_EXCLUSIVE_LOCKS_REQUIRED(critical_section_rtcp_sender_);
   std::unique_ptr<rtcp::RtcpPacket> BuildExtendedReports(
       const RtcpContext& context)
       RTC_EXCLUSIVE_LOCKS_REQUIRED(critical_section_rtcp_sender_);
@@ -214,6 +222,15 @@
   // Full intra request
   uint8_t sequence_number_fir_ RTC_GUARDED_BY(critical_section_rtcp_sender_);
 
+  // Loss Notification
+  struct LossNotificationState {
+    uint16_t last_decoded_seq_num;
+    uint16_t last_received_seq_num;
+    bool decodability_flag;
+  };
+  LossNotificationState loss_notification_state_
+      RTC_GUARDED_BY(critical_section_rtcp_sender_);
+
   // REMB
   int64_t remb_bitrate_ RTC_GUARDED_BY(critical_section_rtcp_sender_);
   std::vector<uint32_t> remb_ssrcs_
diff --git a/modules/rtp_rtcp/source/rtcp_sender_unittest.cc b/modules/rtp_rtcp/source/rtcp_sender_unittest.cc
index e1a436b..d297f3d 100644
--- a/modules/rtp_rtcp/source/rtcp_sender_unittest.cc
+++ b/modules/rtp_rtcp/source/rtcp_sender_unittest.cc
@@ -89,7 +89,7 @@
     rtcp_sender_->SetRemoteSSRC(kRemoteSsrc);
     rtcp_sender_->SetTimestampOffset(kStartRtpTimestamp);
     rtcp_sender_->SetLastRtpTime(kRtpTimestamp, clock_.TimeInMilliseconds(),
-                                 /*paylpad_type=*/0);
+                                 /*payload_type=*/0);
   }
 
   void InsertIncomingPacket(uint32_t remote_ssrc, uint16_t seq_num) {
@@ -376,6 +376,19 @@
   EXPECT_THAT(parser()->nack()->packet_ids(), ElementsAre(0, 1, 16));
 }
 
+TEST_F(RtcpSenderTest, SendLossNotification) {
+  rtcp_sender_->SetRTCPStatus(RtcpMode::kReducedSize);
+  constexpr uint16_t kLastDecoded = 0x1234;
+  constexpr uint16_t kLastReceived = 0x4321;
+  constexpr bool kDecodabilityFlag = true;
+  const int32_t result = rtcp_sender_->SendLossNotification(
+      feedback_state(), kLastDecoded, kLastReceived, kDecodabilityFlag);
+  EXPECT_EQ(result, 0);
+  EXPECT_EQ(1, parser()->loss_notification()->num_packets());
+  EXPECT_EQ(kSenderSsrc, parser()->loss_notification()->sender_ssrc());
+  EXPECT_EQ(kRemoteSsrc, parser()->loss_notification()->media_ssrc());
+}
+
 TEST_F(RtcpSenderTest, RembNotIncludedBeforeSet) {
   rtcp_sender_->SetRTCPStatus(RtcpMode::kReducedSize);
 
@@ -633,7 +646,7 @@
   rtcp_sender_->SetRemoteSSRC(kRemoteSsrc);
   rtcp_sender_->SetTimestampOffset(kStartRtpTimestamp);
   rtcp_sender_->SetLastRtpTime(kRtpTimestamp, clock_.TimeInMilliseconds(),
-                               /*paylpad_type=*/0);
+                               /*payload_type=*/0);
 
   // Set up REMB info to be included with BYE.
   rtcp_sender_->SetRTCPStatus(RtcpMode::kCompound);
diff --git a/modules/rtp_rtcp/source/rtcp_transceiver.cc b/modules/rtp_rtcp/source/rtcp_transceiver.cc
index 57d2142..cec6da9 100644
--- a/modules/rtp_rtcp/source/rtcp_transceiver.cc
+++ b/modules/rtp_rtcp/source/rtcp_transceiver.cc
@@ -16,7 +16,8 @@
 #include "modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h"
 #include "rtc_base/checks.h"
 #include "rtc_base/event.h"
-#include "rtc_base/timeutils.h"
+#include "rtc_base/task_utils/to_queued_task.h"
+#include "rtc_base/time_utils.h"
 
 namespace webrtc {
 namespace {
@@ -41,8 +42,8 @@
 
 void RtcpTransceiver::Stop(std::function<void()> on_destroyed) {
   RTC_DCHECK(rtcp_transceiver_);
-  task_queue_->PostTask(rtc::NewClosure(
-      Destructor{std::move(rtcp_transceiver_)}, std::move(on_destroyed)));
+  task_queue_->PostTask(ToQueuedTask(Destructor{std::move(rtcp_transceiver_)},
+                                     std::move(on_destroyed)));
   RTC_DCHECK(!rtcp_transceiver_);
 }
 
@@ -65,8 +66,7 @@
   auto remove = [ptr, remote_ssrc, observer] {
     ptr->RemoveMediaReceiverRtcpObserver(remote_ssrc, observer);
   };
-  task_queue_->PostTask(
-      rtc::NewClosure(std::move(remove), std::move(on_removed)));
+  task_queue_->PostTask(ToQueuedTask(std::move(remove), std::move(on_removed)));
 }
 
 void RtcpTransceiver::SetReadyToSend(bool ready) {
diff --git a/modules/rtp_rtcp/source/rtcp_transceiver.h b/modules/rtp_rtcp/source/rtcp_transceiver.h
index 9c96751..16fd5a7 100644
--- a/modules/rtp_rtcp/source/rtcp_transceiver.h
+++ b/modules/rtp_rtcp/source/rtcp_transceiver.h
@@ -18,7 +18,7 @@
 
 #include "modules/rtp_rtcp/source/rtcp_transceiver_config.h"
 #include "modules/rtp_rtcp/source/rtcp_transceiver_impl.h"
-#include "rtc_base/copyonwritebuffer.h"
+#include "rtc_base/copy_on_write_buffer.h"
 #include "rtc_base/task_queue.h"
 
 namespace webrtc {
diff --git a/modules/rtp_rtcp/source/rtcp_transceiver_impl.cc b/modules/rtp_rtcp/source/rtcp_transceiver_impl.cc
index 97c2ac0..5d2cd6e 100644
--- a/modules/rtp_rtcp/source/rtcp_transceiver_impl.cc
+++ b/modules/rtp_rtcp/source/rtcp_transceiver_impl.cc
@@ -29,11 +29,11 @@
 #include "modules/rtp_rtcp/source/rtcp_packet/sdes.h"
 #include "modules/rtp_rtcp/source/rtcp_packet/sender_report.h"
 #include "modules/rtp_rtcp/source/time_util.h"
-#include "rtc_base/cancelable_periodic_task.h"
 #include "rtc_base/checks.h"
 #include "rtc_base/logging.h"
 #include "rtc_base/task_queue.h"
-#include "rtc_base/timeutils.h"
+#include "rtc_base/task_utils/repeating_task.h"
+#include "rtc_base/time_utils.h"
 
 namespace webrtc {
 namespace {
@@ -90,15 +90,18 @@
 RtcpTransceiverImpl::RtcpTransceiverImpl(const RtcpTransceiverConfig& config)
     : config_(config), ready_to_send_(config.initial_ready_to_send) {
   RTC_CHECK(config_.Validate());
-  if (ready_to_send_ && config_.schedule_periodic_compound_packets)
-    SchedulePeriodicCompoundPackets(config_.initial_report_delay_ms);
+  if (ready_to_send_ && config_.schedule_periodic_compound_packets) {
+    config_.task_queue->PostTask([this] {
+      SchedulePeriodicCompoundPackets(config_.initial_report_delay_ms);
+    });
+  }
 }
 
 RtcpTransceiverImpl::~RtcpTransceiverImpl() {
   // If RtcpTransceiverImpl is destroyed off task queue, assume it is destroyed
   // after TaskQueue. In that case there is no need to Cancel periodic task.
   if (config_.task_queue == rtc::TaskQueue::Current()) {
-    periodic_task_handle_.Cancel();
+    periodic_task_handle_.Stop();
   }
 }
 
@@ -126,7 +129,7 @@
 void RtcpTransceiverImpl::SetReadyToSend(bool ready) {
   if (config_.schedule_periodic_compound_packets) {
     if (ready_to_send_ && !ready)
-      periodic_task_handle_.Cancel();
+      periodic_task_handle_.Stop();
 
     if (!ready_to_send_ && ready)  // Restart periodic sending.
       SchedulePeriodicCompoundPackets(config_.report_period_ms / 2);
@@ -323,24 +326,19 @@
 void RtcpTransceiverImpl::ReschedulePeriodicCompoundPackets() {
   if (!config_.schedule_periodic_compound_packets)
     return;
-  periodic_task_handle_.Cancel();
+  periodic_task_handle_.Stop();
   RTC_DCHECK(ready_to_send_);
   SchedulePeriodicCompoundPackets(config_.report_period_ms);
 }
 
 void RtcpTransceiverImpl::SchedulePeriodicCompoundPackets(int64_t delay_ms) {
-  auto task = rtc::CreateCancelablePeriodicTask([this] {
-    RTC_DCHECK(config_.schedule_periodic_compound_packets);
-    RTC_DCHECK(ready_to_send_);
-    SendPeriodicCompoundPacket();
-    return config_.report_period_ms;
-  });
-  periodic_task_handle_ = task->GetCancellationHandle();
-
-  if (delay_ms > 0)
-    config_.task_queue->PostDelayedTask(std::move(task), delay_ms);
-  else
-    config_.task_queue->PostTask(std::move(task));
+  periodic_task_handle_ = RepeatingTaskHandle::DelayedStart(
+      config_.task_queue, TimeDelta::ms(delay_ms), [this] {
+        RTC_DCHECK(config_.schedule_periodic_compound_packets);
+        RTC_DCHECK(ready_to_send_);
+        SendPeriodicCompoundPacket();
+        return TimeDelta::ms(config_.report_period_ms);
+      });
 }
 
 void RtcpTransceiverImpl::CreateCompoundPacket(PacketSender* sender) {
diff --git a/modules/rtp_rtcp/source/rtcp_transceiver_impl.h b/modules/rtp_rtcp/source/rtcp_transceiver_impl.h
index eb9086f..b08dd56 100644
--- a/modules/rtp_rtcp/source/rtcp_transceiver_impl.h
+++ b/modules/rtp_rtcp/source/rtcp_transceiver_impl.h
@@ -24,7 +24,7 @@
 #include "modules/rtp_rtcp/source/rtcp_packet/report_block.h"
 #include "modules/rtp_rtcp/source/rtcp_packet/target_bitrate.h"
 #include "modules/rtp_rtcp/source/rtcp_transceiver_config.h"
-#include "rtc_base/cancelable_task_handle.h"
+#include "rtc_base/task_utils/repeating_task.h"
 #include "system_wrappers/include/ntp_time.h"
 
 namespace webrtc {
@@ -96,7 +96,7 @@
   // TODO(danilchap): Remove entries from remote_senders_ that are no longer
   // needed.
   std::map<uint32_t, RemoteSenderState> remote_senders_;
-  rtc::CancelableTaskHandle periodic_task_handle_;
+  RepeatingTaskHandle periodic_task_handle_;
 };
 
 }  // namespace webrtc
diff --git a/modules/rtp_rtcp/source/rtcp_transceiver_impl_unittest.cc b/modules/rtp_rtcp/source/rtcp_transceiver_impl_unittest.cc
index e86d67f..fec2bb7 100644
--- a/modules/rtp_rtcp/source/rtcp_transceiver_impl_unittest.cc
+++ b/modules/rtp_rtcp/source/rtcp_transceiver_impl_unittest.cc
@@ -21,7 +21,7 @@
 #include "modules/rtp_rtcp/source/rtcp_packet/compound_packet.h"
 #include "modules/rtp_rtcp/source/time_util.h"
 #include "rtc_base/event.h"
-#include "rtc_base/fakeclock.h"
+#include "rtc_base/fake_clock.h"
 #include "rtc_base/task_queue.h"
 #include "test/gmock.h"
 #include "test/gtest.h"
@@ -385,7 +385,7 @@
   config.schedule_periodic_compound_packets = false;
   RtcpTransceiverImpl rtcp_transceiver(config);
 
-  rtcp_transceiver.SetRemb(/*bitrate_bps=*/10000, /*ssrc=*/{54321, 64321});
+  rtcp_transceiver.SetRemb(/*bitrate_bps=*/10000, /*ssrcs=*/{54321, 64321});
   rtcp_transceiver.SendCompoundPacket();
 
   EXPECT_EQ(rtcp_parser.remb()->num_packets(), 1);
@@ -404,14 +404,14 @@
   config.schedule_periodic_compound_packets = false;
   RtcpTransceiverImpl rtcp_transceiver(config);
 
-  rtcp_transceiver.SetRemb(/*bitrate_bps=*/10000, /*ssrc=*/{54321, 64321});
+  rtcp_transceiver.SetRemb(/*bitrate_bps=*/10000, /*ssrcs=*/{54321, 64321});
   rtcp_transceiver.SendCompoundPacket();
 
   EXPECT_EQ(rtcp_parser.remb()->num_packets(), 1);
   EXPECT_EQ(rtcp_parser.remb()->bitrate_bps(), 10000u);
   EXPECT_THAT(rtcp_parser.remb()->ssrcs(), ElementsAre(54321, 64321));
 
-  rtcp_transceiver.SetRemb(/*bitrate_bps=*/70000, /*ssrc=*/{67321});
+  rtcp_transceiver.SetRemb(/*bitrate_bps=*/70000, /*ssrcs=*/{67321});
   rtcp_transceiver.SendCompoundPacket();
 
   EXPECT_EQ(rtcp_parser.remb()->num_packets(), 2);
@@ -429,7 +429,7 @@
   config.schedule_periodic_compound_packets = false;
   RtcpTransceiverImpl rtcp_transceiver(config);
 
-  rtcp_transceiver.SetRemb(/*bitrate_bps=*/10000, /*ssrc=*/{54321, 64321});
+  rtcp_transceiver.SetRemb(/*bitrate_bps=*/10000, /*ssrcs=*/{54321, 64321});
   rtcp_transceiver.SendCompoundPacket();
   rtcp_transceiver.SendCompoundPacket();
 
@@ -447,7 +447,7 @@
   config.schedule_periodic_compound_packets = false;
   RtcpTransceiverImpl rtcp_transceiver(config);
 
-  rtcp_transceiver.SetRemb(/*bitrate_bps=*/10000, /*ssrc=*/{54321, 64321});
+  rtcp_transceiver.SetRemb(/*bitrate_bps=*/10000, /*ssrcs=*/{54321, 64321});
   rtcp_transceiver.SendCompoundPacket();
   EXPECT_EQ(transport.num_packets(), 1);
   ASSERT_EQ(rtcp_parser.remb()->num_packets(), 1);
diff --git a/modules/rtp_rtcp/source/rtp_fec_unittest.cc b/modules/rtp_rtcp/source/rtp_fec_unittest.cc
index cbad0ae..d260db4 100644
--- a/modules/rtp_rtcp/source/rtp_fec_unittest.cc
+++ b/modules/rtp_rtcp/source/rtp_fec_unittest.cc
@@ -216,7 +216,7 @@
 
 using FecTypes =
     Types<FlexfecForwardErrorCorrection, UlpfecForwardErrorCorrection>;
-TYPED_TEST_CASE(RtpFecTest, FecTypes);
+TYPED_TEST_SUITE(RtpFecTest, FecTypes);
 
 TYPED_TEST(RtpFecTest, WillProtectMediaPacketsWithLargeSequenceNumberGap) {
   constexpr int kNumImportantPackets = 0;
diff --git a/modules/rtp_rtcp/source/rtp_format_h264.cc b/modules/rtp_rtcp/source/rtp_format_h264.cc
index 7a7bcdf..d10831f 100644
--- a/modules/rtp_rtcp/source/rtp_format_h264.cc
+++ b/modules/rtp_rtcp/source/rtp_format_h264.cc
@@ -43,7 +43,6 @@
 
 static const char* kSpsValidHistogramName = "WebRTC.Video.H264.SpsValid";
 enum SpsValidEvent {
-  kReceivedSpsPocOk = 0,
   kReceivedSpsVuiOk = 1,
   kReceivedSpsRewritten = 2,
   kReceivedSpsParseFailure = 3,
@@ -135,11 +134,6 @@
                                     SpsValidEvent::kSentSpsRewritten,
                                     SpsValidEvent::kSpsRewrittenMax);
           break;
-        case SpsVuiRewriter::ParseResult::kPocOk:
-          RTC_HISTOGRAM_ENUMERATION(kSpsValidHistogramName,
-                                    SpsValidEvent::kSentSpsPocOk,
-                                    SpsValidEvent::kSpsRewrittenMax);
-          break;
         case SpsVuiRewriter::ParseResult::kVuiOk:
           RTC_HISTOGRAM_ENUMERATION(kSpsValidHistogramName,
                                     SpsValidEvent::kSentSpsVuiOk,
@@ -219,10 +213,19 @@
   PayloadSizeLimits limits = limits_;
   // Leave room for the FU-A header.
   limits.max_payload_len -= kFuAHeaderSize;
-  // Ignore single/first/last packet reductions unless it is single/first/last
+  // Update single/first/last packet reductions unless it is single/first/last
   // fragment.
-  if (input_fragments_.size() != 1)
-    limits.single_packet_reduction_len = 0;
+  if (input_fragments_.size() != 1) {
+    // if this fragment is put into a single packet, it might still be the
+    // first or the last packet in the whole sequence of packets.
+    if (fragment_index == input_fragments_.size() - 1) {
+      limits.single_packet_reduction_len = limits_.last_packet_reduction_len;
+    } else if (fragment_index == 0) {
+      limits.single_packet_reduction_len = limits_.first_packet_reduction_len;
+    } else {
+      limits.single_packet_reduction_len = 0;
+    }
+  }
   if (fragment_index != 0)
     limits.first_packet_reduction_len = 0;
   if (fragment_index != input_fragments_.size() - 1)
@@ -550,11 +553,6 @@
                                       SpsValidEvent::kReceivedSpsRewritten,
                                       SpsValidEvent::kSpsRewrittenMax);
             break;
-          case SpsVuiRewriter::ParseResult::kPocOk:
-            RTC_HISTOGRAM_ENUMERATION(kSpsValidHistogramName,
-                                      SpsValidEvent::kReceivedSpsPocOk,
-                                      SpsValidEvent::kSpsRewrittenMax);
-            break;
           case SpsVuiRewriter::ParseResult::kVuiOk:
             RTC_HISTOGRAM_ENUMERATION(kSpsValidHistogramName,
                                       SpsValidEvent::kReceivedSpsVuiOk,
diff --git a/modules/rtp_rtcp/source/rtp_format_h264.h b/modules/rtp_rtcp/source/rtp_format_h264.h
index fbd4fd9..108156f 100644
--- a/modules/rtp_rtcp/source/rtp_format_h264.h
+++ b/modules/rtp_rtcp/source/rtp_format_h264.h
@@ -23,7 +23,7 @@
 #include "modules/rtp_rtcp/source/rtp_packet_to_send.h"
 #include "modules/video_coding/codecs/h264/include/h264_globals.h"
 #include "rtc_base/buffer.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
diff --git a/modules/rtp_rtcp/source/rtp_format_h264_unittest.cc b/modules/rtp_rtcp/source/rtp_format_h264_unittest.cc
index aeab813..7608de3 100644
--- a/modules/rtp_rtcp/source/rtp_format_h264_unittest.cc
+++ b/modules/rtp_rtcp/source/rtp_format_h264_unittest.cc
@@ -202,7 +202,7 @@
   EXPECT_THAT(packets, SizeIs(1));
 }
 
-INSTANTIATE_TEST_CASE_P(
+INSTANTIATE_TEST_SUITE_P(
     PacketMode,
     RtpPacketizerH264ModeTest,
     ::testing::Values(H264PacketizationMode::SingleNalUnit,
@@ -379,6 +379,28 @@
               ElementsAreArray(next_fragment, kStapANaluSize));
 }
 
+TEST(RtpPacketizerH264Test, LastFragmentFitsInSingleButNotLastPacket) {
+  RtpPacketizer::PayloadSizeLimits limits;
+  limits.max_payload_len = 1178;
+  limits.first_packet_reduction_len = 0;
+  limits.last_packet_reduction_len = 20;
+  limits.single_packet_reduction_len = 20;
+  // Actual sizes, which triggered this bug.
+  size_t fragments[] = {20, 8, 18, 1161};
+  RTPFragmentationHeader fragmentation = CreateFragmentation(fragments);
+  rtc::Buffer frame = CreateFrame(fragmentation);
+
+  RtpPacketizerH264 packetizer(
+      frame, limits, H264PacketizationMode::NonInterleaved, fragmentation);
+  std::vector<RtpPacketToSend> packets = FetchAllPackets(&packetizer);
+
+  // Last packet has to be of correct size.
+  // Incorrect implementation might miss this constraint and not split the last
+  // fragment in two packets.
+  EXPECT_LE(static_cast<int>(packets.back().payload_size()),
+            limits.max_payload_len - limits.last_packet_reduction_len);
+}
+
 // Splits frame with payload size |frame_payload_size| without fragmentation,
 // Returns sizes of the payloads excluding fua headers.
 std::vector<int> TestFua(size_t frame_payload_size,
diff --git a/modules/rtp_rtcp/source/rtp_format_video_generic.h b/modules/rtp_rtcp/source/rtp_format_video_generic.h
index 3458d49..982e35a 100644
--- a/modules/rtp_rtcp/source/rtp_format_video_generic.h
+++ b/modules/rtp_rtcp/source/rtp_format_video_generic.h
@@ -16,7 +16,7 @@
 #include "api/array_view.h"
 #include "common_types.h"  // NOLINT(build/include)
 #include "modules/rtp_rtcp/source/rtp_format.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
diff --git a/modules/rtp_rtcp/source/rtp_format_vp8.h b/modules/rtp_rtcp/source/rtp_format_vp8.h
index 444298f..0e0fa52 100644
--- a/modules/rtp_rtcp/source/rtp_format_vp8.h
+++ b/modules/rtp_rtcp/source/rtp_format_vp8.h
@@ -34,7 +34,7 @@
 #include "modules/rtp_rtcp/source/rtp_format.h"
 #include "modules/rtp_rtcp/source/rtp_packet_to_send.h"
 #include "modules/video_coding/codecs/vp8/include/vp8_globals.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
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 07f5f64..03d4e58 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,7 @@
 #include "modules/rtp_rtcp/source/rtp_format_vp8.h"
 #include "modules/video_coding/codecs/vp8/include/vp8_globals.h"
 #include "rtc_base/buffer.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
diff --git a/modules/rtp_rtcp/source/rtp_format_vp9.cc b/modules/rtp_rtcp/source/rtp_format_vp9.cc
index 9cd7514..bbb8e29 100644
--- a/modules/rtp_rtcp/source/rtp_format_vp9.cc
+++ b/modules/rtp_rtcp/source/rtp_format_vp9.cc
@@ -15,7 +15,7 @@
 #include "common_types.h"  // NOLINT(build/include)
 #include "modules/rtp_rtcp/source/rtp_packet_to_send.h"
 #include "modules/video_coding/codecs/interface/common_constants.h"
-#include "rtc_base/bitbuffer.h"
+#include "rtc_base/bit_buffer.h"
 #include "rtc_base/checks.h"
 #include "rtc_base/logging.h"
 
diff --git a/modules/rtp_rtcp/source/rtp_format_vp9.h b/modules/rtp_rtcp/source/rtp_format_vp9.h
index c3b8f17..2918b06 100644
--- a/modules/rtp_rtcp/source/rtp_format_vp9.h
+++ b/modules/rtp_rtcp/source/rtp_format_vp9.h
@@ -29,7 +29,7 @@
 #include "modules/rtp_rtcp/source/rtp_format.h"
 #include "modules/rtp_rtcp/source/rtp_packet_to_send.h"
 #include "modules/video_coding/codecs/vp9/include/vp9_globals.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
diff --git a/modules/rtp_rtcp/source/rtp_generic_frame_descriptor.cc b/modules/rtp_rtcp/source/rtp_generic_frame_descriptor.cc
index c27fb6e..7a8af09 100644
--- a/modules/rtp_rtcp/source/rtp_generic_frame_descriptor.cc
+++ b/modules/rtp_rtcp/source/rtp_generic_frame_descriptor.cc
@@ -99,8 +99,15 @@
 
 void RtpGenericFrameDescriptor::SetByteRepresentation(
     rtc::ArrayView<const uint8_t> byte_representation) {
+  RTC_CHECK(!byte_representation.empty());
   byte_representation_.assign(byte_representation.begin(),
                               byte_representation.end());
+  // Clear end_of_subframe bit.
+  // Because ByteRepresentation is used for frame authentication, bit describing
+  // position of the packet in the frame shouldn't be part of it.
+  // This match RtpVideoSender where descriptor is passed for authentication
+  // before end_of_subframe bit is decided and set, i.e. it is always 0.
+  byte_representation_[0] &= ~0x40;
 }
 
 rtc::ArrayView<const uint8_t>
diff --git a/modules/rtp_rtcp/source/rtp_generic_frame_descriptor.h b/modules/rtp_rtcp/source/rtp_generic_frame_descriptor.h
index 3a6c34d..47a2a74 100644
--- a/modules/rtp_rtcp/source/rtp_generic_frame_descriptor.h
+++ b/modules/rtp_rtcp/source/rtp_generic_frame_descriptor.h
@@ -14,10 +14,13 @@
 #include <stdint.h>
 #include <vector>
 
+#include "absl/types/optional.h"
 #include "api/array_view.h"
 
 namespace webrtc {
 
+class RtpGenericFrameDescriptorExtension;
+
 // Data to put on the wire for FrameDescriptor rtp header extension.
 class RtpGenericFrameDescriptor {
  public:
@@ -34,10 +37,14 @@
   bool LastPacketInSubFrame() const { return end_of_subframe_; }
   void SetLastPacketInSubFrame(bool last) { end_of_subframe_ = last; }
 
-  bool FirstSubFrameInFrame() const { return beginning_of_frame_; }
-  void SetFirstSubFrameInFrame(bool first) { beginning_of_frame_ = first; }
-  bool LastSubFrameInFrame() const { return end_of_frame_; }
-  void SetLastSubFrameInFrame(bool last) { end_of_frame_ = last; }
+  // Denotes whether the frame is discardable. That is, whether skipping it
+  // would have no effect on the decodability of subsequent frames.
+  // An absl::optional is used because version 0 of the extension did not
+  // support this flag. (The optional aspect is relevant only when parsing.)
+  // TODO(bugs.webrtc.org/10243): Make this into a plain bool when v00 of
+  // the extension is deprecated.
+  absl::optional<bool> Discardable() const { return discardable_; }
+  void SetDiscardable(bool discardable) { discardable_ = discardable; }
 
   // Properties below undefined if !FirstPacketInSubFrame()
   // Valid range for temporal layer: [0, 7]
@@ -68,8 +75,8 @@
  private:
   bool beginning_of_subframe_ = false;
   bool end_of_subframe_ = false;
-  bool beginning_of_frame_ = false;
-  bool end_of_frame_ = false;
+
+  absl::optional<bool> discardable_;
 
   uint16_t frame_id_ = 0;
   uint8_t spatial_layers_ = 1;
diff --git a/modules/rtp_rtcp/source/rtp_generic_frame_descriptor_extension.cc b/modules/rtp_rtcp/source/rtp_generic_frame_descriptor_extension.cc
index 7cd120d..a705b5a 100644
--- a/modules/rtp_rtcp/source/rtp_generic_frame_descriptor_extension.cc
+++ b/modules/rtp_rtcp/source/rtp_generic_frame_descriptor_extension.cc
@@ -17,15 +17,21 @@
 
 constexpr uint8_t kFlagBeginOfSubframe = 0x80;
 constexpr uint8_t kFlagEndOfSubframe = 0x40;
-constexpr uint8_t kFlagFirstSubframe = 0x20;
-constexpr uint8_t kFlagLastSubframe = 0x10;
+
+// In version 00, the flags F and L in the first byte correspond to
+// kFlagFirstSubframeV00 and kFlagLastSubframeV00. In practice, they were
+// always set to |true|. In version 01, these flags are deprecated, and we use
+// one of their bits for the discardability flag.
+constexpr uint8_t kFlagFirstSubframeV00 = 0x20;
+constexpr uint8_t kFlagLastSubframeV00 = 0x10;
+constexpr uint8_t kFlagDiscardableV01 = 0x10;
+
 constexpr uint8_t kFlagDependencies = 0x08;
 constexpr uint8_t kMaskTemporalLayer = 0x07;
 
 constexpr uint8_t kFlagMoreDependencies = 0x01;
 constexpr uint8_t kFlageXtendedOffset = 0x02;
 
-}  // namespace
 //       0 1 2 3 4 5 6 7
 //      +-+-+-+-+-+-+-+-+
 //      |B|E|F|L|D|  T  |
@@ -52,10 +58,9 @@
 //      +---------------+
 //      |      ...      |
 //      +-+-+-+-+-+-+-+-+
-constexpr RTPExtensionType RtpGenericFrameDescriptorExtension::kId;
-constexpr char RtpGenericFrameDescriptorExtension::kUri[];
 
-bool RtpGenericFrameDescriptorExtension::Parse(
+bool RtpGenericFrameDescriptorExtensionParse(
+    size_t version,
     rtc::ArrayView<const uint8_t> data,
     RtpGenericFrameDescriptor* descriptor) {
   if (data.empty()) {
@@ -65,8 +70,10 @@
   bool begins_subframe = (data[0] & kFlagBeginOfSubframe) != 0;
   descriptor->SetFirstPacketInSubFrame(begins_subframe);
   descriptor->SetLastPacketInSubFrame((data[0] & kFlagEndOfSubframe) != 0);
-  descriptor->SetFirstSubFrameInFrame((data[0] & kFlagFirstSubframe) != 0);
-  descriptor->SetLastSubFrameInFrame((data[0] & kFlagLastSubframe) != 0);
+
+  if (version >= 1) {
+    descriptor->SetDiscardable((data[0] & kFlagDiscardableV01) != 0);
+  }
 
   // Parse Subframe details provided in 1st packet of subframe.
   if (!begins_subframe) {
@@ -108,7 +115,7 @@
   return true;
 }
 
-size_t RtpGenericFrameDescriptorExtension::ValueSize(
+size_t RtpGenericFrameDescriptorExtensionValueSize(
     const RtpGenericFrameDescriptor& descriptor) {
   if (!descriptor.FirstPacketInSubFrame())
     return 1;
@@ -125,15 +132,24 @@
   return size;
 }
 
-bool RtpGenericFrameDescriptorExtension::Write(
+bool RtpGenericFrameDescriptorExtensionWrite(
+    size_t version,
     rtc::ArrayView<uint8_t> data,
     const RtpGenericFrameDescriptor& descriptor) {
-  RTC_CHECK_EQ(data.size(), ValueSize(descriptor));
+  RTC_CHECK_EQ(data.size(),
+
+               RtpGenericFrameDescriptorExtensionValueSize(descriptor));
   uint8_t base_header =
       (descriptor.FirstPacketInSubFrame() ? kFlagBeginOfSubframe : 0) |
-      (descriptor.LastPacketInSubFrame() ? kFlagEndOfSubframe : 0) |
-      (descriptor.FirstSubFrameInFrame() ? kFlagFirstSubframe : 0) |
-      (descriptor.LastSubFrameInFrame() ? kFlagLastSubframe : 0);
+      (descriptor.LastPacketInSubFrame() ? kFlagEndOfSubframe : 0);
+  if (version == 0) {
+    base_header |= kFlagFirstSubframeV00;
+    base_header |= kFlagLastSubframeV00;
+  } else if (version >= 1) {
+    const absl::optional<bool> discardable = descriptor.Discardable();
+    base_header |= (discardable.value_or(false) ? kFlagDiscardableV01 : 0);
+  }
+
   if (!descriptor.FirstPacketInSubFrame()) {
     data[0] = base_header;
     return true;
@@ -168,4 +184,48 @@
   return true;
 }
 
+}  // namespace
+
+constexpr RTPExtensionType RtpGenericFrameDescriptorExtension00::kId;
+constexpr char RtpGenericFrameDescriptorExtension00::kUri[];
+
+bool RtpGenericFrameDescriptorExtension00::Parse(
+    rtc::ArrayView<const uint8_t> data,
+    RtpGenericFrameDescriptor* descriptor) {
+  return RtpGenericFrameDescriptorExtensionParse(0, data, descriptor);
+}
+
+size_t RtpGenericFrameDescriptorExtension00::ValueSize(
+    const RtpGenericFrameDescriptor& descriptor) {
+  // No difference between existing versions.
+  return RtpGenericFrameDescriptorExtensionValueSize(descriptor);
+}
+
+bool RtpGenericFrameDescriptorExtension00::Write(
+    rtc::ArrayView<uint8_t> data,
+    const RtpGenericFrameDescriptor& descriptor) {
+  return RtpGenericFrameDescriptorExtensionWrite(0, data, descriptor);
+}
+
+constexpr RTPExtensionType RtpGenericFrameDescriptorExtension01::kId;
+constexpr char RtpGenericFrameDescriptorExtension01::kUri[];
+
+bool RtpGenericFrameDescriptorExtension01::Parse(
+    rtc::ArrayView<const uint8_t> data,
+    RtpGenericFrameDescriptor* descriptor) {
+  return RtpGenericFrameDescriptorExtensionParse(1, data, descriptor);
+}
+
+size_t RtpGenericFrameDescriptorExtension01::ValueSize(
+    const RtpGenericFrameDescriptor& descriptor) {
+  // No difference between existing versions.
+  return RtpGenericFrameDescriptorExtensionValueSize(descriptor);
+}
+
+bool RtpGenericFrameDescriptorExtension01::Write(
+    rtc::ArrayView<uint8_t> data,
+    const RtpGenericFrameDescriptor& descriptor) {
+  return RtpGenericFrameDescriptorExtensionWrite(1, data, descriptor);
+}
+
 }  // namespace webrtc
diff --git a/modules/rtp_rtcp/source/rtp_generic_frame_descriptor_extension.h b/modules/rtp_rtcp/source/rtp_generic_frame_descriptor_extension.h
index 0d673e0..a52588e 100644
--- a/modules/rtp_rtcp/source/rtp_generic_frame_descriptor_extension.h
+++ b/modules/rtp_rtcp/source/rtp_generic_frame_descriptor_extension.h
@@ -19,10 +19,10 @@
 
 namespace webrtc {
 
-class RtpGenericFrameDescriptorExtension {
+class RtpGenericFrameDescriptorExtension00 {
  public:
   using value_type = RtpGenericFrameDescriptor;
-  static constexpr RTPExtensionType kId = kRtpExtensionGenericFrameDescriptor;
+  static constexpr RTPExtensionType kId = kRtpExtensionGenericFrameDescriptor00;
   static constexpr char kUri[] =
       "http://www.webrtc.org/experiments/rtp-hdrext/"
       "generic-frame-descriptor-00";
@@ -30,7 +30,23 @@
 
   static bool Parse(rtc::ArrayView<const uint8_t> data,
                     RtpGenericFrameDescriptor* descriptor);
-  static size_t ValueSize(const RtpGenericFrameDescriptor&);
+  static size_t ValueSize(const RtpGenericFrameDescriptor& descriptor);
+  static bool Write(rtc::ArrayView<uint8_t> data,
+                    const RtpGenericFrameDescriptor& descriptor);
+};
+
+class RtpGenericFrameDescriptorExtension01 {
+ public:
+  using value_type = RtpGenericFrameDescriptor;
+  static constexpr RTPExtensionType kId = kRtpExtensionGenericFrameDescriptor01;
+  static constexpr char kUri[] =
+      "http://www.webrtc.org/experiments/rtp-hdrext/"
+      "generic-frame-descriptor-01";
+  static constexpr int kMaxSizeBytes = 16;
+
+  static bool Parse(rtc::ArrayView<const uint8_t> data,
+                    RtpGenericFrameDescriptor* descriptor);
+  static size_t ValueSize(const RtpGenericFrameDescriptor& descriptor);
   static bool Write(rtc::ArrayView<uint8_t> data,
                     const RtpGenericFrameDescriptor& descriptor);
 };
diff --git a/modules/rtp_rtcp/source/rtp_generic_frame_descriptor_extension_unittest.cc b/modules/rtp_rtcp/source/rtp_generic_frame_descriptor_extension_unittest.cc
index 7f8fa2f..13cacb5 100644
--- a/modules/rtp_rtcp/source/rtp_generic_frame_descriptor_extension_unittest.cc
+++ b/modules/rtp_rtcp/source/rtp_generic_frame_descriptor_extension_unittest.cc
@@ -1,5 +1,5 @@
 /*
- *  Copyright (c) 2012 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
@@ -19,30 +19,91 @@
 using ::testing::ElementsAreArray;
 using ::testing::IsEmpty;
 
+constexpr uint8_t kDeprecatedFlags = 0x30;
+
 // TODO(danilchap): Add fuzzer to test for various invalid inputs.
 
-TEST(RtpGenericFrameDescriptorExtensionTest,
-     ParseFirstPacketOfIndependenSubFrame) {
+class RtpGenericFrameDescriptorExtensionTest
+    : public ::testing::Test,
+      public ::testing::WithParamInterface<int> {
+ public:
+  RtpGenericFrameDescriptorExtensionTest() : version_(GetParam()) {}
+
+  bool Parse(rtc::ArrayView<const uint8_t> data,
+             RtpGenericFrameDescriptor* descriptor) const {
+    switch (version_) {
+      case 0:
+        return RtpGenericFrameDescriptorExtension00::Parse(data, descriptor);
+      case 1:
+        return RtpGenericFrameDescriptorExtension01::Parse(data, descriptor);
+    }
+    RTC_NOTREACHED();
+    return false;
+  }
+
+  size_t ValueSize(const RtpGenericFrameDescriptor& descriptor) const {
+    switch (version_) {
+      case 0:
+        return RtpGenericFrameDescriptorExtension00::ValueSize(descriptor);
+      case 1:
+        return RtpGenericFrameDescriptorExtension01::ValueSize(descriptor);
+    }
+    RTC_NOTREACHED();
+    return 0;
+  }
+
+  bool Write(rtc::ArrayView<uint8_t> data,
+             const RtpGenericFrameDescriptor& descriptor) const {
+    switch (version_) {
+      case 0:
+        return RtpGenericFrameDescriptorExtension00::Write(data, descriptor);
+      case 1:
+        return RtpGenericFrameDescriptorExtension01::Write(data, descriptor);
+    }
+    RTC_NOTREACHED();
+    return false;
+  }
+
+ protected:
+  const int version_;
+};
+
+INSTANTIATE_TEST_SUITE_P(,
+                         RtpGenericFrameDescriptorExtensionTest,
+                         ::testing::Values(0, 1));
+
+TEST_P(RtpGenericFrameDescriptorExtensionTest,
+       ParseFirstPacketOfIndependenSubFrame) {
   const int kTemporalLayer = 5;
   constexpr uint8_t kRaw[] = {0x80 | kTemporalLayer, 0x49, 0x12, 0x34};
   RtpGenericFrameDescriptor descriptor;
 
-  ASSERT_TRUE(RtpGenericFrameDescriptorExtension::Parse(kRaw, &descriptor));
+  ASSERT_TRUE(Parse(kRaw, &descriptor));
 
   EXPECT_TRUE(descriptor.FirstPacketInSubFrame());
   EXPECT_FALSE(descriptor.LastPacketInSubFrame());
-  EXPECT_FALSE(descriptor.FirstSubFrameInFrame());
-  EXPECT_FALSE(descriptor.LastSubFrameInFrame());
+
+  const absl::optional<bool> discardable = descriptor.Discardable();
+  if (version_ == 0) {
+    ASSERT_FALSE(discardable.has_value());
+  } else {
+    ASSERT_TRUE(discardable.has_value());
+    EXPECT_FALSE(discardable.value());
+  }
+
   EXPECT_THAT(descriptor.FrameDependenciesDiffs(), IsEmpty());
   EXPECT_EQ(descriptor.TemporalLayer(), kTemporalLayer);
   EXPECT_EQ(descriptor.SpatialLayersBitmask(), 0x49);
   EXPECT_EQ(descriptor.FrameId(), 0x3412);
 }
 
-TEST(RtpGenericFrameDescriptorExtensionTest,
-     WriteFirstPacketOfIndependenSubFrame) {
+TEST_P(RtpGenericFrameDescriptorExtensionTest,
+       WriteFirstPacketOfIndependenSubFrame) {
   const int kTemporalLayer = 5;
-  constexpr uint8_t kRaw[] = {0x80 | kTemporalLayer, 0x49, 0x12, 0x34};
+  uint8_t kRaw[] = {0x80 | kTemporalLayer, 0x49, 0x12, 0x34};
+  if (version_ == 0) {
+    kRaw[0] |= kDeprecatedFlags;
+  }
   RtpGenericFrameDescriptor descriptor;
 
   descriptor.SetFirstPacketInSubFrame(true);
@@ -50,260 +111,263 @@
   descriptor.SetSpatialLayersBitmask(0x49);
   descriptor.SetFrameId(0x3412);
 
-  ASSERT_EQ(RtpGenericFrameDescriptorExtension::ValueSize(descriptor),
-            sizeof(kRaw));
+  ASSERT_EQ(ValueSize(descriptor), sizeof(kRaw));
   uint8_t buffer[sizeof(kRaw)];
-  EXPECT_TRUE(RtpGenericFrameDescriptorExtension::Write(buffer, descriptor));
+  EXPECT_TRUE(Write(buffer, descriptor));
+
   EXPECT_THAT(buffer, ElementsAreArray(kRaw));
 }
 
-TEST(RtpGenericFrameDescriptorExtensionTest, ParseLastPacketOfSubFrame) {
+TEST_P(RtpGenericFrameDescriptorExtensionTest, ParseLastPacketOfSubFrame) {
   constexpr uint8_t kRaw[] = {0x40};
   RtpGenericFrameDescriptor descriptor;
 
-  ASSERT_TRUE(RtpGenericFrameDescriptorExtension::Parse(kRaw, &descriptor));
+  ASSERT_TRUE(Parse(kRaw, &descriptor));
 
   EXPECT_FALSE(descriptor.FirstPacketInSubFrame());
+
+  const absl::optional<bool> discardable = descriptor.Discardable();
+  if (version_ == 0) {
+    ASSERT_FALSE(discardable.has_value());
+  } else {
+    ASSERT_TRUE(discardable.has_value());
+    EXPECT_FALSE(discardable.value());
+  }
+
   EXPECT_TRUE(descriptor.LastPacketInSubFrame());
-  EXPECT_FALSE(descriptor.FirstSubFrameInFrame());
-  EXPECT_FALSE(descriptor.LastSubFrameInFrame());
 }
 
-TEST(RtpGenericFrameDescriptorExtensionTest, WriteLastPacketOfSubFrame) {
-  constexpr uint8_t kRaw[] = {0x40};
+TEST_P(RtpGenericFrameDescriptorExtensionTest, WriteLastPacketOfSubFrame) {
+  uint8_t kRaw[] = {0x40};
+  if (version_ == 0) {
+    kRaw[0] |= kDeprecatedFlags;
+  }
+
   RtpGenericFrameDescriptor descriptor;
   descriptor.SetLastPacketInSubFrame(true);
 
-  ASSERT_EQ(RtpGenericFrameDescriptorExtension::ValueSize(descriptor),
-            sizeof(kRaw));
+  ASSERT_EQ(ValueSize(descriptor), sizeof(kRaw));
   uint8_t buffer[sizeof(kRaw)];
-  EXPECT_TRUE(RtpGenericFrameDescriptorExtension::Write(buffer, descriptor));
-  EXPECT_THAT(buffer, ElementsAreArray(kRaw));
-}
-TEST(RtpGenericFrameDescriptorExtensionTest, ParseFirstSubFrameInFrame) {
-  constexpr uint8_t kRaw[] = {0x20};
-  RtpGenericFrameDescriptor descriptor;
-
-  ASSERT_TRUE(RtpGenericFrameDescriptorExtension::Parse(kRaw, &descriptor));
-
-  EXPECT_FALSE(descriptor.FirstPacketInSubFrame());
-  EXPECT_FALSE(descriptor.LastPacketInSubFrame());
-  EXPECT_TRUE(descriptor.FirstSubFrameInFrame());
-  EXPECT_FALSE(descriptor.LastSubFrameInFrame());
-}
-
-TEST(RtpGenericFrameDescriptorExtensionTest, WriteFirstSubFrameInFrame) {
-  constexpr uint8_t kRaw[] = {0x20};
-  RtpGenericFrameDescriptor descriptor;
-  descriptor.SetFirstSubFrameInFrame(true);
-
-  ASSERT_EQ(RtpGenericFrameDescriptorExtension::ValueSize(descriptor),
-            sizeof(kRaw));
-  uint8_t buffer[sizeof(kRaw)];
-  EXPECT_TRUE(RtpGenericFrameDescriptorExtension::Write(buffer, descriptor));
+  EXPECT_TRUE(Write(buffer, descriptor));
   EXPECT_THAT(buffer, ElementsAreArray(kRaw));
 }
 
-TEST(RtpGenericFrameDescriptorExtensionTest, ParseLastSubFrameInFrame) {
+TEST_P(RtpGenericFrameDescriptorExtensionTest, ParseDiscardable) {
+  if (version_ == 0) {
+    return;
+  }
+
   constexpr uint8_t kRaw[] = {0x10};
   RtpGenericFrameDescriptor descriptor;
-
-  ASSERT_TRUE(RtpGenericFrameDescriptorExtension::Parse(kRaw, &descriptor));
-
-  EXPECT_FALSE(descriptor.FirstPacketInSubFrame());
-  EXPECT_FALSE(descriptor.LastPacketInSubFrame());
-  EXPECT_FALSE(descriptor.FirstSubFrameInFrame());
-  EXPECT_TRUE(descriptor.LastSubFrameInFrame());
+  ASSERT_TRUE(Parse(kRaw, &descriptor));
+  const absl::optional<bool> discardable = descriptor.Discardable();
+  ASSERT_TRUE(discardable.has_value());
+  EXPECT_TRUE(discardable.value());
 }
 
-TEST(RtpGenericFrameDescriptorExtensionTest, WriteLastSubFrameInFrame) {
+TEST_P(RtpGenericFrameDescriptorExtensionTest, WriteDiscardable) {
+  if (version_ == 0) {
+    return;
+  }
+
   constexpr uint8_t kRaw[] = {0x10};
   RtpGenericFrameDescriptor descriptor;
-  descriptor.SetLastSubFrameInFrame(true);
-
-  ASSERT_EQ(RtpGenericFrameDescriptorExtension::ValueSize(descriptor),
-            sizeof(kRaw));
+  descriptor.SetDiscardable(true);
+  ASSERT_EQ(ValueSize(descriptor), sizeof(kRaw));
   uint8_t buffer[sizeof(kRaw)];
-  EXPECT_TRUE(RtpGenericFrameDescriptorExtension::Write(buffer, descriptor));
+  EXPECT_TRUE(Write(buffer, descriptor));
   EXPECT_THAT(buffer, ElementsAreArray(kRaw));
 }
 
-TEST(RtpGenericFrameDescriptorExtensionTest, ParseMinShortFrameDependencies) {
+TEST_P(RtpGenericFrameDescriptorExtensionTest, ParseMinShortFrameDependencies) {
   constexpr uint16_t kDiff = 1;
   constexpr uint8_t kRaw[] = {0x88, 0x01, 0x00, 0x00, 0x04};
   RtpGenericFrameDescriptor descriptor;
 
-  ASSERT_TRUE(RtpGenericFrameDescriptorExtension::Parse(kRaw, &descriptor));
+  ASSERT_TRUE(Parse(kRaw, &descriptor));
   ASSERT_TRUE(descriptor.FirstPacketInSubFrame());
   EXPECT_THAT(descriptor.FrameDependenciesDiffs(), ElementsAre(kDiff));
 }
 
-TEST(RtpGenericFrameDescriptorExtensionTest, WriteMinShortFrameDependencies) {
+TEST_P(RtpGenericFrameDescriptorExtensionTest, WriteMinShortFrameDependencies) {
   constexpr uint16_t kDiff = 1;
-  constexpr uint8_t kRaw[] = {0x88, 0x01, 0x00, 0x00, 0x04};
+  uint8_t kRaw[] = {0x88, 0x01, 0x00, 0x00, 0x04};
+  if (version_ == 0) {
+    kRaw[0] |= kDeprecatedFlags;
+  }
   RtpGenericFrameDescriptor descriptor;
   descriptor.SetFirstPacketInSubFrame(true);
   descriptor.AddFrameDependencyDiff(kDiff);
 
-  ASSERT_EQ(RtpGenericFrameDescriptorExtension::ValueSize(descriptor),
-            sizeof(kRaw));
+  ASSERT_EQ(ValueSize(descriptor), sizeof(kRaw));
   uint8_t buffer[sizeof(kRaw)];
-  EXPECT_TRUE(RtpGenericFrameDescriptorExtension::Write(buffer, descriptor));
+  EXPECT_TRUE(Write(buffer, descriptor));
   EXPECT_THAT(buffer, ElementsAreArray(kRaw));
 }
 
-TEST(RtpGenericFrameDescriptorExtensionTest, ParseMaxShortFrameDependencies) {
+TEST_P(RtpGenericFrameDescriptorExtensionTest, ParseMaxShortFrameDependencies) {
   constexpr uint16_t kDiff = 0x3f;
-  constexpr uint8_t kRaw[] = {0x88, 0x01, 0x00, 0x00, 0xfc};
+  constexpr uint8_t kRaw[] = {0xb8, 0x01, 0x00, 0x00, 0xfc};
   RtpGenericFrameDescriptor descriptor;
 
-  ASSERT_TRUE(RtpGenericFrameDescriptorExtension::Parse(kRaw, &descriptor));
+  ASSERT_TRUE(Parse(kRaw, &descriptor));
   ASSERT_TRUE(descriptor.FirstPacketInSubFrame());
   EXPECT_THAT(descriptor.FrameDependenciesDiffs(), ElementsAre(kDiff));
 }
 
-TEST(RtpGenericFrameDescriptorExtensionTest, WriteMaxShortFrameDependencies) {
+TEST_P(RtpGenericFrameDescriptorExtensionTest, WriteMaxShortFrameDependencies) {
   constexpr uint16_t kDiff = 0x3f;
-  constexpr uint8_t kRaw[] = {0x88, 0x01, 0x00, 0x00, 0xfc};
+  uint8_t kRaw[] = {0x88, 0x01, 0x00, 0x00, 0xfc};
+  if (version_ == 0) {
+    kRaw[0] |= kDeprecatedFlags;
+  }
   RtpGenericFrameDescriptor descriptor;
   descriptor.SetFirstPacketInSubFrame(true);
   descriptor.AddFrameDependencyDiff(kDiff);
 
-  ASSERT_EQ(RtpGenericFrameDescriptorExtension::ValueSize(descriptor),
-            sizeof(kRaw));
+  ASSERT_EQ(ValueSize(descriptor), sizeof(kRaw));
   uint8_t buffer[sizeof(kRaw)];
-  EXPECT_TRUE(RtpGenericFrameDescriptorExtension::Write(buffer, descriptor));
+  EXPECT_TRUE(Write(buffer, descriptor));
   EXPECT_THAT(buffer, ElementsAreArray(kRaw));
 }
 
-TEST(RtpGenericFrameDescriptorExtensionTest, ParseMinLongFrameDependencies) {
+TEST_P(RtpGenericFrameDescriptorExtensionTest, ParseMinLongFrameDependencies) {
   constexpr uint16_t kDiff = 0x40;
-  constexpr uint8_t kRaw[] = {0x88, 0x01, 0x00, 0x00, 0x02, 0x01};
+  constexpr uint8_t kRaw[] = {0xb8, 0x01, 0x00, 0x00, 0x02, 0x01};
   RtpGenericFrameDescriptor descriptor;
 
-  ASSERT_TRUE(RtpGenericFrameDescriptorExtension::Parse(kRaw, &descriptor));
+  ASSERT_TRUE(Parse(kRaw, &descriptor));
   ASSERT_TRUE(descriptor.FirstPacketInSubFrame());
   EXPECT_THAT(descriptor.FrameDependenciesDiffs(), ElementsAre(kDiff));
 }
 
-TEST(RtpGenericFrameDescriptorExtensionTest, WriteMinLongFrameDependencies) {
+TEST_P(RtpGenericFrameDescriptorExtensionTest, WriteMinLongFrameDependencies) {
   constexpr uint16_t kDiff = 0x40;
-  constexpr uint8_t kRaw[] = {0x88, 0x01, 0x00, 0x00, 0x02, 0x01};
+  uint8_t kRaw[] = {0x88, 0x01, 0x00, 0x00, 0x02, 0x01};
+  if (version_ == 0) {
+    kRaw[0] |= kDeprecatedFlags;
+  }
   RtpGenericFrameDescriptor descriptor;
   descriptor.SetFirstPacketInSubFrame(true);
   descriptor.AddFrameDependencyDiff(kDiff);
 
-  ASSERT_EQ(RtpGenericFrameDescriptorExtension::ValueSize(descriptor),
-            sizeof(kRaw));
+  ASSERT_EQ(ValueSize(descriptor), sizeof(kRaw));
   uint8_t buffer[sizeof(kRaw)];
-  EXPECT_TRUE(RtpGenericFrameDescriptorExtension::Write(buffer, descriptor));
+  EXPECT_TRUE(Write(buffer, descriptor));
   EXPECT_THAT(buffer, ElementsAreArray(kRaw));
 }
 
-TEST(RtpGenericFrameDescriptorExtensionTest,
-     ParseLongFrameDependenciesAsBigEndian) {
+TEST_P(RtpGenericFrameDescriptorExtensionTest,
+       ParseLongFrameDependenciesAsBigEndian) {
   constexpr uint16_t kDiff = 0x7654 >> 2;
-  constexpr uint8_t kRaw[] = {0x88, 0x01, 0x00, 0x00, 0x54 | 0x02, 0x76};
+  constexpr uint8_t kRaw[] = {0xb8, 0x01, 0x00, 0x00, 0x54 | 0x02, 0x76};
   RtpGenericFrameDescriptor descriptor;
 
-  ASSERT_TRUE(RtpGenericFrameDescriptorExtension::Parse(kRaw, &descriptor));
+  ASSERT_TRUE(Parse(kRaw, &descriptor));
   ASSERT_TRUE(descriptor.FirstPacketInSubFrame());
   EXPECT_THAT(descriptor.FrameDependenciesDiffs(), ElementsAre(kDiff));
 }
 
-TEST(RtpGenericFrameDescriptorExtensionTest,
-     WriteLongFrameDependenciesAsBigEndian) {
+TEST_P(RtpGenericFrameDescriptorExtensionTest,
+       WriteLongFrameDependenciesAsBigEndian) {
   constexpr uint16_t kDiff = 0x7654 >> 2;
-  constexpr uint8_t kRaw[] = {0x88, 0x01, 0x00, 0x00, 0x54 | 0x02, 0x76};
+  uint8_t kRaw[] = {0x88, 0x01, 0x00, 0x00, 0x54 | 0x02, 0x76};
+  if (version_ == 0) {
+    kRaw[0] |= kDeprecatedFlags;
+  }
   RtpGenericFrameDescriptor descriptor;
   descriptor.SetFirstPacketInSubFrame(true);
   descriptor.AddFrameDependencyDiff(kDiff);
 
-  ASSERT_EQ(RtpGenericFrameDescriptorExtension::ValueSize(descriptor),
-            sizeof(kRaw));
+  ASSERT_EQ(ValueSize(descriptor), sizeof(kRaw));
   uint8_t buffer[sizeof(kRaw)];
-  EXPECT_TRUE(RtpGenericFrameDescriptorExtension::Write(buffer, descriptor));
+  EXPECT_TRUE(Write(buffer, descriptor));
   EXPECT_THAT(buffer, ElementsAreArray(kRaw));
 }
 
-TEST(RtpGenericFrameDescriptorExtensionTest, ParseMaxLongFrameDependencies) {
+TEST_P(RtpGenericFrameDescriptorExtensionTest, ParseMaxLongFrameDependencies) {
   constexpr uint16_t kDiff = 0x3fff;
-  constexpr uint8_t kRaw[] = {0x88, 0x01, 0x00, 0x00, 0xfe, 0xff};
+  constexpr uint8_t kRaw[] = {0xb8, 0x01, 0x00, 0x00, 0xfe, 0xff};
   RtpGenericFrameDescriptor descriptor;
 
-  ASSERT_TRUE(RtpGenericFrameDescriptorExtension::Parse(kRaw, &descriptor));
+  ASSERT_TRUE(Parse(kRaw, &descriptor));
   ASSERT_TRUE(descriptor.FirstPacketInSubFrame());
   EXPECT_THAT(descriptor.FrameDependenciesDiffs(), ElementsAre(kDiff));
 }
 
-TEST(RtpGenericFrameDescriptorExtensionTest, WriteMaxLongFrameDependencies) {
+TEST_P(RtpGenericFrameDescriptorExtensionTest, WriteMaxLongFrameDependencies) {
   constexpr uint16_t kDiff = 0x3fff;
-  constexpr uint8_t kRaw[] = {0x88, 0x01, 0x00, 0x00, 0xfe, 0xff};
+  uint8_t kRaw[] = {0x88, 0x01, 0x00, 0x00, 0xfe, 0xff};
+  if (version_ == 0) {
+    kRaw[0] |= kDeprecatedFlags;
+  }
   RtpGenericFrameDescriptor descriptor;
   descriptor.SetFirstPacketInSubFrame(true);
   descriptor.AddFrameDependencyDiff(kDiff);
 
-  ASSERT_EQ(RtpGenericFrameDescriptorExtension::ValueSize(descriptor),
-            sizeof(kRaw));
+  ASSERT_EQ(ValueSize(descriptor), sizeof(kRaw));
   uint8_t buffer[sizeof(kRaw)];
-  EXPECT_TRUE(RtpGenericFrameDescriptorExtension::Write(buffer, descriptor));
+  EXPECT_TRUE(Write(buffer, descriptor));
   EXPECT_THAT(buffer, ElementsAreArray(kRaw));
 }
 
-TEST(RtpGenericFrameDescriptorExtensionTest, ParseTwoFrameDependencies) {
+TEST_P(RtpGenericFrameDescriptorExtensionTest, ParseTwoFrameDependencies) {
   constexpr uint16_t kDiff1 = 9;
   constexpr uint16_t kDiff2 = 15;
   constexpr uint8_t kRaw[] = {
-      0x88, 0x01, 0x00, 0x00, (kDiff1 << 2) | 0x01, kDiff2 << 2};
+      0xb8, 0x01, 0x00, 0x00, (kDiff1 << 2) | 0x01, kDiff2 << 2};
   RtpGenericFrameDescriptor descriptor;
 
-  ASSERT_TRUE(RtpGenericFrameDescriptorExtension::Parse(kRaw, &descriptor));
+  ASSERT_TRUE(Parse(kRaw, &descriptor));
   ASSERT_TRUE(descriptor.FirstPacketInSubFrame());
   EXPECT_THAT(descriptor.FrameDependenciesDiffs(), ElementsAre(kDiff1, kDiff2));
 }
 
-TEST(RtpGenericFrameDescriptorExtensionTest, WriteTwoFrameDependencies) {
+TEST_P(RtpGenericFrameDescriptorExtensionTest, WriteTwoFrameDependencies) {
   constexpr uint16_t kDiff1 = 9;
   constexpr uint16_t kDiff2 = 15;
-  constexpr uint8_t kRaw[] = {
-      0x88, 0x01, 0x00, 0x00, (kDiff1 << 2) | 0x01, kDiff2 << 2};
+  uint8_t kRaw[] = {0x88, 0x01, 0x00, 0x00, (kDiff1 << 2) | 0x01, kDiff2 << 2};
+  if (version_ == 0) {
+    kRaw[0] |= kDeprecatedFlags;
+  }
   RtpGenericFrameDescriptor descriptor;
   descriptor.SetFirstPacketInSubFrame(true);
   descriptor.AddFrameDependencyDiff(kDiff1);
   descriptor.AddFrameDependencyDiff(kDiff2);
 
-  ASSERT_EQ(RtpGenericFrameDescriptorExtension::ValueSize(descriptor),
-            sizeof(kRaw));
+  ASSERT_EQ(ValueSize(descriptor), sizeof(kRaw));
   uint8_t buffer[sizeof(kRaw)];
-  EXPECT_TRUE(RtpGenericFrameDescriptorExtension::Write(buffer, descriptor));
+  EXPECT_TRUE(Write(buffer, descriptor));
   EXPECT_THAT(buffer, ElementsAreArray(kRaw));
 }
 
-TEST(RtpGenericFrameDescriptorExtensionTest,
-     ParseResolutionOnIndependentFrame) {
+TEST_P(RtpGenericFrameDescriptorExtensionTest,
+       ParseResolutionOnIndependentFrame) {
   constexpr int kWidth = 0x2468;
   constexpr int kHeight = 0x6543;
-  constexpr uint8_t kRaw[] = {0x80, 0x01, 0x00, 0x00, 0x24, 0x68, 0x65, 0x43};
+  constexpr uint8_t kRaw[] = {0xb0, 0x01, 0x00, 0x00, 0x24, 0x68, 0x65, 0x43};
   RtpGenericFrameDescriptor descriptor;
 
-  ASSERT_TRUE(RtpGenericFrameDescriptorExtension::Parse(kRaw, &descriptor));
+  ASSERT_TRUE(Parse(kRaw, &descriptor));
   EXPECT_EQ(descriptor.Width(), kWidth);
   EXPECT_EQ(descriptor.Height(), kHeight);
 }
 
-TEST(RtpGenericFrameDescriptorExtensionTest,
-     WriteResolutionOnIndependentFrame) {
+TEST_P(RtpGenericFrameDescriptorExtensionTest,
+       WriteResolutionOnIndependentFrame) {
   constexpr int kWidth = 0x2468;
   constexpr int kHeight = 0x6543;
-  constexpr uint8_t kRaw[] = {0x80, 0x01, 0x00, 0x00, 0x24, 0x68, 0x65, 0x43};
+  uint8_t kRaw[] = {0x80, 0x01, 0x00, 0x00, 0x24, 0x68, 0x65, 0x43};
+  if (version_ == 0) {
+    kRaw[0] |= kDeprecatedFlags;
+  }
   RtpGenericFrameDescriptor descriptor;
   descriptor.SetFirstPacketInSubFrame(true);
   descriptor.SetResolution(kWidth, kHeight);
 
-  ASSERT_EQ(RtpGenericFrameDescriptorExtension::ValueSize(descriptor),
-            sizeof(kRaw));
+  ASSERT_EQ(ValueSize(descriptor), sizeof(kRaw));
   uint8_t buffer[sizeof(kRaw)];
-  EXPECT_TRUE(RtpGenericFrameDescriptorExtension::Write(buffer, descriptor));
+  EXPECT_TRUE(Write(buffer, descriptor));
   EXPECT_THAT(buffer, ElementsAreArray(kRaw));
 }
 }  // namespace
diff --git a/modules/rtp_rtcp/source/rtp_header_extension_map.cc b/modules/rtp_rtcp/source/rtp_header_extension_map.cc
index 8e0a484..b4aaf3f 100644
--- a/modules/rtp_rtcp/source/rtp_header_extension_map.cc
+++ b/modules/rtp_rtcp/source/rtp_header_extension_map.cc
@@ -35,6 +35,7 @@
     CreateExtensionInfo<AbsoluteSendTime>(),
     CreateExtensionInfo<VideoOrientation>(),
     CreateExtensionInfo<TransportSequenceNumber>(),
+    CreateExtensionInfo<TransportSequenceNumberV2>(),
     CreateExtensionInfo<PlayoutDelayLimits>(),
     CreateExtensionInfo<VideoContentTypeExtension>(),
     CreateExtensionInfo<VideoTimingExtension>(),
@@ -42,7 +43,8 @@
     CreateExtensionInfo<RtpStreamId>(),
     CreateExtensionInfo<RepairedRtpStreamId>(),
     CreateExtensionInfo<RtpMid>(),
-    CreateExtensionInfo<RtpGenericFrameDescriptorExtension>(),
+    CreateExtensionInfo<RtpGenericFrameDescriptorExtension00>(),
+    CreateExtensionInfo<RtpGenericFrameDescriptorExtension01>(),
     CreateExtensionInfo<ColorSpaceExtension>(),
 };
 
diff --git a/modules/rtp_rtcp/source/rtp_header_extension_size.cc b/modules/rtp_rtcp/source/rtp_header_extension_size.cc
index f20ca00..7719922 100644
--- a/modules/rtp_rtcp/source/rtp_header_extension_size.cc
+++ b/modules/rtp_rtcp/source/rtp_header_extension_size.cc
@@ -10,7 +10,7 @@
 
 #include "modules/rtp_rtcp/source/rtp_header_extension_size.h"
 
-#include "api/rtpparameters.h"
+#include "api/rtp_parameters.h"
 
 namespace webrtc {
 
diff --git a/modules/rtp_rtcp/source/rtp_header_extensions.cc b/modules/rtp_rtcp/source/rtp_header_extensions.cc
index 92694cd..1d76ff3 100644
--- a/modules/rtp_rtcp/source/rtp_header_extensions.cc
+++ b/modules/rtp_rtcp/source/rtp_header_extensions.cc
@@ -12,6 +12,7 @@
 
 #include <string.h>
 #include <cmath>
+#include <limits>
 
 #include "modules/rtp_rtcp/include/rtp_cvo.h"
 #include "modules/rtp_rtcp/source/byte_io.h"
@@ -125,27 +126,99 @@
   return true;
 }
 
+// TransportSequenceNumber
+//
 //   0                   1                   2
 //   0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3
 //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-//  |  ID   | L=1   |transport wide sequence number |
+//  |  ID   | L=1   |transport-wide sequence number |
 //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 constexpr RTPExtensionType TransportSequenceNumber::kId;
 constexpr uint8_t TransportSequenceNumber::kValueSizeBytes;
 constexpr const char TransportSequenceNumber::kUri[];
 
 bool TransportSequenceNumber::Parse(rtc::ArrayView<const uint8_t> data,
-                                    uint16_t* value) {
-  if (data.size() != 2)
+                                    uint16_t* transport_sequence_number) {
+  if (data.size() != kValueSizeBytes)
     return false;
-  *value = ByteReader<uint16_t>::ReadBigEndian(data.data());
+  *transport_sequence_number = ByteReader<uint16_t>::ReadBigEndian(data.data());
   return true;
 }
 
 bool TransportSequenceNumber::Write(rtc::ArrayView<uint8_t> data,
-                                    uint16_t value) {
-  RTC_DCHECK_EQ(data.size(), 2);
-  ByteWriter<uint16_t>::WriteBigEndian(data.data(), value);
+                                    uint16_t transport_sequence_number) {
+  RTC_DCHECK_EQ(data.size(), ValueSize(transport_sequence_number));
+  ByteWriter<uint16_t>::WriteBigEndian(data.data(), transport_sequence_number);
+  return true;
+}
+
+// TransportSequenceNumberV2
+//
+// In addition to the format used for TransportSequencNumber, V2 also supports
+// the following packet format where two extra bytes are used to specify that
+// the sender requests immediate feedback.
+//   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
+//  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+//  |  ID   | L=3   |transport-wide sequence number |T|  seq count  |
+//  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+//  |seq count cont.|
+//  +-+-+-+-+-+-+-+-+
+//
+// The bit |T| determines whether the feedback should include timing information
+// or not and |seq_count| determines how many packets the feedback packet should
+// cover including the current packet. If |seq_count| is zero no feedback is
+// requested.
+constexpr RTPExtensionType TransportSequenceNumberV2::kId;
+constexpr uint8_t TransportSequenceNumberV2::kValueSizeBytes;
+constexpr uint8_t
+    TransportSequenceNumberV2::kValueSizeBytesWithoutFeedbackRequest;
+constexpr const char TransportSequenceNumberV2::kUri[];
+constexpr uint16_t TransportSequenceNumberV2::kIncludeTimestampsBit;
+
+bool TransportSequenceNumberV2::Parse(
+    rtc::ArrayView<const uint8_t> data,
+    uint16_t* transport_sequence_number,
+    absl::optional<FeedbackRequest>* feedback_request) {
+  if (data.size() != kValueSizeBytes &&
+      data.size() != kValueSizeBytesWithoutFeedbackRequest)
+    return false;
+
+  *transport_sequence_number = ByteReader<uint16_t>::ReadBigEndian(data.data());
+
+  *feedback_request = absl::nullopt;
+  if (data.size() == kValueSizeBytes) {
+    uint16_t feedback_request_raw =
+        ByteReader<uint16_t>::ReadBigEndian(data.data() + 2);
+    bool include_timestamps =
+        (feedback_request_raw & kIncludeTimestampsBit) != 0;
+    uint16_t sequence_count = feedback_request_raw & ~kIncludeTimestampsBit;
+
+    // If |sequence_count| is zero no feedback is requested.
+    if (sequence_count != 0) {
+      *feedback_request = {include_timestamps, sequence_count};
+    }
+  }
+  return true;
+}
+
+bool TransportSequenceNumberV2::Write(
+    rtc::ArrayView<uint8_t> data,
+    uint16_t transport_sequence_number,
+    const absl::optional<FeedbackRequest>& feedback_request) {
+  RTC_DCHECK_EQ(data.size(),
+                ValueSize(transport_sequence_number, feedback_request));
+
+  ByteWriter<uint16_t>::WriteBigEndian(data.data(), transport_sequence_number);
+
+  if (feedback_request) {
+    RTC_DCHECK_GE(feedback_request->sequence_count, 0);
+    RTC_DCHECK_LT(feedback_request->sequence_count, kIncludeTimestampsBit);
+    uint16_t feedback_request_raw =
+        feedback_request->sequence_count |
+        (feedback_request->include_timestamps ? kIncludeTimestampsBit : 0);
+    ByteWriter<uint16_t>::WriteBigEndian(data.data() + 2, feedback_request_raw);
+  }
   return true;
 }
 
@@ -272,14 +345,14 @@
 // 255 = Invalid. The whole timing frame extension should be ignored.
 //
 //    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 2
-//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-//   |  ID   | len=12|     flags     |     encode start ms delta       |
-//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-//   |    encode finish ms delta     |   packetizer finish ms delta    |
-//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-//   |     pacer exit ms delta       |   network timestamp ms delta    |
-//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+//    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
+//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+//   |  ID   | len=12|     flags     |     encode start ms delta     |
+//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+//   |    encode finish ms delta     |  packetizer finish ms delta   |
+//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+//   |     pacer exit ms delta       |  network timestamp ms delta   |
+//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 //   |  network2 timestamp ms delta  |
 //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 
@@ -436,38 +509,39 @@
 
 // Color space including HDR metadata as an optional field.
 //
-// RTP header extension to carry HDR metadata.
-// Float values are upscaled by a static factor and transmitted as integers.
+// RTP header extension to carry color space information and optionally HDR
+// metadata. The float values in the HDR metadata struct are upscaled by a
+// static factor and transmitted as unsigned integers.
 //
-// Data layout with HDR metadata
+// Data layout of color space with HDR metadata (two-byte RTP header extension)
 //    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 2
-//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-//   |       ID      |   length=30    |   Primaries   |    Transfer    |
-//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-//   |     Matrix    |      Range     |                 luminance_max  |
-//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-//   |               |                  luminance_min                  |
-//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-//   |              mastering_metadata.primary_r.x and .y              |
-//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-//   |              mastering_metadata.primary_g.x and .y              |
-//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-//   |              mastering_metadata.primary_b.x and .y              |
-//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-//   |                mastering_metadata.white.x and .y                |
-//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-//   |     max_content_light_level    | max_frame_average_light_level  |
-//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+//    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
+//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+//   |      ID       |   length=28   |   primaries   |   transfer    |
+//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+//   |    matrix     |range+chr.sit. |         luminance_max         |
+//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+//   |         luminance_min         |            mastering_metadata.|
+//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+//   |primary_r.x and .y             |            mastering_metadata.|
+//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+//   |primary_g.x and .y             |            mastering_metadata.|
+//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+//   |primary_b.x and .y             |            mastering_metadata.|
+//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+//   |white.x and .y                 |    max_content_light_level    |
+//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+//   | max_frame_average_light_level |
+//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 //
-// Data layout without HDR metadata
+// Data layout of color space w/o HDR metadata (one-byte RTP header extension)
 //    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 2
-//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-//   |       ID      |    length=4    |   Primaries   |    Transfer    |
-//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-//   |     Matrix    |      Range     |
-//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
+//    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
+//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+//   |  ID   | L = 3 |   primaries   |   transfer    |    matrix     |
+//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+//   |range+chr.sit. |
+//   +-+-+-+-+-+-+-+-+
 
 constexpr RTPExtensionType ColorSpaceExtension::kId;
 constexpr uint8_t ColorSpaceExtension::kValueSizeBytes;
@@ -482,13 +556,21 @@
 
   size_t offset = 0;
   // Read color space information.
-  if (!color_space->set_primaries_from_uint8(data.data()[offset++]))
+  if (!color_space->set_primaries_from_uint8(data[offset++]))
     return false;
-  if (!color_space->set_transfer_from_uint8(data.data()[offset++]))
+  if (!color_space->set_transfer_from_uint8(data[offset++]))
     return false;
-  if (!color_space->set_matrix_from_uint8(data.data()[offset++]))
+  if (!color_space->set_matrix_from_uint8(data[offset++]))
     return false;
-  if (!color_space->set_range_from_uint8(data.data()[offset++]))
+
+  uint8_t range_and_chroma_siting = data[offset++];
+  if (!color_space->set_range_from_uint8((range_and_chroma_siting >> 4) & 0x03))
+    return false;
+  if (!color_space->set_chroma_siting_horizontal_from_uint8(
+          (range_and_chroma_siting >> 2) & 0x03))
+    return false;
+  if (!color_space->set_chroma_siting_vertical_from_uint8(
+          range_and_chroma_siting & 0x03))
     return false;
 
   // Read HDR metadata if it exists, otherwise clear it.
@@ -496,26 +578,9 @@
     color_space->set_hdr_metadata(nullptr);
   } else {
     HdrMetadata hdr_metadata;
-    offset += ParseLuminance(data.data() + offset,
-                             &hdr_metadata.mastering_metadata.luminance_max,
-                             kLuminanceMaxDenominator);
-    offset += ParseLuminance(data.data() + offset,
-                             &hdr_metadata.mastering_metadata.luminance_min,
-                             kLuminanceMinDenominator);
-    offset += ParseChromaticity(data.data() + offset,
-                                &hdr_metadata.mastering_metadata.primary_r);
-    offset += ParseChromaticity(data.data() + offset,
-                                &hdr_metadata.mastering_metadata.primary_g);
-    offset += ParseChromaticity(data.data() + offset,
-                                &hdr_metadata.mastering_metadata.primary_b);
-    offset += ParseChromaticity(data.data() + offset,
-                                &hdr_metadata.mastering_metadata.white_point);
-    hdr_metadata.max_content_light_level =
-        ByteReader<uint16_t>::ReadBigEndian(data.data() + offset);
-    offset += 2;
-    hdr_metadata.max_frame_average_light_level =
-        ByteReader<uint16_t>::ReadBigEndian(data.data() + offset);
-    offset += 2;
+    offset += ParseHdrMetadata(data.subview(offset), &hdr_metadata);
+    if (!hdr_metadata.Validate())
+      return false;
     color_space->set_hdr_metadata(&hdr_metadata);
   }
   RTC_DCHECK_EQ(ValueSize(*color_space), offset);
@@ -524,43 +589,70 @@
 
 bool ColorSpaceExtension::Write(rtc::ArrayView<uint8_t> data,
                                 const ColorSpace& color_space) {
-  RTC_DCHECK(data.size() >= ValueSize(color_space));
+  RTC_DCHECK_EQ(data.size(), ValueSize(color_space));
   size_t offset = 0;
   // Write color space information.
-  data.data()[offset++] = static_cast<uint8_t>(color_space.primaries());
-  data.data()[offset++] = static_cast<uint8_t>(color_space.transfer());
-  data.data()[offset++] = static_cast<uint8_t>(color_space.matrix());
-  data.data()[offset++] = static_cast<uint8_t>(color_space.range());
+  data[offset++] = static_cast<uint8_t>(color_space.primaries());
+  data[offset++] = static_cast<uint8_t>(color_space.transfer());
+  data[offset++] = static_cast<uint8_t>(color_space.matrix());
+  data[offset++] = CombineRangeAndChromaSiting(
+      color_space.range(), color_space.chroma_siting_horizontal(),
+      color_space.chroma_siting_vertical());
 
   // Write HDR metadata if it exists.
   if (color_space.hdr_metadata()) {
-    const HdrMetadata& hdr_metadata = *color_space.hdr_metadata();
-    offset += WriteLuminance(data.data() + offset,
-                             hdr_metadata.mastering_metadata.luminance_max,
-                             kLuminanceMaxDenominator);
-    offset += WriteLuminance(data.data() + offset,
-                             hdr_metadata.mastering_metadata.luminance_min,
-                             kLuminanceMinDenominator);
-    offset += WriteChromaticity(data.data() + offset,
-                                hdr_metadata.mastering_metadata.primary_r);
-    offset += WriteChromaticity(data.data() + offset,
-                                hdr_metadata.mastering_metadata.primary_g);
-    offset += WriteChromaticity(data.data() + offset,
-                                hdr_metadata.mastering_metadata.primary_b);
-    offset += WriteChromaticity(data.data() + offset,
-                                hdr_metadata.mastering_metadata.white_point);
-
-    ByteWriter<uint16_t>::WriteBigEndian(data.data() + offset,
-                                         hdr_metadata.max_content_light_level);
-    offset += 2;
-    ByteWriter<uint16_t>::WriteBigEndian(
-        data.data() + offset, hdr_metadata.max_frame_average_light_level);
-    offset += 2;
+    offset +=
+        WriteHdrMetadata(data.subview(offset), *color_space.hdr_metadata());
   }
   RTC_DCHECK_EQ(ValueSize(color_space), offset);
   return true;
 }
 
+// Combines range and chroma siting into one byte with the following bit layout:
+// bits 0-1 Chroma siting vertical.
+//      2-3 Chroma siting horizontal.
+//      4-5 Range.
+//      6-7 Unused.
+uint8_t ColorSpaceExtension::CombineRangeAndChromaSiting(
+    ColorSpace::RangeID range,
+    ColorSpace::ChromaSiting chroma_siting_horizontal,
+    ColorSpace::ChromaSiting chroma_siting_vertical) {
+  RTC_DCHECK_LE(static_cast<uint8_t>(range), 3);
+  RTC_DCHECK_LE(static_cast<uint8_t>(chroma_siting_horizontal), 3);
+  RTC_DCHECK_LE(static_cast<uint8_t>(chroma_siting_vertical), 3);
+  return (static_cast<uint8_t>(range) << 4) |
+         (static_cast<uint8_t>(chroma_siting_horizontal) << 2) |
+         static_cast<uint8_t>(chroma_siting_vertical);
+}
+
+size_t ColorSpaceExtension::ParseHdrMetadata(rtc::ArrayView<const uint8_t> data,
+                                             HdrMetadata* hdr_metadata) {
+  RTC_DCHECK_EQ(data.size(),
+                kValueSizeBytes - kValueSizeBytesWithoutHdrMetadata);
+  size_t offset = 0;
+  offset += ParseLuminance(data.data() + offset,
+                           &hdr_metadata->mastering_metadata.luminance_max,
+                           kLuminanceMaxDenominator);
+  offset += ParseLuminance(data.data() + offset,
+                           &hdr_metadata->mastering_metadata.luminance_min,
+                           kLuminanceMinDenominator);
+  offset += ParseChromaticity(data.data() + offset,
+                              &hdr_metadata->mastering_metadata.primary_r);
+  offset += ParseChromaticity(data.data() + offset,
+                              &hdr_metadata->mastering_metadata.primary_g);
+  offset += ParseChromaticity(data.data() + offset,
+                              &hdr_metadata->mastering_metadata.primary_b);
+  offset += ParseChromaticity(data.data() + offset,
+                              &hdr_metadata->mastering_metadata.white_point);
+  hdr_metadata->max_content_light_level =
+      ByteReader<uint16_t>::ReadBigEndian(data.data() + offset);
+  offset += 2;
+  hdr_metadata->max_frame_average_light_level =
+      ByteReader<uint16_t>::ReadBigEndian(data.data() + offset);
+  offset += 2;
+  return offset;
+}
+
 size_t ColorSpaceExtension::ParseChromaticity(
     const uint8_t* data,
     HdrMasteringMetadata::Chromaticity* p) {
@@ -575,16 +667,48 @@
 size_t ColorSpaceExtension::ParseLuminance(const uint8_t* data,
                                            float* f,
                                            int denominator) {
-  uint32_t luminance_scaled = ByteReader<uint32_t, 3>::ReadBigEndian(data);
+  uint16_t luminance_scaled = ByteReader<uint16_t>::ReadBigEndian(data);
   *f = static_cast<float>(luminance_scaled) / denominator;
-  return 3;  // Return number of bytes read.
+  return 2;  // Return number of bytes read.
+}
+
+size_t ColorSpaceExtension::WriteHdrMetadata(rtc::ArrayView<uint8_t> data,
+                                             const HdrMetadata& hdr_metadata) {
+  RTC_DCHECK_EQ(data.size(),
+                kValueSizeBytes - kValueSizeBytesWithoutHdrMetadata);
+  RTC_DCHECK(hdr_metadata.Validate());
+  size_t offset = 0;
+  offset += WriteLuminance(data.data() + offset,
+                           hdr_metadata.mastering_metadata.luminance_max,
+                           kLuminanceMaxDenominator);
+  offset += WriteLuminance(data.data() + offset,
+                           hdr_metadata.mastering_metadata.luminance_min,
+                           kLuminanceMinDenominator);
+  offset += WriteChromaticity(data.data() + offset,
+                              hdr_metadata.mastering_metadata.primary_r);
+  offset += WriteChromaticity(data.data() + offset,
+                              hdr_metadata.mastering_metadata.primary_g);
+  offset += WriteChromaticity(data.data() + offset,
+                              hdr_metadata.mastering_metadata.primary_b);
+  offset += WriteChromaticity(data.data() + offset,
+                              hdr_metadata.mastering_metadata.white_point);
+
+  ByteWriter<uint16_t>::WriteBigEndian(data.data() + offset,
+                                       hdr_metadata.max_content_light_level);
+  offset += 2;
+  ByteWriter<uint16_t>::WriteBigEndian(
+      data.data() + offset, hdr_metadata.max_frame_average_light_level);
+  offset += 2;
+  return offset;
 }
 
 size_t ColorSpaceExtension::WriteChromaticity(
     uint8_t* data,
     const HdrMasteringMetadata::Chromaticity& p) {
   RTC_DCHECK_GE(p.x, 0.0f);
+  RTC_DCHECK_LE(p.x, 1.0f);
   RTC_DCHECK_GE(p.y, 0.0f);
+  RTC_DCHECK_LE(p.y, 1.0f);
   ByteWriter<uint16_t>::WriteBigEndian(
       data, std::round(p.x * kChromaticityDenominator));
   ByteWriter<uint16_t>::WriteBigEndian(
@@ -596,8 +720,10 @@
                                            float f,
                                            int denominator) {
   RTC_DCHECK_GE(f, 0.0f);
-  ByteWriter<uint32_t, 3>::WriteBigEndian(data, std::round(f * denominator));
-  return 3;  // Return number of bytes written.
+  float upscaled_value = f * denominator;
+  RTC_DCHECK_LE(upscaled_value, std::numeric_limits<uint16_t>::max());
+  ByteWriter<uint16_t>::WriteBigEndian(data, std::round(upscaled_value));
+  return 2;  // Return number of bytes written.
 }
 
 bool BaseRtpStringExtension::Parse(rtc::ArrayView<const uint8_t> data,
diff --git a/modules/rtp_rtcp/source/rtp_header_extensions.h b/modules/rtp_rtcp/source/rtp_header_extensions.h
index 42a6216..8aacb9a 100644
--- a/modules/rtp_rtcp/source/rtp_header_extensions.h
+++ b/modules/rtp_rtcp/source/rtp_header_extensions.h
@@ -81,9 +81,38 @@
   static constexpr const char kUri[] =
       "http://www.ietf.org/id/"
       "draft-holmer-rmcat-transport-wide-cc-extensions-01";
-  static bool Parse(rtc::ArrayView<const uint8_t> data, uint16_t* value);
-  static size_t ValueSize(uint16_t value) { return kValueSizeBytes; }
-  static bool Write(rtc::ArrayView<uint8_t> data, uint16_t value);
+  static bool Parse(rtc::ArrayView<const uint8_t> data,
+                    uint16_t* transport_sequence_number);
+  static size_t ValueSize(uint16_t /*transport_sequence_number*/) {
+    return kValueSizeBytes;
+  }
+  static bool Write(rtc::ArrayView<uint8_t> data,
+                    uint16_t transport_sequence_number);
+};
+
+class TransportSequenceNumberV2 {
+ public:
+  static constexpr RTPExtensionType kId =
+      kRtpExtensionTransportSequenceNumber02;
+  static constexpr uint8_t kValueSizeBytes = 4;
+  static constexpr uint8_t kValueSizeBytesWithoutFeedbackRequest = 2;
+  static constexpr const char kUri[] =
+      "http://www.webrtc.org/experiments/rtp-hdrext/transport-wide-cc-02";
+  static bool Parse(rtc::ArrayView<const uint8_t> data,
+                    uint16_t* transport_sequence_number,
+                    absl::optional<FeedbackRequest>* feedback_request);
+  static size_t ValueSize(
+      uint16_t /*transport_sequence_number*/,
+      const absl::optional<FeedbackRequest>& feedback_request) {
+    return feedback_request ? kValueSizeBytes
+                            : kValueSizeBytesWithoutFeedbackRequest;
+  }
+  static bool Write(rtc::ArrayView<uint8_t> data,
+                    uint16_t transport_sequence_number,
+                    const absl::optional<FeedbackRequest>& feedback_request);
+
+ private:
+  static constexpr uint16_t kIncludeTimestampsBit = 1 << 15;
 };
 
 class VideoOrientation {
@@ -186,10 +215,10 @@
  public:
   using value_type = ColorSpace;
   static constexpr RTPExtensionType kId = kRtpExtensionColorSpace;
-  static constexpr uint8_t kValueSizeBytes = 30;
+  static constexpr uint8_t kValueSizeBytes = 28;
   static constexpr uint8_t kValueSizeBytesWithoutHdrMetadata = 4;
-  // TODO(webrtc:8651): Change to a valid uri.
-  static constexpr const char kUri[] = "rtp-colorspace-uri-placeholder";
+  static constexpr const char kUri[] =
+      "http://www.webrtc.org/experiments/rtp-hdrext/color-space";
 
   static bool Parse(rtc::ArrayView<const uint8_t> data,
                     ColorSpace* color_space);
@@ -201,12 +230,21 @@
                     const ColorSpace& color_space);
 
  private:
-  static constexpr int kChromaticityDenominator = 10000;  // 0.0001 resolution.
-  static constexpr int kLuminanceMaxDenominator = 100;    // 0.01 resolution.
+  static constexpr int kChromaticityDenominator = 50000;  // 0.00002 resolution.
+  static constexpr int kLuminanceMaxDenominator = 1;      // 1 resolution.
   static constexpr int kLuminanceMinDenominator = 10000;  // 0.0001 resolution.
+
+  static uint8_t CombineRangeAndChromaSiting(
+      ColorSpace::RangeID range,
+      ColorSpace::ChromaSiting chroma_siting_horizontal,
+      ColorSpace::ChromaSiting chroma_siting_vertical);
+  static size_t ParseHdrMetadata(rtc::ArrayView<const uint8_t> data,
+                                 HdrMetadata* hdr_metadata);
   static size_t ParseChromaticity(const uint8_t* data,
                                   HdrMasteringMetadata::Chromaticity* p);
   static size_t ParseLuminance(const uint8_t* data, float* f, int denominator);
+  static size_t WriteHdrMetadata(rtc::ArrayView<uint8_t> data,
+                                 const HdrMetadata& hdr_metadata);
   static size_t WriteChromaticity(uint8_t* data,
                                   const HdrMasteringMetadata::Chromaticity& p);
   static size_t WriteLuminance(uint8_t* data, float f, int denominator);
diff --git a/modules/rtp_rtcp/source/rtp_header_parser.cc b/modules/rtp_rtcp/source/rtp_header_parser.cc
index 6481a40..4e4c723 100644
--- a/modules/rtp_rtcp/source/rtp_header_parser.cc
+++ b/modules/rtp_rtcp/source/rtp_header_parser.cc
@@ -13,7 +13,7 @@
 
 #include "modules/rtp_rtcp/include/rtp_header_extension_map.h"
 #include "modules/rtp_rtcp/source/rtp_utility.h"
-#include "rtc_base/criticalsection.h"
+#include "rtc_base/critical_section.h"
 #include "rtc_base/thread_annotations.h"
 
 namespace webrtc {
diff --git a/modules/rtp_rtcp/source/rtp_packet.cc b/modules/rtp_rtcp/source/rtp_packet.cc
index 9d4dce4..91f0c59 100644
--- a/modules/rtp_rtcp/source/rtp_packet.cc
+++ b/modules/rtp_rtcp/source/rtp_packet.cc
@@ -14,7 +14,7 @@
 #include <cstring>
 #include <utility>
 
-#include "api/rtpparameters.h"
+#include "api/rtp_parameters.h"
 #include "modules/rtp_rtcp/source/byte_io.h"
 #include "rtc_base/checks.h"
 #include "rtc_base/logging.h"
@@ -61,12 +61,10 @@
 RtpPacket::RtpPacket(const RtpPacket&) = default;
 
 RtpPacket::RtpPacket(const ExtensionManager* extensions, size_t capacity)
-    : buffer_(capacity) {
+    : extensions_(extensions ? *extensions : ExtensionManager()),
+      buffer_(capacity) {
   RTC_DCHECK_GE(capacity, kFixedHeaderSize);
   Clear();
-  if (extensions) {
-    extensions_ = *extensions;
-  }
 }
 
 RtpPacket::~RtpPacket() {}
@@ -569,4 +567,9 @@
   return AllocateRawExtension(id, length);
 }
 
+bool RtpPacket::HasExtension(ExtensionType type) const {
+  // TODO(webrtc:7990): Add support for empty extensions (length==0).
+  return !FindExtension(type).empty();
+}
+
 }  // namespace webrtc
diff --git a/modules/rtp_rtcp/source/rtp_packet.h b/modules/rtp_rtcp/source/rtp_packet.h
index 76666b7..c067580 100644
--- a/modules/rtp_rtcp/source/rtp_packet.h
+++ b/modules/rtp_rtcp/source/rtp_packet.h
@@ -16,7 +16,7 @@
 #include "api/array_view.h"
 #include "modules/rtp_rtcp/include/rtp_header_extension_map.h"
 #include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
-#include "rtc_base/copyonwritebuffer.h"
+#include "rtc_base/copy_on_write_buffer.h"
 #include "rtc_base/deprecation.h"
 
 namespace webrtc {
@@ -95,6 +95,7 @@
   // Header extensions.
   template <typename Extension>
   bool HasExtension() const;
+  bool HasExtension(ExtensionType type) const;
 
   template <typename Extension, typename FirstValue, typename... Values>
   bool GetExtension(FirstValue, Values...) const;
@@ -112,6 +113,14 @@
   template <typename Extension>
   bool ReserveExtension();
 
+  // 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);
+
+  // Find an extension |type|.
+  // Returns view of the raw extension or empty view on failure.
+  rtc::ArrayView<const uint8_t> FindExtension(ExtensionType type) const;
+
   // 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.
@@ -145,10 +154,6 @@
   // with the specified id if not found.
   ExtensionInfo& FindOrCreateExtensionInfo(int id);
 
-  // Find an extension |type|.
-  // 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);
@@ -159,10 +164,6 @@
 
   uint16_t SetExtensionLengthMaybeAddZeroPadding(size_t extensions_offset);
 
-  // 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) { return buffer_.data() + offset; }
   void WriteAt(size_t offset, uint8_t byte) { buffer_.data()[offset] = byte; }
 
@@ -184,7 +185,7 @@
 
 template <typename Extension>
 bool RtpPacket::HasExtension() const {
-  return !FindExtension(Extension::kId).empty();
+  return HasExtension(Extension::kId);
 }
 
 template <typename Extension, typename FirstValue, typename... Values>
diff --git a/modules/rtp_rtcp/source/rtp_packet_history.cc b/modules/rtp_rtcp/source/rtp_packet_history.cc
index 8c1c8eb..ac39e22 100644
--- a/modules/rtp_rtcp/source/rtp_packet_history.cc
+++ b/modules/rtp_rtcp/source/rtp_packet_history.cc
@@ -315,7 +315,7 @@
   state.send_time_ms = stored_packet.send_time_ms;
   state.capture_time_ms = stored_packet.packet->capture_time_ms();
   state.ssrc = stored_packet.packet->Ssrc();
-  state.payload_size = stored_packet.packet->size();
+  state.packet_size = stored_packet.packet->size();
   state.times_retransmitted = stored_packet.times_retransmitted;
   return state;
 }
diff --git a/modules/rtp_rtcp/source/rtp_packet_history.h b/modules/rtp_rtcp/source/rtp_packet_history.h
index 095424e..5e6463b 100644
--- a/modules/rtp_rtcp/source/rtp_packet_history.h
+++ b/modules/rtp_rtcp/source/rtp_packet_history.h
@@ -16,8 +16,8 @@
 #include <vector>
 
 #include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
-#include "rtc_base/constructormagic.h"
-#include "rtc_base/criticalsection.h"
+#include "rtc_base/constructor_magic.h"
+#include "rtc_base/critical_section.h"
 #include "rtc_base/thread_annotations.h"
 
 namespace webrtc {
@@ -44,7 +44,7 @@
     absl::optional<int64_t> send_time_ms;
     int64_t capture_time_ms = 0;
     uint32_t ssrc = 0;
-    size_t payload_size = 0;
+    size_t packet_size = 0;
     // Number of times RE-transmitted, ie not including the first transmission.
     size_t times_retransmitted = 0;
   };
diff --git a/modules/rtp_rtcp/source/rtp_packet_history_unittest.cc b/modules/rtp_rtcp/source/rtp_packet_history_unittest.cc
index 140434c..afa158c 100644
--- a/modules/rtp_rtcp/source/rtp_packet_history_unittest.cc
+++ b/modules/rtp_rtcp/source/rtp_packet_history_unittest.cc
@@ -191,7 +191,7 @@
   EXPECT_EQ(state->send_time_ms, fake_clock_.TimeInMilliseconds());
   EXPECT_EQ(state->capture_time_ms, fake_clock_.TimeInMilliseconds());
   EXPECT_EQ(state->ssrc, kSsrc);
-  EXPECT_EQ(state->payload_size, packet_size);
+  EXPECT_EQ(state->packet_size, packet_size);
   EXPECT_EQ(state->times_retransmitted, 0u);
 
   fake_clock_.AdvanceTimeMilliseconds(1);
@@ -228,7 +228,7 @@
   absl::optional<RtpPacketHistory::PacketState> packet_state =
       hist_.GetPacketState(kStartSeqNum);
   EXPECT_TRUE(packet_state);
-  EXPECT_EQ(len, packet_state->payload_size);
+  EXPECT_EQ(len, packet_state->packet_size);
   EXPECT_EQ(capture_time_ms, packet_state->capture_time_ms);
 
   // Retransmission was allowed, next send it from pacer.
diff --git a/modules/rtp_rtcp/source/rtp_packet_received.cc b/modules/rtp_rtcp/source/rtp_packet_received.cc
index f80fad6..2a36b7b 100644
--- a/modules/rtp_rtcp/source/rtp_packet_received.cc
+++ b/modules/rtp_rtcp/source/rtp_packet_received.cc
@@ -52,6 +52,9 @@
   header->extension.hasAbsoluteSendTime =
       GetExtension<AbsoluteSendTime>(&header->extension.absoluteSendTime);
   header->extension.hasTransportSequenceNumber =
+      GetExtension<TransportSequenceNumberV2>(
+          &header->extension.transportSequenceNumber,
+          &header->extension.feedback_request) ||
       GetExtension<TransportSequenceNumber>(
           &header->extension.transportSequenceNumber);
   header->extension.hasAudioLevel = GetExtension<AudioLevel>(
diff --git a/modules/rtp_rtcp/source/rtp_packet_to_send.h b/modules/rtp_rtcp/source/rtp_packet_to_send.h
index 56b1024..21c9c86 100644
--- a/modules/rtp_rtcp/source/rtp_packet_to_send.h
+++ b/modules/rtp_rtcp/source/rtp_packet_to_send.h
@@ -38,6 +38,10 @@
 
   void set_capture_time_ms(int64_t time) { capture_time_ms_ = time; }
 
+  bool is_fec() const { return is_fec_; }
+
+  void set_is_fec(bool fec) { is_fec_ = fec; }
+
   // Additional data bound to the RTP packet for use in application code,
   // outside of WebRTC.
   rtc::ArrayView<const uint8_t> application_data() const {
@@ -74,6 +78,8 @@
 
  private:
   int64_t capture_time_ms_ = 0;
+  // Used for accounting purposes
+  bool is_fec_ = false;
   std::vector<uint8_t> application_data_;
 };
 
diff --git a/modules/rtp_rtcp/source/rtp_packet_unittest.cc b/modules/rtp_rtcp/source/rtp_packet_unittest.cc
index b1c0e42..84f5020 100644
--- a/modules/rtp_rtcp/source/rtp_packet_unittest.cc
+++ b/modules/rtp_rtcp/source/rtp_packet_unittest.cc
@@ -10,6 +10,7 @@
 #include "modules/rtp_rtcp/source/rtp_packet_received.h"
 #include "modules/rtp_rtcp/source/rtp_packet_to_send.h"
 
+#include "common_video/test/utilities.h"
 #include "modules/rtp_rtcp/include/rtp_header_extension_map.h"
 #include "modules/rtp_rtcp/source/rtp_header_extensions.h"
 #include "rtc_base/random.h"
@@ -186,35 +187,6 @@
     0x00, 0x00, 0x00, 0x00};
 // clang-format on
 
-HdrMetadata CreateTestHdrMetadata() {
-  // Random but reasonable HDR metadata.
-  HdrMetadata hdr_metadata;
-  hdr_metadata.mastering_metadata.luminance_max = 2000.0;
-  hdr_metadata.mastering_metadata.luminance_min = 2.0001;
-  hdr_metadata.mastering_metadata.primary_r.x = 0.3003;
-  hdr_metadata.mastering_metadata.primary_r.y = 0.4004;
-  hdr_metadata.mastering_metadata.primary_g.x = 0.3201;
-  hdr_metadata.mastering_metadata.primary_g.y = 0.4604;
-  hdr_metadata.mastering_metadata.primary_b.x = 0.3409;
-  hdr_metadata.mastering_metadata.primary_b.y = 0.4907;
-  hdr_metadata.mastering_metadata.white_point.x = 0.4103;
-  hdr_metadata.mastering_metadata.white_point.y = 0.4806;
-  hdr_metadata.max_content_light_level = 2345;
-  hdr_metadata.max_frame_average_light_level = 1789;
-  return hdr_metadata;
-}
-
-ColorSpace CreateTestColorSpace(bool with_hdr_metadata) {
-  ColorSpace color_space(
-      ColorSpace::PrimaryID::kBT709, ColorSpace::TransferID::kGAMMA22,
-      ColorSpace::MatrixID::kSMPTE2085, ColorSpace::RangeID::kFull);
-  if (with_hdr_metadata) {
-    HdrMetadata hdr_metadata = CreateTestHdrMetadata();
-    color_space.set_hdr_metadata(&hdr_metadata);
-  }
-  return color_space;
-}
-
 void TestCreateAndParseColorSpaceExtension(bool with_hdr_metadata) {
   // Create packet with extension.
   RtpPacket::ExtensionManager extensions(/*extmap-allow-mixed=*/true);
@@ -855,4 +827,129 @@
   TestCreateAndParseColorSpaceExtension(/*with_hdr_metadata=*/false);
 }
 
+TEST(RtpPacketTest, CreateAndParseTransportSequenceNumber) {
+  // Create a packet with transport sequence number extension populated.
+  RtpPacketToSend::ExtensionManager extensions;
+  constexpr int kExtensionId = 1;
+  extensions.Register<TransportSequenceNumber>(kExtensionId);
+  RtpPacketToSend send_packet(&extensions);
+  send_packet.SetPayloadType(kPayloadType);
+  send_packet.SetSequenceNumber(kSeqNum);
+  send_packet.SetTimestamp(kTimestamp);
+  send_packet.SetSsrc(kSsrc);
+
+  constexpr int kTransportSequenceNumber = 12345;
+  send_packet.SetExtension<TransportSequenceNumber>(kTransportSequenceNumber);
+
+  // Serialize the packet and then parse it again.
+  RtpPacketReceived receive_packet(&extensions);
+  EXPECT_TRUE(receive_packet.Parse(send_packet.Buffer()));
+
+  uint16_t received_transport_sequeunce_number;
+  EXPECT_TRUE(receive_packet.GetExtension<TransportSequenceNumber>(
+      &received_transport_sequeunce_number));
+  EXPECT_EQ(received_transport_sequeunce_number, kTransportSequenceNumber);
+}
+
+TEST(RtpPacketTest, CreateAndParseTransportSequenceNumberV2) {
+  // Create a packet with transport sequence number V2 extension populated.
+  // No feedback request means that the extension will be two bytes unless it's
+  // pre-allocated.
+  RtpPacketToSend::ExtensionManager extensions;
+  constexpr int kExtensionId = 1;
+  extensions.Register<TransportSequenceNumberV2>(kExtensionId);
+  RtpPacketToSend send_packet(&extensions);
+  send_packet.SetPayloadType(kPayloadType);
+  send_packet.SetSequenceNumber(kSeqNum);
+  send_packet.SetTimestamp(kTimestamp);
+  send_packet.SetSsrc(kSsrc);
+
+  constexpr int kTransportSequenceNumber = 12345;
+  send_packet.SetExtension<TransportSequenceNumberV2>(kTransportSequenceNumber,
+                                                      absl::nullopt);
+  EXPECT_EQ(send_packet.GetRawExtension<TransportSequenceNumberV2>().size(),
+            2u);
+
+  // Serialize the packet and then parse it again.
+  RtpPacketReceived receive_packet(&extensions);
+  EXPECT_TRUE(receive_packet.Parse(send_packet.Buffer()));
+
+  uint16_t received_transport_sequeunce_number;
+  absl::optional<FeedbackRequest> received_feedback_request;
+  EXPECT_TRUE(receive_packet.GetExtension<TransportSequenceNumberV2>(
+      &received_transport_sequeunce_number, &received_feedback_request));
+  EXPECT_EQ(received_transport_sequeunce_number, kTransportSequenceNumber);
+  EXPECT_FALSE(received_feedback_request);
+}
+
+TEST(RtpPacketTest, CreateAndParseTransportSequenceNumberV2Preallocated) {
+  // Create a packet with transport sequence number V2 extension populated.
+  // No feedback request means that the extension could be two bytes, but since
+  // it's pre-allocated we don't know if it is with or without feedback request
+  // therefore the size is four bytes.
+  RtpPacketToSend::ExtensionManager extensions;
+  constexpr int kExtensionId = 1;
+  extensions.Register<TransportSequenceNumberV2>(kExtensionId);
+  RtpPacketToSend send_packet(&extensions);
+  send_packet.SetPayloadType(kPayloadType);
+  send_packet.SetSequenceNumber(kSeqNum);
+  send_packet.SetTimestamp(kTimestamp);
+  send_packet.SetSsrc(kSsrc);
+
+  constexpr int kTransportSequenceNumber = 12345;
+  constexpr absl::optional<FeedbackRequest> kNoFeedbackRequest =
+      FeedbackRequest{/*include_timestamps=*/false, /*sequence_count=*/0};
+  send_packet.ReserveExtension<TransportSequenceNumberV2>();
+  send_packet.SetExtension<TransportSequenceNumberV2>(kTransportSequenceNumber,
+                                                      kNoFeedbackRequest);
+  EXPECT_EQ(send_packet.GetRawExtension<TransportSequenceNumberV2>().size(),
+            4u);
+
+  // Serialize the packet and then parse it again.
+  RtpPacketReceived receive_packet(&extensions);
+  EXPECT_TRUE(receive_packet.Parse(send_packet.Buffer()));
+
+  uint16_t received_transport_sequeunce_number;
+  absl::optional<FeedbackRequest> received_feedback_request;
+  EXPECT_TRUE(receive_packet.GetExtension<TransportSequenceNumberV2>(
+      &received_transport_sequeunce_number, &received_feedback_request));
+  EXPECT_EQ(received_transport_sequeunce_number, kTransportSequenceNumber);
+  EXPECT_FALSE(received_feedback_request);
+}
+
+TEST(RtpPacketTest,
+     CreateAndParseTransportSequenceNumberV2WithFeedbackRequest) {
+  // Create a packet with TransportSequenceNumberV2 extension populated.
+  RtpPacketToSend::ExtensionManager extensions;
+  constexpr int kExtensionId = 1;
+  extensions.Register<TransportSequenceNumberV2>(kExtensionId);
+  RtpPacketToSend send_packet(&extensions);
+  send_packet.SetPayloadType(kPayloadType);
+  send_packet.SetSequenceNumber(kSeqNum);
+  send_packet.SetTimestamp(kTimestamp);
+  send_packet.SetSsrc(kSsrc);
+
+  constexpr int kTransportSequenceNumber = 12345;
+  constexpr absl::optional<FeedbackRequest> kFeedbackRequest =
+      FeedbackRequest{/*include_timestamps=*/true, /*sequence_count=*/3};
+  send_packet.SetExtension<TransportSequenceNumberV2>(kTransportSequenceNumber,
+                                                      kFeedbackRequest);
+
+  // Serialize the packet and then parse it again.
+  RtpPacketReceived receive_packet(&extensions);
+  EXPECT_TRUE(receive_packet.Parse(send_packet.Buffer()));
+
+  // Parse transport sequence number and feedback request.
+  uint16_t received_transport_sequeunce_number;
+  absl::optional<FeedbackRequest> received_feedback_request;
+  EXPECT_TRUE(receive_packet.GetExtension<TransportSequenceNumberV2>(
+      &received_transport_sequeunce_number, &received_feedback_request));
+  EXPECT_EQ(received_transport_sequeunce_number, kTransportSequenceNumber);
+  ASSERT_TRUE(received_feedback_request);
+  EXPECT_EQ(received_feedback_request->include_timestamps,
+            kFeedbackRequest->include_timestamps);
+  EXPECT_EQ(received_feedback_request->sequence_count,
+            kFeedbackRequest->sequence_count);
+}
+
 }  // namespace webrtc
diff --git a/modules/rtp_rtcp/source/rtp_rtcp_impl.cc b/modules/rtp_rtcp/source/rtp_rtcp_impl.cc
index 0d0ca96..2adddff 100644
--- a/modules/rtp_rtcp/source/rtp_rtcp_impl.cc
+++ b/modules/rtp_rtcp/source/rtp_rtcp_impl.cc
@@ -17,6 +17,8 @@
 #include <string>
 #include <utility>
 
+#include "absl/memory/memory.h"
+#include "api/transport/field_trial_based_config.h"
 #include "modules/rtp_rtcp/source/rtcp_packet/dlrr.h"
 #include "modules/rtp_rtcp/source/rtp_rtcp_config.h"
 #include "rtc_base/checks.h"
@@ -51,14 +53,6 @@
   }
 }
 
-// Deprecated.
-int32_t RtpRtcp::SetFecParameters(const FecProtectionParams* delta_params,
-                                  const FecProtectionParams* key_params) {
-  RTC_DCHECK(delta_params);
-  RTC_DCHECK(key_params);
-  return SetFecParameters(*delta_params, *key_params) ? 0 : -1;
-}
-
 ModuleRtpRtcpImpl::ModuleRtpRtcpImpl(const Configuration& configuration)
     : rtcp_sender_(configuration.audio,
                    configuration.clock,
@@ -83,7 +77,6 @@
                                                 : kDefaultVideoReportInterval),
                      this),
       clock_(configuration.clock),
-      audio_(configuration.audio),
       keepalive_config_(configuration.keepalive_config),
       last_bitrate_process_time_(clock_->TimeInMilliseconds()),
       last_rtt_process_time_(clock_->TimeInMilliseconds()),
@@ -95,24 +88,32 @@
       nack_last_seq_number_sent_(0),
       key_frame_req_method_(kKeyFrameReqPliRtcp),
       remote_bitrate_(configuration.remote_bitrate_estimator),
+      ack_observer_(configuration.ack_observer),
       rtt_stats_(configuration.rtt_stats),
       rtt_ms_(0) {
+  FieldTrialBasedConfig default_trials;
   if (!configuration.receiver_only) {
     rtp_sender_.reset(new RTPSender(
         configuration.audio, configuration.clock,
         configuration.outgoing_transport, configuration.paced_sender,
-        configuration.flexfec_sender,
+        configuration.flexfec_sender
+            ? absl::make_optional(configuration.flexfec_sender->ssrc())
+            : absl::nullopt,
         configuration.transport_sequence_number_allocator,
         configuration.transport_feedback_callback,
         configuration.send_bitrate_observer,
-        configuration.send_frame_count_observer,
         configuration.send_side_delay_observer, configuration.event_log,
         configuration.send_packet_observer,
         configuration.retransmission_rate_limiter,
         configuration.overhead_observer,
         configuration.populate_network2_timestamp,
         configuration.frame_encryptor, configuration.require_frame_encryption,
-        configuration.extmap_allow_mixed));
+        configuration.extmap_allow_mixed,
+        configuration.field_trials ? *configuration.field_trials
+                                   : default_trials));
+    if (configuration.audio) {
+      audio_ = absl::make_unique<RTPSenderAudio>(clock_, rtp_sender_.get());
+    }
     // Make sure rtcp sender use same timestamp offset as rtp sender.
     rtcp_sender_.SetTimestampOffset(rtp_sender_->TimestampOffset());
 
@@ -264,23 +265,24 @@
   rtcp_receiver_.IncomingPacket(rtcp_packet, length);
 }
 
-int32_t ModuleRtpRtcpImpl::RegisterSendPayload(const CodecInst& voice_codec) {
-  rtcp_sender_.SetRtpClockRate(voice_codec.pltype, voice_codec.plfreq);
-  return rtp_sender_->RegisterPayload(
-      voice_codec.plname, voice_codec.pltype, voice_codec.plfreq,
-      voice_codec.channels, (voice_codec.rate < 0) ? 0 : voice_codec.rate);
+void ModuleRtpRtcpImpl::RegisterAudioSendPayload(int payload_type,
+                                                 absl::string_view payload_name,
+                                                 int frequency,
+                                                 int channels,
+                                                 int rate) {
+  RTC_DCHECK(audio_);
+  rtcp_sender_.SetRtpClockRate(payload_type, frequency);
+  RTC_CHECK_EQ(0, audio_->RegisterAudioPayload(payload_name, payload_type,
+                                               frequency, channels, rate));
 }
 
-void ModuleRtpRtcpImpl::RegisterVideoSendPayload(int payload_type,
-                                                 const char* payload_name) {
-  rtcp_sender_.SetRtpClockRate(payload_type, kVideoPayloadTypeFrequency);
-  RTC_CHECK_EQ(0,
-               rtp_sender_->RegisterPayload(payload_name, payload_type,
-                                            kVideoPayloadTypeFrequency, 0, 0));
+void ModuleRtpRtcpImpl::RegisterSendPayloadFrequency(int payload_type,
+                                                     int payload_frequency) {
+  rtcp_sender_.SetRtpClockRate(payload_type, payload_frequency);
 }
 
 int32_t ModuleRtpRtcpImpl::DeRegisterSendPayload(const int8_t payload_type) {
-  return rtp_sender_->DeRegisterSendPayload(payload_type);
+  return 0;
 }
 
 uint32_t ModuleRtpRtcpImpl::StartTimestamp() const {
@@ -331,6 +333,12 @@
   SetRtcpReceiverSsrcs(ssrc);
 }
 
+void ModuleRtpRtcpImpl::SetRid(const std::string& rid) {
+  if (rtp_sender_) {
+    rtp_sender_->SetRid(rid);
+  }
+}
+
 void ModuleRtpRtcpImpl::SetMid(const std::string& mid) {
   if (rtp_sender_) {
     rtp_sender_->SetMid(mid);
@@ -422,25 +430,33 @@
     const RTPFragmentationHeader* fragmentation,
     const RTPVideoHeader* rtp_video_header,
     uint32_t* transport_frame_id_out) {
-  rtcp_sender_.SetLastRtpTime(time_stamp, capture_time_ms, payload_type);
+  OnSendingRtpFrame(time_stamp, capture_time_ms, payload_type,
+                    kVideoFrameKey == frame_type);
+
+  const uint32_t rtp_timestamp = time_stamp + rtp_sender_->TimestampOffset();
+  if (transport_frame_id_out)
+    *transport_frame_id_out = rtp_timestamp;
+
+  RTC_DCHECK(audio_);
+  RTC_DCHECK(fragmentation == nullptr);
+
+  return audio_->SendAudio(frame_type, payload_type, rtp_timestamp,
+                           payload_data, payload_size);
+}
+
+bool ModuleRtpRtcpImpl::OnSendingRtpFrame(uint32_t timestamp,
+                                          int64_t capture_time_ms,
+                                          int payload_type,
+                                          bool force_sender_report) {
+  if (!Sending())
+    return false;
+
+  rtcp_sender_.SetLastRtpTime(timestamp, capture_time_ms, payload_type);
   // Make sure an RTCP report isn't queued behind a key frame.
-  if (rtcp_sender_.TimeToSendRTCPReport(kVideoFrameKey == frame_type)) {
+  if (rtcp_sender_.TimeToSendRTCPReport(force_sender_report))
     rtcp_sender_.SendRTCP(GetFeedbackState(), kRtcpReport);
-  }
-  int64_t expected_retransmission_time_ms = rtt_ms();
-  if (expected_retransmission_time_ms == 0) {
-    // No rtt available (|kRtpRtcpRttProcessTimeMs| not yet passed?), so try to
-    // poll avg_rtt_ms directly from rtcp receiver.
-    if (rtcp_receiver_.RTT(rtcp_receiver_.RemoteSSRC(), nullptr,
-                           &expected_retransmission_time_ms, nullptr,
-                           nullptr) == -1) {
-      expected_retransmission_time_ms = kDefaultExpectedRetransmissionTimeMs;
-    }
-  }
-  return rtp_sender_->SendOutgoingData(
-      frame_type, payload_type, time_stamp, capture_time_ms, payload_data,
-      payload_size, fragmentation, rtp_video_header, transport_frame_id_out,
-      expected_retransmission_time_ms);
+
+  return true;
 }
 
 bool ModuleRtpRtcpImpl::TimeToSendPacket(uint32_t ssrc,
@@ -525,6 +541,21 @@
   return ret;
 }
 
+int64_t ModuleRtpRtcpImpl::ExpectedRetransmissionTimeMs() const {
+  int64_t expected_retransmission_time_ms = rtt_ms();
+  if (expected_retransmission_time_ms > 0) {
+    return expected_retransmission_time_ms;
+  }
+  // No rtt available (|kRtpRtcpRttProcessTimeMs| not yet passed?), so try to
+  // poll avg_rtt_ms directly from rtcp receiver.
+  if (rtcp_receiver_.RTT(rtcp_receiver_.RemoteSSRC(), nullptr,
+                         &expected_retransmission_time_ms, nullptr,
+                         nullptr) == 0) {
+    return expected_retransmission_time_ms;
+  }
+  return kDefaultExpectedRetransmissionTimeMs;
+}
+
 // Force a send of an RTCP packet.
 // Normal SR and RR are triggered via the process function.
 int32_t ModuleRtpRtcpImpl::SendRTCP(RTCPPacketType packet_type) {
@@ -666,17 +697,6 @@
   rtcp_sender_.SetTmmbn(std::move(bounding_set));
 }
 
-// Returns the currently configured retransmission mode.
-int ModuleRtpRtcpImpl::SelectiveRetransmissions() const {
-  return rtp_sender_->SelectiveRetransmissions();
-}
-
-// Enable or disable a retransmission mode, which decides which packets will
-// be retransmitted if NACKed.
-int ModuleRtpRtcpImpl::SetSelectiveRetransmissions(uint8_t settings) {
-  return rtp_sender_->SetSelectiveRetransmissions(settings);
-}
-
 // Send a Negative acknowledgment packet.
 int32_t ModuleRtpRtcpImpl::SendNACK(const uint16_t* nack_list,
                                     const uint16_t size) {
@@ -766,11 +786,11 @@
 int32_t ModuleRtpRtcpImpl::SendTelephoneEventOutband(const uint8_t key,
                                                      const uint16_t time_ms,
                                                      const uint8_t level) {
-  return rtp_sender_->SendTelephoneEvent(key, time_ms, level);
+  return audio_ ? audio_->SendTelephoneEvent(key, time_ms, level) : -1;
 }
 
 int32_t ModuleRtpRtcpImpl::SetAudioLevel(const uint8_t level_d_bov) {
-  return rtp_sender_->SetAudioLevel(level_d_bov);
+  return audio_ ? audio_->SetAudioLevel(level_d_bov) : -1;
 }
 
 int32_t ModuleRtpRtcpImpl::SetKeyFrameRequestMethod(
@@ -789,15 +809,12 @@
   return -1;
 }
 
-void ModuleRtpRtcpImpl::SetUlpfecConfig(int red_payload_type,
-                                        int ulpfec_payload_type) {
-  rtp_sender_->SetUlpfecConfig(red_payload_type, ulpfec_payload_type);
-}
-
-bool ModuleRtpRtcpImpl::SetFecParameters(
-    const FecProtectionParams& delta_params,
-    const FecProtectionParams& key_params) {
-  return rtp_sender_->SetFecParameters(delta_params, key_params);
+int32_t ModuleRtpRtcpImpl::SendLossNotification(uint16_t last_decoded_seq_num,
+                                                uint16_t last_received_seq_num,
+                                                bool decodability_flag) {
+  return rtcp_sender_.SendLossNotification(
+      GetFeedbackState(), last_decoded_seq_num, last_received_seq_num,
+      decodability_flag);
 }
 
 void ModuleRtpRtcpImpl::SetRemoteSSRC(const uint32_t ssrc) {
@@ -806,13 +823,16 @@
   rtcp_receiver_.SetRemoteSSRC(ssrc);
 }
 
+// TODO(nisse): Delete video_rate amd fec_rate arguments.
 void ModuleRtpRtcpImpl::BitrateSent(uint32_t* total_rate,
                                     uint32_t* video_rate,
                                     uint32_t* fec_rate,
                                     uint32_t* nack_rate) const {
   *total_rate = rtp_sender_->BitrateSent();
-  *video_rate = rtp_sender_->VideoBitrateSent();
-  *fec_rate = rtp_sender_->FecOverheadRate();
+  if (video_rate)
+    *video_rate = 0;
+  if (fec_rate)
+    *fec_rate = 0;
   *nack_rate = rtp_sender_->NackOverheadRate();
 }
 
@@ -841,8 +861,16 @@
 
 void ModuleRtpRtcpImpl::OnReceivedRtcpReportBlocks(
     const ReportBlockList& report_blocks) {
-  if (rtp_sender_)
-    rtp_sender_->OnReceivedRtcpReportBlocks(report_blocks);
+  if (ack_observer_) {
+    uint32_t ssrc = SSRC();
+
+    for (const RTCPReportBlock& report_block : report_blocks) {
+      if (ssrc == report_block.source_ssrc) {
+        ack_observer_->OnReceivedAck(
+            report_block.extended_highest_sequence_number);
+      }
+    }
+  }
 }
 
 bool ModuleRtpRtcpImpl::LastReceivedNTP(
@@ -904,4 +932,13 @@
     const VideoBitrateAllocation& bitrate) {
   rtcp_sender_.SetVideoBitrateAllocation(bitrate);
 }
+
+RTPSender* ModuleRtpRtcpImpl::RtpSender() {
+  return rtp_sender_.get();
+}
+
+const RTPSender* ModuleRtpRtcpImpl::RtpSender() const {
+  return rtp_sender_.get();
+}
+
 }  // namespace webrtc
diff --git a/modules/rtp_rtcp/source/rtp_rtcp_impl.h b/modules/rtp_rtcp/source/rtp_rtcp_impl.h
index 8e9751d..20eb179 100644
--- a/modules/rtp_rtcp/source/rtp_rtcp_impl.h
+++ b/modules/rtp_rtcp/source/rtp_rtcp_impl.h
@@ -32,7 +32,9 @@
 #include "modules/rtp_rtcp/source/rtcp_receiver.h"
 #include "modules/rtp_rtcp/source/rtcp_sender.h"
 #include "modules/rtp_rtcp/source/rtp_sender.h"
-#include "rtc_base/criticalsection.h"
+#include "modules/rtp_rtcp/source/rtp_sender_audio.h"
+#include "modules/rtp_rtcp/source/rtp_sender_video.h"
+#include "rtc_base/critical_section.h"
 #include "rtc_base/gtest_prod_util.h"
 
 namespace webrtc {
@@ -63,10 +65,13 @@
 
   // Sender part.
 
-  int32_t RegisterSendPayload(const CodecInst& voice_codec) override;
-
-  void RegisterVideoSendPayload(int payload_type,
-                                const char* payload_name) override;
+  void RegisterAudioSendPayload(int payload_type,
+                                absl::string_view payload_name,
+                                int frequency,
+                                int channels,
+                                int rate) override;
+  void RegisterSendPayloadFrequency(int payload_type,
+                                    int payload_frequency) override;
 
   int32_t DeRegisterSendPayload(int8_t payload_type) override;
 
@@ -102,6 +107,8 @@
   // Configure SSRC, default is a random number.
   void SetSSRC(uint32_t ssrc) override;
 
+  void SetRid(const std::string& rid) override;
+
   void SetMid(const std::string& mid) override;
 
   void SetCsrcs(const std::vector<uint32_t>& csrcs) override;
@@ -142,6 +149,11 @@
                         const RTPVideoHeader* rtp_video_header,
                         uint32_t* transport_frame_id_out) override;
 
+  bool OnSendingRtpFrame(uint32_t timestamp,
+                         int64_t capture_time_ms,
+                         int payload_type,
+                         bool force_sender_report) override;
+
   bool TimeToSendPacket(uint32_t ssrc,
                         uint16_t sequence_number,
                         int64_t capture_time_ms,
@@ -186,6 +198,8 @@
               int64_t* min_rtt,
               int64_t* max_rtt) const override;
 
+  int64_t ExpectedRetransmissionTimeMs() const override;
+
   // Force a send of an RTCP packet.
   // Normal SR and RR are triggered via the process function.
   int32_t SendRTCP(RTCPPacketType rtcpPacketType) override;
@@ -227,10 +241,6 @@
 
   // (NACK) Negative acknowledgment part.
 
-  int SelectiveRetransmissions() const override;
-
-  int SetSelectiveRetransmissions(uint8_t settings) override;
-
   // Send a Negative acknowledgment packet.
   // TODO(philipel): Deprecate SendNACK and use SendNack instead.
   int32_t SendNACK(const uint16_t* nack_list, uint16_t size) override;
@@ -279,10 +289,9 @@
   // Send a request for a keyframe.
   int32_t RequestKeyFrame() override;
 
-  void SetUlpfecConfig(int red_payload_type, int ulpfec_payload_type) override;
-
-  bool SetFecParameters(const FecProtectionParams& delta_params,
-                        const FecProtectionParams& key_params) override;
+  int32_t SendLossNotification(uint16_t last_decoded_seq_num,
+                               uint16_t last_received_seq_num,
+                               bool decodability_flag) override;
 
   bool LastReceivedNTP(uint32_t* NTPsecs,
                        uint32_t* NTPfrac,
@@ -309,6 +318,9 @@
   void SetVideoBitrateAllocation(
       const VideoBitrateAllocation& bitrate) override;
 
+  RTPSender* RtpSender() override;
+  const RTPSender* RtpSender() const override;
+
  protected:
   bool UpdateRTCPReceiveInformationTimers();
 
@@ -321,7 +333,7 @@
   RTCPReceiver* rtcp_receiver() { return &rtcp_receiver_; }
   const RTCPReceiver* rtcp_receiver() const { return &rtcp_receiver_; }
 
-  const Clock* clock() const { return clock_; }
+  Clock* clock() const { return clock_; }
 
  private:
   FRIEND_TEST_ALL_PREFIXES(RtpRtcpImplTest, Rtt);
@@ -334,12 +346,11 @@
   bool TimeToSendFullNackList(int64_t now) const;
 
   std::unique_ptr<RTPSender> rtp_sender_;
+  std::unique_ptr<RTPSenderAudio> audio_;
   RTCPSender rtcp_sender_;
   RTCPReceiver rtcp_receiver_;
 
-  const Clock* const clock_;
-
-  const bool audio_;
+  Clock* const clock_;
 
   const RtpKeepAliveConfig keepalive_config_;
   int64_t last_bitrate_process_time_;
@@ -354,7 +365,9 @@
 
   KeyFrameRequestMethod key_frame_req_method_;
 
-  RemoteBitrateEstimator* remote_bitrate_;
+  RemoteBitrateEstimator* const remote_bitrate_;
+
+  RtcpAckObserver* const ack_observer_;
 
   RtcpRttStats* const rtt_stats_;
 
diff --git a/modules/rtp_rtcp/source/rtp_rtcp_impl_unittest.cc b/modules/rtp_rtcp/source/rtp_rtcp_impl_unittest.cc
index 632a537..da541a5 100644
--- a/modules/rtp_rtcp/source/rtp_rtcp_impl_unittest.cc
+++ b/modules/rtp_rtcp/source/rtp_rtcp_impl_unittest.cc
@@ -12,9 +12,12 @@
 #include <memory>
 #include <set>
 
+#include "absl/memory/memory.h"
+#include "api/transport/field_trial_based_config.h"
 #include "api/video_codecs/video_codec.h"
 #include "modules/rtp_rtcp/include/rtp_header_parser.h"
 #include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
+#include "modules/rtp_rtcp/source/playout_delay_oracle.h"
 #include "modules/rtp_rtcp/source/rtcp_packet.h"
 #include "modules/rtp_rtcp/source/rtcp_packet/nack.h"
 #include "modules/rtp_rtcp/source/rtp_packet_received.h"
@@ -199,11 +202,15 @@
     sender_.impl_->SetSequenceNumber(kSequenceNumber);
     sender_.impl_->SetStorePacketsStatus(true, 100);
 
+    sender_video_ = absl::make_unique<RTPSenderVideo>(
+        &clock_, sender_.impl_->RtpSender(), nullptr, &playout_delay_oracle_,
+        nullptr, false, FieldTrialBasedConfig());
+
     memset(&codec_, 0, sizeof(VideoCodec));
     codec_.plType = 100;
     codec_.width = 320;
     codec_.height = 180;
-    sender_.impl_->RegisterVideoSendPayload(codec_.plType, "VP8");
+    sender_video_->RegisterPayloadType(codec_.plType, "VP8");
 
     // Receive module.
     EXPECT_EQ(0, receiver_.impl_->SetSendingStatus(false));
@@ -217,10 +224,14 @@
 
   SimulatedClock clock_;
   RtpRtcpModule sender_;
+  PlayoutDelayOracle playout_delay_oracle_;
+  std::unique_ptr<RTPSenderVideo> sender_video_;
   RtpRtcpModule receiver_;
   VideoCodec codec_;
 
-  void SendFrame(const RtpRtcpModule* module, uint8_t tid) {
+  void SendFrame(const RtpRtcpModule* module,
+                 RTPSenderVideo* sender,
+                 uint8_t tid) {
     RTPVideoHeaderVP8 vp8_header = {};
     vp8_header.temporalIdx = tid;
     RTPVideoHeader rtp_video_header;
@@ -236,9 +247,10 @@
     rtp_video_header.video_timing = {0u, 0u, 0u, 0u, 0u, 0u, false};
 
     const uint8_t payload[100] = {0};
-    EXPECT_EQ(true, module->impl_->SendOutgoingData(
-                        kVideoFrameKey, codec_.plType, 0, 0, payload,
-                        sizeof(payload), nullptr, &rtp_video_header, nullptr));
+    EXPECT_TRUE(module->impl_->OnSendingRtpFrame(0, 0, codec_.plType, true));
+    EXPECT_TRUE(sender->SendVideo(kVideoFrameKey, codec_.plType, 0, 0, payload,
+                                  sizeof(payload), nullptr, &rtp_video_header,
+                                  0));
   }
 
   void IncomingRtcpNack(const RtpRtcpModule* module, uint16_t sequence_number) {
@@ -255,44 +267,14 @@
   }
 };
 
-TEST_F(RtpRtcpImplTest, SetSelectiveRetransmissions_BaseLayer) {
-  sender_.impl_->SetSelectiveRetransmissions(kRetransmitBaseLayer);
-  EXPECT_EQ(kRetransmitBaseLayer, sender_.impl_->SelectiveRetransmissions());
-
+TEST_F(RtpRtcpImplTest, RetransmitsAllLayers) {
   // Send frames.
   EXPECT_EQ(0, sender_.RtpSent());
-  SendFrame(&sender_, kBaseLayerTid);    // kSequenceNumber
-  SendFrame(&sender_, kHigherLayerTid);  // kSequenceNumber + 1
-  SendFrame(&sender_, kNoTemporalIdx);   // kSequenceNumber + 2
-  EXPECT_EQ(3, sender_.RtpSent());
-  EXPECT_EQ(kSequenceNumber + 2, sender_.LastRtpSequenceNumber());
-
-  // Min required delay until retransmit = 5 + RTT ms (RTT = 0).
-  clock_.AdvanceTimeMilliseconds(5);
-
-  // Frame with kBaseLayerTid re-sent.
-  IncomingRtcpNack(&sender_, kSequenceNumber);
-  EXPECT_EQ(4, sender_.RtpSent());
-  EXPECT_EQ(kSequenceNumber, sender_.LastRtpSequenceNumber());
-  // Frame with kHigherLayerTid not re-sent.
-  IncomingRtcpNack(&sender_, kSequenceNumber + 1);
-  EXPECT_EQ(4, sender_.RtpSent());
-  // Frame with kNoTemporalIdx re-sent.
-  IncomingRtcpNack(&sender_, kSequenceNumber + 2);
-  EXPECT_EQ(5, sender_.RtpSent());
-  EXPECT_EQ(kSequenceNumber + 2, sender_.LastRtpSequenceNumber());
-}
-
-TEST_F(RtpRtcpImplTest, SetSelectiveRetransmissions_HigherLayers) {
-  const uint8_t kSetting = kRetransmitBaseLayer + kRetransmitHigherLayers;
-  sender_.impl_->SetSelectiveRetransmissions(kSetting);
-  EXPECT_EQ(kSetting, sender_.impl_->SelectiveRetransmissions());
-
-  // Send frames.
-  EXPECT_EQ(0, sender_.RtpSent());
-  SendFrame(&sender_, kBaseLayerTid);    // kSequenceNumber
-  SendFrame(&sender_, kHigherLayerTid);  // kSequenceNumber + 1
-  SendFrame(&sender_, kNoTemporalIdx);   // kSequenceNumber + 2
+  SendFrame(&sender_, sender_video_.get(), kBaseLayerTid);  // kSequenceNumber
+  SendFrame(&sender_, sender_video_.get(),
+            kHigherLayerTid);  // kSequenceNumber + 1
+  SendFrame(&sender_, sender_video_.get(),
+            kNoTemporalIdx);  // kSequenceNumber + 2
   EXPECT_EQ(3, sender_.RtpSent());
   EXPECT_EQ(kSequenceNumber + 2, sender_.LastRtpSequenceNumber());
 
@@ -322,7 +304,7 @@
   receiver_.receive_statistics_->OnRtpPacket(packet);
 
   // Send Frame before sending an SR.
-  SendFrame(&sender_, kBaseLayerTid);
+  SendFrame(&sender_, sender_video_.get(), kBaseLayerTid);
   // Sender module should send an SR.
   EXPECT_EQ(0, sender_.impl_->SendRTCP(kRtcpReport));
 
@@ -370,7 +352,7 @@
   // Sender module should send a response to the last received RTRR (DLRR).
   clock_.AdvanceTimeMilliseconds(1000);
   // Send Frame before sending a SR.
-  SendFrame(&sender_, kBaseLayerTid);
+  SendFrame(&sender_, sender_video_.get(), kBaseLayerTid);
   EXPECT_EQ(0, sender_.impl_->SendRTCP(kRtcpReport));
 
   // Verify RTT.
@@ -399,7 +381,7 @@
   EXPECT_EQ(-1, sender_.RtcpSent().first_packet_time_ms);
   EXPECT_EQ(receiver_.RtcpSent().first_packet_time_ms, current_time);
 
-  SendFrame(&sender_, kBaseLayerTid);
+  SendFrame(&sender_, sender_video_.get(), kBaseLayerTid);
   EXPECT_EQ(sender_.RtcpSent().first_packet_time_ms, current_time);
 }
 
@@ -491,7 +473,7 @@
   uint16_t nack_list[kNackLength] = {123};
   EXPECT_EQ(0U, sender_.RtcpSent().nack_packets);
   // Send Frame before sending a compound RTCP that starts with SR.
-  SendFrame(&sender_, kBaseLayerTid);
+  SendFrame(&sender_, sender_video_.get(), kBaseLayerTid);
   EXPECT_EQ(0, sender_.impl_->SendNACK(nack_list, kNackLength));
   EXPECT_EQ(1U, sender_.RtcpSent().nack_packets);
   EXPECT_THAT(sender_.LastNackListSent(), ElementsAre(123));
@@ -503,7 +485,7 @@
   uint16_t nack_list[kNackLength] = {123};
   EXPECT_EQ(0U, sender_.RtcpSent().nack_packets);
   // Send Frame before sending a compound RTCP that starts with SR.
-  SendFrame(&sender_, kBaseLayerTid);
+  SendFrame(&sender_, sender_video_.get(), kBaseLayerTid);
   EXPECT_EQ(0, sender_.impl_->SendNACK(nack_list, kNackLength));
   EXPECT_EQ(1U, sender_.RtcpSent().nack_packets);
   EXPECT_THAT(sender_.LastNackListSent(), ElementsAre(123));
@@ -528,7 +510,7 @@
   uint16_t nack_list[kNackLength] = {123, 125};
   EXPECT_EQ(0U, sender_.RtcpSent().nack_packets);
   // Send Frame before sending a compound RTCP that starts with SR.
-  SendFrame(&sender_, kBaseLayerTid);
+  SendFrame(&sender_, sender_video_.get(), kBaseLayerTid);
   EXPECT_EQ(0, sender_.impl_->SendNACK(nack_list, kNackLength));
   EXPECT_EQ(1U, sender_.RtcpSent().nack_packets);
   EXPECT_THAT(sender_.LastNackListSent(), ElementsAre(123, 125));
@@ -625,7 +607,7 @@
   EXPECT_EQ(2U, sender_.transport_.NumKeepaliveSent());
 
   // Send actual payload data, no keep-alive expected.
-  SendFrame(&sender_, 0);
+  SendFrame(&sender_, sender_video_.get(), 0);
   sender_.impl_->Process();
   EXPECT_EQ(2U, sender_.transport_.NumKeepaliveSent());
 
@@ -647,7 +629,7 @@
   sender_.SetRtcpReportIntervalAndReset(kVideoReportInterval);
   SetUp();
 
-  SendFrame(&sender_, kBaseLayerTid);
+  SendFrame(&sender_, sender_video_.get(), kBaseLayerTid);
 
   // Initial state
   sender_.impl_->Process();
@@ -666,7 +648,7 @@
   EXPECT_GT(sender_.RtcpSent().first_packet_time_ms, -1);
   EXPECT_EQ(sender_.transport_.NumRtcpSent(), 1u);
 
-  SendFrame(&sender_, kBaseLayerTid);
+  SendFrame(&sender_, sender_video_.get(), kBaseLayerTid);
 
   // Move ahead to the last possible second before second rtcp is expected.
   clock_.AdvanceTimeMilliseconds(kVideoReportInterval * 1 / 2 - 1);
diff --git a/modules/rtp_rtcp/source/rtp_sender.cc b/modules/rtp_rtcp/source/rtp_sender.cc
index ddf91f5..197f52b 100644
--- a/modules/rtp_rtcp/source/rtp_sender.cc
+++ b/modules/rtp_rtcp/source/rtp_sender.cc
@@ -17,26 +17,21 @@
 
 #include "absl/memory/memory.h"
 #include "absl/strings/match.h"
+#include "api/array_view.h"
 #include "logging/rtc_event_log/events/rtc_event_rtp_packet_outgoing.h"
 #include "logging/rtc_event_log/rtc_event_log.h"
-#include "modules/remote_bitrate_estimator/test/bwe_test_logging.h"
 #include "modules/rtp_rtcp/include/rtp_cvo.h"
 #include "modules/rtp_rtcp/source/byte_io.h"
-#include "modules/rtp_rtcp/source/playout_delay_oracle.h"
 #include "modules/rtp_rtcp/source/rtp_generic_frame_descriptor_extension.h"
 #include "modules/rtp_rtcp/source/rtp_header_extensions.h"
 #include "modules/rtp_rtcp/source/rtp_packet_to_send.h"
-#include "modules/rtp_rtcp/source/rtp_sender_audio.h"
-#include "modules/rtp_rtcp/source/rtp_sender_video.h"
 #include "modules/rtp_rtcp/source/time_util.h"
 #include "rtc_base/arraysize.h"
 #include "rtc_base/checks.h"
 #include "rtc_base/logging.h"
 #include "rtc_base/numerics/safe_minmax.h"
 #include "rtc_base/rate_limiter.h"
-#include "rtc_base/timeutils.h"
-#include "rtc_base/trace_event.h"
-#include "system_wrappers/include/field_trial.h"
+#include "rtc_base/time_utils.h"
 
 namespace webrtc {
 
@@ -57,13 +52,18 @@
   return {Extension::kId, Extension::kValueSizeBytes};
 }
 
+template <typename Extension>
+constexpr RtpExtensionSize CreateMaxExtensionSize() {
+  return {Extension::kId, Extension::kMaxValueSizeBytes};
+}
+
 // Size info for header extensions that might be used in padding or FEC packets.
 constexpr RtpExtensionSize kFecOrPaddingExtensionSizes[] = {
     CreateExtensionSize<AbsoluteSendTime>(),
     CreateExtensionSize<TransmissionOffset>(),
     CreateExtensionSize<TransportSequenceNumber>(),
     CreateExtensionSize<PlayoutDelayLimits>(),
-    {RtpMid::kId, RtpMid::kMaxValueSizeBytes},
+    CreateMaxExtensionSize<RtpMid>(),
 };
 
 // Size info for header extensions that might be used in video packets.
@@ -75,26 +75,15 @@
     CreateExtensionSize<VideoOrientation>(),
     CreateExtensionSize<VideoContentTypeExtension>(),
     CreateExtensionSize<VideoTimingExtension>(),
-    {RtpMid::kId, RtpMid::kMaxValueSizeBytes},
-    {RtpGenericFrameDescriptorExtension::kId,
-     RtpGenericFrameDescriptorExtension::kMaxSizeBytes},
+    CreateMaxExtensionSize<RtpStreamId>(),
+    CreateMaxExtensionSize<RepairedRtpStreamId>(),
+    CreateMaxExtensionSize<RtpMid>(),
+    {RtpGenericFrameDescriptorExtension00::kId,
+     RtpGenericFrameDescriptorExtension00::kMaxSizeBytes},
+    {RtpGenericFrameDescriptorExtension01::kId,
+     RtpGenericFrameDescriptorExtension01::kMaxSizeBytes},
 };
 
-const char* FrameTypeToString(FrameType frame_type) {
-  switch (frame_type) {
-    case kEmptyFrame:
-      return "empty";
-    case kAudioFrameSpeech:
-      return "audio_speech";
-    case kAudioFrameCN:
-      return "audio_cn";
-    case kVideoFrameKey:
-      return "video_key";
-    case kVideoFrameDelta:
-      return "video_delta";
-  }
-  return "";
-}
 }  // namespace
 
 RTPSender::RTPSender(
@@ -102,11 +91,10 @@
     Clock* clock,
     Transport* transport,
     RtpPacketSender* paced_sender,
-    FlexfecSender* flexfec_sender,
+    absl::optional<uint32_t> flexfec_ssrc,
     TransportSequenceNumberAllocator* sequence_number_allocator,
     TransportFeedbackObserver* transport_feedback_observer,
     BitrateStatisticsObserver* bitrate_callback,
-    FrameCountObserver* frame_count_observer,
     SendSideDelayObserver* send_side_delay_observer,
     RtcEventLog* event_log,
     SendPacketObserver* send_packet_observer,
@@ -115,29 +103,22 @@
     bool populate_network2_timestamp,
     FrameEncryptorInterface* frame_encryptor,
     bool require_frame_encryption,
-    bool extmap_allow_mixed)
+    bool extmap_allow_mixed,
+    const WebRtcKeyValueConfig& field_trials)
     : clock_(clock),
       // TODO(holmer): Remove this conversion?
       clock_delta_ms_(clock_->TimeInMilliseconds() - rtc::TimeMillis()),
       random_(clock_->TimeInMicroseconds()),
       audio_configured_(audio),
-      audio_(audio ? new RTPSenderAudio(clock, this) : nullptr),
-      video_(audio ? nullptr
-                   : new RTPSenderVideo(clock,
-                                        this,
-                                        flexfec_sender,
-                                        frame_encryptor,
-                                        require_frame_encryption)),
+      flexfec_ssrc_(flexfec_ssrc),
       paced_sender_(paced_sender),
       transport_sequence_number_allocator_(sequence_number_allocator),
       transport_feedback_observer_(transport_feedback_observer),
-      last_capture_time_ms_sent_(0),
       transport_(transport),
       sending_media_(true),  // Default to sending media.
       force_part_of_allocation_(false),
       max_packet_size_(IP_PACKET_SIZE - 28),  // Default is IP-v4/UDP.
       last_payload_type_(-1),
-      payload_type_map_(),
       rtp_header_extension_map_(extmap_allow_mixed),
       packet_history_(clock),
       flexfec_packet_history_(clock),
@@ -149,13 +130,11 @@
       total_bitrate_sent_(kBitrateStatisticsWindowMs,
                           RateStatistics::kBpsScale),
       nack_bitrate_sent_(kBitrateStatisticsWindowMs, RateStatistics::kBpsScale),
-      frame_count_observer_(frame_count_observer),
       send_side_delay_observer_(send_side_delay_observer),
       event_log_(event_log),
       send_packet_observer_(send_packet_observer),
       bitrate_callback_(bitrate_callback),
       // RTP variables
-      remote_ssrc_(0),
       sequence_number_forced_(false),
       last_rtp_timestamp_(0),
       capture_time_ms_(0),
@@ -169,7 +148,8 @@
       overhead_observer_(overhead_observer),
       populate_network2_timestamp_(populate_network2_timestamp),
       send_side_bwe_with_overhead_(
-          webrtc::field_trial::IsEnabled("WebRTC-SendSideBwe-WithOverhead")) {
+          field_trials.Lookup("WebRTC-SendSideBwe-WithOverhead")
+              .find("Enabled") == 0) {
   // This random initialization is not intended to be cryptographic strong.
   timestamp_offset_ = random_.Rand<uint32_t>();
   // Random start, 16 bits. Can't be 0.
@@ -178,7 +158,7 @@
 
   // Store FlexFEC packets in the packet history data structure, so they can
   // be found when paced.
-  if (flexfec_sender) {
+  if (flexfec_ssrc_) {
     flexfec_packet_history_.SetStorePacketsStatus(
         RtpPacketHistory::StorageMode::kStore,
         kMinFlexfecPacketsToStoreForPacing);
@@ -195,12 +175,6 @@
   // variables but we grab them in all other methods. (what's the design?)
   // Start documenting what thread we're on in what method so that it's easier
   // to understand performance attributes and possibly remove locks.
-  while (!payload_type_map_.empty()) {
-    std::map<int8_t, RtpUtility::Payload*>::iterator it =
-        payload_type_map_.begin();
-    delete it->second;
-    payload_type_map_.erase(it);
-  }
 }
 
 rtc::ArrayView<const RtpExtensionSize> RTPSender::FecExtensionSizes() {
@@ -220,20 +194,6 @@
       1000);
 }
 
-uint32_t RTPSender::VideoBitrateSent() const {
-  if (video_) {
-    return video_->VideoBitrateSent();
-  }
-  return 0;
-}
-
-uint32_t RTPSender::FecOverheadRate() const {
-  if (video_) {
-    return video_->FecOverheadRate();
-  }
-  return 0;
-}
-
 uint32_t RTPSender::NackOverheadRate() const {
   rtc::CritScope cs(&statistics_crit_);
   return nack_bitrate_sent_.Rate(clock_->TimeInMilliseconds()).value_or(0);
@@ -265,69 +225,6 @@
   return rtp_header_extension_map_.Deregister(type);
 }
 
-int32_t RTPSender::RegisterPayload(absl::string_view payload_name,
-                                   int8_t payload_number,
-                                   uint32_t frequency,
-                                   size_t channels,
-                                   uint32_t rate) {
-  RTC_DCHECK_LT(payload_name.size(), RTP_PAYLOAD_NAME_SIZE);
-  rtc::CritScope lock(&send_critsect_);
-
-  std::map<int8_t, RtpUtility::Payload*>::iterator it =
-      payload_type_map_.find(payload_number);
-
-  if (payload_type_map_.end() != it) {
-    // We already use this payload type.
-    RtpUtility::Payload* payload = it->second;
-    RTC_DCHECK(payload);
-
-    // Check if it's the same as we already have.
-    if (absl::EqualsIgnoreCase(payload->name, payload_name)) {
-      if (audio_configured_ && payload->typeSpecific.is_audio()) {
-        auto& p = payload->typeSpecific.audio_payload();
-        if (rtc::SafeEq(p.format.clockrate_hz, frequency) &&
-            (p.rate == rate || p.rate == 0 || rate == 0)) {
-          p.rate = rate;
-          // Ensure that we update the rate if new or old is zero.
-          return 0;
-        }
-      }
-      if (!audio_configured_ && !payload->typeSpecific.is_audio()) {
-        return 0;
-      }
-    }
-    return -1;
-  }
-  int32_t ret_val = 0;
-  RtpUtility::Payload* payload = nullptr;
-  if (audio_configured_) {
-    // TODO(mflodman): Change to CreateAudioPayload and make static.
-    ret_val = audio_->RegisterAudioPayload(payload_name, payload_number,
-                                           frequency, channels, rate, &payload);
-  } else {
-    payload = video_->CreateVideoPayload(payload_name, payload_number);
-  }
-  if (payload) {
-    payload_type_map_[payload_number] = payload;
-  }
-  return ret_val;
-}
-
-int32_t RTPSender::DeRegisterSendPayload(int8_t payload_type) {
-  rtc::CritScope lock(&send_critsect_);
-
-  std::map<int8_t, RtpUtility::Payload*>::iterator it =
-      payload_type_map_.find(payload_type);
-
-  if (payload_type_map_.end() == it) {
-    return -1;
-  }
-  RtpUtility::Payload* payload = it->second;
-  delete payload;
-  payload_type_map_.erase(it);
-  return 0;
-}
-
 void RTPSender::SetMaxRtpPacketSize(size_t max_packet_size) {
   RTC_DCHECK_GE(max_packet_size, 100);
   RTC_DCHECK_LE(max_packet_size, IP_PACKET_SIZE);
@@ -373,123 +270,6 @@
   rtx_payload_type_map_[associated_payload_type] = payload_type;
 }
 
-int32_t RTPSender::CheckPayloadType(int8_t payload_type,
-                                    VideoCodecType* video_type) {
-  rtc::CritScope lock(&send_critsect_);
-
-  if (payload_type < 0) {
-    RTC_LOG(LS_ERROR) << "Invalid payload_type " << payload_type << ".";
-    return -1;
-  }
-  if (last_payload_type_ == payload_type) {
-    if (!audio_configured_) {
-      *video_type = video_->VideoCodecType();
-    }
-    return 0;
-  }
-  std::map<int8_t, RtpUtility::Payload*>::iterator it =
-      payload_type_map_.find(payload_type);
-  if (it == payload_type_map_.end()) {
-    RTC_LOG(LS_WARNING) << "Payload type " << static_cast<int>(payload_type)
-                        << " not registered.";
-    return -1;
-  }
-  RtpUtility::Payload* payload = it->second;
-  RTC_DCHECK(payload);
-  if (payload->typeSpecific.is_video() && !audio_configured_) {
-    video_->SetVideoCodecType(
-        payload->typeSpecific.video_payload().videoCodecType);
-    *video_type = payload->typeSpecific.video_payload().videoCodecType;
-  }
-  return 0;
-}
-
-bool RTPSender::SendOutgoingData(FrameType frame_type,
-                                 int8_t payload_type,
-                                 uint32_t capture_timestamp,
-                                 int64_t capture_time_ms,
-                                 const uint8_t* payload_data,
-                                 size_t payload_size,
-                                 const RTPFragmentationHeader* fragmentation,
-                                 const RTPVideoHeader* rtp_header,
-                                 uint32_t* transport_frame_id_out,
-                                 int64_t expected_retransmission_time_ms) {
-  uint32_t ssrc;
-  uint16_t sequence_number;
-  uint32_t rtp_timestamp;
-  {
-    // Drop this packet if we're not sending media packets.
-    rtc::CritScope lock(&send_critsect_);
-    RTC_DCHECK(ssrc_);
-
-    ssrc = *ssrc_;
-    sequence_number = sequence_number_;
-    rtp_timestamp = timestamp_offset_ + capture_timestamp;
-    if (transport_frame_id_out)
-      *transport_frame_id_out = rtp_timestamp;
-    if (!sending_media_)
-      return true;
-  }
-  VideoCodecType video_type = kVideoCodecGeneric;
-  if (CheckPayloadType(payload_type, &video_type) != 0) {
-    RTC_LOG(LS_ERROR) << "Don't send data with unknown payload type: "
-                      << static_cast<int>(payload_type) << ".";
-    return false;
-  }
-
-  switch (frame_type) {
-    case kAudioFrameSpeech:
-    case kAudioFrameCN:
-      RTC_CHECK(audio_configured_);
-      break;
-    case kVideoFrameKey:
-    case kVideoFrameDelta:
-      RTC_CHECK(!audio_configured_);
-      break;
-    case kEmptyFrame:
-      break;
-  }
-
-  bool result;
-  if (audio_configured_) {
-    TRACE_EVENT_ASYNC_STEP1("webrtc", "Audio", rtp_timestamp, "Send", "type",
-                            FrameTypeToString(frame_type));
-    // The only known way to produce of RTPFragmentationHeader for audio is
-    // to use the AudioCodingModule directly.
-    RTC_DCHECK(fragmentation == nullptr);
-    result = audio_->SendAudio(frame_type, payload_type, rtp_timestamp,
-                               payload_data, payload_size);
-  } else {
-    TRACE_EVENT_ASYNC_STEP1("webrtc", "Video", capture_time_ms, "Send", "type",
-                            FrameTypeToString(frame_type));
-    if (frame_type == kEmptyFrame)
-      return true;
-
-    if (rtp_header) {
-      playout_delay_oracle_.UpdateRequest(ssrc, rtp_header->playout_delay,
-                                          sequence_number);
-    }
-
-    result = video_->SendVideo(video_type, frame_type, payload_type,
-                               rtp_timestamp, capture_time_ms, payload_data,
-                               payload_size, fragmentation, rtp_header,
-                               expected_retransmission_time_ms);
-  }
-
-  rtc::CritScope cs(&statistics_crit_);
-  // Note: This is currently only counting for video.
-  if (frame_type == kVideoFrameKey) {
-    ++frame_counts_.key_frames;
-  } else if (frame_type == kVideoFrameDelta) {
-    ++frame_counts_.delta_frames;
-  }
-  if (frame_count_observer_) {
-    frame_count_observer_->FrameCountUpdated(frame_counts_, ssrc);
-  }
-
-  return result;
-}
-
 size_t RTPSender::TrySendRedundantPayloads(size_t bytes_to_send,
                                            const PacedPacketInfo& pacing_info) {
   {
@@ -664,7 +444,7 @@
     return 0;
   }
 
-  const int32_t packet_size = static_cast<int32_t>(stored_packet->payload_size);
+  const int32_t packet_size = static_cast<int32_t>(stored_packet->packet_size);
 
   // Skip retransmission rate check if not configured.
   if (retransmission_rate_limiter_) {
@@ -683,7 +463,7 @@
     paced_sender_->InsertPacket(
         RtpPacketSender::kNormalPriority, stored_packet->ssrc,
         stored_packet->rtp_sequence_number, corrected_capture_tims_ms,
-        stored_packet->payload_size, true);
+        stored_packet->packet_size, true);
 
     return packet_size;
   }
@@ -724,19 +504,6 @@
   return true;
 }
 
-int RTPSender::SelectiveRetransmissions() const {
-  if (!video_)
-    return -1;
-  return video_->SelectiveRetransmissions();
-}
-
-int RTPSender::SetSelectiveRetransmissions(uint8_t settings) {
-  if (!video_)
-    return -1;
-  video_->SetSelectiveRetransmissions(settings);
-  return 0;
-}
-
 void RTPSender::OnReceivedNack(
     const std::vector<uint16_t>& nack_sequence_numbers,
     int64_t avg_rtt) {
@@ -752,11 +519,6 @@
   }
 }
 
-void RTPSender::OnReceivedRtcpReportBlocks(
-    const ReportBlockList& report_blocks) {
-  playout_delay_oracle_.OnReceivedRtcpReportBlocks(report_blocks);
-}
-
 // Called from pacer when we can send the packet.
 bool RTPSender::TimeToSendPacket(uint32_t ssrc,
                                  uint16_t sequence_number,
@@ -874,7 +636,7 @@
   if (counters->first_packet_time_ms == -1)
     counters->first_packet_time_ms = now_ms;
 
-  if (IsFecPacket(packet))
+  if (packet.is_fec())
     counters->fec.AddPacket(packet);
 
   if (is_retransmit) {
@@ -887,22 +649,6 @@
     rtp_stats_callback_->DataCountersUpdated(*counters, packet.Ssrc());
 }
 
-bool RTPSender::IsFecPacket(const RtpPacketToSend& packet) const {
-  if (!video_)
-    return false;
-
-  // FlexFEC.
-  if (packet.Ssrc() == FlexfecSsrc())
-    return true;
-
-  // RED+ULPFEC.
-  int pt_red;
-  int pt_fec;
-  video_->GetUlpfecConfig(&pt_red, &pt_fec);
-  return static_cast<int>(packet.PayloadType()) == pt_red &&
-         static_cast<int>(packet.payload()[0]) == pt_fec;
-}
-
 size_t RTPSender::TimeToSendPadding(size_t bytes,
                                     const PacedPacketInfo& pacing_info) {
   if (bytes == 0)
@@ -919,29 +665,15 @@
   RTC_DCHECK(packet);
   int64_t now_ms = clock_->TimeInMilliseconds();
 
-  if (video_) {
-    BWE_TEST_LOGGING_PLOT_WITH_SSRC(1, "VideoTotBitrate_kbps", now_ms,
-                                    ActualSendBitrateKbit(), packet->Ssrc());
-    BWE_TEST_LOGGING_PLOT_WITH_SSRC(1, "VideoFecBitrate_kbps", now_ms,
-                                    FecOverheadRate() / 1000, packet->Ssrc());
-    BWE_TEST_LOGGING_PLOT_WITH_SSRC(1, "VideoNackBitrate_kbps", now_ms,
-                                    NackOverheadRate() / 1000, packet->Ssrc());
-  } else {
-    BWE_TEST_LOGGING_PLOT_WITH_SSRC(1, "AudioTotBitrate_kbps", now_ms,
-                                    ActualSendBitrateKbit(), packet->Ssrc());
-    BWE_TEST_LOGGING_PLOT_WITH_SSRC(1, "AudioNackBitrate_kbps", now_ms,
-                                    NackOverheadRate() / 1000, packet->Ssrc());
-  }
-
   uint32_t ssrc = packet->Ssrc();
-  absl::optional<uint32_t> flexfec_ssrc = FlexfecSsrc();
   if (paced_sender_) {
     uint16_t seq_no = packet->SequenceNumber();
     // Correct offset between implementations of millisecond time stamps in
     // TickTime and Clock.
     int64_t corrected_time_ms = packet->capture_time_ms() + clock_delta_ms_;
-    size_t payload_length = packet->payload_size();
-    if (ssrc == flexfec_ssrc) {
+    size_t packet_size =
+        send_side_bwe_with_overhead_ ? packet->size() : packet->payload_size();
+    if (ssrc == FlexfecSsrc()) {
       // Store FlexFEC packets in the history here, so they can be found
       // when the pacer calls TimeToSendPacket.
       flexfec_packet_history_.PutRtpPacket(std::move(packet), storage,
@@ -951,11 +683,7 @@
     }
 
     paced_sender_->InsertPacket(priority, ssrc, seq_no, corrected_time_ms,
-                                payload_length, false);
-    if (last_capture_time_ms_sent_ == 0 ||
-        corrected_time_ms > last_capture_time_ms_sent_) {
-      last_capture_time_ms_sent_ = corrected_time_ms;
-    }
+                                packet_size, false);
     return true;
   }
 
@@ -1171,14 +899,15 @@
   packet->ReserveExtension<AbsoluteSendTime>();
   packet->ReserveExtension<TransmissionOffset>();
   packet->ReserveExtension<TransportSequenceNumber>();
-  if (playout_delay_oracle_.send_playout_delay()) {
-    packet->SetExtension<PlayoutDelayLimits>(
-        playout_delay_oracle_.playout_delay());
-  }
+
   if (!mid_.empty()) {
     // This is a no-op if the MID header extension is not registered.
     packet->SetExtension<RtpMid>(mid_);
   }
+  if (!rid_.empty()) {
+    // This is a no-op if the RID header extension is not registered.
+    packet->SetExtension<RtpStreamId>(rid_);
+  }
   return packet;
 }
 
@@ -1263,6 +992,13 @@
   return *ssrc_;
 }
 
+void RTPSender::SetRid(const std::string& rid) {
+  // RID is used in simulcast scenario when multiple layers share the same mid.
+  rtc::CritScope lock(&send_critsect_);
+  RTC_DCHECK_LE(rid.length(), RtpStreamId::kMaxValueSizeBytes);
+  rid_ = rid;
+}
+
 void RTPSender::SetMid(const std::string& mid) {
   // This is configured via the API.
   rtc::CritScope lock(&send_critsect_);
@@ -1270,10 +1006,7 @@
 }
 
 absl::optional<uint32_t> RTPSender::FlexfecSsrc() const {
-  if (video_) {
-    return video_->FlexfecSsrc();
-  }
-  return absl::nullopt;
+  return flexfec_ssrc_;
 }
 
 void RTPSender::SetCsrcs(const std::vector<uint32_t>& csrcs) {
@@ -1293,42 +1026,58 @@
   return sequence_number_;
 }
 
-// Audio.
-int32_t RTPSender::SendTelephoneEvent(uint8_t key,
-                                      uint16_t time_ms,
-                                      uint8_t level) {
-  if (!audio_configured_) {
-    return -1;
+static void CopyHeaderAndExtensionsToRtxPacket(const RtpPacketToSend& packet,
+                                               RtpPacketToSend* rtx_packet) {
+  // Set the relevant fixed packet headers. The following are not set:
+  // * Payload type - it is replaced in rtx packets.
+  // * Sequence number - RTX has a separate sequence numbering.
+  // * SSRC - RTX stream has its own SSRC.
+  rtx_packet->SetMarker(packet.Marker());
+  rtx_packet->SetTimestamp(packet.Timestamp());
+
+  // Set the variable fields in the packet header:
+  // * CSRCs - must be set before header extensions.
+  // * Header extensions - replace Rid header with RepairedRid header.
+  const std::vector<uint32_t> csrcs = packet.Csrcs();
+  rtx_packet->SetCsrcs(csrcs);
+  for (int extension = kRtpExtensionNone + 1;
+       extension < kRtpExtensionNumberOfExtensions; ++extension) {
+    RTPExtensionType source_extension =
+        static_cast<RTPExtensionType>(extension);
+    // Rid header should be replaced with RepairedRid header
+    RTPExtensionType destination_extension =
+        source_extension == kRtpExtensionRtpStreamId
+            ? kRtpExtensionRepairedRtpStreamId
+            : source_extension;
+
+    // Empty extensions should be supported, so not checking |source.empty()|.
+    if (!packet.HasExtension(source_extension)) {
+      continue;
+    }
+
+    rtc::ArrayView<const uint8_t> source =
+        packet.FindExtension(source_extension);
+
+    rtc::ArrayView<uint8_t> destination =
+        rtx_packet->AllocateExtension(destination_extension, source.size());
+
+    // Could happen if any:
+    // 1. Extension has 0 length.
+    // 2. Extension is not registered in destination.
+    // 3. Allocating extension in destination failed.
+    if (destination.empty() || source.size() != destination.size()) {
+      continue;
+    }
+
+    std::memcpy(destination.begin(), source.begin(), destination.size());
   }
-  return audio_->SendTelephoneEvent(key, time_ms, level);
-}
-
-int32_t RTPSender::SetAudioLevel(uint8_t level_d_bov) {
-  return audio_->SetAudioLevel(level_d_bov);
-}
-
-void RTPSender::SetUlpfecConfig(int red_payload_type, int ulpfec_payload_type) {
-  RTC_DCHECK(!audio_configured_);
-  video_->SetUlpfecConfig(red_payload_type, ulpfec_payload_type);
-}
-
-bool RTPSender::SetFecParameters(const FecProtectionParams& delta_params,
-                                 const FecProtectionParams& key_params) {
-  if (audio_configured_) {
-    return false;
-  }
-  video_->SetFecParameters(delta_params, key_params);
-  return true;
 }
 
 std::unique_ptr<RtpPacketToSend> RTPSender::BuildRtxPacket(
     const RtpPacketToSend& packet) {
-  // TODO(danilchap): Create rtx packet with extra capacity for SRTP
-  // when transport interface would be updated to take buffer class.
-  std::unique_ptr<RtpPacketToSend> rtx_packet(new RtpPacketToSend(
-      &rtp_header_extension_map_, packet.size() + kRtxHeaderSize));
+  std::unique_ptr<RtpPacketToSend> rtx_packet;
+
   // Add original RTP header.
-  rtx_packet->CopyHeaderFrom(packet);
   {
     rtc::CritScope lock(&send_critsect_);
     if (!sending_media_)
@@ -1340,6 +1089,10 @@
     auto kv = rtx_payload_type_map_.find(packet.PayloadType());
     if (kv == rtx_payload_type_map_.end())
       return nullptr;
+
+    rtx_packet = absl::make_unique<RtpPacketToSend>(&rtp_header_extension_map_,
+                                                    max_packet_size_);
+
     rtx_packet->SetPayloadType(kv->second);
 
     // Replace sequence number.
@@ -1348,16 +1101,30 @@
     // Replace SSRC.
     rtx_packet->SetSsrc(*ssrc_rtx_);
 
-    // Possibly include the MID header extension.
+    CopyHeaderAndExtensionsToRtxPacket(packet, rtx_packet.get());
+
+    // The spec indicates that it is possible for a sender to stop sending mids
+    // once the SSRCs have been bound on the receiver. As a result the source
+    // rtp packet might not have the MID header extension set.
+    // However, the SSRC of the RTX stream might not have been bound on the
+    // receiver. This means that we should include it here.
+    // The same argument goes for the Repaired RID extension.
     if (!mid_.empty()) {
       // This is a no-op if the MID header extension is not registered.
       rtx_packet->SetExtension<RtpMid>(mid_);
     }
+    if (!rid_.empty()) {
+      // This is a no-op if the Repaired-RID header extension is not registered.
+      // rtx_packet->SetExtension<RepairedRtpStreamId>(rid_);
+    }
   }
+  RTC_DCHECK(rtx_packet);
 
   uint8_t* rtx_payload =
       rtx_packet->AllocatePayload(packet.payload_size() + kRtxHeaderSize);
-  RTC_DCHECK(rtx_payload);
+  if (rtx_payload == nullptr)
+    return nullptr;
+
   // Add OSN (original sequence number).
   ByteWriter<uint16_t>::WriteBigEndian(rtx_payload, packet.SequenceNumber());
 
diff --git a/modules/rtp_rtcp/source/rtp_sender.h b/modules/rtp_rtcp/source/rtp_sender.h
index f9bbbdd..f08eb89 100644
--- a/modules/rtp_rtcp/source/rtp_sender.h
+++ b/modules/rtp_rtcp/source/rtp_sender.h
@@ -21,16 +21,15 @@
 #include "absl/types/optional.h"
 #include "api/array_view.h"
 #include "api/call/transport.h"
+#include "api/transport/webrtc_key_value_config.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"
 #include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
-#include "modules/rtp_rtcp/source/playout_delay_oracle.h"
 #include "modules/rtp_rtcp/source/rtp_packet_history.h"
 #include "modules/rtp_rtcp/source/rtp_rtcp_config.h"
-#include "modules/rtp_rtcp/source/rtp_utility.h"
-#include "rtc_base/constructormagic.h"
-#include "rtc_base/criticalsection.h"
+#include "rtc_base/constructor_magic.h"
+#include "rtc_base/critical_section.h"
 #include "rtc_base/deprecation.h"
 #include "rtc_base/random.h"
 #include "rtc_base/rate_statistics.h"
@@ -43,8 +42,6 @@
 class RateLimiter;
 class RtcEventLog;
 class RtpPacketToSend;
-class RTPSenderAudio;
-class RTPSenderVideo;
 
 class RTPSender {
  public:
@@ -52,13 +49,10 @@
             Clock* clock,
             Transport* transport,
             RtpPacketSender* paced_sender,
-            // TODO(brandtr): Remove |flexfec_sender| when that is hooked up
-            // to PacedSender instead.
-            FlexfecSender* flexfec_sender,
+            absl::optional<uint32_t> flexfec_ssrc,
             TransportSequenceNumberAllocator* sequence_number_allocator,
             TransportFeedbackObserver* transport_feedback_callback,
             BitrateStatisticsObserver* bitrate_callback,
-            FrameCountObserver* frame_count_observer,
             SendSideDelayObserver* send_side_delay_observer,
             RtcEventLog* event_log,
             SendPacketObserver* send_packet_observer,
@@ -67,7 +61,8 @@
             bool populate_network2_timestamp,
             FrameEncryptorInterface* frame_encryptor,
             bool require_frame_encryption,
-            bool extmap_allow_mixed);
+            bool extmap_allow_mixed,
+            const WebRtcKeyValueConfig& field_trials);
 
   ~RTPSender();
 
@@ -75,18 +70,8 @@
 
   uint16_t ActualSendBitrateKbit() const;
 
-  uint32_t VideoBitrateSent() const;
-  uint32_t FecOverheadRate() const;
   uint32_t NackOverheadRate() const;
 
-  int32_t RegisterPayload(absl::string_view payload_name,
-                          const int8_t payload_type,
-                          const uint32_t frequency,
-                          const size_t channels,
-                          const uint32_t rate);
-
-  int32_t DeRegisterSendPayload(const int8_t payload_type);
-
   void SetSendingMediaStatus(bool enabled);
   bool SendingMedia() const;
 
@@ -100,6 +85,8 @@
 
   void SetSSRC(uint32_t ssrc);
 
+  void SetRid(const std::string& rid);
+
   void SetMid(const std::string& mid);
 
   uint16_t SequenceNumber() const;
@@ -109,17 +96,6 @@
 
   void SetMaxRtpPacketSize(size_t max_packet_size);
 
-  bool SendOutgoingData(FrameType frame_type,
-                        int8_t payload_type,
-                        uint32_t timestamp,
-                        int64_t capture_time_ms,
-                        const uint8_t* payload_data,
-                        size_t payload_size,
-                        const RTPFragmentationHeader* fragmentation,
-                        const RTPVideoHeader* rtp_header,
-                        uint32_t* transport_frame_id_out,
-                        int64_t expected_retransmission_time_ms);
-
   void SetExtmapAllowMixed(bool extmap_allow_mixed);
 
   // RTP header extension
@@ -136,8 +112,6 @@
   size_t TimeToSendPadding(size_t bytes, const PacedPacketInfo& pacing_info);
 
   // NACK.
-  int SelectiveRetransmissions() const;
-  int SetSelectiveRetransmissions(uint8_t settings);
   void OnReceivedNack(const std::vector<uint16_t>& nack_sequence_numbers,
                       int64_t avg_rtt);
 
@@ -147,10 +121,6 @@
 
   int32_t ReSendPacket(uint16_t packet_id);
 
-  // Feedback to decide when to stop sending the playout delay and MID header
-  // extensions.
-  void OnReceivedRtcpReportBlocks(const ReportBlockList& report_blocks);
-
   // RTX.
   void SetRtxStatus(int mode);
   int RtxStatus() const;
@@ -184,27 +154,11 @@
 
   absl::optional<uint32_t> FlexfecSsrc() const;
 
+  // Sends packet to |transport_| or to the pacer, depending on configuration.
   bool SendToNetwork(std::unique_ptr<RtpPacketToSend> packet,
                      StorageType storage,
                      RtpPacketSender::Priority priority);
 
-  // Audio.
-
-  // Send a DTMF tone using RFC 2833 (4733).
-  int32_t SendTelephoneEvent(uint8_t key, uint16_t time_ms, uint8_t level);
-
-  // Store the audio level in d_bov for
-  // header-extension-for-audio-level-indication.
-  int32_t SetAudioLevel(uint8_t level_d_bov);
-
-  uint32_t MaxConfiguredBitrateVideo() const;
-
-  // ULPFEC.
-  void SetUlpfecConfig(int red_payload_type, int ulpfec_payload_type);
-
-  bool SetFecParameters(const FecProtectionParams& delta_params,
-                        const FecProtectionParams& key_params);
-
   // Called on update of RTP statistics.
   void RegisterRtpStatisticsCallback(StreamDataCountersCallback* callback);
   StreamDataCountersCallback* GetRtpStatisticsCallback() const;
@@ -221,9 +175,6 @@
 
   void SetRtt(int64_t rtt_ms);
 
- protected:
-  int32_t CheckPayloadType(int8_t payload_type, VideoCodecType* video_type);
-
  private:
   // Maps capture time in milliseconds to send-side delay in milliseconds.
   // Send-side delay is the difference between transmission time and capture
@@ -245,6 +196,7 @@
   std::unique_ptr<RtpPacketToSend> BuildRtxPacket(
       const RtpPacketToSend& packet);
 
+  // Sends packet on to |transport_|, leaving the RTP module.
   bool SendPacketToNetwork(const RtpPacketToSend& packet,
                            const PacketOptions& options,
                            const PacedPacketInfo& pacing_info);
@@ -274,13 +226,12 @@
   Random random_ RTC_GUARDED_BY(send_critsect_);
 
   const bool audio_configured_;
-  const std::unique_ptr<RTPSenderAudio> audio_;
-  const std::unique_ptr<RTPSenderVideo> video_;
+
+  const absl::optional<uint32_t> flexfec_ssrc_;
 
   RtpPacketSender* const paced_sender_;
   TransportSequenceNumberAllocator* const transport_sequence_number_allocator_;
   TransportFeedbackObserver* const transport_feedback_observer_;
-  int64_t last_capture_time_ms_sent_;
   rtc::CriticalSection send_critsect_;
 
   Transport* transport_;
@@ -289,16 +240,10 @@
   size_t max_packet_size_;
 
   int8_t last_payload_type_ RTC_GUARDED_BY(send_critsect_);
-  std::map<int8_t, RtpUtility::Payload*> payload_type_map_;
 
   RtpHeaderExtensionMap rtp_header_extension_map_
       RTC_GUARDED_BY(send_critsect_);
 
-  // Tracks the current request for playout delay limits from application
-  // and decides whether the current RTP frame should include the playout
-  // delay extension on header.
-  PlayoutDelayOracle playout_delay_oracle_;
-
   RtpPacketHistory packet_history_;
   // TODO(brandtr): Remove |flexfec_packet_history_| when the FlexfecSender
   // is hooked up to the PacedSender.
@@ -309,14 +254,12 @@
   SendDelayMap send_delays_ RTC_GUARDED_BY(statistics_crit_);
   SendDelayMap::const_iterator max_delay_it_ RTC_GUARDED_BY(statistics_crit_);
   int64_t sum_delays_ms_ RTC_GUARDED_BY(statistics_crit_);
-  FrameCounts frame_counts_ RTC_GUARDED_BY(statistics_crit_);
   StreamDataCounters rtp_stats_ RTC_GUARDED_BY(statistics_crit_);
   StreamDataCounters rtx_rtp_stats_ RTC_GUARDED_BY(statistics_crit_);
   StreamDataCountersCallback* rtp_stats_callback_
       RTC_GUARDED_BY(statistics_crit_);
   RateStatistics total_bitrate_sent_ RTC_GUARDED_BY(statistics_crit_);
   RateStatistics nack_bitrate_sent_ RTC_GUARDED_BY(statistics_crit_);
-  FrameCountObserver* const frame_count_observer_;
   SendSideDelayObserver* const send_side_delay_observer_;
   RtcEventLog* const event_log_;
   SendPacketObserver* const send_packet_observer_;
@@ -324,13 +267,14 @@
 
   // RTP variables
   uint32_t timestamp_offset_ RTC_GUARDED_BY(send_critsect_);
-  uint32_t remote_ssrc_ RTC_GUARDED_BY(send_critsect_);
   bool sequence_number_forced_ RTC_GUARDED_BY(send_critsect_);
   uint16_t sequence_number_ RTC_GUARDED_BY(send_critsect_);
   uint16_t sequence_number_rtx_ RTC_GUARDED_BY(send_critsect_);
   // Must be explicitly set by the application, use of absl::optional
   // only to keep track of correct use.
   absl::optional<uint32_t> ssrc_ RTC_GUARDED_BY(send_critsect_);
+  // RID value to send in the RID or RepairedRID header extension.
+  std::string rid_ RTC_GUARDED_BY(send_critsect_);
   // MID value to send in the MID header extension.
   std::string mid_ RTC_GUARDED_BY(send_critsect_);
   uint32_t last_rtp_timestamp_ RTC_GUARDED_BY(send_critsect_);
diff --git a/modules/rtp_rtcp/source/rtp_sender_audio.cc b/modules/rtp_rtcp/source/rtp_sender_audio.cc
index 636cccc..56d0884 100644
--- a/modules/rtp_rtcp/source/rtp_sender_audio.cc
+++ b/modules/rtp_rtcp/source/rtp_sender_audio.cc
@@ -16,6 +16,7 @@
 
 #include "absl/strings/match.h"
 #include "api/audio_codecs/audio_format.h"
+#include "modules/remote_bitrate_estimator/test/bwe_test_logging.h"
 #include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
 #include "modules/rtp_rtcp/source/byte_io.h"
 #include "modules/rtp_rtcp/source/rtp_header_extensions.h"
@@ -27,6 +28,24 @@
 
 namespace webrtc {
 
+namespace {
+
+const char* FrameTypeToString(FrameType frame_type) {
+  switch (frame_type) {
+    case kEmptyFrame:
+      return "empty";
+    case kAudioFrameSpeech:
+      return "audio_speech";
+    case kAudioFrameCN:
+      return "audio_cn";
+    default:
+      RTC_NOTREACHED();
+      return "";
+  }
+}
+
+}  // namespace
+
 RTPSenderAudio::RTPSenderAudio(Clock* clock, RTPSender* rtp_sender)
     : clock_(clock), rtp_sender_(rtp_sender) {}
 
@@ -36,8 +55,7 @@
                                              const int8_t payload_type,
                                              const uint32_t frequency,
                                              const size_t channels,
-                                             const uint32_t rate,
-                                             RtpUtility::Payload** payload) {
+                                             const uint32_t rate) {
   if (absl::EqualsIgnoreCase(payload_name, "cn")) {
     rtc::CritScope cs(&send_audio_critsect_);
     //  we can have multiple CNG payload types
@@ -65,10 +83,6 @@
     dtmf_payload_freq_ = frequency;
     return 0;
   }
-  *payload = new RtpUtility::Payload(
-      payload_name,
-      PayloadUnion(AudioPayload{
-          SdpAudioFormat(payload_name, frequency, channels), rate}));
   return 0;
 }
 
@@ -120,6 +134,12 @@
                                uint32_t rtp_timestamp,
                                const uint8_t* payload_data,
                                size_t payload_size) {
+  RTC_DCHECK(frame_type == kAudioFrameSpeech || frame_type == kAudioFrameCN ||
+             frame_type == kEmptyFrame);
+
+  TRACE_EVENT_ASYNC_STEP1("webrtc", "Audio", rtp_timestamp, "Send", "type",
+                          FrameTypeToString(frame_type));
+
   // From RFC 4733:
   // A source has wide latitude as to how often it sends event updates. A
   // natural interval is the spacing between non-event audio packets. [...]
@@ -238,7 +258,7 @@
   TRACE_EVENT_ASYNC_END2("webrtc", "Audio", rtp_timestamp, "timestamp",
                          packet->Timestamp(), "seqnum",
                          packet->SequenceNumber());
-  bool send_result = rtp_sender_->SendToNetwork(
+  bool send_result = LogAndSendToNetwork(
       std::move(packet), kAllowRetransmission, RtpPacketSender::kHighPriority);
   if (first_packet_sent_()) {
     RTC_LOG(LS_INFO) << "First audio RTP packet sent to pacer";
@@ -322,11 +342,29 @@
     dtmfbuffer[1] = E | R | volume;
     ByteWriter<uint16_t>::WriteBigEndian(dtmfbuffer + 2, duration);
 
-    result = rtp_sender_->SendToNetwork(std::move(packet), kAllowRetransmission,
-                                        RtpPacketSender::kHighPriority);
+    result = LogAndSendToNetwork(std::move(packet), kAllowRetransmission,
+                                 RtpPacketSender::kHighPriority);
     send_count--;
   } while (send_count > 0 && result);
 
   return result;
 }
+
+bool RTPSenderAudio::LogAndSendToNetwork(
+    std::unique_ptr<RtpPacketToSend> packet,
+    StorageType storage,
+    RtpPacketSender::Priority priority) {
+#if BWE_TEST_LOGGING_COMPILE_TIME_ENABLE
+  int64_t now_ms = clock_->TimeInMilliseconds();
+  BWE_TEST_LOGGING_PLOT_WITH_SSRC(1, "AudioTotBitrate_kbps", now_ms,
+                                  rtp_sender_->ActualSendBitrateKbit(),
+                                  packet->Ssrc());
+  BWE_TEST_LOGGING_PLOT_WITH_SSRC(1, "AudioNackBitrate_kbps", now_ms,
+                                  rtp_sender_->NackOverheadRate() / 1000,
+                                  packet->Ssrc());
+#endif
+
+  return rtp_sender_->SendToNetwork(std::move(packet), storage, priority);
+}
+
 }  // namespace webrtc
diff --git a/modules/rtp_rtcp/source/rtp_sender_audio.h b/modules/rtp_rtcp/source/rtp_sender_audio.h
index 1dbe5b5..fa58943 100644
--- a/modules/rtp_rtcp/source/rtp_sender_audio.h
+++ b/modules/rtp_rtcp/source/rtp_sender_audio.h
@@ -14,14 +14,15 @@
 #include <stddef.h>
 #include <stdint.h>
 
+#include <memory>
+
 #include "absl/strings/string_view.h"
 #include "common_types.h"  // NOLINT(build/include)
 #include "modules/rtp_rtcp/source/dtmf_queue.h"
 #include "modules/rtp_rtcp/source/rtp_sender.h"
-#include "modules/rtp_rtcp/source/rtp_utility.h"
-#include "rtc_base/constructormagic.h"
-#include "rtc_base/criticalsection.h"
-#include "rtc_base/onetimeevent.h"
+#include "rtc_base/constructor_magic.h"
+#include "rtc_base/critical_section.h"
+#include "rtc_base/one_time_event.h"
 #include "rtc_base/thread_annotations.h"
 #include "system_wrappers/include/clock.h"
 
@@ -36,8 +37,7 @@
                                int8_t payload_type,
                                uint32_t frequency,
                                size_t channels,
-                               uint32_t rate,
-                               RtpUtility::Payload** payload);
+                               uint32_t rate);
 
   bool SendAudio(FrameType frame_type,
                  int8_t payload_type,
@@ -63,6 +63,10 @@
   bool MarkerBit(FrameType frame_type, int8_t payload_type);
 
  private:
+  bool LogAndSendToNetwork(std::unique_ptr<RtpPacketToSend> packet,
+                           StorageType storage,
+                           RtpPacketSender::Priority priority);
+
   Clock* const clock_ = nullptr;
   RTPSender* const rtp_sender_ = nullptr;
 
diff --git a/modules/rtp_rtcp/source/rtp_sender_audio_unittest.cc b/modules/rtp_rtcp/source/rtp_sender_audio_unittest.cc
new file mode 100644
index 0000000..31b0048
--- /dev/null
+++ b/modules/rtp_rtcp/source/rtp_sender_audio_unittest.cc
@@ -0,0 +1,178 @@
+/*
+ *  Copyright (c) 2019 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include <vector>
+
+#include "api/transport/field_trial_based_config.h"
+#include "modules/rtp_rtcp/include/rtp_header_extension_map.h"
+#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
+#include "modules/rtp_rtcp/source/rtp_header_extensions.h"
+#include "modules/rtp_rtcp/source/rtp_packet_received.h"
+#include "modules/rtp_rtcp/source/rtp_sender.h"
+#include "modules/rtp_rtcp/source/rtp_sender_audio.h"
+#include "test/gmock.h"
+#include "test/gtest.h"
+
+namespace webrtc {
+
+namespace {
+enum : int {  // The first valid value is 1.
+  kAudioLevelExtensionId = 1,
+};
+
+const uint16_t kSeqNum = 33;
+const uint32_t kSsrc = 725242;
+const uint8_t kAudioLevel = 0x5a;
+const uint64_t kStartTime = 123456789;
+
+using ::testing::_;
+using ::testing::ElementsAreArray;
+
+class LoopbackTransportTest : public webrtc::Transport {
+ public:
+  LoopbackTransportTest() {
+    receivers_extensions_.Register(kRtpExtensionAudioLevel,
+                                   kAudioLevelExtensionId);
+  }
+
+  bool SendRtp(const uint8_t* data,
+               size_t len,
+               const PacketOptions& /*options*/) override {
+    sent_packets_.push_back(RtpPacketReceived(&receivers_extensions_));
+    EXPECT_TRUE(sent_packets_.back().Parse(data, len));
+    return true;
+  }
+  bool SendRtcp(const uint8_t* data, size_t len) override { return false; }
+  const RtpPacketReceived& last_sent_packet() { return sent_packets_.back(); }
+  int packets_sent() { return sent_packets_.size(); }
+
+ private:
+  RtpHeaderExtensionMap receivers_extensions_;
+  std::vector<RtpPacketReceived> sent_packets_;
+};
+
+}  // namespace
+
+class RtpSenderAudioTest : public ::testing::Test {
+ public:
+  RtpSenderAudioTest()
+      : fake_clock_(kStartTime),
+        rtp_sender_(true,
+                    &fake_clock_,
+                    &transport_,
+                    nullptr,
+                    absl::nullopt,
+                    nullptr,
+                    nullptr,
+                    nullptr,
+                    nullptr,
+                    nullptr,
+                    nullptr,
+                    nullptr,
+                    nullptr,
+                    false,
+                    nullptr,
+                    false,
+                    false,
+                    FieldTrialBasedConfig()),
+        rtp_sender_audio_(&fake_clock_, &rtp_sender_) {
+    rtp_sender_.SetSSRC(kSsrc);
+    rtp_sender_.SetSequenceNumber(kSeqNum);
+  }
+
+  SimulatedClock fake_clock_;
+  LoopbackTransportTest transport_;
+  RTPSender rtp_sender_;
+  RTPSenderAudio rtp_sender_audio_;
+};
+
+TEST_F(RtpSenderAudioTest, SendAudio) {
+  const char payload_name[] = "PAYLOAD_NAME";
+  const uint8_t payload_type = 127;
+  ASSERT_EQ(0, rtp_sender_audio_.RegisterAudioPayload(
+                   payload_name, payload_type, 48000, 0, 1500));
+  uint8_t payload[] = {47, 11, 32, 93, 89};
+
+  ASSERT_TRUE(rtp_sender_audio_.SendAudio(kAudioFrameCN, payload_type, 4321,
+                                          payload, sizeof(payload)));
+
+  auto sent_payload = transport_.last_sent_packet().payload();
+  EXPECT_THAT(sent_payload, ElementsAreArray(payload));
+}
+
+TEST_F(RtpSenderAudioTest, SendAudioWithAudioLevelExtension) {
+  EXPECT_EQ(0, rtp_sender_audio_.SetAudioLevel(kAudioLevel));
+  EXPECT_EQ(0, rtp_sender_.RegisterRtpHeaderExtension(kRtpExtensionAudioLevel,
+                                                      kAudioLevelExtensionId));
+
+  const char payload_name[] = "PAYLOAD_NAME";
+  const uint8_t payload_type = 127;
+  ASSERT_EQ(0, rtp_sender_audio_.RegisterAudioPayload(
+                   payload_name, payload_type, 48000, 0, 1500));
+
+  uint8_t payload[] = {47, 11, 32, 93, 89};
+
+  ASSERT_TRUE(rtp_sender_audio_.SendAudio(kAudioFrameCN, payload_type, 4321,
+                                          payload, sizeof(payload)));
+
+  auto sent_payload = transport_.last_sent_packet().payload();
+  EXPECT_THAT(sent_payload, ElementsAreArray(payload));
+  // Verify AudioLevel extension.
+  bool voice_activity;
+  uint8_t audio_level;
+  EXPECT_TRUE(transport_.last_sent_packet().GetExtension<AudioLevel>(
+      &voice_activity, &audio_level));
+  EXPECT_EQ(kAudioLevel, audio_level);
+  EXPECT_FALSE(voice_activity);
+}
+
+// As RFC4733, named telephone events are carried as part of the audio stream
+// and must use the same sequence number and timestamp base as the regular
+// audio channel.
+// This test checks the marker bit for the first packet and the consequent
+// packets of the same telephone event. Since it is specifically for DTMF
+// events, ignoring audio packets and sending kEmptyFrame instead of those.
+TEST_F(RtpSenderAudioTest, CheckMarkerBitForTelephoneEvents) {
+  const char* kDtmfPayloadName = "telephone-event";
+  const uint32_t kPayloadFrequency = 8000;
+  const uint8_t kPayloadType = 126;
+  ASSERT_EQ(0, rtp_sender_audio_.RegisterAudioPayload(
+                   kDtmfPayloadName, kPayloadType, kPayloadFrequency, 0, 0));
+  // For Telephone events, payload is not added to the registered payload list,
+  // it will register only the payload used for audio stream.
+  // Registering the payload again for audio stream with different payload name.
+  const char* kPayloadName = "payload_name";
+  ASSERT_EQ(0, rtp_sender_audio_.RegisterAudioPayload(
+                   kPayloadName, kPayloadType, kPayloadFrequency, 1, 0));
+  // Start time is arbitrary.
+  uint32_t capture_timestamp = fake_clock_.TimeInMilliseconds();
+  // DTMF event key=9, duration=500 and attenuationdB=10
+  rtp_sender_audio_.SendTelephoneEvent(9, 500, 10);
+  // 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.
+  ASSERT_TRUE(rtp_sender_audio_.SendAudio(kEmptyFrame, kPayloadType,
+                                          capture_timestamp, nullptr, 0));
+  // 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_audio_.SendAudio(
+      kEmptyFrame, kPayloadType, capture_timestamp + 2000, nullptr, 0));
+
+  // Marker Bit should be set to 1 for first packet.
+  EXPECT_TRUE(transport_.last_sent_packet().Marker());
+
+  ASSERT_TRUE(rtp_sender_audio_.SendAudio(
+      kEmptyFrame, kPayloadType, capture_timestamp + 4000, nullptr, 0));
+  // Marker Bit should be set to 0 for rest of the packets.
+  EXPECT_FALSE(transport_.last_sent_packet().Marker());
+}
+
+}  // namespace webrtc
diff --git a/modules/rtp_rtcp/source/rtp_sender_unittest.cc b/modules/rtp_rtcp/source/rtp_sender_unittest.cc
index a687bcb..1c74e7e 100644
--- a/modules/rtp_rtcp/source/rtp_sender_unittest.cc
+++ b/modules/rtp_rtcp/source/rtp_sender_unittest.cc
@@ -12,6 +12,8 @@
 #include <vector>
 
 #include "absl/memory/memory.h"
+#include "api/transport/field_trial_based_config.h"
+#include "api/video/video_codec_constants.h"
 #include "api/video/video_timing.h"
 #include "logging/rtc_event_log/events/rtc_event.h"
 #include "logging/rtc_event_log/mock/mock_rtc_event_log.h"
@@ -30,7 +32,6 @@
 #include "modules/rtp_rtcp/source/rtp_sender_video.h"
 #include "modules/rtp_rtcp/source/rtp_utility.h"
 #include "rtc_base/arraysize.h"
-#include "rtc_base/buffer.h"
 #include "rtc_base/rate_limiter.h"
 #include "test/field_trial.h"
 #include "test/gmock.h"
@@ -40,28 +41,32 @@
 namespace webrtc {
 
 namespace {
-const int kTransmissionTimeOffsetExtensionId = 1;
-const int kAbsoluteSendTimeExtensionId = 14;
-const int kTransportSequenceNumberExtensionId = 13;
-const int kVideoTimingExtensionId = 12;
-const int kMidExtensionId = 11;
+enum : int {  // The first valid value is 1.
+  kAbsoluteSendTimeExtensionId = 1,
+  kAudioLevelExtensionId,
+  kGenericDescriptorId00,
+  kGenericDescriptorId01,
+  kMidExtensionId,
+  kRepairedRidExtensionId,
+  kRidExtensionId,
+  kTransmissionTimeOffsetExtensionId,
+  kTransportSequenceNumberExtensionId,
+  kVideoRotationExtensionId,
+  kVideoTimingExtensionId,
+};
+
 const int kPayload = 100;
 const int kRtxPayload = 98;
 const uint32_t kTimestamp = 10;
 const uint16_t kSeqNum = 33;
 const uint32_t kSsrc = 725242;
-const int kMaxPacketLength = 1500;
-const uint8_t kAudioLevel = 0x5a;
 const uint16_t kTransportSequenceNumber = 0xaabbu;
-const uint8_t kAudioLevelExtensionId = 9;
-const int kAudioPayload = 103;
 const uint64_t kStartTime = 123456789;
 const size_t kMaxPaddingSize = 224u;
-const int kVideoRotationExtensionId = 5;
-const size_t kGenericHeaderLength = 1;
 const uint8_t kPayloadData[] = {47, 11, 32, 93, 89};
 const int64_t kDefaultExpectedRetransmissionTimeMs = 125;
-const int kGenericDescriptorId = 10;
+const char kNoRid[] = "";
+const char kNoMid[] = "";
 
 using ::testing::_;
 using ::testing::ElementsAre;
@@ -89,8 +94,13 @@
     receivers_extensions_.Register(kRtpExtensionVideoTiming,
                                    kVideoTimingExtensionId);
     receivers_extensions_.Register(kRtpExtensionMid, kMidExtensionId);
-    receivers_extensions_.Register(kRtpExtensionGenericFrameDescriptor,
-                                   kGenericDescriptorId);
+    receivers_extensions_.Register(kRtpExtensionGenericFrameDescriptor00,
+                                   kGenericDescriptorId00);
+    receivers_extensions_.Register(kRtpExtensionGenericFrameDescriptor01,
+                                   kGenericDescriptorId01);
+    receivers_extensions_.Register(kRtpExtensionRtpStreamId, kRidExtensionId);
+    receivers_extensions_.Register(kRtpExtensionRepairedRtpStreamId,
+                                   kRepairedRidExtensionId);
   }
 
   bool SendRtp(const uint8_t* data,
@@ -171,7 +181,6 @@
         mock_paced_sender_(),
         retransmission_rate_limiter_(&fake_clock_, 1000),
         rtp_sender_(),
-        payload_(kPayload),
         transport_(),
         kMarkerBit(true),
         field_trials_(GetParam() ? "WebRTC-SendSideBwe-WithOverhead/Enabled/"
@@ -182,10 +191,10 @@
   void SetUpRtpSender(bool pacer, bool populate_network2) {
     rtp_sender_.reset(new RTPSender(
         false, &fake_clock_, &transport_, pacer ? &mock_paced_sender_ : nullptr,
-        nullptr, &seq_num_allocator_, nullptr, nullptr, nullptr, nullptr,
+        absl::nullopt, &seq_num_allocator_, nullptr, nullptr, nullptr,
         &mock_rtc_event_log_, &send_packet_observer_,
         &retransmission_rate_limiter_, nullptr, populate_network2, nullptr,
-        false, false));
+        false, false, FieldTrialBasedConfig()));
     rtp_sender_->SetSequenceNumber(kSeqNum);
     rtp_sender_->SetTimestampOffset(0);
     rtp_sender_->SetSSRC(kSsrc);
@@ -199,31 +208,10 @@
   testing::StrictMock<MockTransportFeedbackObserver> feedback_observer_;
   RateLimiter retransmission_rate_limiter_;
   std::unique_ptr<RTPSender> rtp_sender_;
-  int payload_;
   LoopbackTransportTest transport_;
   const bool kMarkerBit;
   test::ScopedFieldTrials field_trials_;
 
-  void VerifyRTPHeaderCommon(const RTPHeader& rtp_header) {
-    VerifyRTPHeaderCommon(rtp_header, kMarkerBit, 0);
-  }
-
-  void VerifyRTPHeaderCommon(const RTPHeader& rtp_header, bool marker_bit) {
-    VerifyRTPHeaderCommon(rtp_header, marker_bit, 0);
-  }
-
-  void VerifyRTPHeaderCommon(const RTPHeader& rtp_header,
-                             bool marker_bit,
-                             uint8_t number_of_csrcs) {
-    EXPECT_EQ(marker_bit, rtp_header.markerBit);
-    EXPECT_EQ(payload_, rtp_header.payloadType);
-    EXPECT_EQ(kSeqNum, rtp_header.sequenceNumber);
-    EXPECT_EQ(kTimestamp, rtp_header.timestamp);
-    EXPECT_EQ(rtp_sender_->SSRC(), rtp_header.ssrc);
-    EXPECT_EQ(number_of_csrcs, rtp_header.numCSRCs);
-    EXPECT_EQ(0U, rtp_header.paddingLength);
-  }
-
   std::unique_ptr<RtpPacketToSend> BuildRtpPacket(int payload_type,
                                                   bool marker_bit,
                                                   uint32_t timestamp,
@@ -249,19 +237,9 @@
                                            RtpPacketSender::kNormalPriority));
   }
 
-  void SendGenericPayload() {
-    const uint32_t kTimestamp = 1234;
-    const uint8_t kPayloadType = 127;
+  void SendGenericPacket() {
     const int64_t kCaptureTimeMs = fake_clock_.TimeInMilliseconds();
-    char payload_name[RTP_PAYLOAD_NAME_SIZE] = "GENERIC";
-    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, &video_header, nullptr,
-        kDefaultExpectedRetransmissionTimeMs));
+    SendPacket(kCaptureTimeMs, sizeof(kPayloadData));
   }
 };
 
@@ -272,34 +250,6 @@
   void SetUp() override { SetUpRtpSender(false, false); }
 };
 
-class TestRtpSenderVideo : public RTPSenderVideo {
- public:
-  TestRtpSenderVideo(Clock* clock,
-                     RTPSender* rtp_sender,
-                     FlexfecSender* flexfec_sender)
-      : RTPSenderVideo(clock, rtp_sender, flexfec_sender, nullptr, false) {}
-  ~TestRtpSenderVideo() override {}
-
-  StorageType GetStorageType(const RTPVideoHeader& header,
-                             int32_t retransmission_settings,
-                             int64_t expected_retransmission_time_ms) {
-    return RTPSenderVideo::GetStorageType(GetTemporalId(header),
-                                          retransmission_settings,
-                                          expected_retransmission_time_ms);
-  }
-};
-
-class RtpSenderVideoTest : public RtpSenderTest {
- protected:
-  void SetUp() override {
-    // TODO(pbos): Set up to use pacer.
-    SetUpRtpSender(false, false);
-    rtp_sender_video_.reset(
-        new TestRtpSenderVideo(&fake_clock_, rtp_sender_.get(), nullptr));
-  }
-  std::unique_ptr<TestRtpSenderVideo> rtp_sender_video_;
-};
-
 TEST_P(RtpSenderTestWithoutPacer, AllocatePacketSetCsrc) {
   // Configure rtp_sender with csrc.
   std::vector<uint32_t> csrcs;
@@ -381,10 +331,10 @@
   MockTransport transport;
   const bool kEnableAudio = true;
   rtp_sender_.reset(new RTPSender(
-      kEnableAudio, &fake_clock_, &transport, &mock_paced_sender_, nullptr,
-      nullptr, nullptr, nullptr, nullptr, nullptr, &mock_rtc_event_log_,
+      kEnableAudio, &fake_clock_, &transport, &mock_paced_sender_,
+      absl::nullopt, nullptr, nullptr, nullptr, nullptr, &mock_rtc_event_log_,
       nullptr, &retransmission_rate_limiter_, nullptr, false, nullptr, false,
-      false));
+      false, FieldTrialBasedConfig()));
   rtp_sender_->SetTimestampOffset(0);
   rtp_sender_->SetSSRC(kSsrc);
 
@@ -427,11 +377,12 @@
        TransportFeedbackObserverGetsCorrectByteCount) {
   constexpr int kRtpOverheadBytesPerPacket = 12 + 8;
   testing::NiceMock<MockOverheadObserver> mock_overhead_observer;
-  rtp_sender_.reset(new RTPSender(
-      false, &fake_clock_, &transport_, nullptr, nullptr, &seq_num_allocator_,
-      &feedback_observer_, nullptr, nullptr, nullptr, &mock_rtc_event_log_,
-      nullptr, &retransmission_rate_limiter_, &mock_overhead_observer, false,
-      nullptr, false, false));
+  rtp_sender_.reset(
+      new RTPSender(false, &fake_clock_, &transport_, nullptr, absl::nullopt,
+                    &seq_num_allocator_, &feedback_observer_, nullptr, nullptr,
+                    &mock_rtc_event_log_, nullptr,
+                    &retransmission_rate_limiter_, &mock_overhead_observer,
+                    false, nullptr, false, false, FieldTrialBasedConfig()));
   rtp_sender_->SetSSRC(kSsrc);
   EXPECT_EQ(0, rtp_sender_->RegisterRtpHeaderExtension(
                    kRtpExtensionTransportSequenceNumber,
@@ -440,9 +391,8 @@
       .WillOnce(testing::Return(kTransportSequenceNumber));
 
   const size_t expected_bytes =
-      GetParam() ? sizeof(kPayloadData) + kGenericHeaderLength +
-                       kRtpOverheadBytesPerPacket
-                 : sizeof(kPayloadData) + kGenericHeaderLength;
+      GetParam() ? sizeof(kPayloadData) + kRtpOverheadBytesPerPacket
+                 : sizeof(kPayloadData);
 
   EXPECT_CALL(feedback_observer_,
               AddPacket(rtp_sender_->SSRC(), kTransportSequenceNumber,
@@ -451,15 +401,16 @@
   EXPECT_CALL(mock_overhead_observer,
               OnOverheadChanged(kRtpOverheadBytesPerPacket))
       .Times(1);
-  SendGenericPayload();
+  SendGenericPacket();
 }
 
 TEST_P(RtpSenderTestWithoutPacer, SendsPacketsWithTransportSequenceNumber) {
-  rtp_sender_.reset(new RTPSender(
-      false, &fake_clock_, &transport_, nullptr, nullptr, &seq_num_allocator_,
-      &feedback_observer_, nullptr, nullptr, nullptr, &mock_rtc_event_log_,
-      &send_packet_observer_, &retransmission_rate_limiter_, nullptr, false,
-      nullptr, false, false));
+  rtp_sender_.reset(
+      new RTPSender(false, &fake_clock_, &transport_, nullptr, absl::nullopt,
+                    &seq_num_allocator_, &feedback_observer_, nullptr, nullptr,
+                    &mock_rtc_event_log_, &send_packet_observer_,
+                    &retransmission_rate_limiter_, nullptr, false, nullptr,
+                    false, false, FieldTrialBasedConfig()));
   rtp_sender_->SetSSRC(kSsrc);
   EXPECT_EQ(0, rtp_sender_->RegisterRtpHeaderExtension(
                    kRtpExtensionTransportSequenceNumber,
@@ -476,7 +427,7 @@
                         PacedPacketInfo()))
       .Times(1);
 
-  SendGenericPayload();
+  SendGenericPacket();
 
   const auto& packet = transport_.last_sent_packet();
   uint16_t transport_seq_no;
@@ -487,14 +438,15 @@
 }
 
 TEST_P(RtpSenderTestWithoutPacer, PacketOptionsNoRetransmission) {
-  rtp_sender_.reset(new RTPSender(
-      false, &fake_clock_, &transport_, nullptr, nullptr, &seq_num_allocator_,
-      &feedback_observer_, nullptr, nullptr, nullptr, &mock_rtc_event_log_,
-      &send_packet_observer_, &retransmission_rate_limiter_, nullptr, false,
-      nullptr, false, false));
+  rtp_sender_.reset(
+      new RTPSender(false, &fake_clock_, &transport_, nullptr, absl::nullopt,
+                    &seq_num_allocator_, &feedback_observer_, nullptr, nullptr,
+                    &mock_rtc_event_log_, &send_packet_observer_,
+                    &retransmission_rate_limiter_, nullptr, false, nullptr,
+                    false, false, FieldTrialBasedConfig()));
   rtp_sender_->SetSSRC(kSsrc);
 
-  SendGenericPayload();
+  SendGenericPacket();
 
   EXPECT_FALSE(transport_.last_options_.is_retransmit);
 }
@@ -507,7 +459,7 @@
   EXPECT_CALL(seq_num_allocator_, AllocateSequenceNumber())
       .WillOnce(testing::Return(kTransportSequenceNumber));
   EXPECT_CALL(send_packet_observer_, OnSendPacket).Times(1);
-  SendGenericPayload();
+  SendGenericPacket();
   EXPECT_TRUE(transport_.last_options_.included_in_feedback);
 }
 
@@ -520,7 +472,7 @@
   EXPECT_CALL(seq_num_allocator_, AllocateSequenceNumber())
       .WillOnce(testing::Return(kTransportSequenceNumber));
   EXPECT_CALL(send_packet_observer_, OnSendPacket).Times(1);
-  SendGenericPayload();
+  SendGenericPacket();
   EXPECT_TRUE(transport_.last_options_.included_in_allocation);
 }
 
@@ -528,33 +480,38 @@
        SetsIncludedInAllocationWhenForcedAsPartOfAllocation) {
   SetUpRtpSender(false, false);
   rtp_sender_->SetAsPartOfAllocation(true);
-  SendGenericPayload();
+  SendGenericPacket();
   EXPECT_FALSE(transport_.last_options_.included_in_feedback);
   EXPECT_TRUE(transport_.last_options_.included_in_allocation);
 }
 
 TEST_P(RtpSenderTestWithoutPacer, DoesnSetIncludedInAllocationByDefault) {
   SetUpRtpSender(false, false);
-  SendGenericPayload();
+  SendGenericPacket();
   EXPECT_FALSE(transport_.last_options_.included_in_feedback);
   EXPECT_FALSE(transport_.last_options_.included_in_allocation);
 }
 
 TEST_P(RtpSenderTestWithoutPacer, OnSendSideDelayUpdated) {
   testing::StrictMock<MockSendSideDelayObserver> send_side_delay_observer_;
-  rtp_sender_.reset(new RTPSender(
-      false, &fake_clock_, &transport_, nullptr, nullptr, nullptr, nullptr,
-      nullptr, nullptr, &send_side_delay_observer_, &mock_rtc_event_log_,
-      nullptr, nullptr, nullptr, false, nullptr, false, false));
+  rtp_sender_.reset(
+      new RTPSender(false, &fake_clock_, &transport_, nullptr, absl::nullopt,
+                    nullptr, nullptr, nullptr, &send_side_delay_observer_,
+                    &mock_rtc_event_log_, nullptr, nullptr, nullptr, false,
+                    nullptr, false, false, FieldTrialBasedConfig()));
   rtp_sender_->SetSSRC(kSsrc);
+  PlayoutDelayOracle playout_delay_oracle;
+  RTPSenderVideo rtp_sender_video(&fake_clock_, rtp_sender_.get(), nullptr,
+                                  &playout_delay_oracle, nullptr, false,
+                                  FieldTrialBasedConfig());
 
   const uint8_t kPayloadType = 127;
+  const char payload_name[] = "GENERIC";
+
+  rtp_sender_video.RegisterPayloadType(kPayloadType, payload_name);
+
   const uint32_t kCaptureTimeMsToRtpTimestamp = 90;  // 90 kHz clock
-  char payload_name[RTP_PAYLOAD_NAME_SIZE] = "GENERIC";
   RTPVideoHeader video_header;
-  EXPECT_EQ(0, rtp_sender_->RegisterPayload(payload_name, kPayloadType,
-                                            1000 * kCaptureTimeMsToRtpTimestamp,
-                                            0, 1500));
 
   // Send packet with 10 ms send-side delay. The average and max should be 10
   // ms.
@@ -562,10 +519,10 @@
       .Times(1);
   int64_t capture_time_ms = fake_clock_.TimeInMilliseconds();
   fake_clock_.AdvanceTimeMilliseconds(10);
-  EXPECT_TRUE(rtp_sender_->SendOutgoingData(
+  EXPECT_TRUE(rtp_sender_video.SendVideo(
       kVideoFrameKey, kPayloadType,
       capture_time_ms * kCaptureTimeMsToRtpTimestamp, capture_time_ms,
-      kPayloadData, sizeof(kPayloadData), nullptr, &video_header, nullptr,
+      kPayloadData, sizeof(kPayloadData), nullptr, &video_header,
       kDefaultExpectedRetransmissionTimeMs));
 
   // Send another packet with 20 ms delay. The average
@@ -573,10 +530,10 @@
   EXPECT_CALL(send_side_delay_observer_, SendSideDelayUpdated(15, 20, kSsrc))
       .Times(1);
   fake_clock_.AdvanceTimeMilliseconds(10);
-  EXPECT_TRUE(rtp_sender_->SendOutgoingData(
+  EXPECT_TRUE(rtp_sender_video.SendVideo(
       kVideoFrameKey, kPayloadType,
       capture_time_ms * kCaptureTimeMsToRtpTimestamp, capture_time_ms,
-      kPayloadData, sizeof(kPayloadData), nullptr, &video_header, nullptr,
+      kPayloadData, sizeof(kPayloadData), nullptr, &video_header,
       kDefaultExpectedRetransmissionTimeMs));
 
   // Send another packet at the same time, which replaces the last packet.
@@ -585,10 +542,10 @@
   EXPECT_CALL(send_side_delay_observer_, SendSideDelayUpdated(5, 10, kSsrc))
       .Times(1);
   capture_time_ms = fake_clock_.TimeInMilliseconds();
-  EXPECT_TRUE(rtp_sender_->SendOutgoingData(
+  EXPECT_TRUE(rtp_sender_video.SendVideo(
       kVideoFrameKey, kPayloadType,
       capture_time_ms * kCaptureTimeMsToRtpTimestamp, capture_time_ms,
-      kPayloadData, sizeof(kPayloadData), nullptr, &video_header, nullptr,
+      kPayloadData, sizeof(kPayloadData), nullptr, &video_header,
       kDefaultExpectedRetransmissionTimeMs));
 
   // Send a packet 1 second later. The earlier packets should have timed
@@ -598,10 +555,10 @@
   fake_clock_.AdvanceTimeMilliseconds(1);
   EXPECT_CALL(send_side_delay_observer_, SendSideDelayUpdated(1, 1, kSsrc))
       .Times(1);
-  EXPECT_TRUE(rtp_sender_->SendOutgoingData(
+  EXPECT_TRUE(rtp_sender_video.SendVideo(
       kVideoFrameKey, kPayloadType,
       capture_time_ms * kCaptureTimeMsToRtpTimestamp, capture_time_ms,
-      kPayloadData, sizeof(kPayloadData), nullptr, &video_header, nullptr,
+      kPayloadData, sizeof(kPayloadData), nullptr, &video_header,
       kDefaultExpectedRetransmissionTimeMs));
 }
 
@@ -615,15 +572,16 @@
               OnSendPacket(kTransportSequenceNumber, _, _))
       .Times(1);
 
-  SendGenericPayload();
+  SendGenericPacket();
 }
 
 TEST_P(RtpSenderTest, SendsPacketsWithTransportSequenceNumber) {
   rtp_sender_.reset(new RTPSender(
-      false, &fake_clock_, &transport_, &mock_paced_sender_, nullptr,
-      &seq_num_allocator_, &feedback_observer_, nullptr, nullptr, nullptr,
+      false, &fake_clock_, &transport_, &mock_paced_sender_, absl::nullopt,
+      &seq_num_allocator_, &feedback_observer_, nullptr, nullptr,
       &mock_rtc_event_log_, &send_packet_observer_,
-      &retransmission_rate_limiter_, nullptr, false, nullptr, false, false));
+      &retransmission_rate_limiter_, nullptr, false, nullptr, false, false,
+      FieldTrialBasedConfig()));
   rtp_sender_->SetSequenceNumber(kSeqNum);
   rtp_sender_->SetSSRC(kSsrc);
   rtp_sender_->SetStorePacketsStatus(true, 10);
@@ -642,7 +600,7 @@
                         PacedPacketInfo()))
       .Times(1);
 
-  SendGenericPayload();
+  SendGenericPacket();
   rtp_sender_->TimeToSendPacket(kSsrc, kSeqNum,
                                 fake_clock_.TimeInMilliseconds(), false,
                                 PacedPacketInfo());
@@ -974,7 +932,7 @@
   EXPECT_CALL(mock_paced_sender_, InsertPacket(_, kSsrc, kSeqNum, _, _, _))
       .Times(1);
 
-  SendGenericPayload();  // Packet passed to pacer.
+  SendGenericPacket();  // Packet passed to pacer.
   const bool kIsRetransmit = false;
   rtp_sender_->TimeToSendPacket(kSsrc, kSeqNum,
                                 fake_clock_.TimeInMilliseconds(), kIsRetransmit,
@@ -994,7 +952,7 @@
   EXPECT_CALL(mock_paced_sender_, InsertPacket(_, kSsrc, kSeqNum, _, _, _))
       .Times(1);
 
-  SendGenericPayload();  // Packet passed to pacer.
+  SendGenericPacket();  // Packet passed to pacer.
   const bool kIsRetransmit = true;
   rtp_sender_->TimeToSendPacket(kSsrc, kSeqNum,
                                 fake_clock_.TimeInMilliseconds(), kIsRetransmit,
@@ -1005,10 +963,10 @@
 
 TEST_P(RtpSenderTest, OnSendPacketNotUpdatedWithoutSeqNumAllocator) {
   rtp_sender_.reset(new RTPSender(
-      false, &fake_clock_, &transport_, &mock_paced_sender_, nullptr,
+      false, &fake_clock_, &transport_, &mock_paced_sender_, absl::nullopt,
       nullptr /* TransportSequenceNumberAllocator */, nullptr, nullptr, nullptr,
-      nullptr, nullptr, &send_packet_observer_, &retransmission_rate_limiter_,
-      nullptr, false, nullptr, false, false));
+      nullptr, &send_packet_observer_, &retransmission_rate_limiter_, nullptr,
+      false, nullptr, false, false, FieldTrialBasedConfig()));
   rtp_sender_->SetSequenceNumber(kSeqNum);
   rtp_sender_->SetSSRC(kSsrc);
   EXPECT_EQ(0, rtp_sender_->RegisterRtpHeaderExtension(
@@ -1021,7 +979,7 @@
   EXPECT_CALL(mock_paced_sender_, InsertPacket(_, kSsrc, kSeqNum, _, _, _))
       .Times(1);
 
-  SendGenericPayload();  // Packet passed to pacer.
+  SendGenericPacket();  // Packet passed to pacer.
   const bool kIsRetransmit = false;
   rtp_sender_->TimeToSendPacket(kSsrc, kSeqNum,
                                 fake_clock_.TimeInMilliseconds(), kIsRetransmit,
@@ -1032,9 +990,10 @@
 TEST_P(RtpSenderTest, SendRedundantPayloads) {
   MockTransport transport;
   rtp_sender_.reset(new RTPSender(
-      false, &fake_clock_, &transport, &mock_paced_sender_, nullptr, nullptr,
+      false, &fake_clock_, &transport, &mock_paced_sender_, absl::nullopt,
       nullptr, nullptr, nullptr, nullptr, &mock_rtc_event_log_, nullptr,
-      &retransmission_rate_limiter_, nullptr, false, nullptr, false, false));
+      &retransmission_rate_limiter_, nullptr, false, nullptr, false, false,
+      FieldTrialBasedConfig()));
   rtp_sender_->SetSequenceNumber(kSeqNum);
   rtp_sender_->SetSSRC(kSsrc);
   rtp_sender_->SetRtxPayloadType(kRtxPayload, kPayload);
@@ -1107,17 +1066,20 @@
 }
 
 TEST_P(RtpSenderTestWithoutPacer, SendGenericVideo) {
-  char payload_name[RTP_PAYLOAD_NAME_SIZE] = "GENERIC";
+  const char payload_name[] = "GENERIC";
   const uint8_t payload_type = 127;
-  ASSERT_EQ(0, rtp_sender_->RegisterPayload(payload_name, payload_type, 90000,
-                                            0, 1500));
+  PlayoutDelayOracle playout_delay_oracle;
+  RTPSenderVideo rtp_sender_video(&fake_clock_, rtp_sender_.get(), nullptr,
+                                  &playout_delay_oracle, nullptr, false,
+                                  FieldTrialBasedConfig());
+  rtp_sender_video.RegisterPayloadType(payload_type, payload_name);
   uint8_t payload[] = {47, 11, 32, 93, 89};
 
   // Send keyframe
   RTPVideoHeader video_header;
-  ASSERT_TRUE(rtp_sender_->SendOutgoingData(
+  ASSERT_TRUE(rtp_sender_video.SendVideo(
       kVideoFrameKey, payload_type, 1234, 4321, payload, sizeof(payload),
-      nullptr, &video_header, nullptr, kDefaultExpectedRetransmissionTimeMs));
+      nullptr, &video_header, kDefaultExpectedRetransmissionTimeMs));
 
   auto sent_payload = transport_.last_sent_packet().payload();
   uint8_t generic_header = sent_payload[0];
@@ -1130,9 +1092,9 @@
   payload[1] = 42;
   payload[4] = 13;
 
-  ASSERT_TRUE(rtp_sender_->SendOutgoingData(
+  ASSERT_TRUE(rtp_sender_video.SendVideo(
       kVideoFrameDelta, payload_type, 1234, 4321, payload, sizeof(payload),
-      nullptr, &video_header, nullptr, kDefaultExpectedRetransmissionTimeMs));
+      nullptr, &video_header, kDefaultExpectedRetransmissionTimeMs));
 
   sent_payload = transport_.last_sent_packet().payload();
   generic_header = sent_payload[0];
@@ -1142,11 +1104,11 @@
 }
 
 TEST_P(RtpSenderTest, SendFlexfecPackets) {
+  constexpr uint32_t kTimestamp = 1234;
   constexpr int kMediaPayloadType = 127;
   constexpr int kFlexfecPayloadType = 118;
   constexpr uint32_t kMediaSsrc = 1234;
   constexpr uint32_t kFlexfecSsrc = 5678;
-  const char kNoMid[] = "";
   const std::vector<RtpExtension> kNoRtpExtensions;
   const std::vector<RtpExtensionSize> kNoRtpExtensionSizes;
   FlexfecSender flexfec_sender(kFlexfecPayloadType, kFlexfecSsrc, kMediaSsrc,
@@ -1155,20 +1117,26 @@
 
   // Reset |rtp_sender_| to use FlexFEC.
   rtp_sender_.reset(new RTPSender(
-      false, &fake_clock_, &transport_, &mock_paced_sender_, &flexfec_sender,
-      &seq_num_allocator_, nullptr, nullptr, nullptr, nullptr,
-      &mock_rtc_event_log_, &send_packet_observer_,
-      &retransmission_rate_limiter_, nullptr, false, nullptr, false, false));
+      false, &fake_clock_, &transport_, &mock_paced_sender_, kFlexfecSsrc,
+      &seq_num_allocator_, nullptr, nullptr, nullptr, &mock_rtc_event_log_,
+      &send_packet_observer_, &retransmission_rate_limiter_, nullptr, false,
+      nullptr, false, false, FieldTrialBasedConfig()));
   rtp_sender_->SetSSRC(kMediaSsrc);
   rtp_sender_->SetSequenceNumber(kSeqNum);
   rtp_sender_->SetStorePacketsStatus(true, 10);
 
+  PlayoutDelayOracle playout_delay_oracle;
+  RTPSenderVideo rtp_sender_video(&fake_clock_, rtp_sender_.get(),
+                                  &flexfec_sender, &playout_delay_oracle,
+                                  nullptr, false, FieldTrialBasedConfig());
+  rtp_sender_video.RegisterPayloadType(kMediaPayloadType, "GENERIC");
+
   // Parameters selected to generate a single FEC packet per media packet.
   FecProtectionParams params;
   params.fec_rate = 15;
   params.max_fec_frames = 1;
   params.fec_mask_type = kFecMaskRandom;
-  rtp_sender_->SetFecParameters(params, params);
+  rtp_sender_video.SetFecParameters(params, params);
 
   EXPECT_CALL(mock_paced_sender_,
               InsertPacket(RtpPacketSender::kLowPriority, kMediaSsrc, kSeqNum,
@@ -1177,7 +1145,13 @@
   EXPECT_CALL(mock_paced_sender_, InsertPacket(RtpPacketSender::kLowPriority,
                                                kFlexfecSsrc, _, _, _, false))
       .WillOnce(testing::SaveArg<2>(&flexfec_seq_num));
-  SendGenericPayload();
+
+  RTPVideoHeader video_header;
+  EXPECT_TRUE(rtp_sender_video.SendVideo(
+      kVideoFrameKey, kMediaPayloadType, kTimestamp,
+      fake_clock_.TimeInMilliseconds(), kPayloadData, sizeof(kPayloadData),
+      nullptr, &video_header, kDefaultExpectedRetransmissionTimeMs));
+
   EXPECT_CALL(mock_rtc_event_log_,
               LogProxy(SameRtcEventTypeAs(RtcEvent::Type::RtpPacketOutgoing)))
       .Times(2);
@@ -1201,11 +1175,12 @@
 // TODO(ilnik): because of webrtc:7859. Once FEC moved below pacer, this test
 // should be removed.
 TEST_P(RtpSenderTest, NoFlexfecForTimingFrames) {
+  constexpr uint32_t kTimestamp = 1234;
+  const int64_t kCaptureTimeMs = fake_clock_.TimeInMilliseconds();
   constexpr int kMediaPayloadType = 127;
   constexpr int kFlexfecPayloadType = 118;
   constexpr uint32_t kMediaSsrc = 1234;
   constexpr uint32_t kFlexfecSsrc = 5678;
-  const char kNoMid[] = "";
   const std::vector<RtpExtension> kNoRtpExtensions;
   const std::vector<RtpExtensionSize> kNoRtpExtensionSizes;
 
@@ -1215,14 +1190,21 @@
 
   // Reset |rtp_sender_| to use FlexFEC.
   rtp_sender_.reset(new RTPSender(
-      false, &fake_clock_, &transport_, &mock_paced_sender_, &flexfec_sender,
-      &seq_num_allocator_, nullptr, nullptr, nullptr, nullptr,
+      false, &fake_clock_, &transport_, &mock_paced_sender_,
+      flexfec_sender.ssrc(), &seq_num_allocator_, nullptr, nullptr, nullptr,
       &mock_rtc_event_log_, &send_packet_observer_,
-      &retransmission_rate_limiter_, nullptr, false, nullptr, false, false));
+      &retransmission_rate_limiter_, nullptr, false, nullptr, false, false,
+      FieldTrialBasedConfig()));
   rtp_sender_->SetSSRC(kMediaSsrc);
   rtp_sender_->SetSequenceNumber(kSeqNum);
   rtp_sender_->SetStorePacketsStatus(true, 10);
 
+  PlayoutDelayOracle playout_delay_oracle;
+  RTPSenderVideo rtp_sender_video(&fake_clock_, rtp_sender_.get(),
+                                  &flexfec_sender, &playout_delay_oracle,
+                                  nullptr, false, FieldTrialBasedConfig());
+  rtp_sender_video.RegisterPayloadType(kMediaPayloadType, "GENERIC");
+
   // Need extension to be registered for timing frames to be sent.
   ASSERT_EQ(0, rtp_sender_->RegisterRtpHeaderExtension(
                    kRtpExtensionVideoTiming, kVideoTimingExtensionId));
@@ -1232,7 +1214,7 @@
   params.fec_rate = 15;
   params.max_fec_frames = 1;
   params.fec_mask_type = kFecMaskRandom;
-  rtp_sender_->SetFecParameters(params, params);
+  rtp_sender_video.SetFecParameters(params, params);
 
   EXPECT_CALL(mock_paced_sender_,
               InsertPacket(RtpPacketSender::kLowPriority, kMediaSsrc, kSeqNum,
@@ -1241,17 +1223,11 @@
                                                kFlexfecSsrc, _, _, _, false))
       .Times(0);  // Not called because packet should not be protected.
 
-  const uint32_t kTimestamp = 1234;
-  const uint8_t kPayloadType = 127;
-  const int64_t kCaptureTimeMs = fake_clock_.TimeInMilliseconds();
-  char payload_name[RTP_PAYLOAD_NAME_SIZE] = "GENERIC";
-  EXPECT_EQ(0, rtp_sender_->RegisterPayload(payload_name, kPayloadType, 90000,
-                                            0, 1500));
   RTPVideoHeader video_header;
   video_header.video_timing.flags = VideoSendTiming::kTriggeredByTimer;
-  EXPECT_TRUE(rtp_sender_->SendOutgoingData(
-      kVideoFrameKey, kPayloadType, kTimestamp, kCaptureTimeMs, kPayloadData,
-      sizeof(kPayloadData), nullptr, &video_header, nullptr,
+  EXPECT_TRUE(rtp_sender_video.SendVideo(
+      kVideoFrameKey, kMediaPayloadType, kTimestamp, kCaptureTimeMs,
+      kPayloadData, sizeof(kPayloadData), nullptr, &video_header,
       kDefaultExpectedRetransmissionTimeMs));
 
   EXPECT_CALL(mock_rtc_event_log_,
@@ -1275,9 +1251,9 @@
               InsertPacket(RtpPacketSender::kLowPriority, kMediaSsrc,
                            kSeqNum + 1, _, _, false));
   video_header.video_timing.flags = VideoSendTiming::kInvalid;
-  EXPECT_TRUE(rtp_sender_->SendOutgoingData(
-      kVideoFrameKey, kPayloadType, kTimestamp + 1, kCaptureTimeMs + 1,
-      kPayloadData, sizeof(kPayloadData), nullptr, &video_header, nullptr,
+  EXPECT_TRUE(rtp_sender_video.SendVideo(
+      kVideoFrameKey, kMediaPayloadType, kTimestamp + 1, kCaptureTimeMs + 1,
+      kPayloadData, sizeof(kPayloadData), nullptr, &video_header,
       kDefaultExpectedRetransmissionTimeMs));
 
   EXPECT_CALL(mock_rtc_event_log_,
@@ -1301,11 +1277,11 @@
 }
 
 TEST_P(RtpSenderTestWithoutPacer, SendFlexfecPackets) {
+  constexpr uint32_t kTimestamp = 1234;
   constexpr int kMediaPayloadType = 127;
   constexpr int kFlexfecPayloadType = 118;
   constexpr uint32_t kMediaSsrc = 1234;
   constexpr uint32_t kFlexfecSsrc = 5678;
-  const char kNoMid[] = "";
   const std::vector<RtpExtension> kNoRtpExtensions;
   const std::vector<RtpExtensionSize> kNoRtpExtensionSizes;
   FlexfecSender flexfec_sender(kFlexfecPayloadType, kFlexfecSsrc, kMediaSsrc,
@@ -1314,24 +1290,35 @@
 
   // Reset |rtp_sender_| to use FlexFEC.
   rtp_sender_.reset(new RTPSender(
-      false, &fake_clock_, &transport_, nullptr, &flexfec_sender,
-      &seq_num_allocator_, nullptr, nullptr, nullptr, nullptr,
-      &mock_rtc_event_log_, &send_packet_observer_,
-      &retransmission_rate_limiter_, nullptr, false, nullptr, false, false));
+      false, &fake_clock_, &transport_, nullptr, flexfec_sender.ssrc(),
+      &seq_num_allocator_, nullptr, nullptr, nullptr, &mock_rtc_event_log_,
+      &send_packet_observer_, &retransmission_rate_limiter_, nullptr, false,
+      nullptr, false, false, FieldTrialBasedConfig()));
   rtp_sender_->SetSSRC(kMediaSsrc);
   rtp_sender_->SetSequenceNumber(kSeqNum);
 
+  PlayoutDelayOracle playout_delay_oracle;
+  RTPSenderVideo rtp_sender_video(&fake_clock_, rtp_sender_.get(),
+                                  &flexfec_sender, &playout_delay_oracle,
+                                  nullptr, false, FieldTrialBasedConfig());
+  rtp_sender_video.RegisterPayloadType(kMediaPayloadType, "GENERIC");
+
   // Parameters selected to generate a single FEC packet per media packet.
   FecProtectionParams params;
   params.fec_rate = 15;
   params.max_fec_frames = 1;
   params.fec_mask_type = kFecMaskRandom;
-  rtp_sender_->SetFecParameters(params, params);
+  rtp_sender_video.SetFecParameters(params, params);
 
   EXPECT_CALL(mock_rtc_event_log_,
               LogProxy(SameRtcEventTypeAs(RtcEvent::Type::RtpPacketOutgoing)))
       .Times(2);
-  SendGenericPayload();
+  RTPVideoHeader video_header;
+  EXPECT_TRUE(rtp_sender_video.SendVideo(
+      kVideoFrameKey, kMediaPayloadType, kTimestamp,
+      fake_clock_.TimeInMilliseconds(), kPayloadData, sizeof(kPayloadData),
+      nullptr, &video_header, kDefaultExpectedRetransmissionTimeMs));
+
   ASSERT_EQ(2, transport_.packets_sent());
   const RtpPacketReceived& media_packet = transport_.sent_packets_[0];
   EXPECT_EQ(kMediaPayloadType, media_packet.PayloadType());
@@ -1353,8 +1340,8 @@
   rtp_sender_->SetSendingMediaStatus(true);
 
   // Send a couple packets.
-  SendGenericPayload();
-  SendGenericPayload();
+  SendGenericPacket();
+  SendGenericPacket();
 
   // Expect both packets to have the MID set.
   ASSERT_EQ(2u, transport_.sent_packets_.size());
@@ -1365,11 +1352,65 @@
   }
 }
 
+TEST_P(RtpSenderTestWithoutPacer, RidIncludedOnSentPackets) {
+  const char kRid[] = "f";
+
+  rtp_sender_->SetSendingMediaStatus(false);
+  rtp_sender_->RegisterRtpHeaderExtension(kRtpExtensionRtpStreamId,
+                                          kRidExtensionId);
+  rtp_sender_->SetRid(kRid);
+  rtp_sender_->SetSendingMediaStatus(true);
+
+  SendGenericPacket();
+
+  ASSERT_EQ(1u, transport_.sent_packets_.size());
+  const RtpPacketReceived& packet = transport_.sent_packets_[0];
+  std::string rid;
+  ASSERT_TRUE(packet.GetExtension<RtpStreamId>(&rid));
+  EXPECT_EQ(kRid, rid);
+}
+
+TEST_P(RtpSenderTestWithoutPacer, RidIncludedOnRtxSentPackets) {
+  const char kRid[] = "f";
+
+  rtp_sender_->SetSendingMediaStatus(false);
+  rtp_sender_->RegisterRtpHeaderExtension(kRtpExtensionRtpStreamId,
+                                          kRidExtensionId);
+  rtp_sender_->RegisterRtpHeaderExtension(kRtpExtensionRepairedRtpStreamId,
+                                          kRepairedRidExtensionId);
+  rtp_sender_->SetRid(kRid);
+  rtp_sender_->SetSendingMediaStatus(true);
+
+  rtp_sender_->SetRtxStatus(kRtxRetransmitted | kRtxRedundantPayloads);
+  rtp_sender_->SetRtxSsrc(1234);
+  rtp_sender_->SetRtxPayloadType(kRtxPayload, kPayload);
+
+  rtp_sender_->SetStorePacketsStatus(true, 10);
+
+  SendGenericPacket();
+  ASSERT_EQ(1u, transport_.sent_packets_.size());
+  const RtpPacketReceived& packet = transport_.sent_packets_[0];
+  std::string rid;
+  ASSERT_TRUE(packet.GetExtension<RtpStreamId>(&rid));
+  EXPECT_EQ(kRid, rid);
+  rid = kNoRid;
+  EXPECT_FALSE(packet.GetExtension<RepairedRtpStreamId>(&rid));
+
+  uint16_t packet_id = packet.SequenceNumber();
+  rtp_sender_->ReSendPacket(packet_id);
+  ASSERT_EQ(2u, transport_.sent_packets_.size());
+  const RtpPacketReceived& rtx_packet = transport_.sent_packets_[1];
+  ASSERT_TRUE(rtx_packet.GetExtension<RepairedRtpStreamId>(&rid));
+  EXPECT_EQ(kRid, rid);
+  EXPECT_FALSE(rtx_packet.HasExtension<RtpStreamId>());
+}
+
 TEST_P(RtpSenderTest, FecOverheadRate) {
+  constexpr uint32_t kTimestamp = 1234;
+  constexpr int kMediaPayloadType = 127;
   constexpr int kFlexfecPayloadType = 118;
   constexpr uint32_t kMediaSsrc = 1234;
   constexpr uint32_t kFlexfecSsrc = 5678;
-  const char kNoMid[] = "";
   const std::vector<RtpExtension> kNoRtpExtensions;
   const std::vector<RtpExtensionSize> kNoRtpExtensionSizes;
   FlexfecSender flexfec_sender(kFlexfecPayloadType, kFlexfecSsrc, kMediaSsrc,
@@ -1378,19 +1419,25 @@
 
   // Reset |rtp_sender_| to use FlexFEC.
   rtp_sender_.reset(new RTPSender(
-      false, &fake_clock_, &transport_, &mock_paced_sender_, &flexfec_sender,
-      &seq_num_allocator_, nullptr, nullptr, nullptr, nullptr,
+      false, &fake_clock_, &transport_, &mock_paced_sender_,
+      flexfec_sender.ssrc(), &seq_num_allocator_, nullptr, nullptr, nullptr,
       &mock_rtc_event_log_, &send_packet_observer_,
-      &retransmission_rate_limiter_, nullptr, false, nullptr, false, false));
+      &retransmission_rate_limiter_, nullptr, false, nullptr, false, false,
+      FieldTrialBasedConfig()));
   rtp_sender_->SetSSRC(kMediaSsrc);
   rtp_sender_->SetSequenceNumber(kSeqNum);
 
+  PlayoutDelayOracle playout_delay_oracle;
+  RTPSenderVideo rtp_sender_video(&fake_clock_, rtp_sender_.get(),
+                                  &flexfec_sender, &playout_delay_oracle,
+                                  nullptr, false, FieldTrialBasedConfig());
+  rtp_sender_video.RegisterPayloadType(kMediaPayloadType, "GENERIC");
   // Parameters selected to generate a single FEC packet per media packet.
   FecProtectionParams params;
   params.fec_rate = 15;
   params.max_fec_frames = 1;
   params.fec_mask_type = kFecMaskRandom;
-  rtp_sender_->SetFecParameters(params, params);
+  rtp_sender_video.SetFecParameters(params, params);
 
   constexpr size_t kNumMediaPackets = 10;
   constexpr size_t kNumFecPackets = kNumMediaPackets;
@@ -1398,7 +1445,13 @@
   EXPECT_CALL(mock_paced_sender_, InsertPacket(_, _, _, _, _, false))
       .Times(kNumMediaPackets + kNumFecPackets);
   for (size_t i = 0; i < kNumMediaPackets; ++i) {
-    SendGenericPayload();
+    RTPVideoHeader video_header;
+
+    EXPECT_TRUE(rtp_sender_video.SendVideo(
+        kVideoFrameKey, kMediaPayloadType, kTimestamp,
+        fake_clock_.TimeInMilliseconds(), kPayloadData, sizeof(kPayloadData),
+        nullptr, &video_header, kDefaultExpectedRetransmissionTimeMs));
+
     fake_clock_.AdvanceTimeMilliseconds(kTimeBetweenPacketsMs);
   }
   constexpr size_t kRtpHeaderLength = 12;
@@ -1409,63 +1462,7 @@
                                    kGenericCodecHeaderLength + kPayloadLength;
   EXPECT_NEAR(kNumFecPackets * kPacketLength * 8 /
                   (kNumFecPackets * kTimeBetweenPacketsMs / 1000.0f),
-              rtp_sender_->FecOverheadRate(), 500);
-}
-
-TEST_P(RtpSenderTest, FrameCountCallbacks) {
-  class TestCallback : public FrameCountObserver {
-   public:
-    TestCallback() : FrameCountObserver(), num_calls_(0), ssrc_(0) {}
-    ~TestCallback() override = default;
-
-    void FrameCountUpdated(const FrameCounts& frame_counts,
-                           uint32_t ssrc) override {
-      ++num_calls_;
-      ssrc_ = ssrc;
-      frame_counts_ = frame_counts;
-    }
-
-    uint32_t num_calls_;
-    uint32_t ssrc_;
-    FrameCounts frame_counts_;
-  } callback;
-
-  rtp_sender_.reset(new RTPSender(
-      false, &fake_clock_, &transport_, &mock_paced_sender_, nullptr, nullptr,
-      nullptr, nullptr, &callback, nullptr, nullptr, nullptr,
-      &retransmission_rate_limiter_, nullptr, false, nullptr, false, false));
-  rtp_sender_->SetSSRC(kSsrc);
-  char payload_name[RTP_PAYLOAD_NAME_SIZE] = "GENERIC";
-  const uint8_t payload_type = 127;
-  ASSERT_EQ(0, rtp_sender_->RegisterPayload(payload_name, payload_type, 90000,
-                                            0, 1500));
-  uint8_t payload[] = {47, 11, 32, 93, 89};
-  rtp_sender_->SetStorePacketsStatus(true, 1);
-  uint32_t ssrc = rtp_sender_->SSRC();
-
-  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, &video_header, nullptr, kDefaultExpectedRetransmissionTimeMs));
-
-  EXPECT_EQ(1U, callback.num_calls_);
-  EXPECT_EQ(ssrc, callback.ssrc_);
-  EXPECT_EQ(1, callback.frame_counts_.key_frames);
-  EXPECT_EQ(0, callback.frame_counts_.delta_frames);
-
-  ASSERT_TRUE(rtp_sender_->SendOutgoingData(
-      kVideoFrameDelta, payload_type, 1234, 4321, payload, sizeof(payload),
-      nullptr, &video_header, nullptr, kDefaultExpectedRetransmissionTimeMs));
-
-  EXPECT_EQ(2U, callback.num_calls_);
-  EXPECT_EQ(ssrc, callback.ssrc_);
-  EXPECT_EQ(1, callback.frame_counts_.key_frames);
-  EXPECT_EQ(1, callback.frame_counts_.delta_frames);
-
-  rtp_sender_.reset();
+              rtp_sender_video.FecOverheadRate(), 500);
 }
 
 TEST_P(RtpSenderTest, BitrateCallbacks) {
@@ -1493,12 +1490,21 @@
     uint32_t total_bitrate_;
     uint32_t retransmit_bitrate_;
   } callback;
-  rtp_sender_.reset(new RTPSender(
-      false, &fake_clock_, &transport_, nullptr, nullptr, nullptr, nullptr,
-      &callback, nullptr, nullptr, nullptr, nullptr,
-      &retransmission_rate_limiter_, nullptr, false, nullptr, false, false));
+  rtp_sender_.reset(
+      new RTPSender(false, &fake_clock_, &transport_, nullptr, absl::nullopt,
+                    nullptr, nullptr, &callback, nullptr, nullptr, nullptr,
+                    &retransmission_rate_limiter_, nullptr, false, nullptr,
+                    false, false, FieldTrialBasedConfig()));
   rtp_sender_->SetSSRC(kSsrc);
 
+  PlayoutDelayOracle playout_delay_oracle;
+  RTPSenderVideo rtp_sender_video(&fake_clock_, rtp_sender_.get(), nullptr,
+                                  &playout_delay_oracle, nullptr, false,
+                                  FieldTrialBasedConfig());
+  const char payload_name[] = "GENERIC";
+  const uint8_t payload_type = 127;
+  rtp_sender_video.RegisterPayloadType(payload_type, payload_name);
+
   // Simulate kNumPackets sent with kPacketInterval ms intervals, with the
   // number of packets selected so that we fill (but don't overflow) the one
   // second averaging window.
@@ -1509,10 +1515,6 @@
   // Overhead = 12 bytes RTP header + 1 byte generic header.
   const uint32_t kPacketOverhead = 13;
 
-  char payload_name[RTP_PAYLOAD_NAME_SIZE] = "GENERIC";
-  const uint8_t payload_type = 127;
-  ASSERT_EQ(0, rtp_sender_->RegisterPayload(payload_name, payload_type, 90000,
-                                            0, 1500));
   uint8_t payload[] = {47, 11, 32, 93, 89};
   rtp_sender_->SetStorePacketsStatus(true, 1);
   uint32_t ssrc = rtp_sender_->SSRC();
@@ -1523,9 +1525,9 @@
   // Send a few frames.
   RTPVideoHeader video_header;
   for (uint32_t i = 0; i < kNumPackets; ++i) {
-    ASSERT_TRUE(rtp_sender_->SendOutgoingData(
+    ASSERT_TRUE(rtp_sender_video.SendVideo(
         kVideoFrameKey, payload_type, 1234, 4321, payload, sizeof(payload),
-        nullptr, &video_header, nullptr, kDefaultExpectedRetransmissionTimeMs));
+        nullptr, &video_header, kDefaultExpectedRetransmissionTimeMs));
     fake_clock_.AdvanceTimeMilliseconds(kPacketInterval);
   }
 
@@ -1547,21 +1549,6 @@
   rtp_sender_.reset();
 }
 
-class RtpSenderAudioTest : public RtpSenderTest {
- protected:
-  RtpSenderAudioTest() {}
-
-  void SetUp() override {
-    payload_ = kAudioPayload;
-    rtp_sender_.reset(new RTPSender(
-        true, &fake_clock_, &transport_, nullptr, nullptr, nullptr, nullptr,
-        nullptr, nullptr, nullptr, nullptr, nullptr,
-        &retransmission_rate_limiter_, nullptr, false, nullptr, false, false));
-    rtp_sender_->SetSSRC(kSsrc);
-    rtp_sender_->SetSequenceNumber(kSeqNum);
-  }
-};
-
 TEST_P(RtpSenderTestWithoutPacer, StreamDataCountersCallbacks) {
   class TestCallback : public StreamDataCountersCallback {
    public:
@@ -1595,10 +1582,13 @@
 
   const uint8_t kRedPayloadType = 96;
   const uint8_t kUlpfecPayloadType = 97;
-  char payload_name[RTP_PAYLOAD_NAME_SIZE] = "GENERIC";
+  const char payload_name[] = "GENERIC";
   const uint8_t payload_type = 127;
-  ASSERT_EQ(0, rtp_sender_->RegisterPayload(payload_name, payload_type, 90000,
-                                            0, 1500));
+  PlayoutDelayOracle playout_delay_oracle;
+  RTPSenderVideo rtp_sender_video(&fake_clock_, rtp_sender_.get(), nullptr,
+                                  &playout_delay_oracle, nullptr, false,
+                                  FieldTrialBasedConfig());
+  rtp_sender_video.RegisterPayloadType(payload_type, payload_name);
   uint8_t payload[] = {47, 11, 32, 93, 89};
   rtp_sender_->SetStorePacketsStatus(true, 1);
   uint32_t ssrc = rtp_sender_->SSRC();
@@ -1607,9 +1597,9 @@
 
   // Send a frame.
   RTPVideoHeader video_header;
-  ASSERT_TRUE(rtp_sender_->SendOutgoingData(
+  ASSERT_TRUE(rtp_sender_video.SendVideo(
       kVideoFrameKey, payload_type, 1234, 4321, payload, sizeof(payload),
-      nullptr, &video_header, nullptr, kDefaultExpectedRetransmissionTimeMs));
+      nullptr, &video_header, kDefaultExpectedRetransmissionTimeMs));
   StreamDataCounters expected;
   expected.transmitted.payload_bytes = 6;
   expected.transmitted.header_bytes = 12;
@@ -1643,15 +1633,15 @@
   callback.Matches(ssrc, expected);
 
   // Send ULPFEC.
-  rtp_sender_->SetUlpfecConfig(kRedPayloadType, kUlpfecPayloadType);
+  rtp_sender_video.SetUlpfecConfig(kRedPayloadType, kUlpfecPayloadType);
   FecProtectionParams fec_params;
   fec_params.fec_mask_type = kFecMaskRandom;
   fec_params.fec_rate = 1;
   fec_params.max_fec_frames = 1;
-  rtp_sender_->SetFecParameters(fec_params, fec_params);
-  ASSERT_TRUE(rtp_sender_->SendOutgoingData(
+  rtp_sender_video.SetFecParameters(fec_params, fec_params);
+  ASSERT_TRUE(rtp_sender_video.SendVideo(
       kVideoFrameDelta, payload_type, 1234, 4321, payload, sizeof(payload),
-      nullptr, &video_header, nullptr, kDefaultExpectedRetransmissionTimeMs));
+      nullptr, &video_header, kDefaultExpectedRetransmissionTimeMs));
   expected.transmitted.payload_bytes = 40;
   expected.transmitted.header_bytes = 60;
   expected.transmitted.packets = 5;
@@ -1661,111 +1651,15 @@
   rtp_sender_->RegisterRtpStatisticsCallback(nullptr);
 }
 
-TEST_P(RtpSenderAudioTest, SendAudio) {
-  char payload_name[RTP_PAYLOAD_NAME_SIZE] = "PAYLOAD_NAME";
-  const uint8_t payload_type = 127;
-  ASSERT_EQ(0, rtp_sender_->RegisterPayload(payload_name, payload_type, 48000,
-                                            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, &video_header, nullptr, kDefaultExpectedRetransmissionTimeMs));
-
-  auto sent_payload = transport_.last_sent_packet().payload();
-  EXPECT_THAT(sent_payload, ElementsAreArray(payload));
-}
-
-TEST_P(RtpSenderAudioTest, SendAudioWithAudioLevelExtension) {
-  EXPECT_EQ(0, rtp_sender_->SetAudioLevel(kAudioLevel));
-  EXPECT_EQ(0, rtp_sender_->RegisterRtpHeaderExtension(kRtpExtensionAudioLevel,
-                                                       kAudioLevelExtensionId));
-
-  char payload_name[RTP_PAYLOAD_NAME_SIZE] = "PAYLOAD_NAME";
-  const uint8_t payload_type = 127;
-  ASSERT_EQ(0, rtp_sender_->RegisterPayload(payload_name, payload_type, 48000,
-                                            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, &video_header, nullptr, kDefaultExpectedRetransmissionTimeMs));
-
-  auto sent_payload = transport_.last_sent_packet().payload();
-  EXPECT_THAT(sent_payload, ElementsAreArray(payload));
-  // Verify AudioLevel extension.
-  bool voice_activity;
-  uint8_t audio_level;
-  EXPECT_TRUE(transport_.last_sent_packet().GetExtension<AudioLevel>(
-      &voice_activity, &audio_level));
-  EXPECT_EQ(kAudioLevel, audio_level);
-  EXPECT_FALSE(voice_activity);
-}
-
-// As RFC4733, named telephone events are carried as part of the audio stream
-// and must use the same sequence number and timestamp base as the regular
-// audio channel.
-// This test checks the marker bit for the first packet and the consequent
-// packets of the same telephone event. Since it is specifically for DTMF
-// events, ignoring audio packets and sending kEmptyFrame instead of those.
-TEST_P(RtpSenderAudioTest, CheckMarkerBitForTelephoneEvents) {
-  const char* kDtmfPayloadName = "telephone-event";
-  const uint32_t kPayloadFrequency = 8000;
-  const uint8_t kPayloadType = 126;
-  ASSERT_EQ(0, rtp_sender_->RegisterPayload(kDtmfPayloadName, kPayloadType,
-                                            kPayloadFrequency, 0, 0));
-  // For Telephone events, payload is not added to the registered payload list,
-  // it will register only the payload used for audio stream.
-  // Registering the payload again for audio stream with different payload name.
-  const char* kPayloadName = "payload_name";
-  ASSERT_EQ(0, rtp_sender_->RegisterPayload(kPayloadName, kPayloadType,
-                                            kPayloadFrequency, 1, 0));
-  int64_t capture_time_ms = fake_clock_.TimeInMilliseconds();
-  // DTMF event key=9, duration=500 and attenuationdB=10
-  rtp_sender_->SendTelephoneEvent(9, 500, 10);
-  // 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,
-      &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,
-      &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,
-      &video_header, nullptr, kDefaultExpectedRetransmissionTimeMs));
-  // Marker Bit should be set to 0 for rest of the packets.
-  EXPECT_FALSE(transport_.last_sent_packet().Marker());
-}
-
 TEST_P(RtpSenderTestWithoutPacer, BytesReportedCorrectly) {
-  const char* kPayloadName = "GENERIC";
+  // XXX const char* kPayloadName = "GENERIC";
   const uint8_t kPayloadType = 127;
   rtp_sender_->SetSSRC(1234);
   rtp_sender_->SetRtxSsrc(4321);
   rtp_sender_->SetRtxPayloadType(kPayloadType - 1, kPayloadType);
   rtp_sender_->SetRtxStatus(kRtxRetransmitted | kRtxRedundantPayloads);
 
-  ASSERT_EQ(0, rtp_sender_->RegisterPayload(kPayloadName, kPayloadType, 90000,
-                                            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, &video_header, nullptr, kDefaultExpectedRetransmissionTimeMs));
-
+  SendGenericPacket();
   // Will send 2 full-size padding packets.
   rtp_sender_->TimeToSendPadding(1, PacedPacketInfo());
   rtp_sender_->TimeToSendPadding(1, PacedPacketInfo());
@@ -1774,9 +1668,9 @@
   StreamDataCounters rtx_stats;
   rtp_sender_->GetDataCounters(&rtp_stats, &rtx_stats);
 
-  // Payload + 1-byte generic header.
+  // Payload
   EXPECT_GT(rtp_stats.first_packet_time_ms, -1);
-  EXPECT_EQ(rtp_stats.transmitted.payload_bytes, sizeof(payload) + 1);
+  EXPECT_EQ(rtp_stats.transmitted.payload_bytes, sizeof(kPayloadData));
   EXPECT_EQ(rtp_stats.transmitted.header_bytes, 12u);
   EXPECT_EQ(rtp_stats.transmitted.padding_bytes, 0u);
   EXPECT_EQ(rtx_stats.transmitted.payload_bytes, 0u);
@@ -1829,406 +1723,18 @@
   EXPECT_EQ(kNumPackets * 2, transport_.packets_sent());
 }
 
-TEST_P(RtpSenderVideoTest, KeyFrameHasCVO) {
-  uint8_t kFrame[kMaxPacketLength];
-  EXPECT_EQ(0, rtp_sender_->RegisterRtpHeaderExtension(
-                   kRtpExtensionVideoRotation, kVideoRotationExtensionId));
-
-  RTPVideoHeader hdr;
-  hdr.rotation = kVideoRotation_0;
-  rtp_sender_video_->SendVideo(kVideoCodecGeneric, kVideoFrameKey, kPayload,
-                               kTimestamp, 0, kFrame, sizeof(kFrame), nullptr,
-                               &hdr, kDefaultExpectedRetransmissionTimeMs);
-
-  VideoRotation rotation;
-  EXPECT_TRUE(
-      transport_.last_sent_packet().GetExtension<VideoOrientation>(&rotation));
-  EXPECT_EQ(kVideoRotation_0, rotation);
-}
-
-TEST_P(RtpSenderVideoTest, TimingFrameHasPacketizationTimstampSet) {
-  uint8_t kFrame[kMaxPacketLength];
-  const int64_t kPacketizationTimeMs = 100;
-  const int64_t kEncodeStartDeltaMs = 10;
-  const int64_t kEncodeFinishDeltaMs = 50;
-  EXPECT_EQ(0, rtp_sender_->RegisterRtpHeaderExtension(
-                   kRtpExtensionVideoTiming, kVideoTimingExtensionId));
-
-  const int64_t kCaptureTimestamp = fake_clock_.TimeInMilliseconds();
-
-  RTPVideoHeader hdr;
-  hdr.video_timing.flags = VideoSendTiming::kTriggeredByTimer;
-  hdr.video_timing.encode_start_delta_ms = kEncodeStartDeltaMs;
-  hdr.video_timing.encode_finish_delta_ms = kEncodeFinishDeltaMs;
-
-  fake_clock_.AdvanceTimeMilliseconds(kPacketizationTimeMs);
-  rtp_sender_video_->SendVideo(kVideoCodecGeneric, kVideoFrameKey, kPayload,
-                               kTimestamp, kCaptureTimestamp, kFrame,
-                               sizeof(kFrame), nullptr, &hdr,
-                               kDefaultExpectedRetransmissionTimeMs);
-  VideoSendTiming timing;
-  EXPECT_TRUE(transport_.last_sent_packet().GetExtension<VideoTimingExtension>(
-      &timing));
-  EXPECT_EQ(kPacketizationTimeMs, timing.packetization_finish_delta_ms);
-  EXPECT_EQ(kEncodeStartDeltaMs, timing.encode_start_delta_ms);
-  EXPECT_EQ(kEncodeFinishDeltaMs, timing.encode_finish_delta_ms);
-}
-
-TEST_P(RtpSenderVideoTest, DeltaFrameHasCVOWhenChanged) {
-  uint8_t kFrame[kMaxPacketLength];
-  EXPECT_EQ(0, rtp_sender_->RegisterRtpHeaderExtension(
-                   kRtpExtensionVideoRotation, kVideoRotationExtensionId));
-
-  RTPVideoHeader hdr;
-  hdr.rotation = kVideoRotation_90;
-  EXPECT_TRUE(rtp_sender_video_->SendVideo(
-      kVideoCodecGeneric, kVideoFrameKey, kPayload, kTimestamp, 0, kFrame,
-      sizeof(kFrame), nullptr, &hdr, kDefaultExpectedRetransmissionTimeMs));
-
-  hdr.rotation = kVideoRotation_0;
-  EXPECT_TRUE(rtp_sender_video_->SendVideo(
-      kVideoCodecGeneric, kVideoFrameDelta, kPayload, kTimestamp + 1, 0, kFrame,
-      sizeof(kFrame), nullptr, &hdr, kDefaultExpectedRetransmissionTimeMs));
-
-  VideoRotation rotation;
-  EXPECT_TRUE(
-      transport_.last_sent_packet().GetExtension<VideoOrientation>(&rotation));
-  EXPECT_EQ(kVideoRotation_0, rotation);
-}
-
-TEST_P(RtpSenderVideoTest, DeltaFrameHasCVOWhenNonZero) {
-  uint8_t kFrame[kMaxPacketLength];
-  EXPECT_EQ(0, rtp_sender_->RegisterRtpHeaderExtension(
-                   kRtpExtensionVideoRotation, kVideoRotationExtensionId));
-
-  RTPVideoHeader hdr;
-  hdr.rotation = kVideoRotation_90;
-  EXPECT_TRUE(rtp_sender_video_->SendVideo(
-      kVideoCodecGeneric, kVideoFrameKey, kPayload, kTimestamp, 0, kFrame,
-      sizeof(kFrame), nullptr, &hdr, kDefaultExpectedRetransmissionTimeMs));
-
-  EXPECT_TRUE(rtp_sender_video_->SendVideo(
-      kVideoCodecGeneric, kVideoFrameDelta, kPayload, kTimestamp + 1, 0, kFrame,
-      sizeof(kFrame), nullptr, &hdr, kDefaultExpectedRetransmissionTimeMs));
-
-  VideoRotation rotation;
-  EXPECT_TRUE(
-      transport_.last_sent_packet().GetExtension<VideoOrientation>(&rotation));
-  EXPECT_EQ(kVideoRotation_90, rotation);
-}
-
-// Make sure rotation is parsed correctly when the Camera (C) and Flip (F) bits
-// are set in the CVO byte.
-TEST_P(RtpSenderVideoTest, SendVideoWithCameraAndFlipCVO) {
-  // Test extracting rotation when Camera (C) and Flip (F) bits are zero.
-  EXPECT_EQ(kVideoRotation_0, ConvertCVOByteToVideoRotation(0));
-  EXPECT_EQ(kVideoRotation_90, ConvertCVOByteToVideoRotation(1));
-  EXPECT_EQ(kVideoRotation_180, ConvertCVOByteToVideoRotation(2));
-  EXPECT_EQ(kVideoRotation_270, ConvertCVOByteToVideoRotation(3));
-  // Test extracting rotation when Camera (C) and Flip (F) bits are set.
-  const int flip_bit = 1 << 2;
-  const int camera_bit = 1 << 3;
-  EXPECT_EQ(kVideoRotation_0,
-            ConvertCVOByteToVideoRotation(flip_bit | camera_bit | 0));
-  EXPECT_EQ(kVideoRotation_90,
-            ConvertCVOByteToVideoRotation(flip_bit | camera_bit | 1));
-  EXPECT_EQ(kVideoRotation_180,
-            ConvertCVOByteToVideoRotation(flip_bit | camera_bit | 2));
-  EXPECT_EQ(kVideoRotation_270,
-            ConvertCVOByteToVideoRotation(flip_bit | camera_bit | 3));
-}
-
-TEST_P(RtpSenderVideoTest, RetransmissionTypesGeneric) {
-  RTPVideoHeader header;
-  header.codec = kVideoCodecGeneric;
-
-  EXPECT_EQ(kDontRetransmit,
-            rtp_sender_video_->GetStorageType(
-                header, kRetransmitOff, kDefaultExpectedRetransmissionTimeMs));
-  EXPECT_EQ(kAllowRetransmission, rtp_sender_video_->GetStorageType(
-                                      header, kRetransmitBaseLayer,
-                                      kDefaultExpectedRetransmissionTimeMs));
-  EXPECT_EQ(kAllowRetransmission, rtp_sender_video_->GetStorageType(
-                                      header, kRetransmitHigherLayers,
-                                      kDefaultExpectedRetransmissionTimeMs));
-  EXPECT_EQ(kAllowRetransmission,
-            rtp_sender_video_->GetStorageType(
-                header, kConditionallyRetransmitHigherLayers,
-                kDefaultExpectedRetransmissionTimeMs));
-  EXPECT_EQ(kAllowRetransmission, rtp_sender_video_->GetStorageType(
-                                      header, kRetransmitAllPackets,
-                                      kDefaultExpectedRetransmissionTimeMs));
-}
-
-TEST_P(RtpSenderVideoTest, RetransmissionTypesH264) {
-  RTPVideoHeader header;
-  header.video_type_header.emplace<RTPVideoHeaderH264>().packetization_mode =
-      H264PacketizationMode::NonInterleaved;
-  header.codec = kVideoCodecH264;
-
-  EXPECT_EQ(kDontRetransmit,
-            rtp_sender_video_->GetStorageType(
-                header, kRetransmitOff, kDefaultExpectedRetransmissionTimeMs));
-  EXPECT_EQ(kAllowRetransmission, rtp_sender_video_->GetStorageType(
-                                      header, kRetransmitBaseLayer,
-                                      kDefaultExpectedRetransmissionTimeMs));
-  EXPECT_EQ(kAllowRetransmission, rtp_sender_video_->GetStorageType(
-                                      header, kRetransmitHigherLayers,
-                                      kDefaultExpectedRetransmissionTimeMs));
-  EXPECT_EQ(kAllowRetransmission,
-            rtp_sender_video_->GetStorageType(
-                header, kConditionallyRetransmitHigherLayers,
-                kDefaultExpectedRetransmissionTimeMs));
-  EXPECT_EQ(kAllowRetransmission, rtp_sender_video_->GetStorageType(
-                                      header, kRetransmitAllPackets,
-                                      kDefaultExpectedRetransmissionTimeMs));
-}
-
-TEST_P(RtpSenderVideoTest, RetransmissionTypesVP8BaseLayer) {
-  RTPVideoHeader header;
-  header.codec = kVideoCodecVP8;
-  auto& vp8_header = header.video_type_header.emplace<RTPVideoHeaderVP8>();
-  vp8_header.temporalIdx = 0;
-
-  EXPECT_EQ(kDontRetransmit,
-            rtp_sender_video_->GetStorageType(
-                header, kRetransmitOff, kDefaultExpectedRetransmissionTimeMs));
-  EXPECT_EQ(kAllowRetransmission, rtp_sender_video_->GetStorageType(
-                                      header, kRetransmitBaseLayer,
-                                      kDefaultExpectedRetransmissionTimeMs));
-  EXPECT_EQ(kDontRetransmit, rtp_sender_video_->GetStorageType(
-                                 header, kRetransmitHigherLayers,
-                                 kDefaultExpectedRetransmissionTimeMs));
-  EXPECT_EQ(kAllowRetransmission,
-            rtp_sender_video_->GetStorageType(
-                header, kRetransmitHigherLayers | kRetransmitBaseLayer,
-                kDefaultExpectedRetransmissionTimeMs));
-  EXPECT_EQ(kDontRetransmit, rtp_sender_video_->GetStorageType(
-                                 header, kConditionallyRetransmitHigherLayers,
-                                 kDefaultExpectedRetransmissionTimeMs));
-  EXPECT_EQ(
-      kAllowRetransmission,
-      rtp_sender_video_->GetStorageType(
-          header, kRetransmitBaseLayer | kConditionallyRetransmitHigherLayers,
-          kDefaultExpectedRetransmissionTimeMs));
-  EXPECT_EQ(kAllowRetransmission, rtp_sender_video_->GetStorageType(
-                                      header, kRetransmitAllPackets,
-                                      kDefaultExpectedRetransmissionTimeMs));
-}
-
-TEST_P(RtpSenderVideoTest, RetransmissionTypesVP8HigherLayers) {
-  RTPVideoHeader header;
-  header.codec = kVideoCodecVP8;
-
-  auto& vp8_header = header.video_type_header.emplace<RTPVideoHeaderVP8>();
-  for (int tid = 1; tid <= kMaxTemporalStreams; ++tid) {
-    vp8_header.temporalIdx = tid;
-
-    EXPECT_EQ(kDontRetransmit, rtp_sender_video_->GetStorageType(
-                                   header, kRetransmitOff,
-                                   kDefaultExpectedRetransmissionTimeMs));
-    EXPECT_EQ(kDontRetransmit, rtp_sender_video_->GetStorageType(
-                                   header, kRetransmitBaseLayer,
-                                   kDefaultExpectedRetransmissionTimeMs));
-    EXPECT_EQ(kAllowRetransmission, rtp_sender_video_->GetStorageType(
-                                        header, kRetransmitHigherLayers,
-                                        kDefaultExpectedRetransmissionTimeMs));
-    EXPECT_EQ(kAllowRetransmission,
-              rtp_sender_video_->GetStorageType(
-                  header, kRetransmitHigherLayers | kRetransmitBaseLayer,
-                  kDefaultExpectedRetransmissionTimeMs));
-    EXPECT_EQ(kAllowRetransmission, rtp_sender_video_->GetStorageType(
-                                        header, kRetransmitAllPackets,
-                                        kDefaultExpectedRetransmissionTimeMs));
-  }
-}
-
-TEST_P(RtpSenderVideoTest, RetransmissionTypesVP9) {
-  RTPVideoHeader header;
-  header.codec = kVideoCodecVP9;
-
-  auto& vp9_header = header.video_type_header.emplace<RTPVideoHeaderVP9>();
-  for (int tid = 1; tid <= kMaxTemporalStreams; ++tid) {
-    vp9_header.temporal_idx = tid;
-
-    EXPECT_EQ(kDontRetransmit, rtp_sender_video_->GetStorageType(
-                                   header, kRetransmitOff,
-                                   kDefaultExpectedRetransmissionTimeMs));
-    EXPECT_EQ(kDontRetransmit, rtp_sender_video_->GetStorageType(
-                                   header, kRetransmitBaseLayer,
-                                   kDefaultExpectedRetransmissionTimeMs));
-    EXPECT_EQ(kAllowRetransmission, rtp_sender_video_->GetStorageType(
-                                        header, kRetransmitHigherLayers,
-                                        kDefaultExpectedRetransmissionTimeMs));
-    EXPECT_EQ(kAllowRetransmission,
-              rtp_sender_video_->GetStorageType(
-                  header, kRetransmitHigherLayers | kRetransmitBaseLayer,
-                  kDefaultExpectedRetransmissionTimeMs));
-    EXPECT_EQ(kAllowRetransmission, rtp_sender_video_->GetStorageType(
-                                        header, kRetransmitAllPackets,
-                                        kDefaultExpectedRetransmissionTimeMs));
-  }
-}
-
-TEST_P(RtpSenderVideoTest, ConditionalRetransmit) {
-  const int64_t kFrameIntervalMs = 33;
-  const int64_t kRttMs = (kFrameIntervalMs * 3) / 2;
-  const uint8_t kSettings =
-      kRetransmitBaseLayer | kConditionallyRetransmitHigherLayers;
-
-  // Insert VP8 frames for all temporal layers, but stop before the final index.
-  RTPVideoHeader header;
-  header.codec = kVideoCodecVP8;
-
-  // Fill averaging window to prevent rounding errors.
-  constexpr int kNumRepetitions =
-      (RTPSenderVideo::kTLRateWindowSizeMs + (kFrameIntervalMs / 2)) /
-      kFrameIntervalMs;
-  constexpr int kPattern[] = {0, 2, 1, 2};
-  auto& vp8_header = header.video_type_header.emplace<RTPVideoHeaderVP8>();
-  for (size_t i = 0; i < arraysize(kPattern) * kNumRepetitions; ++i) {
-    vp8_header.temporalIdx = kPattern[i % arraysize(kPattern)];
-    rtp_sender_video_->GetStorageType(header, kSettings, kRttMs);
-    fake_clock_.AdvanceTimeMilliseconds(kFrameIntervalMs);
-  }
-
-  // Since we're at the start of the pattern, the next expected frame in TL0 is
-  // right now. We will wait at most one expected retransmission time before
-  // acknowledging that it did not arrive, which means this frame and the next
-  // will not be retransmitted.
-  vp8_header.temporalIdx = 1;
-  EXPECT_EQ(StorageType::kDontRetransmit,
-            rtp_sender_video_->GetStorageType(header, kSettings, kRttMs));
-  fake_clock_.AdvanceTimeMilliseconds(kFrameIntervalMs);
-  EXPECT_EQ(StorageType::kDontRetransmit,
-            rtp_sender_video_->GetStorageType(header, kSettings, kRttMs));
-  fake_clock_.AdvanceTimeMilliseconds(kFrameIntervalMs);
-
-  // The TL0 frame did not arrive. So allow retransmission.
-  EXPECT_EQ(StorageType::kAllowRetransmission,
-            rtp_sender_video_->GetStorageType(header, kSettings, kRttMs));
-  fake_clock_.AdvanceTimeMilliseconds(kFrameIntervalMs);
-
-  // Insert a frame for TL2. We just had frame in TL1, so the next one there is
-  // in three frames away. TL0 is still too far in the past. So, allow
-  // retransmission.
-  vp8_header.temporalIdx = 2;
-  EXPECT_EQ(StorageType::kAllowRetransmission,
-            rtp_sender_video_->GetStorageType(header, kSettings, kRttMs));
-  fake_clock_.AdvanceTimeMilliseconds(kFrameIntervalMs);
-
-  // Another TL2, next in TL1 is two frames away. Allow again.
-  EXPECT_EQ(StorageType::kAllowRetransmission,
-            rtp_sender_video_->GetStorageType(header, kSettings, kRttMs));
-  fake_clock_.AdvanceTimeMilliseconds(kFrameIntervalMs);
-
-  // Yet another TL2, next in TL1 is now only one frame away, so don't store
-  // for retransmission.
-  EXPECT_EQ(StorageType::kDontRetransmit,
-            rtp_sender_video_->GetStorageType(header, kSettings, kRttMs));
-}
-
-TEST_P(RtpSenderVideoTest, ConditionalRetransmitLimit) {
-  const int64_t kFrameIntervalMs = 200;
-  const int64_t kRttMs = (kFrameIntervalMs * 3) / 2;
-  const int32_t kSettings =
-      kRetransmitBaseLayer | kConditionallyRetransmitHigherLayers;
-
-  // Insert VP8 frames for all temporal layers, but stop before the final index.
-  RTPVideoHeader header;
-  header.codec = kVideoCodecVP8;
-
-  // Fill averaging window to prevent rounding errors.
-  constexpr int kNumRepetitions =
-      (RTPSenderVideo::kTLRateWindowSizeMs + (kFrameIntervalMs / 2)) /
-      kFrameIntervalMs;
-  constexpr int kPattern[] = {0, 2, 2, 2};
-  auto& vp8_header = header.video_type_header.emplace<RTPVideoHeaderVP8>();
-  for (size_t i = 0; i < arraysize(kPattern) * kNumRepetitions; ++i) {
-    vp8_header.temporalIdx = kPattern[i % arraysize(kPattern)];
-
-    rtp_sender_video_->GetStorageType(header, kSettings, kRttMs);
-    fake_clock_.AdvanceTimeMilliseconds(kFrameIntervalMs);
-  }
-
-  // Since we're at the start of the pattern, the next expected frame will be
-  // right now in TL0. Put it in TL1 instead. Regular rules would dictate that
-  // we don't store for retransmission because we expect a frame in a lower
-  // layer, but that last frame in TL1 was a long time ago in absolute terms,
-  // so allow retransmission anyway.
-  vp8_header.temporalIdx = 1;
-  EXPECT_EQ(StorageType::kAllowRetransmission,
-            rtp_sender_video_->GetStorageType(header, kSettings, kRttMs));
-}
-
-TEST_P(RtpSenderVideoTest, PopulateGenericFrameDescriptor) {
-  const int64_t kFrameId = 100000;
-  uint8_t kFrame[100];
-  EXPECT_EQ(0, rtp_sender_->RegisterRtpHeaderExtension(
-                   kRtpExtensionGenericFrameDescriptor, kGenericDescriptorId));
-
-  RTPVideoHeader hdr;
-  RTPVideoHeader::GenericDescriptorInfo& generic = hdr.generic.emplace();
-  generic.frame_id = kFrameId;
-  generic.temporal_index = 3;
-  generic.spatial_index = 2;
-  generic.higher_spatial_layers.push_back(4);
-  generic.dependencies.push_back(kFrameId - 1);
-  generic.dependencies.push_back(kFrameId - 500);
-  rtp_sender_video_->SendVideo(kVideoCodecGeneric, kVideoFrameDelta, kPayload,
-                               kTimestamp, 0, kFrame, sizeof(kFrame), nullptr,
-                               &hdr, kDefaultExpectedRetransmissionTimeMs);
-
-  RtpGenericFrameDescriptor descriptor_wire;
-  EXPECT_EQ(1U, transport_.sent_packets_.size());
-  EXPECT_TRUE(
-      transport_.last_sent_packet()
-          .GetExtension<RtpGenericFrameDescriptorExtension>(&descriptor_wire));
-  EXPECT_EQ(static_cast<uint16_t>(generic.frame_id), descriptor_wire.FrameId());
-  EXPECT_EQ(generic.temporal_index, descriptor_wire.TemporalLayer());
-  EXPECT_THAT(descriptor_wire.FrameDependenciesDiffs(), ElementsAre(1, 500));
-  uint8_t spatial_bitmask = 0x14;
-  EXPECT_EQ(spatial_bitmask, descriptor_wire.SpatialLayersBitmask());
-}
-
-TEST_P(RtpSenderVideoTest,
-       UsesMinimalVp8DescriptorWhenGenericFrameDescriptorExtensionIsUsed) {
-  const int64_t kFrameId = 100000;
-  const size_t kFrameSize = 100;
-  uint8_t kFrame[kFrameSize];
-  ASSERT_TRUE(rtp_sender_->RegisterRtpHeaderExtension(
-      RtpGenericFrameDescriptorExtension::kUri, kGenericDescriptorId));
-
-  RTPVideoHeader hdr;
-  hdr.codec = kVideoCodecVP8;
-  RTPVideoHeaderVP8& vp8 = hdr.video_type_header.emplace<RTPVideoHeaderVP8>();
-  vp8.pictureId = kFrameId % 0X7FFF;
-  vp8.tl0PicIdx = 13;
-  vp8.temporalIdx = 1;
-  vp8.keyIdx = 2;
-  RTPVideoHeader::GenericDescriptorInfo& generic = hdr.generic.emplace();
-  generic.frame_id = kFrameId;
-  rtp_sender_video_->SendVideo(kVideoCodecVP8, kVideoFrameDelta, kPayload,
-                               kTimestamp, 0, kFrame, sizeof(kFrame), nullptr,
-                               &hdr, kDefaultExpectedRetransmissionTimeMs);
-
-  ASSERT_THAT(transport_.sent_packets_, SizeIs(1));
-  // Expect only minimal 1-byte vp8 descriptor was generated.
-  EXPECT_THAT(transport_.sent_packets_[0].payload_size(), 1 + kFrameSize);
-}
-
 TEST_P(RtpSenderTest, OnOverheadChanged) {
   MockOverheadObserver mock_overhead_observer;
   rtp_sender_.reset(
-      new RTPSender(false, &fake_clock_, &transport_, nullptr, nullptr, nullptr,
+      new RTPSender(false, &fake_clock_, &transport_, nullptr, absl::nullopt,
                     nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
                     &retransmission_rate_limiter_, &mock_overhead_observer,
-                    false, nullptr, false, false));
+                    false, nullptr, false, false, FieldTrialBasedConfig()));
   rtp_sender_->SetSSRC(kSsrc);
 
   // RTP overhead is 12B.
   EXPECT_CALL(mock_overhead_observer, OnOverheadChanged(12)).Times(1);
-  SendGenericPayload();
+  SendGenericPacket();
 
   rtp_sender_->RegisterRtpHeaderExtension(kRtpExtensionTransmissionTimeOffset,
                                           kTransmissionTimeOffsetExtensionId);
@@ -2236,29 +1742,30 @@
   // TransmissionTimeOffset extension has a size of 8B.
   // 12B + 8B = 20B
   EXPECT_CALL(mock_overhead_observer, OnOverheadChanged(20)).Times(1);
-  SendGenericPayload();
+  SendGenericPacket();
 }
 
 TEST_P(RtpSenderTest, DoesNotUpdateOverheadOnEqualSize) {
   MockOverheadObserver mock_overhead_observer;
   rtp_sender_.reset(
-      new RTPSender(false, &fake_clock_, &transport_, nullptr, nullptr, nullptr,
+      new RTPSender(false, &fake_clock_, &transport_, nullptr, absl::nullopt,
                     nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
                     &retransmission_rate_limiter_, &mock_overhead_observer,
-                    false, nullptr, false, false));
+                    false, nullptr, false, false, FieldTrialBasedConfig()));
   rtp_sender_->SetSSRC(kSsrc);
 
   EXPECT_CALL(mock_overhead_observer, OnOverheadChanged(_)).Times(1);
-  SendGenericPayload();
-  SendGenericPayload();
+  SendGenericPacket();
+  SendGenericPacket();
 }
 
 TEST_P(RtpSenderTest, SendsKeepAlive) {
   MockTransport transport;
-  rtp_sender_.reset(new RTPSender(
-      false, &fake_clock_, &transport, nullptr, nullptr, nullptr, nullptr,
-      nullptr, nullptr, nullptr, &mock_rtc_event_log_, nullptr,
-      &retransmission_rate_limiter_, nullptr, false, nullptr, false, false));
+  rtp_sender_.reset(
+      new RTPSender(false, &fake_clock_, &transport, nullptr, absl::nullopt,
+                    nullptr, nullptr, nullptr, nullptr, &mock_rtc_event_log_,
+                    nullptr, &retransmission_rate_limiter_, nullptr, false,
+                    nullptr, false, false, FieldTrialBasedConfig()));
   rtp_sender_->SetSequenceNumber(kSeqNum);
   rtp_sender_->SetTimestampOffset(0);
   rtp_sender_->SetSSRC(kSsrc);
@@ -2286,16 +1793,11 @@
   EXPECT_EQ(kSeqNum + 1, rtp_sender_->SequenceNumber());
 }
 
-INSTANTIATE_TEST_CASE_P(WithAndWithoutOverhead,
-                        RtpSenderTest,
-                        ::testing::Bool());
-INSTANTIATE_TEST_CASE_P(WithAndWithoutOverhead,
-                        RtpSenderTestWithoutPacer,
-                        ::testing::Bool());
-INSTANTIATE_TEST_CASE_P(WithAndWithoutOverhead,
-                        RtpSenderVideoTest,
-                        ::testing::Bool());
-INSTANTIATE_TEST_CASE_P(WithAndWithoutOverhead,
-                        RtpSenderAudioTest,
-                        ::testing::Bool());
+INSTANTIATE_TEST_SUITE_P(WithAndWithoutOverhead,
+                         RtpSenderTest,
+                         ::testing::Bool());
+INSTANTIATE_TEST_SUITE_P(WithAndWithoutOverhead,
+                         RtpSenderTestWithoutPacer,
+                         ::testing::Bool());
+
 }  // namespace webrtc
diff --git a/modules/rtp_rtcp/source/rtp_sender_video.cc b/modules/rtp_rtcp/source/rtp_sender_video.cc
index cb0b665..8b835bd 100644
--- a/modules/rtp_rtcp/source/rtp_sender_video.cc
+++ b/modules/rtp_rtcp/source/rtp_sender_video.cc
@@ -20,7 +20,8 @@
 
 #include "absl/memory/memory.h"
 #include "absl/strings/match.h"
-#include "api/crypto/frameencryptorinterface.h"
+#include "api/crypto/frame_encryptor_interface.h"
+#include "modules/remote_bitrate_estimator/test/bwe_test_logging.h"
 #include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
 #include "modules/rtp_rtcp/source/byte_io.h"
 #include "modules/rtp_rtcp/source/rtp_format_video_generic.h"
@@ -52,11 +53,21 @@
 }
 
 void AddRtpHeaderExtensions(const RTPVideoHeader& video_header,
+                            const absl::optional<PlayoutDelay>& playout_delay,
                             FrameType frame_type,
                             bool set_video_rotation,
+                            bool set_color_space,
+                            bool set_frame_marking,
                             bool first_packet,
                             bool last_packet,
                             RtpPacketToSend* packet) {
+  // Color space requires two-byte header extensions if HDR metadata is
+  // included. Therefore, it's best to add this extension first so that the
+  // other extensions in the same packet are written as two-byte headers at
+  // once.
+  if (last_packet && set_color_space && video_header.color_space)
+    packet->SetExtension<ColorSpaceExtension>(video_header.color_space.value());
+
   if (last_packet && set_video_rotation)
     packet->SetExtension<VideoOrientation>(video_header.rotation);
 
@@ -69,12 +80,23 @@
       video_header.video_timing.flags != VideoSendTiming::kInvalid)
     packet->SetExtension<VideoTimingExtension>(video_header.video_timing);
 
+  // If transmitted, add to all packets; ack logic depends on this.
+  if (playout_delay) {
+    packet->SetExtension<PlayoutDelayLimits>(*playout_delay);
+  }
+
+  if (set_frame_marking) {
+    FrameMarking frame_marking = video_header.frame_marking;
+    frame_marking.start_of_frame = first_packet;
+    frame_marking.end_of_frame = last_packet;
+    packet->SetExtension<FrameMarkingExtension>(frame_marking);
+  }
+
   if (video_header.generic) {
     RtpGenericFrameDescriptor generic_descriptor;
     generic_descriptor.SetFirstPacketInSubFrame(first_packet);
     generic_descriptor.SetLastPacketInSubFrame(last_packet);
-    generic_descriptor.SetFirstSubFrameInFrame(true);
-    generic_descriptor.SetLastSubFrameInFrame(true);
+    generic_descriptor.SetDiscardable(video_header.generic->discardable);
 
     if (first_packet) {
       generic_descriptor.SetFrameId(
@@ -99,8 +121,13 @@
                                          video_header.height);
       }
     }
-    packet->SetExtension<RtpGenericFrameDescriptorExtension>(
-        generic_descriptor);
+    if (!packet->SetExtension<RtpGenericFrameDescriptorExtension01>(
+            generic_descriptor) &&
+        !packet->SetExtension<RtpGenericFrameDescriptorExtension00>(
+            generic_descriptor)) {
+      RTC_LOG(LS_ERROR)
+          << "Could not set RTP extension - Generic Frame Descriptor";
+    }
   }
 }
 
@@ -118,19 +145,58 @@
   return false;
 }
 
+bool IsBaseLayer(const RTPVideoHeader& video_header) {
+  switch (video_header.codec) {
+    case kVideoCodecVP8: {
+      const auto& vp8 =
+          absl::get<RTPVideoHeaderVP8>(video_header.video_type_header);
+      return (vp8.temporalIdx == 0 || vp8.temporalIdx == kNoTemporalIdx);
+    }
+    case kVideoCodecVP9: {
+      const auto& vp9 =
+          absl::get<RTPVideoHeaderVP9>(video_header.video_type_header);
+      return (vp9.temporal_idx == 0 || vp9.temporal_idx == kNoTemporalIdx);
+    }
+    case kVideoCodecH264:
+      // TODO(kron): Implement logic for H264 once WebRTC supports temporal
+      // layers for H264.
+      break;
+    default:
+      break;
+  }
+  return true;
+}
+
+const char* FrameTypeToString(FrameType frame_type) {
+  switch (frame_type) {
+    case kEmptyFrame:
+      return "empty";
+    case kVideoFrameKey:
+      return "video_key";
+    case kVideoFrameDelta:
+      return "video_delta";
+    default:
+      RTC_NOTREACHED();
+      return "";
+  }
+}
+
 }  // namespace
 
 RTPSenderVideo::RTPSenderVideo(Clock* clock,
                                RTPSender* rtp_sender,
                                FlexfecSender* flexfec_sender,
+                               PlayoutDelayOracle* playout_delay_oracle,
                                FrameEncryptorInterface* frame_encryptor,
-                               bool require_frame_encryption)
+                               bool require_frame_encryption,
+                               const WebRtcKeyValueConfig& field_trials)
     : rtp_sender_(rtp_sender),
       clock_(clock),
-      video_type_(kVideoCodecGeneric),
       retransmission_settings_(kRetransmitBaseLayer |
                                kConditionallyRetransmitHigherLayers),
       last_rotation_(kVideoRotation_0),
+      transmit_color_space_next_frame_(false),
+      playout_delay_oracle_(playout_delay_oracle),
       red_payload_type_(-1),
       ulpfec_payload_type_(-1),
       flexfec_sender_(flexfec_sender),
@@ -138,24 +204,21 @@
       key_fec_params_{0, 1, kFecMaskRandom},
       fec_bitrate_(1000, RateStatistics::kBpsScale),
       video_bitrate_(1000, RateStatistics::kBpsScale),
+      packetization_overhead_bitrate_(1000, RateStatistics::kBpsScale),
       frame_encryptor_(frame_encryptor),
-      require_frame_encryption_(require_frame_encryption) {}
+      require_frame_encryption_(require_frame_encryption),
+      generic_descriptor_auth_experiment_(
+          field_trials.Lookup("WebRTC-GenericDescriptorAuth").find("Enabled") ==
+          0) {
+  RTC_DCHECK(playout_delay_oracle_);
+}
 
 RTPSenderVideo::~RTPSenderVideo() {}
 
-void RTPSenderVideo::SetVideoCodecType(enum VideoCodecType video_type) {
-  video_type_ = video_type;
-}
+void RTPSenderVideo::RegisterPayloadType(int8_t payload_type,
+                                         absl::string_view payload_name) {
+  VideoCodecType video_type;
 
-VideoCodecType RTPSenderVideo::VideoCodecType() const {
-  return video_type_;
-}
-
-// Static.
-RtpUtility::Payload* RTPSenderVideo::CreateVideoPayload(
-    absl::string_view payload_name,
-    int8_t payload_type) {
-  enum VideoCodecType video_type = kVideoCodecGeneric;
   if (absl::EqualsIgnoreCase(payload_name, "VP8")) {
     video_type = kVideoCodecVP8;
   } else if (absl::EqualsIgnoreCase(payload_name, "VP9")) {
@@ -169,9 +232,15 @@
   } else {
     video_type = kVideoCodecGeneric;
   }
-  VideoPayload vp;
-  vp.videoCodecType = video_type;
-  return new RtpUtility::Payload(payload_name, PayloadUnion(vp));
+
+  rtc::CritScope cs(&payload_type_crit_);
+  payload_type_map_[payload_type] = video_type;
+
+  // Backward compatibility for older receivers without temporal layer logic
+  if (video_type == kVideoCodecH264) {
+    rtc::CritScope cs(&crit_);
+    retransmission_settings_ = kRetransmitBaseLayer | kRetransmitHigherLayers;
+  }
 }
 
 void RTPSenderVideo::SendVideoPacket(std::unique_ptr<RtpPacketToSend> packet,
@@ -179,8 +248,8 @@
   // Remember some values about the packet before sending it away.
   size_t packet_size = packet->size();
   uint16_t seq_num = packet->SequenceNumber();
-  if (!rtp_sender_->SendToNetwork(std::move(packet), storage,
-                                  RtpPacketSender::kLowPriority)) {
+  if (!LogAndSendToNetwork(std::move(packet), storage,
+                           RtpPacketSender::kLowPriority)) {
     RTC_LOG(LS_WARNING) << "Failed to send video packet " << seq_num;
     return;
   }
@@ -199,7 +268,6 @@
   BuildRedPayload(*media_packet, red_packet.get());
 
   std::vector<std::unique_ptr<RedPacket>> fec_packets;
-  StorageType fec_storage = kDontRetransmit;
   {
     // Only protect while creating RED and FEC packets, not when sending.
     rtc::CritScope cs(&crit_);
@@ -217,15 +285,13 @@
         fec_packets = ulpfec_generator_.GetUlpfecPacketsAsRed(
             red_payload_type_, ulpfec_payload_type_, first_fec_sequence_number);
         RTC_DCHECK_EQ(num_fec_packets, fec_packets.size());
-        if (retransmission_settings_ & kRetransmitFECPackets)
-          fec_storage = kAllowRetransmission;
       }
     }
   }
   // Send |red_packet| instead of |packet| for allocated sequence number.
   size_t red_packet_size = red_packet->size();
-  if (rtp_sender_->SendToNetwork(std::move(red_packet), media_packet_storage,
-                                 RtpPacketSender::kLowPriority)) {
+  if (LogAndSendToNetwork(std::move(red_packet), media_packet_storage,
+                          RtpPacketSender::kLowPriority)) {
     rtc::CritScope cs(&stats_crit_);
     video_bitrate_.Update(red_packet_size, clock_->TimeInMilliseconds());
   } else {
@@ -238,9 +304,10 @@
         new RtpPacketToSend(*media_packet));
     RTC_CHECK(rtp_packet->Parse(fec_packet->data(), fec_packet->length()));
     rtp_packet->set_capture_time_ms(media_packet->capture_time_ms());
+    rtp_packet->set_is_fec(true);
     uint16_t fec_sequence_number = rtp_packet->SequenceNumber();
-    if (rtp_sender_->SendToNetwork(std::move(rtp_packet), fec_storage,
-                                   RtpPacketSender::kLowPriority)) {
+    if (LogAndSendToNetwork(std::move(rtp_packet), kDontRetransmit,
+                            RtpPacketSender::kLowPriority)) {
       rtc::CritScope cs(&stats_crit_);
       fec_bitrate_.Update(fec_packet->length(), clock_->TimeInMilliseconds());
     } else {
@@ -267,8 +334,8 @@
     for (auto& fec_packet : fec_packets) {
       size_t packet_length = fec_packet->size();
       uint16_t seq_num = fec_packet->SequenceNumber();
-      if (rtp_sender_->SendToNetwork(std::move(fec_packet), kDontRetransmit,
-                                     RtpPacketSender::kLowPriority)) {
+      if (LogAndSendToNetwork(std::move(fec_packet), kDontRetransmit,
+                              RtpPacketSender::kLowPriority)) {
         rtc::CritScope cs(&stats_crit_);
         fec_bitrate_.Update(packet_length, clock_->TimeInMilliseconds());
       } else {
@@ -278,6 +345,24 @@
   }
 }
 
+bool RTPSenderVideo::LogAndSendToNetwork(
+    std::unique_ptr<RtpPacketToSend> packet,
+    StorageType storage,
+    RtpPacketSender::Priority priority) {
+#if BWE_TEST_LOGGING_COMPILE_TIME_ENABLE
+  int64_t now_ms = clock_->TimeInMilliseconds();
+  BWE_TEST_LOGGING_PLOT_WITH_SSRC(1, "VideoTotBitrate_kbps", now_ms,
+                                  rtp_sender_->ActualSendBitrateKbit(),
+                                  packet->Ssrc());
+  BWE_TEST_LOGGING_PLOT_WITH_SSRC(1, "VideoFecBitrate_kbps", now_ms,
+                                  FecOverheadRate() / 1000, packet->Ssrc());
+  BWE_TEST_LOGGING_PLOT_WITH_SSRC(1, "VideoNackBitrate_kbps", now_ms,
+                                  rtp_sender_->NackOverheadRate() / 1000,
+                                  packet->Ssrc());
+#endif
+  return rtp_sender_->SendToNetwork(std::move(packet), storage, priority);
+}
+
 void RTPSenderVideo::SetUlpfecConfig(int red_payload_type,
                                      int ulpfec_payload_type) {
   // Sanity check. Per the definition of UlpfecConfig (see config.h),
@@ -300,13 +385,6 @@
   key_fec_params_ = FecProtectionParams{0, 1, kFecMaskRandom};
 }
 
-void RTPSenderVideo::GetUlpfecConfig(int* red_payload_type,
-                                     int* ulpfec_payload_type) const {
-  rtc::CritScope cs(&crit_);
-  *red_payload_type = red_payload_type_;
-  *ulpfec_payload_type = ulpfec_payload_type_;
-}
-
 size_t RTPSenderVideo::CalculateFecPacketOverhead() const {
   if (flexfec_enabled())
     return flexfec_sender_->MaxPacketOverhead();
@@ -343,8 +421,7 @@
   return absl::nullopt;
 }
 
-bool RTPSenderVideo::SendVideo(enum VideoCodecType video_type,
-                               FrameType frame_type,
+bool RTPSenderVideo::SendVideo(FrameType frame_type,
                                int8_t payload_type,
                                uint32_t rtp_timestamp,
                                int64_t capture_time_ms,
@@ -353,6 +430,15 @@
                                const RTPFragmentationHeader* fragmentation,
                                const RTPVideoHeader* video_header,
                                int64_t expected_retransmission_time_ms) {
+  RTC_DCHECK(frame_type == kVideoFrameKey || frame_type == kVideoFrameDelta ||
+             frame_type == kEmptyFrame);
+
+  TRACE_EVENT_ASYNC_STEP1("webrtc", "Video", capture_time_ms, "Send", "type",
+                          FrameTypeToString(frame_type));
+
+  if (frame_type == kEmptyFrame)
+    return true;
+
   if (payload_size == 0)
     return false;
   RTC_CHECK(video_header);
@@ -361,6 +447,12 @@
   bool red_enabled;
   int32_t retransmission_settings;
   bool set_video_rotation;
+  bool set_color_space = false;
+  bool set_frame_marking = video_header->codec == kVideoCodecH264 &&
+        video_header->frame_marking.temporal_id != kNoTemporalIdx;
+
+  const absl::optional<PlayoutDelay> playout_delay =
+      playout_delay_oracle_->PlayoutDelayToSend(video_header->playout_delay);
   {
     rtc::CritScope cs(&crit_);
     // According to
@@ -380,6 +472,21 @@
                          video_header->rotation != kVideoRotation_0;
     last_rotation_ = video_header->rotation;
 
+    // Send color space when changed or if the frame is a key frame. Keep
+    // sending color space information until the first base layer frame to
+    // guarantee that the information is retrieved by the receiver.
+    if (video_header->color_space != last_color_space_) {
+      last_color_space_ = video_header->color_space;
+      set_color_space = true;
+      transmit_color_space_next_frame_ = !IsBaseLayer(*video_header);
+    } else {
+      set_color_space =
+          frame_type == kVideoFrameKey || transmit_color_space_next_frame_;
+      transmit_color_space_next_frame_ = transmit_color_space_next_frame_
+                                             ? !IsBaseLayer(*video_header)
+                                             : false;
+    }
+
     // FEC settings.
     const FecProtectionParams& fec_params =
         frame_type == kVideoFrameKey ? key_fec_params_ : delta_fec_params_;
@@ -409,13 +516,17 @@
   auto middle_packet = absl::make_unique<RtpPacketToSend>(*single_packet);
   auto last_packet = absl::make_unique<RtpPacketToSend>(*single_packet);
   // Simplest way to estimate how much extensions would occupy is to set them.
-  AddRtpHeaderExtensions(*video_header, frame_type, set_video_rotation,
+  AddRtpHeaderExtensions(*video_header, playout_delay, frame_type,
+                         set_video_rotation, set_color_space, set_frame_marking,
                          /*first=*/true, /*last=*/true, single_packet.get());
-  AddRtpHeaderExtensions(*video_header, frame_type, set_video_rotation,
+  AddRtpHeaderExtensions(*video_header, playout_delay, frame_type,
+                         set_video_rotation, set_color_space, set_frame_marking,
                          /*first=*/true, /*last=*/false, first_packet.get());
-  AddRtpHeaderExtensions(*video_header, frame_type, set_video_rotation,
+  AddRtpHeaderExtensions(*video_header, playout_delay, frame_type,
+                         set_video_rotation, set_color_space, set_frame_marking,
                          /*first=*/false, /*last=*/false, middle_packet.get());
-  AddRtpHeaderExtensions(*video_header, frame_type, set_video_rotation,
+  AddRtpHeaderExtensions(*video_header, playout_delay, frame_type,
+                         set_video_rotation, set_color_space, set_frame_marking,
                          /*first=*/false, /*last=*/true, last_packet.get());
 
   RTC_DCHECK_GT(packet_capacity, single_packet->headers_size());
@@ -439,8 +550,21 @@
 
   RTPVideoHeader minimized_video_header;
   const RTPVideoHeader* packetize_video_header = video_header;
+
+  rtc::ArrayView<const uint8_t> generic_descriptor_raw_00 =
+      first_packet->GetRawExtension<RtpGenericFrameDescriptorExtension00>();
+  rtc::ArrayView<const uint8_t> generic_descriptor_raw_01 =
+      first_packet->GetRawExtension<RtpGenericFrameDescriptorExtension01>();
+
+  if (!generic_descriptor_raw_00.empty() &&
+      !generic_descriptor_raw_01.empty()) {
+    RTC_LOG(LS_WARNING) << "Two versions of GFD extension used.";
+    return false;
+  }
+
   rtc::ArrayView<const uint8_t> generic_descriptor_raw =
-      first_packet->GetRawExtension<RtpGenericFrameDescriptorExtension>();
+      !generic_descriptor_raw_01.empty() ? generic_descriptor_raw_01
+                                         : generic_descriptor_raw_00;
   if (!generic_descriptor_raw.empty()) {
     if (MinimizeDescriptor(*video_header, &minimized_video_header)) {
       packetize_video_header = &minimized_video_header;
@@ -460,9 +584,15 @@
     encrypted_video_payload.SetSize(max_ciphertext_size);
 
     size_t bytes_written = 0;
+
+    // Only enable header authentication if the field trial is enabled.
+    rtc::ArrayView<const uint8_t> additional_data;
+    if (generic_descriptor_auth_experiment_) {
+      additional_data = generic_descriptor_raw;
+    }
+
     if (frame_encryptor_->Encrypt(
-            cricket::MEDIA_TYPE_VIDEO, first_packet->Ssrc(),
-            /*additional_data=*/nullptr,
+            cricket::MEDIA_TYPE_VIDEO, first_packet->Ssrc(), additional_data,
             rtc::MakeArrayView(payload_data, payload_size),
             encrypted_video_payload, &bytes_written) != 0) {
       return false;
@@ -477,6 +607,17 @@
         << "one is required since require_frame_encryptor is set";
   }
 
+  VideoCodecType video_type;
+  {
+    rtc::CritScope cs(&payload_type_crit_);
+    const auto it = payload_type_map_.find(payload_type);
+    if (it == payload_type_map_.end()) {
+      RTC_LOG(LS_ERROR) << "Payload type " << static_cast<int>(payload_type)
+                        << " not registered.";
+      return false;
+    }
+    video_type = it->second;
+  }
   std::unique_ptr<RtpPacketizer> packetizer = RtpPacketizer::Create(
       video_type, rtc::MakeArrayView(payload_data, payload_size), limits,
       *packetize_video_header, frame_type, fragmentation);
@@ -486,6 +627,17 @@
                                        expected_retransmission_time_ms);
   size_t num_packets = packetizer->NumPackets();
 
+  size_t unpacketized_payload_size;
+  if (fragmentation && fragmentation->fragmentationVectorSize > 0) {
+    unpacketized_payload_size = 0;
+    for (uint16_t i = 0; i < fragmentation->fragmentationVectorSize; ++i) {
+      unpacketized_payload_size += fragmentation->fragmentationLength[i];
+    }
+  } else {
+    unpacketized_payload_size = payload_size;
+  }
+  size_t packetized_payload_size = 0;
+
   if (num_packets == 0)
     return false;
 
@@ -516,7 +668,12 @@
     RTC_DCHECK_LE(packet->payload_size(), expected_payload_capacity);
     if (!rtp_sender_->AssignSequenceNumber(packet.get()))
       return false;
+    packetized_payload_size += packet->payload_size();
 
+    if (i == 0) {
+      playout_delay_oracle_->OnSentPacket(packet->SequenceNumber(),
+                                          playout_delay);
+    }
     // No FEC protection for upper temporal layers, if used.
     bool protect_packet = temporal_id == 0 || temporal_id == kNoTemporalIdx;
 
@@ -555,6 +712,12 @@
     }
   }
 
+  rtc::CritScope cs(&stats_crit_);
+  RTC_DCHECK_GE(packetized_payload_size, unpacketized_payload_size);
+  packetization_overhead_bitrate_.Update(
+      packetized_payload_size - unpacketized_payload_size,
+      clock_->TimeInMilliseconds());
+
   TRACE_EVENT_ASYNC_END1("webrtc", "Video", capture_time_ms, "timestamp",
                          rtp_timestamp);
   return true;
@@ -570,14 +733,10 @@
   return fec_bitrate_.Rate(clock_->TimeInMilliseconds()).value_or(0);
 }
 
-int RTPSenderVideo::SelectiveRetransmissions() const {
-  rtc::CritScope cs(&crit_);
-  return retransmission_settings_;
-}
-
-void RTPSenderVideo::SetSelectiveRetransmissions(uint8_t settings) {
-  rtc::CritScope cs(&crit_);
-  retransmission_settings_ = settings;
+uint32_t RTPSenderVideo::PacketizationOverheadBps() const {
+  rtc::CritScope cs(&stats_crit_);
+  return packetization_overhead_bitrate_.Rate(clock_->TimeInMilliseconds())
+      .value_or(0);
 }
 
 StorageType RTPSenderVideo::GetStorageType(
@@ -586,8 +745,6 @@
     int64_t expected_retransmission_time_ms) {
   if (retransmission_settings == kRetransmitOff)
     return StorageType::kDontRetransmit;
-  if (retransmission_settings == kRetransmitAllPackets)
-    return StorageType::kAllowRetransmission;
 
   rtc::CritScope cs(&stats_crit_);
   // Media packet storage.
@@ -618,7 +775,12 @@
     uint8_t operator()(const RTPVideoHeaderH264&) { return kNoTemporalIdx; }
     uint8_t operator()(const absl::monostate&) { return kNoTemporalIdx; }
   };
-  return absl::visit(TemporalIdGetter(), header.video_type_header);
+  switch (header.codec) {
+    case kVideoCodecH264:
+      return header.frame_marking.temporal_id;
+    default:
+      return absl::visit(TemporalIdGetter(), header.video_type_header);
+  }
 }
 
 bool RTPSenderVideo::UpdateConditionalRetransmit(
diff --git a/modules/rtp_rtcp/source/rtp_sender_video.h b/modules/rtp_rtcp/source/rtp_sender_video.h
index d3a898b..9772b86 100644
--- a/modules/rtp_rtcp/source/rtp_sender_video.h
+++ b/modules/rtp_rtcp/source/rtp_sender_video.h
@@ -19,12 +19,12 @@
 #include "common_types.h"  // NOLINT(build/include)
 #include "modules/rtp_rtcp/include/flexfec_sender.h"
 #include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
+#include "modules/rtp_rtcp/source/playout_delay_oracle.h"
 #include "modules/rtp_rtcp/source/rtp_rtcp_config.h"
 #include "modules/rtp_rtcp/source/rtp_sender.h"
-#include "modules/rtp_rtcp/source/rtp_utility.h"
 #include "modules/rtp_rtcp/source/ulpfec_generator.h"
-#include "rtc_base/criticalsection.h"
-#include "rtc_base/onetimeevent.h"
+#include "rtc_base/critical_section.h"
+#include "rtc_base/one_time_event.h"
 #include "rtc_base/rate_statistics.h"
 #include "rtc_base/sequenced_task_checker.h"
 #include "rtc_base/thread_annotations.h"
@@ -35,6 +35,17 @@
 class RtpPacketizer;
 class RtpPacketToSend;
 
+// kConditionallyRetransmitHigherLayers allows retransmission of video frames
+// in higher layers if either the last frame in that layer was too far back in
+// time, or if we estimate that a new frame will be available in a lower layer
+// in a shorter time than it would take to request and receive a retransmission.
+enum RetransmissionMode : uint8_t {
+  kRetransmitOff = 0x0,
+  kRetransmitBaseLayer = 0x2,
+  kRetransmitHigherLayers = 0x4,
+  kConditionallyRetransmitHigherLayers = 0x8,
+};
+
 class RTPSenderVideo {
  public:
   static constexpr int64_t kTLRateWindowSizeMs = 2500;
@@ -42,17 +53,13 @@
   RTPSenderVideo(Clock* clock,
                  RTPSender* rtpSender,
                  FlexfecSender* flexfec_sender,
+                 PlayoutDelayOracle* playout_delay_oracle,
                  FrameEncryptorInterface* frame_encryptor,
-                 bool require_frame_encryption);
+                 bool require_frame_encryption,
+                 const WebRtcKeyValueConfig& field_trials);
   virtual ~RTPSenderVideo();
 
-  virtual enum VideoCodecType VideoCodecType() const;
-
-  static RtpUtility::Payload* CreateVideoPayload(absl::string_view payload_name,
-                                                 int8_t payload_type);
-
-  bool SendVideo(enum VideoCodecType video_type,
-                 FrameType frame_type,
+  bool SendVideo(FrameType frame_type,
                  int8_t payload_type,
                  uint32_t capture_timestamp,
                  int64_t capture_time_ms,
@@ -62,13 +69,17 @@
                  const RTPVideoHeader* video_header,
                  int64_t expected_retransmission_time_ms);
 
-  void SetVideoCodecType(enum VideoCodecType type);
+  void RegisterPayloadType(int8_t payload_type, absl::string_view payload_name);
 
-  // ULPFEC.
+  // Set RED and ULPFEC payload types. A payload type of -1 means that the
+  // corresponding feature is turned off. Note that we DO NOT support enabling
+  // ULPFEC without enabling RED, and RED is only ever used when ULPFEC is
+  // enabled.
   void SetUlpfecConfig(int red_payload_type, int ulpfec_payload_type);
-  void GetUlpfecConfig(int* red_payload_type, int* ulpfec_payload_type) const;
 
   // FlexFEC/ULPFEC.
+  // Set FEC rates, max frames before FEC is sent, and type of FEC masks.
+  // Returns false on failure.
   void SetFecParameters(const FecProtectionParams& delta_params,
                         const FecProtectionParams& key_params);
 
@@ -78,8 +89,10 @@
   uint32_t VideoBitrateSent() const;
   uint32_t FecOverheadRate() const;
 
-  int SelectiveRetransmissions() const;
-  void SetSelectiveRetransmissions(uint8_t settings);
+  // Returns the current packetization overhead rate, in bps. Note that this is
+  // the payload overhead, eg the VP8 payload headers, not the RTP headers
+  // or extension/
+  uint32_t PacketizationOverheadBps() const;
 
  protected:
   static uint8_t GetTemporalId(const RTPVideoHeader& header);
@@ -115,6 +128,10 @@
                                   StorageType media_packet_storage,
                                   bool protect_media_packet);
 
+  bool LogAndSendToNetwork(std::unique_ptr<RtpPacketToSend> packet,
+                           StorageType storage,
+                           RtpPacketSender::Priority priority);
+
   bool red_enabled() const RTC_EXCLUSIVE_LOCKS_REQUIRED(crit_) {
     return red_payload_type_ >= 0;
   }
@@ -132,12 +149,23 @@
   RTPSender* const rtp_sender_;
   Clock* const clock_;
 
+  // Maps payload type to codec type, for packetization.
+  // TODO(nisse): Set on construction, to avoid lock.
+  rtc::CriticalSection payload_type_crit_;
+  std::map<int8_t, VideoCodecType> payload_type_map_
+      RTC_GUARDED_BY(payload_type_crit_);
+
   // Should never be held when calling out of this class.
   rtc::CriticalSection crit_;
 
-  enum VideoCodecType video_type_;
   int32_t retransmission_settings_ RTC_GUARDED_BY(crit_);
   VideoRotation last_rotation_ RTC_GUARDED_BY(crit_);
+  absl::optional<ColorSpace> last_color_space_ RTC_GUARDED_BY(crit_);
+  bool transmit_color_space_next_frame_ RTC_GUARDED_BY(crit_);
+  // Tracks the current request for playout delay limits from application
+  // and decides whether the current RTP frame should include the playout
+  // delay extension on header.
+  PlayoutDelayOracle* const playout_delay_oracle_;
 
   // RED/ULPFEC.
   int red_payload_type_ RTC_GUARDED_BY(crit_);
@@ -157,6 +185,7 @@
   RateStatistics fec_bitrate_ RTC_GUARDED_BY(stats_crit_);
   // Bitrate used for video payload and RTP headers.
   RateStatistics video_bitrate_ RTC_GUARDED_BY(stats_crit_);
+  RateStatistics packetization_overhead_bitrate_ RTC_GUARDED_BY(stats_crit_);
 
   std::map<int, TemporalLayerStats> frame_stats_by_temporal_layer_
       RTC_GUARDED_BY(stats_crit_);
@@ -169,6 +198,8 @@
   // initialized frame_encryptor_ before being sent out of the network.
   // Otherwise these payloads will be dropped.
   bool require_frame_encryption_;
+  // Set to true if the generic descriptor should be authenticated.
+  const bool generic_descriptor_auth_experiment_;
 };
 
 }  // namespace webrtc
diff --git a/modules/rtp_rtcp/source/rtp_sender_video_unittest.cc b/modules/rtp_rtcp/source/rtp_sender_video_unittest.cc
new file mode 100644
index 0000000..fbd15c6
--- /dev/null
+++ b/modules/rtp_rtcp/source/rtp_sender_video_unittest.cc
@@ -0,0 +1,644 @@
+/*
+ *  Copyright (c) 2019 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include <string>
+#include <vector>
+
+#include "api/video/video_codec_constants.h"
+#include "api/video/video_timing.h"
+#include "modules/rtp_rtcp/include/rtp_cvo.h"
+#include "modules/rtp_rtcp/include/rtp_header_extension_map.h"
+#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
+#include "modules/rtp_rtcp/source/rtp_format_video_generic.h"
+#include "modules/rtp_rtcp/source/rtp_generic_frame_descriptor.h"
+#include "modules/rtp_rtcp/source/rtp_generic_frame_descriptor_extension.h"
+#include "modules/rtp_rtcp/source/rtp_header_extensions.h"
+#include "modules/rtp_rtcp/source/rtp_packet_received.h"
+#include "modules/rtp_rtcp/source/rtp_sender.h"
+#include "modules/rtp_rtcp/source/rtp_sender_video.h"
+#include "rtc_base/arraysize.h"
+#include "rtc_base/rate_limiter.h"
+#include "test/gmock.h"
+#include "test/gtest.h"
+
+namespace webrtc {
+
+namespace {
+
+using ::testing::ElementsAre;
+
+enum : int {  // The first valid value is 1.
+  kAbsoluteSendTimeExtensionId = 1,
+  kFrameMarkingExtensionId,
+  kGenericDescriptorId00,
+  kGenericDescriptorId01,
+  kTransmissionTimeOffsetExtensionId,
+  kTransportSequenceNumberExtensionId,
+  kVideoRotationExtensionId,
+  kVideoTimingExtensionId,
+};
+
+constexpr int kPayload = 100;
+constexpr uint32_t kTimestamp = 10;
+constexpr uint16_t kSeqNum = 33;
+constexpr uint32_t kSsrc = 725242;
+constexpr int kMaxPacketLength = 1500;
+constexpr uint64_t kStartTime = 123456789;
+constexpr int64_t kDefaultExpectedRetransmissionTimeMs = 125;
+
+class LoopbackTransportTest : public webrtc::Transport {
+ public:
+  LoopbackTransportTest() {
+    receivers_extensions_.Register(kRtpExtensionTransmissionTimeOffset,
+                                   kTransmissionTimeOffsetExtensionId);
+    receivers_extensions_.Register(kRtpExtensionAbsoluteSendTime,
+                                   kAbsoluteSendTimeExtensionId);
+    receivers_extensions_.Register(kRtpExtensionTransportSequenceNumber,
+                                   kTransportSequenceNumberExtensionId);
+    receivers_extensions_.Register(kRtpExtensionVideoRotation,
+                                   kVideoRotationExtensionId);
+    receivers_extensions_.Register(kRtpExtensionVideoTiming,
+                                   kVideoTimingExtensionId);
+    receivers_extensions_.Register(kRtpExtensionGenericFrameDescriptor00,
+                                   kGenericDescriptorId00);
+    receivers_extensions_.Register(kRtpExtensionGenericFrameDescriptor01,
+                                   kGenericDescriptorId01);
+    receivers_extensions_.Register(kRtpExtensionFrameMarking,
+                                   kFrameMarkingExtensionId);
+  }
+
+  bool SendRtp(const uint8_t* data,
+               size_t len,
+               const PacketOptions& options) override {
+    sent_packets_.push_back(RtpPacketReceived(&receivers_extensions_));
+    EXPECT_TRUE(sent_packets_.back().Parse(data, len));
+    return true;
+  }
+  bool SendRtcp(const uint8_t* data, size_t len) override { return false; }
+  const RtpPacketReceived& last_sent_packet() { return sent_packets_.back(); }
+  int packets_sent() { return sent_packets_.size(); }
+
+ private:
+  RtpHeaderExtensionMap receivers_extensions_;
+  std::vector<RtpPacketReceived> sent_packets_;
+};
+
+}  // namespace
+
+class TestRtpSenderVideo : public RTPSenderVideo {
+ public:
+  TestRtpSenderVideo(Clock* clock,
+                     RTPSender* rtp_sender,
+                     FlexfecSender* flexfec_sender,
+                     const WebRtcKeyValueConfig& field_trials)
+      : RTPSenderVideo(clock,
+                       rtp_sender,
+                       flexfec_sender,
+                       &playout_delay_oracle_,
+                       nullptr,
+                       false,
+                       field_trials) {}
+  ~TestRtpSenderVideo() override {}
+
+  StorageType GetStorageType(const RTPVideoHeader& header,
+                             int32_t retransmission_settings,
+                             int64_t expected_retransmission_time_ms) {
+    return RTPSenderVideo::GetStorageType(GetTemporalId(header),
+                                          retransmission_settings,
+                                          expected_retransmission_time_ms);
+  }
+  PlayoutDelayOracle playout_delay_oracle_;
+};
+
+class FieldTrials : public WebRtcKeyValueConfig {
+ public:
+  explicit FieldTrials(bool use_send_side_bwe_with_overhead)
+      : use_send_side_bwe_with_overhead_(use_send_side_bwe_with_overhead) {}
+
+  std::string Lookup(absl::string_view key) const override {
+    return key == "WebRTC-SendSideBwe-WithOverhead" &&
+                   use_send_side_bwe_with_overhead_
+               ? "Enabled"
+               : "";
+  }
+
+ private:
+  bool use_send_side_bwe_with_overhead_;
+};
+
+class RtpSenderVideoTest : public ::testing::TestWithParam<bool> {
+ public:
+  RtpSenderVideoTest()
+      : field_trials_(GetParam()),
+        fake_clock_(kStartTime),
+        retransmission_rate_limiter_(&fake_clock_, 1000),
+        // TODO(pbos): Set up to use pacer.
+        rtp_sender_(false,
+                    &fake_clock_,
+                    &transport_,
+                    nullptr,
+                    absl::nullopt,
+                    nullptr,
+                    nullptr,
+                    nullptr,
+                    nullptr,
+                    nullptr,
+                    nullptr,
+                    &retransmission_rate_limiter_,
+                    nullptr,
+                    false,
+                    nullptr,
+                    false,
+                    false,
+                    field_trials_),
+        rtp_sender_video_(&fake_clock_, &rtp_sender_, nullptr, field_trials_) {
+    rtp_sender_.SetSequenceNumber(kSeqNum);
+    rtp_sender_.SetTimestampOffset(0);
+    rtp_sender_.SetSSRC(kSsrc);
+
+    rtp_sender_video_.RegisterPayloadType(kPayload, "generic");
+  }
+
+  void PopulateGenericFrameDescriptor(int version);
+
+  void UsesMinimalVp8DescriptorWhenGenericFrameDescriptorExtensionIsUsed(
+      int version);
+
+ protected:
+  FieldTrials field_trials_;
+  SimulatedClock fake_clock_;
+  LoopbackTransportTest transport_;
+  RateLimiter retransmission_rate_limiter_;
+
+  RTPSender rtp_sender_;
+  TestRtpSenderVideo rtp_sender_video_;
+};
+
+TEST_P(RtpSenderVideoTest, KeyFrameHasCVO) {
+  uint8_t kFrame[kMaxPacketLength];
+  EXPECT_EQ(0, rtp_sender_.RegisterRtpHeaderExtension(
+                   kRtpExtensionVideoRotation, kVideoRotationExtensionId));
+
+  RTPVideoHeader hdr;
+  hdr.rotation = kVideoRotation_0;
+  rtp_sender_video_.SendVideo(kVideoFrameKey, kPayload, kTimestamp, 0, kFrame,
+                              sizeof(kFrame), nullptr, &hdr,
+                              kDefaultExpectedRetransmissionTimeMs);
+
+  VideoRotation rotation;
+  EXPECT_TRUE(
+      transport_.last_sent_packet().GetExtension<VideoOrientation>(&rotation));
+  EXPECT_EQ(kVideoRotation_0, rotation);
+}
+
+TEST_P(RtpSenderVideoTest, TimingFrameHasPacketizationTimstampSet) {
+  uint8_t kFrame[kMaxPacketLength];
+  const int64_t kPacketizationTimeMs = 100;
+  const int64_t kEncodeStartDeltaMs = 10;
+  const int64_t kEncodeFinishDeltaMs = 50;
+  EXPECT_EQ(0, rtp_sender_.RegisterRtpHeaderExtension(kRtpExtensionVideoTiming,
+                                                      kVideoTimingExtensionId));
+
+  const int64_t kCaptureTimestamp = fake_clock_.TimeInMilliseconds();
+
+  RTPVideoHeader hdr;
+  hdr.video_timing.flags = VideoSendTiming::kTriggeredByTimer;
+  hdr.video_timing.encode_start_delta_ms = kEncodeStartDeltaMs;
+  hdr.video_timing.encode_finish_delta_ms = kEncodeFinishDeltaMs;
+
+  fake_clock_.AdvanceTimeMilliseconds(kPacketizationTimeMs);
+  rtp_sender_video_.SendVideo(
+      kVideoFrameKey, kPayload, kTimestamp, kCaptureTimestamp, kFrame,
+      sizeof(kFrame), nullptr, &hdr, kDefaultExpectedRetransmissionTimeMs);
+  VideoSendTiming timing;
+  EXPECT_TRUE(transport_.last_sent_packet().GetExtension<VideoTimingExtension>(
+      &timing));
+  EXPECT_EQ(kPacketizationTimeMs, timing.packetization_finish_delta_ms);
+  EXPECT_EQ(kEncodeStartDeltaMs, timing.encode_start_delta_ms);
+  EXPECT_EQ(kEncodeFinishDeltaMs, timing.encode_finish_delta_ms);
+}
+
+TEST_P(RtpSenderVideoTest, DeltaFrameHasCVOWhenChanged) {
+  uint8_t kFrame[kMaxPacketLength];
+  EXPECT_EQ(0, rtp_sender_.RegisterRtpHeaderExtension(
+                   kRtpExtensionVideoRotation, kVideoRotationExtensionId));
+
+  RTPVideoHeader hdr;
+  hdr.rotation = kVideoRotation_90;
+  EXPECT_TRUE(rtp_sender_video_.SendVideo(
+      kVideoFrameKey, kPayload, kTimestamp, 0, kFrame, sizeof(kFrame), nullptr,
+      &hdr, kDefaultExpectedRetransmissionTimeMs));
+
+  hdr.rotation = kVideoRotation_0;
+  EXPECT_TRUE(rtp_sender_video_.SendVideo(
+      kVideoFrameDelta, kPayload, kTimestamp + 1, 0, kFrame, sizeof(kFrame),
+      nullptr, &hdr, kDefaultExpectedRetransmissionTimeMs));
+
+  VideoRotation rotation;
+  EXPECT_TRUE(
+      transport_.last_sent_packet().GetExtension<VideoOrientation>(&rotation));
+  EXPECT_EQ(kVideoRotation_0, rotation);
+}
+
+TEST_P(RtpSenderVideoTest, DeltaFrameHasCVOWhenNonZero) {
+  uint8_t kFrame[kMaxPacketLength];
+  EXPECT_EQ(0, rtp_sender_.RegisterRtpHeaderExtension(
+                   kRtpExtensionVideoRotation, kVideoRotationExtensionId));
+
+  RTPVideoHeader hdr;
+  hdr.rotation = kVideoRotation_90;
+  EXPECT_TRUE(rtp_sender_video_.SendVideo(
+      kVideoFrameKey, kPayload, kTimestamp, 0, kFrame, sizeof(kFrame), nullptr,
+      &hdr, kDefaultExpectedRetransmissionTimeMs));
+
+  EXPECT_TRUE(rtp_sender_video_.SendVideo(
+      kVideoFrameDelta, kPayload, kTimestamp + 1, 0, kFrame, sizeof(kFrame),
+      nullptr, &hdr, kDefaultExpectedRetransmissionTimeMs));
+
+  VideoRotation rotation;
+  EXPECT_TRUE(
+      transport_.last_sent_packet().GetExtension<VideoOrientation>(&rotation));
+  EXPECT_EQ(kVideoRotation_90, rotation);
+}
+
+TEST_P(RtpSenderVideoTest, CheckH264FrameMarking) {
+  uint8_t kFrame[kMaxPacketLength];
+  EXPECT_EQ(0, rtp_sender_.RegisterRtpHeaderExtension(
+                   kRtpExtensionFrameMarking, kFrameMarkingExtensionId));
+
+  RTPFragmentationHeader frag;
+  frag.VerifyAndAllocateFragmentationHeader(1);
+  frag.fragmentationOffset[0] = 0;
+  frag.fragmentationLength[0] = sizeof(kFrame);
+
+  RTPVideoHeader hdr;
+  hdr.video_type_header.emplace<RTPVideoHeaderH264>().packetization_mode =
+      H264PacketizationMode::NonInterleaved;
+  hdr.codec = kVideoCodecH264;
+  hdr.frame_marking.temporal_id = kNoTemporalIdx;
+  hdr.frame_marking.tl0_pic_idx = 99;
+  hdr.frame_marking.base_layer_sync = true;
+  rtp_sender_video_.SendVideo(kVideoFrameDelta, kPayload,
+                               kTimestamp, 0, kFrame, sizeof(kFrame), &frag,
+                               &hdr, kDefaultExpectedRetransmissionTimeMs);
+
+  FrameMarking fm;
+  EXPECT_FALSE(
+      transport_.last_sent_packet().GetExtension<FrameMarkingExtension>(&fm));
+
+  hdr.frame_marking.temporal_id = 0;
+  rtp_sender_video_.SendVideo(kVideoFrameDelta, kPayload,
+                               kTimestamp + 1, 0, kFrame, sizeof(kFrame), &frag,
+                               &hdr, kDefaultExpectedRetransmissionTimeMs);
+
+  EXPECT_TRUE(
+      transport_.last_sent_packet().GetExtension<FrameMarkingExtension>(&fm));
+  EXPECT_EQ(hdr.frame_marking.temporal_id, fm.temporal_id);
+  EXPECT_EQ(hdr.frame_marking.tl0_pic_idx, fm.tl0_pic_idx);
+  EXPECT_EQ(hdr.frame_marking.base_layer_sync, fm.base_layer_sync);
+}
+
+// Make sure rotation is parsed correctly when the Camera (C) and Flip (F) bits
+// are set in the CVO byte.
+TEST_P(RtpSenderVideoTest, SendVideoWithCameraAndFlipCVO) {
+  // Test extracting rotation when Camera (C) and Flip (F) bits are zero.
+  EXPECT_EQ(kVideoRotation_0, ConvertCVOByteToVideoRotation(0));
+  EXPECT_EQ(kVideoRotation_90, ConvertCVOByteToVideoRotation(1));
+  EXPECT_EQ(kVideoRotation_180, ConvertCVOByteToVideoRotation(2));
+  EXPECT_EQ(kVideoRotation_270, ConvertCVOByteToVideoRotation(3));
+  // Test extracting rotation when Camera (C) and Flip (F) bits are set.
+  const int flip_bit = 1 << 2;
+  const int camera_bit = 1 << 3;
+  EXPECT_EQ(kVideoRotation_0,
+            ConvertCVOByteToVideoRotation(flip_bit | camera_bit | 0));
+  EXPECT_EQ(kVideoRotation_90,
+            ConvertCVOByteToVideoRotation(flip_bit | camera_bit | 1));
+  EXPECT_EQ(kVideoRotation_180,
+            ConvertCVOByteToVideoRotation(flip_bit | camera_bit | 2));
+  EXPECT_EQ(kVideoRotation_270,
+            ConvertCVOByteToVideoRotation(flip_bit | camera_bit | 3));
+}
+
+TEST_P(RtpSenderVideoTest, RetransmissionTypesGeneric) {
+  RTPVideoHeader header;
+  header.codec = kVideoCodecGeneric;
+
+  EXPECT_EQ(kDontRetransmit,
+            rtp_sender_video_.GetStorageType(
+                header, kRetransmitOff, kDefaultExpectedRetransmissionTimeMs));
+  EXPECT_EQ(kAllowRetransmission, rtp_sender_video_.GetStorageType(
+                                      header, kRetransmitBaseLayer,
+                                      kDefaultExpectedRetransmissionTimeMs));
+  EXPECT_EQ(kAllowRetransmission, rtp_sender_video_.GetStorageType(
+                                      header, kRetransmitHigherLayers,
+                                      kDefaultExpectedRetransmissionTimeMs));
+  EXPECT_EQ(kAllowRetransmission,
+            rtp_sender_video_.GetStorageType(
+                header, kConditionallyRetransmitHigherLayers,
+                kDefaultExpectedRetransmissionTimeMs));
+}
+
+TEST_P(RtpSenderVideoTest, RetransmissionTypesH264) {
+  RTPVideoHeader header;
+  header.video_type_header.emplace<RTPVideoHeaderH264>().packetization_mode =
+      H264PacketizationMode::NonInterleaved;
+  header.codec = kVideoCodecH264;
+  header.frame_marking.temporal_id = kNoTemporalIdx;
+
+  EXPECT_EQ(kDontRetransmit,
+            rtp_sender_video_.GetStorageType(
+                header, kRetransmitOff, kDefaultExpectedRetransmissionTimeMs));
+  EXPECT_EQ(kAllowRetransmission, rtp_sender_video_.GetStorageType(
+                                      header, kRetransmitBaseLayer,
+                                      kDefaultExpectedRetransmissionTimeMs));
+  EXPECT_EQ(kAllowRetransmission, rtp_sender_video_.GetStorageType(
+                                      header, kRetransmitHigherLayers,
+                                      kDefaultExpectedRetransmissionTimeMs));
+  EXPECT_EQ(kAllowRetransmission,
+            rtp_sender_video_.GetStorageType(
+                header, kConditionallyRetransmitHigherLayers,
+                kDefaultExpectedRetransmissionTimeMs));
+
+  // Test higher level retransmit.
+  for (int tid = 0; tid <= kMaxTemporalStreams; ++tid) {
+    header.frame_marking.temporal_id = tid;
+    EXPECT_EQ(kAllowRetransmission,
+              rtp_sender_video_.GetStorageType(
+                  header, kRetransmitHigherLayers | kRetransmitBaseLayer,
+                  kDefaultExpectedRetransmissionTimeMs));
+  }
+}
+
+TEST_P(RtpSenderVideoTest, RetransmissionTypesVP8BaseLayer) {
+  RTPVideoHeader header;
+  header.codec = kVideoCodecVP8;
+  auto& vp8_header = header.video_type_header.emplace<RTPVideoHeaderVP8>();
+  vp8_header.temporalIdx = 0;
+
+  EXPECT_EQ(kDontRetransmit,
+            rtp_sender_video_.GetStorageType(
+                header, kRetransmitOff, kDefaultExpectedRetransmissionTimeMs));
+  EXPECT_EQ(kAllowRetransmission, rtp_sender_video_.GetStorageType(
+                                      header, kRetransmitBaseLayer,
+                                      kDefaultExpectedRetransmissionTimeMs));
+  EXPECT_EQ(kDontRetransmit, rtp_sender_video_.GetStorageType(
+                                 header, kRetransmitHigherLayers,
+                                 kDefaultExpectedRetransmissionTimeMs));
+  EXPECT_EQ(kAllowRetransmission,
+            rtp_sender_video_.GetStorageType(
+                header, kRetransmitHigherLayers | kRetransmitBaseLayer,
+                kDefaultExpectedRetransmissionTimeMs));
+  EXPECT_EQ(kDontRetransmit, rtp_sender_video_.GetStorageType(
+                                 header, kConditionallyRetransmitHigherLayers,
+                                 kDefaultExpectedRetransmissionTimeMs));
+  EXPECT_EQ(
+      kAllowRetransmission,
+      rtp_sender_video_.GetStorageType(
+          header, kRetransmitBaseLayer | kConditionallyRetransmitHigherLayers,
+          kDefaultExpectedRetransmissionTimeMs));
+}
+
+TEST_P(RtpSenderVideoTest, RetransmissionTypesVP8HigherLayers) {
+  RTPVideoHeader header;
+  header.codec = kVideoCodecVP8;
+
+  auto& vp8_header = header.video_type_header.emplace<RTPVideoHeaderVP8>();
+  for (int tid = 1; tid <= kMaxTemporalStreams; ++tid) {
+    vp8_header.temporalIdx = tid;
+
+    EXPECT_EQ(kDontRetransmit, rtp_sender_video_.GetStorageType(
+                                   header, kRetransmitOff,
+                                   kDefaultExpectedRetransmissionTimeMs));
+    EXPECT_EQ(kDontRetransmit, rtp_sender_video_.GetStorageType(
+                                   header, kRetransmitBaseLayer,
+                                   kDefaultExpectedRetransmissionTimeMs));
+    EXPECT_EQ(kAllowRetransmission, rtp_sender_video_.GetStorageType(
+                                        header, kRetransmitHigherLayers,
+                                        kDefaultExpectedRetransmissionTimeMs));
+    EXPECT_EQ(kAllowRetransmission,
+              rtp_sender_video_.GetStorageType(
+                  header, kRetransmitHigherLayers | kRetransmitBaseLayer,
+                  kDefaultExpectedRetransmissionTimeMs));
+  }
+}
+
+TEST_P(RtpSenderVideoTest, RetransmissionTypesVP9) {
+  RTPVideoHeader header;
+  header.codec = kVideoCodecVP9;
+
+  auto& vp9_header = header.video_type_header.emplace<RTPVideoHeaderVP9>();
+  for (int tid = 1; tid <= kMaxTemporalStreams; ++tid) {
+    vp9_header.temporal_idx = tid;
+
+    EXPECT_EQ(kDontRetransmit, rtp_sender_video_.GetStorageType(
+                                   header, kRetransmitOff,
+                                   kDefaultExpectedRetransmissionTimeMs));
+    EXPECT_EQ(kDontRetransmit, rtp_sender_video_.GetStorageType(
+                                   header, kRetransmitBaseLayer,
+                                   kDefaultExpectedRetransmissionTimeMs));
+    EXPECT_EQ(kAllowRetransmission, rtp_sender_video_.GetStorageType(
+                                        header, kRetransmitHigherLayers,
+                                        kDefaultExpectedRetransmissionTimeMs));
+    EXPECT_EQ(kAllowRetransmission,
+              rtp_sender_video_.GetStorageType(
+                  header, kRetransmitHigherLayers | kRetransmitBaseLayer,
+                  kDefaultExpectedRetransmissionTimeMs));
+  }
+}
+
+TEST_P(RtpSenderVideoTest, ConditionalRetransmit) {
+  const int64_t kFrameIntervalMs = 33;
+  const int64_t kRttMs = (kFrameIntervalMs * 3) / 2;
+  const uint8_t kSettings =
+      kRetransmitBaseLayer | kConditionallyRetransmitHigherLayers;
+
+  // Insert VP8 frames for all temporal layers, but stop before the final index.
+  RTPVideoHeader header;
+  header.codec = kVideoCodecVP8;
+
+  // Fill averaging window to prevent rounding errors.
+  constexpr int kNumRepetitions =
+      (RTPSenderVideo::kTLRateWindowSizeMs + (kFrameIntervalMs / 2)) /
+      kFrameIntervalMs;
+  constexpr int kPattern[] = {0, 2, 1, 2};
+  auto& vp8_header = header.video_type_header.emplace<RTPVideoHeaderVP8>();
+  for (size_t i = 0; i < arraysize(kPattern) * kNumRepetitions; ++i) {
+    vp8_header.temporalIdx = kPattern[i % arraysize(kPattern)];
+    rtp_sender_video_.GetStorageType(header, kSettings, kRttMs);
+    fake_clock_.AdvanceTimeMilliseconds(kFrameIntervalMs);
+  }
+
+  // Since we're at the start of the pattern, the next expected frame in TL0 is
+  // right now. We will wait at most one expected retransmission time before
+  // acknowledging that it did not arrive, which means this frame and the next
+  // will not be retransmitted.
+  vp8_header.temporalIdx = 1;
+  EXPECT_EQ(StorageType::kDontRetransmit,
+            rtp_sender_video_.GetStorageType(header, kSettings, kRttMs));
+  fake_clock_.AdvanceTimeMilliseconds(kFrameIntervalMs);
+  EXPECT_EQ(StorageType::kDontRetransmit,
+            rtp_sender_video_.GetStorageType(header, kSettings, kRttMs));
+  fake_clock_.AdvanceTimeMilliseconds(kFrameIntervalMs);
+
+  // The TL0 frame did not arrive. So allow retransmission.
+  EXPECT_EQ(StorageType::kAllowRetransmission,
+            rtp_sender_video_.GetStorageType(header, kSettings, kRttMs));
+  fake_clock_.AdvanceTimeMilliseconds(kFrameIntervalMs);
+
+  // Insert a frame for TL2. We just had frame in TL1, so the next one there is
+  // in three frames away. TL0 is still too far in the past. So, allow
+  // retransmission.
+  vp8_header.temporalIdx = 2;
+  EXPECT_EQ(StorageType::kAllowRetransmission,
+            rtp_sender_video_.GetStorageType(header, kSettings, kRttMs));
+  fake_clock_.AdvanceTimeMilliseconds(kFrameIntervalMs);
+
+  // Another TL2, next in TL1 is two frames away. Allow again.
+  EXPECT_EQ(StorageType::kAllowRetransmission,
+            rtp_sender_video_.GetStorageType(header, kSettings, kRttMs));
+  fake_clock_.AdvanceTimeMilliseconds(kFrameIntervalMs);
+
+  // Yet another TL2, next in TL1 is now only one frame away, so don't store
+  // for retransmission.
+  EXPECT_EQ(StorageType::kDontRetransmit,
+            rtp_sender_video_.GetStorageType(header, kSettings, kRttMs));
+}
+
+TEST_P(RtpSenderVideoTest, ConditionalRetransmitLimit) {
+  const int64_t kFrameIntervalMs = 200;
+  const int64_t kRttMs = (kFrameIntervalMs * 3) / 2;
+  const int32_t kSettings =
+      kRetransmitBaseLayer | kConditionallyRetransmitHigherLayers;
+
+  // Insert VP8 frames for all temporal layers, but stop before the final index.
+  RTPVideoHeader header;
+  header.codec = kVideoCodecVP8;
+
+  // Fill averaging window to prevent rounding errors.
+  constexpr int kNumRepetitions =
+      (RTPSenderVideo::kTLRateWindowSizeMs + (kFrameIntervalMs / 2)) /
+      kFrameIntervalMs;
+  constexpr int kPattern[] = {0, 2, 2, 2};
+  auto& vp8_header = header.video_type_header.emplace<RTPVideoHeaderVP8>();
+  for (size_t i = 0; i < arraysize(kPattern) * kNumRepetitions; ++i) {
+    vp8_header.temporalIdx = kPattern[i % arraysize(kPattern)];
+
+    rtp_sender_video_.GetStorageType(header, kSettings, kRttMs);
+    fake_clock_.AdvanceTimeMilliseconds(kFrameIntervalMs);
+  }
+
+  // Since we're at the start of the pattern, the next expected frame will be
+  // right now in TL0. Put it in TL1 instead. Regular rules would dictate that
+  // we don't store for retransmission because we expect a frame in a lower
+  // layer, but that last frame in TL1 was a long time ago in absolute terms,
+  // so allow retransmission anyway.
+  vp8_header.temporalIdx = 1;
+  EXPECT_EQ(StorageType::kAllowRetransmission,
+            rtp_sender_video_.GetStorageType(header, kSettings, kRttMs));
+}
+
+void RtpSenderVideoTest::PopulateGenericFrameDescriptor(int version) {
+  const RTPExtensionType ext_type =
+      (version == 0) ? RTPExtensionType::kRtpExtensionGenericFrameDescriptor00
+                     : RTPExtensionType::kRtpExtensionGenericFrameDescriptor01;
+  const int ext_id =
+      (version == 0) ? kGenericDescriptorId00 : kGenericDescriptorId01;
+
+  const int64_t kFrameId = 100000;
+  uint8_t kFrame[100];
+  EXPECT_EQ(0, rtp_sender_.RegisterRtpHeaderExtension(ext_type, ext_id));
+
+  RTPVideoHeader hdr;
+  RTPVideoHeader::GenericDescriptorInfo& generic = hdr.generic.emplace();
+  generic.frame_id = kFrameId;
+  generic.temporal_index = 3;
+  generic.spatial_index = 2;
+  generic.higher_spatial_layers.push_back(4);
+  generic.dependencies.push_back(kFrameId - 1);
+  generic.dependencies.push_back(kFrameId - 500);
+  rtp_sender_video_.SendVideo(kVideoFrameDelta, kPayload, kTimestamp, 0, kFrame,
+                              sizeof(kFrame), nullptr, &hdr,
+                              kDefaultExpectedRetransmissionTimeMs);
+
+  RtpGenericFrameDescriptor descriptor_wire;
+  EXPECT_EQ(1, transport_.packets_sent());
+  if (version == 0) {
+    ASSERT_TRUE(transport_.last_sent_packet()
+                    .GetExtension<RtpGenericFrameDescriptorExtension00>(
+                        &descriptor_wire));
+  } else {
+    ASSERT_TRUE(transport_.last_sent_packet()
+                    .GetExtension<RtpGenericFrameDescriptorExtension01>(
+                        &descriptor_wire));
+  }
+  EXPECT_EQ(static_cast<uint16_t>(generic.frame_id), descriptor_wire.FrameId());
+  EXPECT_EQ(generic.temporal_index, descriptor_wire.TemporalLayer());
+  EXPECT_THAT(descriptor_wire.FrameDependenciesDiffs(), ElementsAre(1, 500));
+  uint8_t spatial_bitmask = 0x14;
+  EXPECT_EQ(spatial_bitmask, descriptor_wire.SpatialLayersBitmask());
+}
+
+TEST_P(RtpSenderVideoTest, PopulateGenericFrameDescriptor00) {
+  PopulateGenericFrameDescriptor(0);
+}
+
+TEST_P(RtpSenderVideoTest, PopulateGenericFrameDescriptor01) {
+  PopulateGenericFrameDescriptor(1);
+}
+
+void RtpSenderVideoTest::
+    UsesMinimalVp8DescriptorWhenGenericFrameDescriptorExtensionIsUsed(
+        int version) {
+  const int64_t kFrameId = 100000;
+  const size_t kFrameSize = 100;
+  uint8_t kFrame[kFrameSize];
+
+  if (version == 0) {
+    ASSERT_TRUE(rtp_sender_.RegisterRtpHeaderExtension(
+        RtpGenericFrameDescriptorExtension00::kUri, kGenericDescriptorId00));
+  } else {
+    ASSERT_TRUE(rtp_sender_.RegisterRtpHeaderExtension(
+        RtpGenericFrameDescriptorExtension01::kUri, kGenericDescriptorId01));
+  }
+
+  RTPVideoHeader hdr;
+  hdr.codec = kVideoCodecVP8;
+  RTPVideoHeaderVP8& vp8 = hdr.video_type_header.emplace<RTPVideoHeaderVP8>();
+  vp8.pictureId = kFrameId % 0X7FFF;
+  vp8.tl0PicIdx = 13;
+  vp8.temporalIdx = 1;
+  vp8.keyIdx = 2;
+  RTPVideoHeader::GenericDescriptorInfo& generic = hdr.generic.emplace();
+  generic.frame_id = kFrameId;
+  rtp_sender_video_.RegisterPayloadType(kPayload, "vp8");
+  rtp_sender_video_.SendVideo(kVideoFrameDelta, kPayload, kTimestamp, 0, kFrame,
+                              sizeof(kFrame), nullptr, &hdr,
+                              kDefaultExpectedRetransmissionTimeMs);
+
+  ASSERT_EQ(transport_.packets_sent(), 1);
+  // Expect only minimal 1-byte vp8 descriptor was generated.
+  EXPECT_EQ(transport_.last_sent_packet().payload_size(), 1 + kFrameSize);
+}
+
+TEST_P(RtpSenderVideoTest,
+       UsesMinimalVp8DescriptorWhenGenericFrameDescriptorExtensionIsUsed00) {
+  UsesMinimalVp8DescriptorWhenGenericFrameDescriptorExtensionIsUsed(0);
+}
+
+TEST_P(RtpSenderVideoTest,
+       UsesMinimalVp8DescriptorWhenGenericFrameDescriptorExtensionIsUsed01) {
+  UsesMinimalVp8DescriptorWhenGenericFrameDescriptorExtensionIsUsed(1);
+}
+
+INSTANTIATE_TEST_SUITE_P(WithAndWithoutOverhead,
+                         RtpSenderVideoTest,
+                         ::testing::Bool());
+
+}  // namespace webrtc
diff --git a/modules/rtp_rtcp/source/rtp_utility.cc b/modules/rtp_rtcp/source/rtp_utility.cc
index 44c671f..8811bf1 100644
--- a/modules/rtp_rtcp/source/rtp_utility.cc
+++ b/modules/rtp_rtcp/source/rtp_utility.cc
@@ -24,7 +24,6 @@
 #include "modules/video_coding/codecs/interface/common_constants.h"
 #include "rtc_base/checks.h"
 #include "rtc_base/logging.h"
-#include "rtc_base/stringutils.h"
 
 namespace webrtc {
 
@@ -434,6 +433,10 @@
           header->extension.hasTransportSequenceNumber = true;
           break;
         }
+        case kRtpExtensionTransportSequenceNumber02:
+          RTC_LOG(WARNING) << "TransportSequenceNumberV2 unsupported by rtp "
+                              "header parser.";
+          break;
         case kRtpExtensionPlayoutDelay: {
           if (len != 2) {
             RTC_LOG(LS_WARNING) << "Incorrect playout delay len: " << len;
@@ -503,7 +506,8 @@
           header->extension.mid.Set(rtc::MakeArrayView(ptr, len + 1));
           break;
         }
-        case kRtpExtensionGenericFrameDescriptor:
+        case kRtpExtensionGenericFrameDescriptor00:
+        case kRtpExtensionGenericFrameDescriptor01:
           RTC_LOG(WARNING)
               << "RtpGenericFrameDescriptor unsupported by rtp header parser.";
           break;
diff --git a/modules/rtp_rtcp/source/rtp_utility.h b/modules/rtp_rtcp/source/rtp_utility.h
index 4085174..bbfb886 100644
--- a/modules/rtp_rtcp/source/rtp_utility.h
+++ b/modules/rtp_rtcp/source/rtp_utility.h
@@ -26,16 +26,6 @@
 
 namespace RtpUtility {
 
-struct Payload {
-  Payload(absl::string_view payload_name, const PayloadUnion& pu)
-      : typeSpecific(pu) {
-    size_t clipped_size = payload_name.copy(name, sizeof(name) - 1);
-    name[clipped_size] = '\0';
-  }
-  char name[RTP_PAYLOAD_NAME_SIZE];
-  PayloadUnion typeSpecific;
-};
-
 // Round up to the nearest size that is a multiple of 4.
 size_t Word32Align(size_t size);
 
diff --git a/modules/rtp_rtcp/source/rtp_video_header.h b/modules/rtp_rtcp/source/rtp_video_header.h
index 1c75f53..417c38c 100644
--- a/modules/rtp_rtcp/source/rtp_video_header.h
+++ b/modules/rtp_rtcp/source/rtp_video_header.h
@@ -15,6 +15,7 @@
 #include "absl/container/inlined_vector.h"
 #include "absl/types/optional.h"
 #include "absl/types/variant.h"
+#include "api/video/color_space.h"
 #include "api/video/video_codec_type.h"
 #include "api/video/video_content_type.h"
 #include "api/video/video_frame_marking.h"
@@ -42,6 +43,7 @@
     int temporal_index = 0;
     absl::InlinedVector<int64_t, 5> dependencies;
     absl::InlinedVector<int, 5> higher_spatial_layers;
+    bool discardable = false;
   };
 
   RTPVideoHeader();
@@ -62,7 +64,8 @@
 
   PlayoutDelay playout_delay = {-1, -1};
   VideoSendTiming video_timing;
-  FrameMarking frame_marking;
+  FrameMarking frame_marking = {false, false, false, false, false, 0xFF, 0, 0};
+  absl::optional<ColorSpace> color_space;
   RTPVideoTypeHeader video_type_header;
 };
 
diff --git a/modules/rtp_rtcp/source/time_util.cc b/modules/rtp_rtcp/source/time_util.cc
index e65329d..806f9a9 100644
--- a/modules/rtp_rtcp/source/time_util.cc
+++ b/modules/rtp_rtcp/source/time_util.cc
@@ -13,7 +13,7 @@
 #include <algorithm>
 
 #include "rtc_base/checks.h"
-#include "rtc_base/timeutils.h"
+#include "rtc_base/time_utils.h"
 
 namespace webrtc {
 namespace {
diff --git a/modules/rtp_rtcp/source/time_util_unittest.cc b/modules/rtp_rtcp/source/time_util_unittest.cc
index 0ff4f7b..f4315e5 100644
--- a/modules/rtp_rtcp/source/time_util_unittest.cc
+++ b/modules/rtp_rtcp/source/time_util_unittest.cc
@@ -9,8 +9,8 @@
  */
 #include "modules/rtp_rtcp/source/time_util.h"
 
-#include "rtc_base/fakeclock.h"
-#include "rtc_base/timeutils.h"
+#include "rtc_base/fake_clock.h"
+#include "rtc_base/time_utils.h"
 #include "system_wrappers/include/clock.h"
 #include "test/gtest.h"
 
diff --git a/modules/rtp_rtcp/source/ulpfec_header_reader_writer.cc b/modules/rtp_rtcp/source/ulpfec_header_reader_writer.cc
index 22af7e7..7086b13 100644
--- a/modules/rtp_rtcp/source/ulpfec_header_reader_writer.cc
+++ b/modules/rtp_rtcp/source/ulpfec_header_reader_writer.cc
@@ -12,10 +12,10 @@
 
 #include <string.h>
 
+#include "api/scoped_refptr.h"
 #include "modules/rtp_rtcp/source/byte_io.h"
 #include "modules/rtp_rtcp/source/forward_error_correction_internal.h"
 #include "rtc_base/checks.h"
-#include "rtc_base/scoped_ref_ptr.h"
 
 namespace webrtc {
 
diff --git a/modules/rtp_rtcp/source/ulpfec_header_reader_writer_unittest.cc b/modules/rtp_rtcp/source/ulpfec_header_reader_writer_unittest.cc
index a1d1bd5..2ad1239 100644
--- a/modules/rtp_rtcp/source/ulpfec_header_reader_writer_unittest.cc
+++ b/modules/rtp_rtcp/source/ulpfec_header_reader_writer_unittest.cc
@@ -13,13 +13,13 @@
 #include <memory>
 #include <utility>
 
+#include "api/scoped_refptr.h"
 #include "modules/rtp_rtcp/source/byte_io.h"
 #include "modules/rtp_rtcp/source/forward_error_correction.h"
 #include "modules/rtp_rtcp/source/forward_error_correction_internal.h"
 #include "modules/rtp_rtcp/source/ulpfec_header_reader_writer.h"
 #include "rtc_base/checks.h"
 #include "rtc_base/random.h"
-#include "rtc_base/scoped_ref_ptr.h"
 #include "test/gtest.h"
 
 namespace webrtc {
diff --git a/modules/rtp_rtcp/source/ulpfec_receiver_impl.cc b/modules/rtp_rtcp/source/ulpfec_receiver_impl.cc
index 7da6b88..614d4aa 100644
--- a/modules/rtp_rtcp/source/ulpfec_receiver_impl.cc
+++ b/modules/rtp_rtcp/source/ulpfec_receiver_impl.cc
@@ -14,10 +14,10 @@
 #include <memory>
 #include <utility>
 
+#include "api/scoped_refptr.h"
 #include "modules/rtp_rtcp/source/byte_io.h"
 #include "rtc_base/logging.h"
-#include "rtc_base/scoped_ref_ptr.h"
-#include "system_wrappers/include/clock.h"
+#include "rtc_base/time_utils.h"
 
 namespace webrtc {
 
@@ -141,8 +141,7 @@
   }
   ++packet_counter_.num_packets;
   if (packet_counter_.first_packet_time_ms == -1) {
-    packet_counter_.first_packet_time_ms =
-        Clock::GetRealTimeClock()->TimeInMilliseconds();
+    packet_counter_.first_packet_time_ms = rtc::TimeMillis();
   }
 
   std::unique_ptr<ForwardErrorCorrection::ReceivedPacket>
diff --git a/modules/rtp_rtcp/source/ulpfec_receiver_impl.h b/modules/rtp_rtcp/source/ulpfec_receiver_impl.h
index 0943266..2821513 100644
--- a/modules/rtp_rtcp/source/ulpfec_receiver_impl.h
+++ b/modules/rtp_rtcp/source/ulpfec_receiver_impl.h
@@ -20,7 +20,7 @@
 #include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
 #include "modules/rtp_rtcp/include/ulpfec_receiver.h"
 #include "modules/rtp_rtcp/source/forward_error_correction.h"
-#include "rtc_base/criticalsection.h"
+#include "rtc_base/critical_section.h"
 
 namespace webrtc {
 
diff --git a/modules/video_coding/codecs/h264/include/h264_globals.h b/modules/video_coding/codecs/h264/include/h264_globals.h
index e321500..321a6b7 100644
--- a/modules/video_coding/codecs/h264/include/h264_globals.h
+++ b/modules/video_coding/codecs/h264/include/h264_globals.h
@@ -15,6 +15,8 @@
 #define MODULES_VIDEO_CODING_CODECS_H264_INCLUDE_H264_GLOBALS_H_
 
 #include <string>
+#include "modules/video_coding/codecs/interface/common_constants.h"
+
 
 #include "rtc_base/checks.h"
 
diff --git a/modules/video_coding/codecs/interface/common_constants.h b/modules/video_coding/codecs/interface/common_constants.h
index 2fdcb90..a8fc629 100644
--- a/modules/video_coding/codecs/interface/common_constants.h
+++ b/modules/video_coding/codecs/interface/common_constants.h
@@ -14,6 +14,8 @@
 #ifndef MODULES_VIDEO_CODING_CODECS_INTERFACE_COMMON_CONSTANTS_H_
 #define MODULES_VIDEO_CODING_CODECS_INTERFACE_COMMON_CONSTANTS_H_
 
+#include <stdint.h>
+
 namespace webrtc {
 
 const int16_t kNoPictureId = -1;
diff --git a/modules/video_coding/codecs/vp8/include/temporal_layers_checker.h b/modules/video_coding/codecs/vp8/include/temporal_layers_checker.h
index ae14f68..3d1671a 100644
--- a/modules/video_coding/codecs/vp8/include/temporal_layers_checker.h
+++ b/modules/video_coding/codecs/vp8/include/temporal_layers_checker.h
@@ -15,6 +15,7 @@
 
 #include <memory>
 
+#include "api/video_codecs/vp8_frame_config.h"
 #include "api/video_codecs/vp8_temporal_layers.h"
 
 namespace webrtc {
@@ -27,9 +28,8 @@
   explicit TemporalLayersChecker(int num_temporal_layers);
   virtual ~TemporalLayersChecker() {}
 
-  virtual bool CheckTemporalConfig(
-      bool frame_is_keyframe,
-      const Vp8TemporalLayers::FrameConfig& frame_config);
+  virtual bool CheckTemporalConfig(bool frame_is_keyframe,
+                                   const Vp8FrameConfig& frame_config);
 
   static std::unique_ptr<TemporalLayersChecker> CreateTemporalLayersChecker(
       Vp8TemporalLayersType type,
@@ -46,7 +46,7 @@
                                  bool* need_sync,
                                  bool frame_is_keyframe,
                                  uint8_t temporal_layer,
-                                 webrtc::Vp8TemporalLayers::BufferFlags flags,
+                                 Vp8FrameConfig::BufferFlags flags,
                                  uint32_t sequence_number,
                                  uint32_t* lowest_sequence_referenced);
   BufferState last_;
diff --git a/modules/video_coding/codecs/vp9/include/vp9_globals.h b/modules/video_coding/codecs/vp9/include/vp9_globals.h
index aa532a6..895e2de 100644
--- a/modules/video_coding/codecs/vp9/include/vp9_globals.h
+++ b/modules/video_coding/codecs/vp9/include/vp9_globals.h
@@ -15,6 +15,7 @@
 #define MODULES_VIDEO_CODING_CODECS_VP9_INCLUDE_VP9_GLOBALS_H_
 
 #include <assert.h>
+#include <stdint.h>
 
 #include "modules/video_coding/codecs/interface/common_constants.h"
 
diff --git a/rtc_base/BUILD.gn b/rtc_base/BUILD.gn
index c88815f..a79e690 100644
--- a/rtc_base/BUILD.gn
+++ b/rtc_base/BUILD.gn
@@ -79,33 +79,32 @@
     ":safe_minmax",
     ":type_traits",
     "../api:array_view",
+    "../api:scoped_refptr",
     "../system_wrappers:field_trial",
     "experiments:field_trial_parser",
     "system:arch",
     "system:unused",
     "third_party/base64",
-    "//third_party/abseil-cpp/absl/memory:memory",
+    "//third_party/abseil-cpp/absl/memory",
     "//third_party/abseil-cpp/absl/types:optional",
   ]
 
   sources = [
     "bind.h",
-    "bitbuffer.cc",
-    "bitbuffer.h",
-    "bitrateallocationstrategy.cc",
-    "bitrateallocationstrategy.h",
+    "bit_buffer.cc",
+    "bit_buffer.h",
+    "bitrate_allocation_strategy.cc",
+    "bitrate_allocation_strategy.h",
     "buffer.h",
-    "bufferqueue.cc",
-    "bufferqueue.h",
-    "bytebuffer.cc",
-    "bytebuffer.h",
-    "byteorder.h",
-    "copyonwritebuffer.cc",
-    "copyonwritebuffer.h",
+    "buffer_queue.cc",
+    "buffer_queue.h",
+    "byte_buffer.cc",
+    "byte_buffer.h",
+    "byte_order.h",
+    "copy_on_write_buffer.cc",
+    "copy_on_write_buffer.h",
     "event_tracer.cc",
     "event_tracer.h",
-    "file.cc",
-    "file.h",
     "flags.cc",
     "flags.h",
     "function_view.h",
@@ -119,7 +118,7 @@
     "numerics/moving_max_counter.h",
     "numerics/sample_counter.cc",
     "numerics/sample_counter.h",
-    "onetimeevent.h",
+    "one_time_event.h",
     "platform_file.cc",
     "platform_file.h",
     "race_checker.cc",
@@ -128,24 +127,19 @@
     "random.h",
     "rate_statistics.cc",
     "rate_statistics.h",
-    "ratetracker.cc",
-    "ratetracker.h",
+    "rate_tracker.cc",
+    "rate_tracker.h",
     "swap_queue.h",
     "template_util.h",
-    "timestampaligner.cc",
-    "timestampaligner.h",
+    "timestamp_aligner.cc",
+    "timestamp_aligner.h",
     "trace_event.h",
     "zero_memory.cc",
     "zero_memory.h",
   ]
 
-  if (is_posix || is_fuchsia) {
-    sources += [ "file_posix.cc" ]
-  }
-
   if (is_win) {
     sources += [
-      "file_win.cc",
       "win/windows_version.cc",
       "win/windows_version.h",
     ]
@@ -169,7 +163,6 @@
     ":macromagic",
     ":platform_thread",
     ":platform_thread_types",
-    ":ptr_util",
     ":refcount",
     ":rtc_event",
     ":safe_conversions",
@@ -184,7 +177,7 @@
   visibility = [ "*" ]
   sources = [
     "arraysize.h",
-    "constructormagic.h",
+    "constructor_magic.h",
     "format_macros.h",
     "stringize_macros.h",
     "thread_annotations.h",
@@ -201,22 +194,12 @@
   ]
 }
 
-rtc_source_set("ptr_util") {
-  visibility = [ "*" ]
-  sources = [
-    "scoped_ref_ptr.h",
-  ]
-  deps = [
-    "../api:scoped_refptr",
-  ]
-}
-
 rtc_source_set("refcount") {
   visibility = [ "*" ]
   sources = [
-    "refcount.h",
-    "refcountedobject.h",
-    "refcounter.h",
+    "ref_count.h",
+    "ref_counted_object.h",
+    "ref_counter.h",
   ]
   deps = [
     ":atomicops",
@@ -226,8 +209,8 @@
 
 rtc_source_set("criticalsection") {
   sources = [
-    "criticalsection.cc",
-    "criticalsection.h",
+    "critical_section.cc",
+    "critical_section.h",
   ]
   deps = [
     ":atomicops",
@@ -258,6 +241,7 @@
     ":rtc_event",
     ":thread_checker",
     ":timeutils",
+    "//third_party/abseil-cpp/absl/strings",
   ]
 }
 
@@ -342,7 +326,7 @@
 
 rtc_source_set("atomicops") {
   sources = [
-    "atomicops.h",
+    "atomic_ops.h",
   ]
 }
 
@@ -417,8 +401,8 @@
 rtc_source_set("timeutils") {
   visibility = [ "*" ]
   sources = [
-    "timeutils.cc",
-    "timeutils.h",
+    "time_utils.cc",
+    "time_utils.h",
   ]
   deps = [
     ":checks",
@@ -429,14 +413,14 @@
 
 rtc_source_set("stringutils") {
   sources = [
+    "string_encode.cc",
+    "string_encode.h",
     "string_to_number.cc",
     "string_to_number.h",
-    "stringencode.cc",
-    "stringencode.h",
+    "string_utils.cc",
+    "string_utils.h",
     "strings/string_builder.cc",
     "strings/string_builder.h",
-    "stringutils.cc",
-    "stringutils.h",
   ]
   deps = [
     ":checks",
@@ -484,69 +468,36 @@
 
 rtc_source_set("rtc_task_queue") {
   visibility = [ "*" ]
-  deps = []
-  public_deps = [
-    ":rtc_task_queue_api",
-  ]
-
-  if (rtc_link_task_queue_impl) {
-    deps += [ ":rtc_task_queue_impl" ]
-  }
-}
-
-# WebRTC targets must not directly depend on rtc_task_queue_api or
-# rtc_task_queue_impl. Instead, depend on rtc_task_queue.
-# The build flag |rtc_link_task_queue_impl| decides if WebRTC targets will link
-# to the default implemenation in rtc_task_queue_impl or if an externally
-# provided implementation should be used. An external implementation should
-# depend on rtc_task_queue_api.
-rtc_source_set("rtc_task_queue_api") {
-  # The visibility list is commented out so that we won't break external
-  # implementations, but left here to manually test as well as for sake of what
-  # targets we expect to depend on rtc_task_queue_api.
-  # visibility = [
-  #   ":rtc_task_queue",
-  #   ":rtc_task_queue_impl",
-  #   ":sequenced_task_checker",
-  # ]
   sources = [
+    "task_queue.cc",
     "task_queue.h",
   ]
   deps = [
     ":macromagic",
-    ":ptr_util",
+    "../api/task_queue",
+    "../api/task_queue:global_task_queue_factory",
     "system:rtc_export",
+    "task_utils:to_queued_task",
     "//third_party/abseil-cpp/absl/memory",
   ]
+
+  # TODO(danilchap): Move this conditional dependency to global_task_queue_factory
+  # after removing task_queue_impl -> global_task_queue_factory dependency in chromium.
+  if (build_with_chromium) {
+    deps += [ "../../webrtc_overrides:task_queue_impl" ]
+  }
 }
 
-rtc_source_set("rtc_cancelable_task") {
-  sources = [
-    "cancelable_periodic_task.h",
-    "cancelable_task_handle.cc",
-    "cancelable_task_handle.h",
-  ]
-  deps = [
-    ":checks",
-    ":logging",
-    ":macromagic",
-    ":ptr_util",
-    ":refcount",
-    ":rtc_task_queue",
-    ":safe_conversions",
-    ":sequenced_task_checker",
-    ":thread_checker",
-    "//third_party/abseil-cpp/absl/memory",
-  ]
+rtc_source_set("rtc_task_queue_api") {
+  visibility = [ "*" ]
 }
 
 if (rtc_enable_libevent) {
   rtc_source_set("rtc_task_queue_libevent") {
-    visibility = [ ":rtc_task_queue_impl" ]
+    visibility = [ "../api/task_queue:default_task_queue_factory" ]
     sources = [
       "task_queue_libevent.cc",
-      "task_queue_posix.cc",
-      "task_queue_posix.h",
+      "task_queue_libevent.h",
     ]
     deps = [
       ":checks",
@@ -555,12 +506,11 @@
       ":macromagic",
       ":platform_thread",
       ":platform_thread_types",
-      ":ptr_util",
-      ":refcount",
-      ":rtc_task_queue_api",
       ":safe_conversions",
       ":timeutils",
-      "system:unused",
+      "../api/task_queue",
+      "//third_party/abseil-cpp/absl/memory",
+      "//third_party/abseil-cpp/absl/strings",
     ]
     if (rtc_build_libevent) {
       deps += [ "//base/third_party/libevent" ]
@@ -570,27 +520,27 @@
 
 if (is_mac || is_ios) {
   rtc_source_set("rtc_task_queue_gcd") {
-    visibility = [ ":rtc_task_queue_impl" ]
+    visibility = [ "../api/task_queue:default_task_queue_factory" ]
     sources = [
       "task_queue_gcd.cc",
-      "task_queue_posix.cc",
-      "task_queue_posix.h",
+      "task_queue_gcd.h",
     ]
     deps = [
       ":checks",
       ":logging",
-      ":ptr_util",
-      ":refcount",
-      ":rtc_task_queue_api",
+      "../api/task_queue",
+      "//third_party/abseil-cpp/absl/memory",
+      "//third_party/abseil-cpp/absl/strings",
     ]
   }
 }
 
 if (is_win) {
   rtc_source_set("rtc_task_queue_win") {
-    visibility = [ ":rtc_task_queue_impl" ]
+    visibility = [ "../api/task_queue:default_task_queue_factory" ]
     sources = [
       "task_queue_win.cc",
+      "task_queue_win.h",
     ]
     deps = [
       ":checks",
@@ -598,20 +548,21 @@
       ":logging",
       ":macromagic",
       ":platform_thread",
-      ":ptr_util",
-      ":refcount",
       ":rtc_event",
-      ":rtc_task_queue_api",
       ":safe_conversions",
       ":timeutils",
+      "../api/task_queue",
+      "//third_party/abseil-cpp/absl/memory",
+      "//third_party/abseil-cpp/absl/strings",
     ]
   }
 }
 
 rtc_source_set("rtc_task_queue_stdlib") {
-  visibility = [ ":rtc_task_queue_impl" ]
+  visibility = [ "../api/task_queue:default_task_queue_factory" ]
   sources = [
     "task_queue_stdlib.cc",
+    "task_queue_stdlib.h",
   ]
   deps = [
     ":checks",
@@ -619,41 +570,15 @@
     ":logging",
     ":macromagic",
     ":platform_thread",
-    ":ptr_util",
-    ":refcount",
     ":rtc_event",
-    ":rtc_task_queue_api",
     ":safe_conversions",
     ":timeutils",
+    "../api/task_queue",
+    "//third_party/abseil-cpp/absl/memory",
+    "//third_party/abseil-cpp/absl/strings",
   ]
 }
 
-rtc_source_set("rtc_task_queue_impl") {
-  visibility = [ "*" ]
-  if (rtc_enable_libevent) {
-    deps = [
-      ":rtc_task_queue_libevent",
-    ]
-  } else {
-    if (is_mac || is_ios) {
-      deps = [
-        ":rtc_task_queue_gcd",
-      ]
-    }
-    if (is_win) {
-      if (current_os == "winuwp") {
-        deps = [
-          ":rtc_task_queue_stdlib",
-        ]
-      } else {
-        deps = [
-          ":rtc_task_queue_win",
-        ]
-      }
-    }
-  }
-}
-
 rtc_source_set("sequenced_task_checker") {
   sources = [
     "sequenced_task_checker.h",
@@ -664,8 +589,8 @@
     ":checks",
     ":criticalsection",
     ":macromagic",
-    ":rtc_task_queue",
     ":thread_checker",
+    "../api/task_queue",
   ]
 }
 
@@ -675,9 +600,9 @@
     "weak_ptr.h",
   ]
   deps = [
-    ":ptr_util",
     ":refcount",
     ":sequenced_task_checker",
+    "../api:scoped_refptr",
   ]
 }
 
@@ -689,6 +614,8 @@
     "numerics/moving_average.h",
     "numerics/moving_median_filter.h",
     "numerics/percentile_filter.h",
+    "numerics/samples_stats_counter.cc",
+    "numerics/samples_stats_counter.h",
     "numerics/sequence_number_util.h",
   ]
   deps = [
@@ -722,6 +649,142 @@
   }
 }
 
+rtc_source_set("net_helpers") {
+  # TODO(bugs.webrtc.org/9987): This build target will soon contain
+  #                             the following files:
+  # sources = [
+  #   "net_helpers.cc",
+  #   "net_helpers.h",
+  # ]
+}
+
+rtc_source_set("async_resolver_interface") {
+  visibility = [ "*" ]
+  # TODO(bugs.webrtc.org/9987): This build target will soon contain
+  #                             the following files:
+  # sources = [
+  #   "async_resolver_interface.cc",
+  #   "async_resolver_interface.h",
+  # ]
+}
+
+rtc_source_set("ip_address") {
+  visibility = [ "*" ]
+  # TODO(bugs.webrtc.org/9987): This build target will soon contain
+  #                             the following files:
+  # sources = [
+  #   "ip_address.cc",
+  #   "ip_address.h",
+  # ]
+}
+
+rtc_source_set("socket_address") {
+  visibility = [ "*" ]
+  # TODO(bugs.webrtc.org/9987): This build target will soon contain
+  #                             the following files:
+  # sources = [
+  #   "socket_address.cc",
+  #   "socket_address.h",
+  # ]
+}
+
+rtc_source_set("null_socket_server") {
+  # TODO(bugs.webrtc.org/9987): This build target will soon contain
+  #                             the following files:
+  # sources = [
+  #   "null_socket_server.cc",
+  #   "null_socket_server.h",
+  # ]
+}
+
+rtc_source_set("socket_server") {
+  # TODO(bugs.webrtc.org/9987): This build target will soon contain
+  #                             the following files:
+  # sources = [
+  #   "socket_server.h",
+  # ]
+}
+
+rtc_source_set("threading") {
+  visibility = [ "*" ]
+  # TODO(bugs.webrtc.org/9987): This build target will soon contain
+  #                             the following files:
+  # sources = [
+  #   "asyncresolver.cc",
+  #   "asyncresolver.h",
+  #   "defaultsocketserver.cc",
+  #   "defaultsocketserver.h",
+  #   "message_handler.cc",
+  #   "message_handler.h",
+  #   "message_queue.cc",
+  #   "message_queue.h",
+  #   "network_monitor.cc",
+  #   "network_monitor.h",
+  #   "physical_socket_server.cc",
+  #   "physical_socket_server.h",
+  #   "signal_thread.cc",
+  #   "signal_thread.h",
+  #   "thread.cc",
+  #   "thread.h",
+  # ]
+}
+
+rtc_source_set("socket_factory") {
+  # TODO(bugs.webrtc.org/9987): This build target will soon contain
+  #                             the following files:
+  # sources = [
+  #   "socket_factory.h",
+  # ]
+}
+
+rtc_source_set("async_socket") {
+  # TODO(bugs.webrtc.org/9987): This build target will soon contain
+  #                             the following files:
+  # sources = [
+  #   "async_socket.cc",
+  #   "async_socket.h",
+  # ]
+}
+
+rtc_source_set("socket") {
+  # TODO(bugs.webrtc.org/9987): This build target will soon contain
+  #                             the following files:
+  # sources = [
+  #   "socket.cc",
+  #   "socket.h",
+  # ]
+}
+
+rtc_source_set("network_constants") {
+  # TODO(bugs.webrtc.org/9987): This build target will soon contain
+  #                             the following files:
+  # sources = [
+  #   "network_constants.h",
+  # ]
+}
+
+if (is_android) {
+  rtc_source_set("ifaddrs_android") {
+    # TODO(bugs.webrtc.org/9987): This build target will soon contain
+    #                             the following files:
+    # sources = [
+    #   "ifaddrs_android.cc",
+    #   "ifaddrs_android.h",
+    # ]
+  }
+}
+
+if (is_win) {
+  rtc_source_set("win32") {
+    # TODO(bugs.webrtc.org/9987): This build target will soon contain
+    #                             the following files:
+    # sources = [
+    #   "win32.cc",
+    #   "win32.h",
+    # ]
+  }
+}
+
 rtc_static_library("rtc_base") {
   visibility = [ "*" ]
   cflags = []
@@ -730,13 +793,13 @@
   defines = []
   deps = [
     ":checks",
-
-    # For deprecation of rtc::PacketTime, in asyncpacketsocket.h.
-    ":deprecation",
     ":stringutils",
     "..:webrtc_common",
     "../api:array_view",
+    "../api:scoped_refptr",
+    "../system_wrappers:field_trial",
     "network:sent_packet",
+    "system:file_wrapper",
     "third_party/base64",
     "third_party/sigslot",
     "//third_party/abseil-cpp/absl/memory",
@@ -751,109 +814,111 @@
   all_dependent_configs = [ ":rtc_base_all_dependent_config" ]
 
   sources = [
-    "asyncinvoker-inl.h",
-    "asyncinvoker.cc",
-    "asyncinvoker.h",
-    "asyncpacketsocket.cc",
-    "asyncpacketsocket.h",
-    "asyncresolverinterface.cc",
-    "asyncresolverinterface.h",
-    "asyncsocket.cc",
-    "asyncsocket.h",
-    "asynctcpsocket.cc",
-    "asynctcpsocket.h",
-    "asyncudpsocket.cc",
-    "asyncudpsocket.h",
+    "async_invoker.cc",
+    "async_invoker.h",
+    "async_invoker_inl.h",
+    "async_packet_socket.cc",
+    "async_packet_socket.h",
+    "async_resolver_interface.cc",
+    "async_resolver_interface.h",
+    "async_socket.cc",
+    "async_socket.h",
+    "async_tcp_socket.cc",
+    "async_tcp_socket.h",
+    "async_udp_socket.cc",
+    "async_udp_socket.h",
     "crc32.cc",
     "crc32.h",
-    "cryptstring.cc",
-    "cryptstring.h",
+    "crypt_string.cc",
+    "crypt_string.h",
     "data_rate_limiter.cc",
     "data_rate_limiter.h",
     "dscp.h",
-    "filerotatingstream.cc",
-    "filerotatingstream.h",
+    "file_rotating_stream.cc",
+    "file_rotating_stream.h",
     "gunit_prod.h",
     "helpers.cc",
     "helpers.h",
-    "httpcommon.cc",
-    "httpcommon.h",
-    "ipaddress.cc",
-    "ipaddress.h",
+    "http_common.cc",
+    "http_common.h",
+    "ip_address.cc",
+    "ip_address.h",
     "keep_ref_until_done.h",
     "key_derivation.cc",
     "key_derivation.h",
     "mdns_responder_interface.h",
-    "messagedigest.cc",
-    "messagedigest.h",
-    "messagehandler.cc",
-    "messagehandler.h",
-    "messagequeue.cc",
-    "messagequeue.h",
-    "nethelper.cc",
-    "nethelper.h",
-    "nethelpers.cc",
-    "nethelpers.h",
+    "message_digest.cc",
+    "message_digest.h",
+    "message_handler.cc",
+    "message_handler.h",
+    "message_queue.cc",
+    "message_queue.h",
+    "net_helper.cc",
+    "net_helper.h",
+    "net_helpers.cc",
+    "net_helpers.h",
     "network.cc",
     "network.h",
     "network_constants.h",
-    "networkmonitor.cc",
-    "networkmonitor.h",
-    "networkroute.h",
-    "nullsocketserver.cc",
-    "nullsocketserver.h",
+    "network_monitor.cc",
+    "network_monitor.h",
+    "network_route.h",
+    "null_socket_server.cc",
+    "null_socket_server.h",
     "openssl.h",
+    "openssl_adapter.cc",
+    "openssl_adapter.h",
+    "openssl_certificate.cc",
+    "openssl_certificate.h",
+    "openssl_digest.cc",
+    "openssl_digest.h",
+    "openssl_identity.cc",
+    "openssl_identity.h",
     "openssl_key_derivation_hkdf.cc",
     "openssl_key_derivation_hkdf.h",
-    "openssladapter.cc",
-    "openssladapter.h",
-    "opensslcertificate.cc",
-    "opensslcertificate.h",
-    "openssldigest.cc",
-    "openssldigest.h",
-    "opensslidentity.cc",
-    "opensslidentity.h",
-    "opensslsessioncache.cc",
-    "opensslsessioncache.h",
-    "opensslstreamadapter.cc",
-    "opensslstreamadapter.h",
-    "opensslutility.cc",
-    "opensslutility.h",
-    "physicalsocketserver.cc",
-    "physicalsocketserver.h",
-    "proxyinfo.cc",
-    "proxyinfo.h",
-    "rtccertificate.cc",
-    "rtccertificate.h",
-    "rtccertificategenerator.cc",
-    "rtccertificategenerator.h",
-    "signalthread.cc",
-    "signalthread.h",
-    "sigslotrepeater.h",
+    "openssl_session_cache.cc",
+    "openssl_session_cache.h",
+    "openssl_stream_adapter.cc",
+    "openssl_stream_adapter.h",
+    "openssl_utility.cc",
+    "openssl_utility.h",
+    "physical_socket_server.cc",
+    "physical_socket_server.h",
+    "proxy_info.cc",
+    "proxy_info.h",
+    "rtc_certificate.cc",
+    "rtc_certificate.h",
+    "rtc_certificate_generator.cc",
+    "rtc_certificate_generator.h",
+    "signal_thread.cc",
+    "signal_thread.h",
+    "sigslot_repeater.h",
     "socket.cc",
     "socket.h",
-    "socketadapters.cc",
-    "socketadapters.h",
-    "socketaddress.cc",
-    "socketaddress.h",
-    "socketaddresspair.cc",
-    "socketaddresspair.h",
-    "socketfactory.h",
-    "socketserver.h",
-    "ssladapter.cc",
-    "ssladapter.h",
-    "sslcertificate.cc",
-    "sslcertificate.h",
-    "sslfingerprint.cc",
-    "sslfingerprint.h",
-    "sslidentity.cc",
-    "sslidentity.h",
-    "sslstreamadapter.cc",
-    "sslstreamadapter.h",
+    "socket_adapters.cc",
+    "socket_adapters.h",
+    "socket_address.cc",
+    "socket_address.h",
+    "socket_address_pair.cc",
+    "socket_address_pair.h",
+    "socket_factory.h",
+    "socket_server.h",
+    "ssl_adapter.cc",
+    "ssl_adapter.h",
+    "ssl_certificate.cc",
+    "ssl_certificate.h",
+    "ssl_fingerprint.cc",
+    "ssl_fingerprint.h",
+    "ssl_identity.cc",
+    "ssl_identity.h",
+    "ssl_stream_adapter.cc",
+    "ssl_stream_adapter.h",
     "stream.cc",
     "stream.h",
     "thread.cc",
     "thread.h",
+    "unique_id_generator.cc",
+    "unique_id_generator.h",
   ]
 
   if (build_with_chromium) {
@@ -862,19 +927,19 @@
   } else {
     sources += [
       "callback.h",
-      "logsinks.cc",
-      "logsinks.h",
-      "numerics/mathutils.h",
-      "rollingaccumulator.h",
-      "sslroots.h",
+      "log_sinks.cc",
+      "log_sinks.h",
+      "numerics/math_utils.h",
+      "rolling_accumulator.h",
+      "ssl_roots.h",
     ]
 
     if (is_win) {
-      sources += [ "win32socketinit.h" ]
+      sources += [ "win32_socket_init.h" ]
       if (current_os != "winuwp") {
         sources += [
-          "win32socketserver.cc",
-          "win32socketserver.h",
+          "win32_socket_server.cc",
+          "win32_socket_server.h",
         ]
       }
     }
@@ -888,8 +953,8 @@
 
   if (is_android) {
     sources += [
-      "ifaddrs-android.cc",
-      "ifaddrs-android.h",
+      "ifaddrs_android.cc",
+      "ifaddrs_android.h",
     ]
 
     libs += [
@@ -899,7 +964,7 @@
   }
 
   if (is_ios || is_mac) {
-    sources += [ "macifaddrs_converter.cc" ]
+    sources += [ "mac_ifaddrs_converter.cc" ]
     deps += [ "system:cocoa_threading" ]
   }
 
@@ -923,8 +988,8 @@
 
   if (is_mac) {
     sources += [
-      "macutils.cc",
-      "macutils.h",
+      "mac_utils.cc",
+      "mac_utils.h",
     ]
   }
 
@@ -932,8 +997,8 @@
     sources += [
       "win32.cc",
       "win32.h",
-      "win32window.cc",
-      "win32window.h",
+      "win32_window.cc",
+      "win32_window.h",
     ]
 
     libs += [
@@ -978,14 +1043,15 @@
     ":rtc_base_tests_utils",
     ":stringutils",
     "../test:test_support",
+    "//third_party/abseil-cpp/absl/strings",
   ]
 }
 
 rtc_source_set("testclient") {
   testonly = true
   sources = [
-    "testclient.cc",
-    "testclient.h",
+    "test_client.cc",
+    "test_client.h",
   ]
   deps = [
     ":criticalsection",
@@ -994,7 +1060,7 @@
     ":rtc_base",
     ":rtc_base_tests_utils",
     ":timeutils",
-    "//third_party/abseil-cpp/absl/memory:memory",
+    "//third_party/abseil-cpp/absl/memory",
   ]
 }
 
@@ -1003,38 +1069,40 @@
   sources = [
     "cpu_time.cc",
     "cpu_time.h",
+    "fake_clock.cc",
+    "fake_clock.h",
     "fake_mdns_responder.h",
-    "fakeclock.cc",
-    "fakeclock.h",
-    "fakenetwork.h",
-    "fakesslidentity.cc",
-    "fakesslidentity.h",
-    "firewallsocketserver.cc",
-    "firewallsocketserver.h",
+    "fake_network.h",
+    "fake_ssl_identity.cc",
+    "fake_ssl_identity.h",
+    "firewall_socket_server.cc",
+    "firewall_socket_server.h",
     "memory_stream.cc",
     "memory_stream.h",
     "memory_usage.cc",
     "memory_usage.h",
-    "natserver.cc",
-    "natserver.h",
-    "natsocketfactory.cc",
-    "natsocketfactory.h",
-    "nattypes.cc",
-    "nattypes.h",
-    "proxyserver.cc",
-    "proxyserver.h",
-    "sigslottester.h",
+    "nat_server.cc",
+    "nat_server.h",
+    "nat_socket_factory.cc",
+    "nat_socket_factory.h",
+    "nat_types.cc",
+    "nat_types.h",
+    "proxy_server.cc",
+    "proxy_server.h",
+    "server_socket_adapters.cc",
+    "server_socket_adapters.h",
+    "sigslot_tester.h",
     "sigslottester.h.pump",
-    "socketstream.cc",
-    "socketstream.h",
-    "testbase64.h",
-    "testcertificateverifier.h",
-    "testechoserver.cc",
-    "testechoserver.h",
-    "testutils.cc",
-    "testutils.h",
-    "virtualsocketserver.cc",
-    "virtualsocketserver.h",
+    "socket_stream.cc",
+    "socket_stream.h",
+    "test_base64.h",
+    "test_certificate_verifier.h",
+    "test_echo_server.cc",
+    "test_echo_server.h",
+    "test_utils.cc",
+    "test_utils.h",
+    "virtual_socket_server.cc",
+    "virtual_socket_server.h",
   ]
   deps = [
     ":checks",
@@ -1057,6 +1125,7 @@
     ":checks",
     ":rtc_base_approved",
     ":rtc_task_queue",
+    "task_utils:to_queued_task",
   ]
 }
 
@@ -1070,6 +1139,7 @@
       ":gunit_helpers",
       ":rtc_base",
       ":rtc_base_tests_utils",
+      "../test:test_support",
       "third_party/sigslot",
     ]
   }
@@ -1100,12 +1170,12 @@
 
     sources = [
       "cpu_time_unittest.cc",
-      "filerotatingstream_unittest.cc",
-      "nullsocketserver_unittest.cc",
-      "physicalsocketserver_unittest.cc",
+      "file_rotating_stream_unittest.cc",
+      "null_socket_server_unittest.cc",
+      "physical_socket_server_unittest.cc",
+      "socket_address_unittest.cc",
       "socket_unittest.cc",
       "socket_unittest.h",
-      "socketaddress_unittest.cc",
     ]
     deps = [
       ":checks",
@@ -1117,34 +1187,31 @@
       "../system_wrappers:system_wrappers",
       "../test:fileutils",
       "../test:test_support",
+      "third_party/sigslot:sigslot",
       "//testing/gtest",
       "//third_party/abseil-cpp/absl/memory",
     ]
     if (is_win) {
-      sources += [ "win32socketserver_unittest.cc" ]
+      sources += [ "win32_socket_server_unittest.cc" ]
     }
   }
 
   rtc_source_set("rtc_base_approved_unittests") {
     testonly = true
-    if (is_msan) {
-      cflags = [ "-fsanitize=memory" ]
-    }
     sources = [
-      "atomicops_unittest.cc",
+      "atomic_ops_unittest.cc",
       "base64_unittest.cc",
       "bind_unittest.cc",
-      "bitbuffer_unittest.cc",
-      "bitrateallocationstrategy_unittest.cc",
+      "bit_buffer_unittest.cc",
+      "bitrate_allocation_strategy_unittest.cc",
+      "buffer_queue_unittest.cc",
       "buffer_unittest.cc",
-      "bufferqueue_unittest.cc",
-      "bytebuffer_unittest.cc",
-      "byteorder_unittest.cc",
-      "copyonwritebuffer_unittest.cc",
-      "criticalsection_unittest.cc",
+      "byte_buffer_unittest.cc",
+      "byte_order_unittest.cc",
+      "copy_on_write_buffer_unittest.cc",
+      "critical_section_unittest.cc",
       "event_tracer_unittest.cc",
       "event_unittest.cc",
-      "file_unittest.cc",
       "function_view_unittest.cc",
       "logging_unittest.cc",
       "numerics/histogram_percentile_counter_unittest.cc",
@@ -1153,26 +1220,26 @@
       "numerics/safe_compare_unittest.cc",
       "numerics/safe_minmax_unittest.cc",
       "numerics/sample_counter_unittest.cc",
-      "onetimeevent_unittest.cc",
+      "one_time_event_unittest.cc",
       "platform_file_unittest.cc",
       "platform_thread_unittest.cc",
       "random_unittest.cc",
       "rate_limiter_unittest.cc",
       "rate_statistics_unittest.cc",
-      "ratetracker_unittest.cc",
-      "refcountedobject_unittest.cc",
+      "rate_tracker_unittest.cc",
+      "ref_counted_object_unittest.cc",
       "sanitizer_unittest.cc",
+      "string_encode_unittest.cc",
       "string_to_number_unittest.cc",
-      "stringencode_unittest.cc",
+      "string_utils_unittest.cc",
       "stringize_macros_unittest.cc",
       "strings/string_builder_unittest.cc",
-      "stringutils_unittest.cc",
       "swap_queue_unittest.cc",
       "thread_annotations_unittest.cc",
       "thread_checker_unittest.cc",
-      "timestampaligner_unittest.cc",
-      "timeutils_unittest.cc",
-      "virtualsocket_unittest.cc",
+      "time_utils_unittest.cc",
+      "timestamp_aligner_unittest.cc",
+      "virtual_socket_unittest.cc",
       "zero_memory_unittest.cc",
     ]
     if (is_win) {
@@ -1193,11 +1260,14 @@
       ":stringutils",
       ":testclient",
       "../api:array_view",
+      "../api:scoped_refptr",
+      "../api/units:time_delta",
       "../system_wrappers:system_wrappers",
       "../test:fileutils",
       "../test:test_support",
       "memory:unittests",
       "third_party/base64",
+      "third_party/sigslot:sigslot",
       "//third_party/abseil-cpp/absl/memory",
     ]
   }
@@ -1207,7 +1277,6 @@
     testonly = true
 
     sources = [
-      "cancelable_periodic_task_unittest.cc",
       "task_queue_unittest.cc",
     ]
     deps = [
@@ -1215,10 +1284,9 @@
       ":rtc_base_approved",
       ":rtc_base_tests_main",
       ":rtc_base_tests_utils",
-      ":rtc_cancelable_task",
       ":rtc_task_queue",
-      ":rtc_task_queue_for_test",
       "../test:test_support",
+      "//third_party/abseil-cpp/absl/memory",
     ]
   }
 
@@ -1253,6 +1321,7 @@
       ":rtc_task_queue",
       ":weak_ptr",
       "../test:test_support",
+      "//third_party/abseil-cpp/absl/memory",
     ]
   }
 
@@ -1264,6 +1333,7 @@
       "numerics/moving_average_unittest.cc",
       "numerics/moving_median_filter_unittest.cc",
       "numerics/percentile_filter_unittest.cc",
+      "numerics/samples_stats_counter_unittest.cc",
       "numerics/sequence_number_util_unittest.cc",
     ]
     deps = [
@@ -1298,37 +1368,38 @@
       "crc32_unittest.cc",
       "data_rate_limiter_unittest.cc",
       "helpers_unittest.cc",
-      "ipaddress_unittest.cc",
+      "ip_address_unittest.cc",
       "memory_usage_unittest.cc",
-      "messagedigest_unittest.cc",
-      "messagequeue_unittest.cc",
+      "message_digest_unittest.cc",
+      "message_queue_unittest.cc",
       "nat_unittest.cc",
       "network_unittest.cc",
       "proxy_unittest.cc",
-      "rollingaccumulator_unittest.cc",
-      "rtccertificate_unittest.cc",
-      "rtccertificategenerator_unittest.cc",
-      "signalthread_unittest.cc",
-      "sigslottester_unittest.cc",
+      "rolling_accumulator_unittest.cc",
+      "rtc_certificate_generator_unittest.cc",
+      "rtc_certificate_unittest.cc",
+      "signal_thread_unittest.cc",
+      "sigslot_tester_unittest.cc",
       "stream_unittest.cc",
-      "testclient_unittest.cc",
+      "test_client_unittest.cc",
       "thread_unittest.cc",
+      "unique_id_generator_unittest.cc",
     ]
     if (is_win) {
       sources += [
         "win32_unittest.cc",
-        "win32window_unittest.cc",
+        "win32_window_unittest.cc",
       ]
     }
     if (is_posix || is_fuchsia) {
       sources += [
+        "openssl_adapter_unittest.cc",
         "openssl_key_derivation_hkdf_unittest.cc",
-        "openssladapter_unittest.cc",
-        "opensslsessioncache_unittest.cc",
-        "opensslutility_unittest.cc",
-        "ssladapter_unittest.cc",
-        "sslidentity_unittest.cc",
-        "sslstreamadapter_unittest.cc",
+        "openssl_session_cache_unittest.cc",
+        "openssl_utility_unittest.cc",
+        "ssl_adapter_unittest.cc",
+        "ssl_identity_unittest.cc",
+        "ssl_stream_adapter_unittest.cc",
       ]
     }
     deps = [
@@ -1339,6 +1410,7 @@
       ":stringutils",
       ":testclient",
       "../api:array_view",
+      "../test:field_trial",
       "../test:fileutils",
       "../test:test_support",
       "third_party/sigslot",
@@ -1368,5 +1440,8 @@
       "java/src/org/webrtc/Size.java",
       "java/src/org/webrtc/ThreadUtils.java",
     ]
+    deps = [
+      "//third_party/android_deps:android_support_annotations_java",
+    ]
   }
 }
diff --git a/rtc_base/asyncinvoker.cc b/rtc_base/async_invoker.cc
similarity index 99%
rename from rtc_base/asyncinvoker.cc
rename to rtc_base/async_invoker.cc
index f0dd188..8584bda 100644
--- a/rtc_base/asyncinvoker.cc
+++ b/rtc_base/async_invoker.cc
@@ -8,7 +8,7 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#include "rtc_base/asyncinvoker.h"
+#include "rtc_base/async_invoker.h"
 
 #include "rtc_base/checks.h"
 #include "rtc_base/logging.h"
diff --git a/rtc_base/asyncinvoker.h b/rtc_base/async_invoker.h
similarity index 97%
rename from rtc_base/asyncinvoker.h
rename to rtc_base/async_invoker.h
index 474ec7c..f15955d 100644
--- a/rtc_base/asyncinvoker.h
+++ b/rtc_base/async_invoker.h
@@ -8,19 +8,19 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#ifndef RTC_BASE_ASYNCINVOKER_H_
-#define RTC_BASE_ASYNCINVOKER_H_
+#ifndef RTC_BASE_ASYNC_INVOKER_H_
+#define RTC_BASE_ASYNC_INVOKER_H_
 
 #include <atomic>
 #include <memory>
 #include <utility>
 
-#include "rtc_base/asyncinvoker-inl.h"
+#include "api/scoped_refptr.h"
+#include "rtc_base/async_invoker_inl.h"
 #include "rtc_base/bind.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 #include "rtc_base/event.h"
-#include "rtc_base/refcountedobject.h"
-#include "rtc_base/scoped_ref_ptr.h"
+#include "rtc_base/ref_counted_object.h"
 #include "rtc_base/third_party/sigslot/sigslot.h"
 #include "rtc_base/thread.h"
 
@@ -262,4 +262,4 @@
 
 }  // namespace rtc
 
-#endif  // RTC_BASE_ASYNCINVOKER_H_
+#endif  // RTC_BASE_ASYNC_INVOKER_H_
diff --git a/rtc_base/asyncinvoker-inl.h b/rtc_base/async_invoker_inl.h
similarity index 86%
rename from rtc_base/asyncinvoker-inl.h
rename to rtc_base/async_invoker_inl.h
index 0dadc0f..bd9b0d1 100644
--- a/rtc_base/asyncinvoker-inl.h
+++ b/rtc_base/async_invoker_inl.h
@@ -8,15 +8,15 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#ifndef RTC_BASE_ASYNCINVOKER_INL_H_
-#define RTC_BASE_ASYNCINVOKER_INL_H_
+#ifndef RTC_BASE_ASYNC_INVOKER_INL_H_
+#define RTC_BASE_ASYNC_INVOKER_INL_H_
 
+#include "api/scoped_refptr.h"
 #include "rtc_base/bind.h"
-#include "rtc_base/criticalsection.h"
+#include "rtc_base/critical_section.h"
 #include "rtc_base/event.h"
-#include "rtc_base/messagehandler.h"
-#include "rtc_base/refcountedobject.h"
-#include "rtc_base/scoped_ref_ptr.h"
+#include "rtc_base/message_handler.h"
+#include "rtc_base/ref_counted_object.h"
 #include "rtc_base/third_party/sigslot/sigslot.h"
 #include "rtc_base/thread.h"
 #include "rtc_base/thread_annotations.h"
@@ -58,4 +58,4 @@
 
 }  // namespace rtc
 
-#endif  // RTC_BASE_ASYNCINVOKER_INL_H_
+#endif  // RTC_BASE_ASYNC_INVOKER_INL_H_
diff --git a/rtc_base/asyncpacketsocket.cc b/rtc_base/async_packet_socket.cc
similarity index 94%
rename from rtc_base/asyncpacketsocket.cc
rename to rtc_base/async_packet_socket.cc
index 7e0cc8f..a708fae 100644
--- a/rtc_base/asyncpacketsocket.cc
+++ b/rtc_base/async_packet_socket.cc
@@ -8,8 +8,8 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#include "rtc_base/asyncpacketsocket.h"
-#include "rtc_base/nethelper.h"
+#include "rtc_base/async_packet_socket.h"
+#include "rtc_base/net_helper.h"
 
 namespace rtc {
 
@@ -42,4 +42,4 @@
   }
 }
 
-};  // namespace rtc
+}  // namespace rtc
diff --git a/rtc_base/asyncpacketsocket.h b/rtc_base/async_packet_socket.h
similarity index 93%
rename from rtc_base/asyncpacketsocket.h
rename to rtc_base/async_packet_socket.h
index 44d6c67..3afff3b 100644
--- a/rtc_base/asyncpacketsocket.h
+++ b/rtc_base/async_packet_socket.h
@@ -8,15 +8,15 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#ifndef RTC_BASE_ASYNCPACKETSOCKET_H_
-#define RTC_BASE_ASYNCPACKETSOCKET_H_
+#ifndef RTC_BASE_ASYNC_PACKET_SOCKET_H_
+#define RTC_BASE_ASYNC_PACKET_SOCKET_H_
 
-#include "rtc_base/constructormagic.h"
-#include "rtc_base/deprecation.h"
+#include "rtc_base/constructor_magic.h"
 #include "rtc_base/dscp.h"
+#include "rtc_base/network/sent_packet.h"
 #include "rtc_base/socket.h"
 #include "rtc_base/third_party/sigslot/sigslot.h"
-#include "rtc_base/timeutils.h"
+#include "rtc_base/time_utils.h"
 
 namespace rtc {
 
@@ -51,10 +51,6 @@
   PacketInfo info_signaled_after_sent;
 };
 
-// TODO(bugs.webrtc.org/9584): Compatibility alias, delete as soon as downstream
-// code is updated.
-typedef int64_t PacketTime;
-
 // Provides the ability to receive packets asynchronously. Sends are not
 // buffered since it is acceptable to drop packets under high load.
 class AsyncPacketSocket : public sigslot::has_slots<> {
@@ -144,4 +140,4 @@
 
 }  // namespace rtc
 
-#endif  // RTC_BASE_ASYNCPACKETSOCKET_H_
+#endif  // RTC_BASE_ASYNC_PACKET_SOCKET_H_
diff --git a/rtc_base/asyncresolverinterface.cc b/rtc_base/async_resolver_interface.cc
similarity index 88%
rename from rtc_base/asyncresolverinterface.cc
rename to rtc_base/async_resolver_interface.cc
index b2880f2..ff8c87e 100644
--- a/rtc_base/asyncresolverinterface.cc
+++ b/rtc_base/async_resolver_interface.cc
@@ -8,7 +8,7 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#include "rtc_base/asyncresolverinterface.h"
+#include "rtc_base/async_resolver_interface.h"
 
 namespace rtc {
 
@@ -16,4 +16,4 @@
 
 AsyncResolverInterface::~AsyncResolverInterface() = default;
 
-};  // namespace rtc
+}  // namespace rtc
diff --git a/rtc_base/asyncresolverinterface.h b/rtc_base/async_resolver_interface.h
similarity index 92%
rename from rtc_base/asyncresolverinterface.h
rename to rtc_base/async_resolver_interface.h
index f3df884..0f5e989 100644
--- a/rtc_base/asyncresolverinterface.h
+++ b/rtc_base/async_resolver_interface.h
@@ -8,10 +8,10 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#ifndef RTC_BASE_ASYNCRESOLVERINTERFACE_H_
-#define RTC_BASE_ASYNCRESOLVERINTERFACE_H_
+#ifndef RTC_BASE_ASYNC_RESOLVER_INTERFACE_H_
+#define RTC_BASE_ASYNC_RESOLVER_INTERFACE_H_
 
-#include "rtc_base/socketaddress.h"
+#include "rtc_base/socket_address.h"
 #include "rtc_base/third_party/sigslot/sigslot.h"
 
 namespace rtc {
diff --git a/rtc_base/asyncsocket.cc b/rtc_base/async_socket.cc
similarity index 98%
rename from rtc_base/asyncsocket.cc
rename to rtc_base/async_socket.cc
index acd5415..ab3f99e 100644
--- a/rtc_base/asyncsocket.cc
+++ b/rtc_base/async_socket.cc
@@ -8,7 +8,7 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#include "rtc_base/asyncsocket.h"
+#include "rtc_base/async_socket.h"
 #include "rtc_base/checks.h"
 
 namespace rtc {
diff --git a/rtc_base/asyncsocket.h b/rtc_base/async_socket.h
similarity index 94%
rename from rtc_base/asyncsocket.h
rename to rtc_base/async_socket.h
index 0abdc27..7b2f0e0 100644
--- a/rtc_base/asyncsocket.h
+++ b/rtc_base/async_socket.h
@@ -8,10 +8,14 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#ifndef RTC_BASE_ASYNCSOCKET_H_
-#define RTC_BASE_ASYNCSOCKET_H_
+#ifndef RTC_BASE_ASYNC_SOCKET_H_
+#define RTC_BASE_ASYNC_SOCKET_H_
+
+#include <stddef.h>
+#include <stdint.h>
 
 #include "rtc_base/socket.h"
+#include "rtc_base/socket_address.h"
 #include "rtc_base/third_party/sigslot/sigslot.h"
 
 namespace rtc {
@@ -79,4 +83,4 @@
 
 }  // namespace rtc
 
-#endif  // RTC_BASE_ASYNCSOCKET_H_
+#endif  // RTC_BASE_ASYNC_SOCKET_H_
diff --git a/rtc_base/asynctcpsocket.cc b/rtc_base/async_tcp_socket.cc
similarity index 97%
rename from rtc_base/asynctcpsocket.cc
rename to rtc_base/async_tcp_socket.cc
index 666b335..148e459 100644
--- a/rtc_base/asynctcpsocket.cc
+++ b/rtc_base/async_tcp_socket.cc
@@ -8,17 +8,19 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#include "rtc_base/asynctcpsocket.h"
+#include "rtc_base/async_tcp_socket.h"
 
+#include <stdint.h>
 #include <string.h>
-
 #include <algorithm>
 #include <memory>
 
-#include "rtc_base/byteorder.h"
+#include "rtc_base/byte_order.h"
 #include "rtc_base/checks.h"
 #include "rtc_base/logging.h"
-#include "rtc_base/timeutils.h"  // for TimeMillis
+#include "rtc_base/network/sent_packet.h"
+#include "rtc_base/third_party/sigslot/sigslot.h"
+#include "rtc_base/time_utils.h"  // for TimeMillis
 
 #if defined(WEBRTC_POSIX)
 #include <errno.h>
diff --git a/rtc_base/asynctcpsocket.h b/rtc_base/async_tcp_socket.h
similarity index 92%
rename from rtc_base/asynctcpsocket.h
rename to rtc_base/async_tcp_socket.h
index 9567dd9..ae12a94 100644
--- a/rtc_base/asynctcpsocket.h
+++ b/rtc_base/async_tcp_socket.h
@@ -8,18 +8,18 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#ifndef RTC_BASE_ASYNCTCPSOCKET_H_
-#define RTC_BASE_ASYNCTCPSOCKET_H_
+#ifndef RTC_BASE_ASYNC_TCP_SOCKET_H_
+#define RTC_BASE_ASYNC_TCP_SOCKET_H_
 
 #include <stddef.h>
 #include <memory>
 
-#include "rtc_base/asyncpacketsocket.h"
-#include "rtc_base/asyncsocket.h"
+#include "rtc_base/async_packet_socket.h"
+#include "rtc_base/async_socket.h"
 #include "rtc_base/buffer.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 #include "rtc_base/socket.h"
-#include "rtc_base/socketaddress.h"
+#include "rtc_base/socket_address.h"
 
 namespace rtc {
 
@@ -109,4 +109,4 @@
 
 }  // namespace rtc
 
-#endif  // RTC_BASE_ASYNCTCPSOCKET_H_
+#endif  // RTC_BASE_ASYNC_TCP_SOCKET_H_
diff --git a/rtc_base/asynctcpsocket_unittest.cc b/rtc_base/async_tcp_socket_unittest.cc
similarity index 93%
rename from rtc_base/asynctcpsocket_unittest.cc
rename to rtc_base/async_tcp_socket_unittest.cc
index e8fd96c..69b5392 100644
--- a/rtc_base/asynctcpsocket_unittest.cc
+++ b/rtc_base/async_tcp_socket_unittest.cc
@@ -11,9 +11,9 @@
 #include <memory>
 #include <string>
 
-#include "rtc_base/asynctcpsocket.h"
+#include "rtc_base/async_tcp_socket.h"
 #include "rtc_base/gunit.h"
-#include "rtc_base/virtualsocketserver.h"
+#include "rtc_base/virtual_socket_server.h"
 
 namespace rtc {
 
diff --git a/rtc_base/asyncudpsocket.cc b/rtc_base/async_udp_socket.cc
similarity index 95%
rename from rtc_base/asyncudpsocket.cc
rename to rtc_base/async_udp_socket.cc
index 2f9011c..8521910 100644
--- a/rtc_base/asyncudpsocket.cc
+++ b/rtc_base/async_udp_socket.cc
@@ -8,9 +8,16 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#include "rtc_base/asyncudpsocket.h"
+#include "rtc_base/async_udp_socket.h"
+
+#include <stdint.h>
+#include <string>
+
 #include "rtc_base/checks.h"
 #include "rtc_base/logging.h"
+#include "rtc_base/network/sent_packet.h"
+#include "rtc_base/third_party/sigslot/sigslot.h"
+#include "rtc_base/time_utils.h"
 
 namespace rtc {
 
diff --git a/rtc_base/asyncudpsocket.h b/rtc_base/async_udp_socket.h
similarity index 89%
rename from rtc_base/asyncudpsocket.h
rename to rtc_base/async_udp_socket.h
index 030946d..237c88d 100644
--- a/rtc_base/asyncudpsocket.h
+++ b/rtc_base/async_udp_socket.h
@@ -8,17 +8,17 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#ifndef RTC_BASE_ASYNCUDPSOCKET_H_
-#define RTC_BASE_ASYNCUDPSOCKET_H_
+#ifndef RTC_BASE_ASYNC_UDP_SOCKET_H_
+#define RTC_BASE_ASYNC_UDP_SOCKET_H_
 
 #include <stddef.h>
 #include <memory>
 
-#include "rtc_base/asyncpacketsocket.h"
-#include "rtc_base/asyncsocket.h"
+#include "rtc_base/async_packet_socket.h"
+#include "rtc_base/async_socket.h"
 #include "rtc_base/socket.h"
-#include "rtc_base/socketaddress.h"
-#include "rtc_base/socketfactory.h"
+#include "rtc_base/socket_address.h"
+#include "rtc_base/socket_factory.h"
 
 namespace rtc {
 
@@ -68,4 +68,4 @@
 
 }  // namespace rtc
 
-#endif  // RTC_BASE_ASYNCUDPSOCKET_H_
+#endif  // RTC_BASE_ASYNC_UDP_SOCKET_H_
diff --git a/rtc_base/asyncudpsocket_unittest.cc b/rtc_base/async_udp_socket_unittest.cc
similarity index 91%
rename from rtc_base/asyncudpsocket_unittest.cc
rename to rtc_base/async_udp_socket_unittest.cc
index 33b3d13..0484c3a 100644
--- a/rtc_base/asyncudpsocket_unittest.cc
+++ b/rtc_base/async_udp_socket_unittest.cc
@@ -11,10 +11,10 @@
 #include <memory>
 #include <string>
 
-#include "rtc_base/asyncudpsocket.h"
+#include "rtc_base/async_udp_socket.h"
 #include "rtc_base/gunit.h"
-#include "rtc_base/physicalsocketserver.h"
-#include "rtc_base/virtualsocketserver.h"
+#include "rtc_base/physical_socket_server.h"
+#include "rtc_base/virtual_socket_server.h"
 
 namespace rtc {
 
diff --git a/rtc_base/atomicops.h b/rtc_base/atomic_ops.h
similarity index 96%
rename from rtc_base/atomicops.h
rename to rtc_base/atomic_ops.h
index 16fa603..18a24a8 100644
--- a/rtc_base/atomicops.h
+++ b/rtc_base/atomic_ops.h
@@ -8,8 +8,8 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#ifndef RTC_BASE_ATOMICOPS_H_
-#define RTC_BASE_ATOMICOPS_H_
+#ifndef RTC_BASE_ATOMIC_OPS_H_
+#define RTC_BASE_ATOMIC_OPS_H_
 
 #if defined(WEBRTC_WIN)
 // clang-format off
@@ -76,4 +76,4 @@
 
 }  // namespace rtc
 
-#endif  // RTC_BASE_ATOMICOPS_H_
+#endif  // RTC_BASE_ATOMIC_OPS_H_
diff --git a/rtc_base/atomicops_unittest.cc b/rtc_base/atomic_ops_unittest.cc
similarity index 100%
rename from rtc_base/atomicops_unittest.cc
rename to rtc_base/atomic_ops_unittest.cc
diff --git a/rtc_base/base64_unittest.cc b/rtc_base/base64_unittest.cc
index bdf8559..dcc4d1b 100644
--- a/rtc_base/base64_unittest.cc
+++ b/rtc_base/base64_unittest.cc
@@ -9,13 +9,17 @@
  */
 
 #include "rtc_base/third_party/base64/base64.h"
-#include "rtc_base/gunit.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <algorithm>
+
 #include "rtc_base/logging.h"
+#include "rtc_base/test_base64.h"
+#include "test/gtest.h"
 
-#include "rtc_base/testbase64.h"
-
-using namespace std;
-using namespace rtc;
+namespace rtc {
+namespace {
 
 static struct {
   size_t plain_length;
@@ -333,7 +337,7 @@
                     size_t szdest) {
   std::string escaped;
   Base64::EncodeFromArray((const char*)src, szsrc, &escaped);
-  memcpy(dest, escaped.data(), min(escaped.size(), szdest));
+  memcpy(dest, escaped.data(), std::min(escaped.size(), szdest));
   return escaped.size();
 }
 
@@ -344,7 +348,7 @@
   std::string unescaped;
   EXPECT_TRUE(
       Base64::DecodeFromArray(src, szsrc, Base64::DO_LAX, &unescaped, nullptr));
-  memcpy(dest, unescaped.data(), min(unescaped.size(), szdest));
+  memcpy(dest, unescaped.data(), std::min(unescaped.size(), szdest));
   return unescaped.size();
 }
 
@@ -1444,3 +1448,6 @@
   EXPECT_FALSE(Base64::GetNextBase64Char('&', &next_char));
   EXPECT_FALSE(Base64::GetNextBase64Char('Z', nullptr));
 }
+
+}  // namespace
+}  // namespace rtc
diff --git a/rtc_base/bind.h b/rtc_base/bind.h
index 9f225f1..16ac556 100644
--- a/rtc_base/bind.h
+++ b/rtc_base/bind.h
@@ -64,7 +64,7 @@
 #include <tuple>
 #include <type_traits>
 
-#include "rtc_base/scoped_ref_ptr.h"
+#include "api/scoped_refptr.h"
 #include "rtc_base/template_util.h"
 
 #define NONAME
diff --git a/rtc_base/bind_unittest.cc b/rtc_base/bind_unittest.cc
index ed0913f..a62e547 100644
--- a/rtc_base/bind_unittest.cc
+++ b/rtc_base/bind_unittest.cc
@@ -8,13 +8,12 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#include <type_traits>
+#include <string>
 
 #include "rtc_base/bind.h"
-#include "rtc_base/gunit.h"
-
-#include "rtc_base/refcount.h"
-#include "rtc_base/refcountedobject.h"
+#include "rtc_base/ref_count.h"
+#include "rtc_base/ref_counted_object.h"
+#include "test/gtest.h"
 
 namespace rtc {
 
diff --git a/rtc_base/bitbuffer.cc b/rtc_base/bit_buffer.cc
similarity index 99%
rename from rtc_base/bitbuffer.cc
rename to rtc_base/bit_buffer.cc
index be72d55..59b71fc 100644
--- a/rtc_base/bitbuffer.cc
+++ b/rtc_base/bit_buffer.cc
@@ -8,7 +8,7 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#include "rtc_base/bitbuffer.h"
+#include "rtc_base/bit_buffer.h"
 
 #include <algorithm>
 #include <limits>
diff --git a/rtc_base/bitbuffer.h b/rtc_base/bit_buffer.h
similarity index 97%
rename from rtc_base/bitbuffer.h
rename to rtc_base/bit_buffer.h
index ba96a12..b03677c 100644
--- a/rtc_base/bitbuffer.h
+++ b/rtc_base/bit_buffer.h
@@ -8,13 +8,13 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#ifndef RTC_BASE_BITBUFFER_H_
-#define RTC_BASE_BITBUFFER_H_
+#ifndef RTC_BASE_BIT_BUFFER_H_
+#define RTC_BASE_BIT_BUFFER_H_
 
 #include <stddef.h>  // For size_t.
 #include <stdint.h>  // For integer types.
 
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace rtc {
 
@@ -123,4 +123,4 @@
 
 }  // namespace rtc
 
-#endif  // RTC_BASE_BITBUFFER_H_
+#endif  // RTC_BASE_BIT_BUFFER_H_
diff --git a/rtc_base/bitbuffer_unittest.cc b/rtc_base/bit_buffer_unittest.cc
similarity index 98%
rename from rtc_base/bitbuffer_unittest.cc
rename to rtc_base/bit_buffer_unittest.cc
index a3f140f..20c0049 100644
--- a/rtc_base/bitbuffer_unittest.cc
+++ b/rtc_base/bit_buffer_unittest.cc
@@ -8,10 +8,13 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#include "rtc_base/bitbuffer.h"
+#include "rtc_base/bit_buffer.h"
+
+#include <limits>
+
 #include "rtc_base/arraysize.h"
-#include "rtc_base/bytebuffer.h"
-#include "rtc_base/gunit.h"
+#include "rtc_base/byte_buffer.h"
+#include "test/gtest.h"
 
 namespace rtc {
 
diff --git a/rtc_base/bitrateallocationstrategy.cc b/rtc_base/bitrate_allocation_strategy.cc
similarity index 98%
rename from rtc_base/bitrateallocationstrategy.cc
rename to rtc_base/bitrate_allocation_strategy.cc
index 46e6674..34a61ef 100644
--- a/rtc_base/bitrateallocationstrategy.cc
+++ b/rtc_base/bitrate_allocation_strategy.cc
@@ -8,7 +8,7 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#include "rtc_base/bitrateallocationstrategy.h"
+#include "rtc_base/bitrate_allocation_strategy.h"
 
 #include <algorithm>
 #include <cstddef>
@@ -45,6 +45,7 @@
 std::vector<uint32_t> BitrateAllocationStrategy::SetAllBitratesToMinimum(
     const std::vector<BitrateAllocationStrategy::TrackConfig>& track_configs) {
   std::vector<uint32_t> track_allocations;
+  track_allocations.reserve(track_configs.size());
   for (const auto& track_config : track_configs) {
     track_allocations.push_back(track_config.min_bitrate_bps);
   }
diff --git a/rtc_base/bitrateallocationstrategy.h b/rtc_base/bitrate_allocation_strategy.h
similarity index 96%
rename from rtc_base/bitrateallocationstrategy.h
rename to rtc_base/bitrate_allocation_strategy.h
index 13a4eee..fc54373 100644
--- a/rtc_base/bitrateallocationstrategy.h
+++ b/rtc_base/bitrate_allocation_strategy.h
@@ -8,8 +8,8 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#ifndef RTC_BASE_BITRATEALLOCATIONSTRATEGY_H_
-#define RTC_BASE_BITRATEALLOCATIONSTRATEGY_H_
+#ifndef RTC_BASE_BITRATE_ALLOCATION_STRATEGY_H_
+#define RTC_BASE_BITRATE_ALLOCATION_STRATEGY_H_
 
 #include <stdint.h>
 #include <string>
@@ -117,4 +117,4 @@
 };
 }  // namespace rtc
 
-#endif  // RTC_BASE_BITRATEALLOCATIONSTRATEGY_H_
+#endif  // RTC_BASE_BITRATE_ALLOCATION_STRATEGY_H_
diff --git a/rtc_base/bitrateallocationstrategy_unittest.cc b/rtc_base/bitrate_allocation_strategy_unittest.cc
similarity index 98%
rename from rtc_base/bitrateallocationstrategy_unittest.cc
rename to rtc_base/bitrate_allocation_strategy_unittest.cc
index f4c7ee7..aea3966 100644
--- a/rtc_base/bitrateallocationstrategy_unittest.cc
+++ b/rtc_base/bitrate_allocation_strategy_unittest.cc
@@ -8,8 +8,11 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#include "rtc_base/bitrateallocationstrategy.h"
-#include "rtc_base/gunit.h"
+#include "rtc_base/bitrate_allocation_strategy.h"
+
+#include <cstdint>
+
+#include "test/gtest.h"
 
 namespace rtc {
 
diff --git a/rtc_base/buffer.h b/rtc_base/buffer.h
index f9291b9..e95636a 100644
--- a/rtc_base/buffer.h
+++ b/rtc_base/buffer.h
@@ -11,6 +11,7 @@
 #ifndef RTC_BASE_BUFFER_H_
 #define RTC_BASE_BUFFER_H_
 
+#include <stdint.h>
 #include <algorithm>
 #include <cstring>
 #include <memory>
diff --git a/rtc_base/bufferqueue.cc b/rtc_base/buffer_queue.cc
similarity index 98%
rename from rtc_base/bufferqueue.cc
rename to rtc_base/buffer_queue.cc
index 74f7a50..8f3ead9 100644
--- a/rtc_base/bufferqueue.cc
+++ b/rtc_base/buffer_queue.cc
@@ -8,7 +8,7 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#include "rtc_base/bufferqueue.h"
+#include "rtc_base/buffer_queue.h"
 
 #include <stdint.h>
 #include <string.h>
diff --git a/rtc_base/bufferqueue.h b/rtc_base/buffer_queue.h
similarity index 90%
rename from rtc_base/bufferqueue.h
rename to rtc_base/buffer_queue.h
index 63f5182..bce3c8a 100644
--- a/rtc_base/bufferqueue.h
+++ b/rtc_base/buffer_queue.h
@@ -8,16 +8,16 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#ifndef RTC_BASE_BUFFERQUEUE_H_
-#define RTC_BASE_BUFFERQUEUE_H_
+#ifndef RTC_BASE_BUFFER_QUEUE_H_
+#define RTC_BASE_BUFFER_QUEUE_H_
 
 #include <stddef.h>
 #include <deque>
 #include <vector>
 
 #include "rtc_base/buffer.h"
-#include "rtc_base/constructormagic.h"
-#include "rtc_base/criticalsection.h"
+#include "rtc_base/constructor_magic.h"
+#include "rtc_base/critical_section.h"
 #include "rtc_base/thread_annotations.h"
 
 namespace rtc {
@@ -60,4 +60,4 @@
 
 }  // namespace rtc
 
-#endif  // RTC_BASE_BUFFERQUEUE_H_
+#endif  // RTC_BASE_BUFFER_QUEUE_H_
diff --git a/rtc_base/bufferqueue_unittest.cc b/rtc_base/buffer_queue_unittest.cc
similarity index 97%
rename from rtc_base/bufferqueue_unittest.cc
rename to rtc_base/buffer_queue_unittest.cc
index 11d115f..2a2f8cc 100644
--- a/rtc_base/bufferqueue_unittest.cc
+++ b/rtc_base/buffer_queue_unittest.cc
@@ -8,8 +8,11 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#include "rtc_base/bufferqueue.h"
-#include "rtc_base/gunit.h"
+#include "rtc_base/buffer_queue.h"
+
+#include <string.h>
+
+#include "test/gtest.h"
 
 namespace rtc {
 
diff --git a/rtc_base/buffer_unittest.cc b/rtc_base/buffer_unittest.cc
index b2f47c1..40d9edc 100644
--- a/rtc_base/buffer_unittest.cc
+++ b/rtc_base/buffer_unittest.cc
@@ -10,12 +10,12 @@
 
 #include "rtc_base/buffer.h"
 
-#include "api/array_view.h"
-#include "rtc_base/gunit.h"
-
-#include <type_traits>
+#include <cstdint>
 #include <utility>
 
+#include "api/array_view.h"
+#include "test/gtest.h"
+
 namespace rtc {
 
 namespace {
diff --git a/rtc_base/bytebuffer.cc b/rtc_base/byte_buffer.cc
similarity index 99%
rename from rtc_base/bytebuffer.cc
rename to rtc_base/byte_buffer.cc
index f8ce1a2..9f79120 100644
--- a/rtc_base/bytebuffer.cc
+++ b/rtc_base/byte_buffer.cc
@@ -8,7 +8,7 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#include "rtc_base/bytebuffer.h"
+#include "rtc_base/byte_buffer.h"
 
 #include <string.h>
 
diff --git a/rtc_base/bytebuffer.h b/rtc_base/byte_buffer.h
similarity index 97%
rename from rtc_base/bytebuffer.h
rename to rtc_base/byte_buffer.h
index 4d25c21..73e9040 100644
--- a/rtc_base/bytebuffer.h
+++ b/rtc_base/byte_buffer.h
@@ -8,16 +8,16 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#ifndef RTC_BASE_BYTEBUFFER_H_
-#define RTC_BASE_BYTEBUFFER_H_
+#ifndef RTC_BASE_BYTE_BUFFER_H_
+#define RTC_BASE_BYTE_BUFFER_H_
 
 #include <stddef.h>
 #include <stdint.h>
 #include <string>
 
 #include "rtc_base/buffer.h"
-#include "rtc_base/byteorder.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/byte_order.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace rtc {
 
@@ -201,4 +201,4 @@
 
 }  // namespace rtc
 
-#endif  // RTC_BASE_BYTEBUFFER_H_
+#endif  // RTC_BASE_BYTE_BUFFER_H_
diff --git a/rtc_base/bytebuffer_unittest.cc b/rtc_base/byte_buffer_unittest.cc
similarity index 98%
rename from rtc_base/bytebuffer_unittest.cc
rename to rtc_base/byte_buffer_unittest.cc
index 718f35c..eafe670 100644
--- a/rtc_base/bytebuffer_unittest.cc
+++ b/rtc_base/byte_buffer_unittest.cc
@@ -8,10 +8,13 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#include "rtc_base/bytebuffer.h"
+#include "rtc_base/byte_buffer.h"
+
+#include <string.h>
+
 #include "rtc_base/arraysize.h"
-#include "rtc_base/byteorder.h"
-#include "rtc_base/gunit.h"
+#include "rtc_base/byte_order.h"
+#include "test/gtest.h"
 
 namespace rtc {
 
diff --git a/rtc_base/byteorder.h b/rtc_base/byte_order.h
similarity index 97%
rename from rtc_base/byteorder.h
rename to rtc_base/byte_order.h
index 86546a5..2b50f0d 100644
--- a/rtc_base/byteorder.h
+++ b/rtc_base/byte_order.h
@@ -8,8 +8,8 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#ifndef RTC_BASE_BYTEORDER_H_
-#define RTC_BASE_BYTEORDER_H_
+#ifndef RTC_BASE_BYTE_ORDER_H_
+#define RTC_BASE_BYTE_ORDER_H_
 
 #include <stdint.h>
 
@@ -177,4 +177,4 @@
 
 }  // namespace rtc
 
-#endif  // RTC_BASE_BYTEORDER_H_
+#endif  // RTC_BASE_BYTE_ORDER_H_
diff --git a/rtc_base/byteorder_unittest.cc b/rtc_base/byte_order_unittest.cc
similarity index 97%
rename from rtc_base/byteorder_unittest.cc
rename to rtc_base/byte_order_unittest.cc
index 75509de..82b5fe9 100644
--- a/rtc_base/byteorder_unittest.cc
+++ b/rtc_base/byte_order_unittest.cc
@@ -10,8 +10,8 @@
 
 #include <stdint.h>
 
-#include "rtc_base/byteorder.h"
-#include "rtc_base/gunit.h"
+#include "rtc_base/byte_order.h"
+#include "test/gtest.h"
 
 namespace rtc {
 
diff --git a/rtc_base/callback.h b/rtc_base/callback.h
index 65b7c9c..4751221 100644
--- a/rtc_base/callback.h
+++ b/rtc_base/callback.h
@@ -62,9 +62,9 @@
 #ifndef RTC_BASE_CALLBACK_H_
 #define RTC_BASE_CALLBACK_H_
 
-#include "rtc_base/refcount.h"
-#include "rtc_base/refcountedobject.h"
-#include "rtc_base/scoped_ref_ptr.h"
+#include "api/scoped_refptr.h"
+#include "rtc_base/ref_count.h"
+#include "rtc_base/ref_counted_object.h"
 
 namespace rtc {
 
diff --git a/rtc_base/callback.h.pump b/rtc_base/callback.h.pump
index 2c40eab..dc5fb3a 100644
--- a/rtc_base/callback.h.pump
+++ b/rtc_base/callback.h.pump
@@ -57,9 +57,9 @@
 #ifndef RTC_BASE_CALLBACK_H_
 #define RTC_BASE_CALLBACK_H_
 
-#include "rtc_base/refcount.h"
-#include "rtc_base/refcountedobject.h"
-#include "rtc_base/scoped_ref_ptr.h"
+#include "rtc_base/ref_count.h"
+#include "rtc_base/ref_counted_object.h"
+#include "api/scoped_refptr.h"
 
 namespace rtc {
 
diff --git a/rtc_base/callback_unittest.cc b/rtc_base/callback_unittest.cc
index ae86a4c..8767295 100644
--- a/rtc_base/callback_unittest.cc
+++ b/rtc_base/callback_unittest.cc
@@ -9,10 +9,11 @@
  */
 
 #include "rtc_base/callback.h"
+
 #include "rtc_base/bind.h"
-#include "rtc_base/gunit.h"
 #include "rtc_base/keep_ref_until_done.h"
-#include "rtc_base/refcount.h"
+#include "rtc_base/ref_count.h"
+#include "test/gtest.h"
 
 namespace rtc {
 
diff --git a/rtc_base/cancelable_periodic_task.h b/rtc_base/cancelable_periodic_task.h
deleted file mode 100644
index d113015..0000000
--- a/rtc_base/cancelable_periodic_task.h
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- *  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_CANCELABLE_PERIODIC_TASK_H_
-#define RTC_BASE_CANCELABLE_PERIODIC_TASK_H_
-
-#include <memory>
-#include <type_traits>
-#include <utility>
-
-#include "absl/memory/memory.h"
-#include "rtc_base/cancelable_task_handle.h"
-#include "rtc_base/checks.h"
-#include "rtc_base/logging.h"
-#include "rtc_base/numerics/safe_conversions.h"
-
-namespace rtc {
-namespace cancelable_periodic_task_internal {
-// CancelablePeriodicTask runs a closure multiple times with delay decided
-// by the return value of the closure itself.
-// The task can be canceled with the handle returned by GetCancelationHandle().
-// Note that the task can only be canceled on the task queue where it runs.
-template <typename Closure>
-class CancelablePeriodicTask final : public BaseCancelableTask {
- public:
-  // |closure| should return time in ms until next run.
-  explicit CancelablePeriodicTask(Closure&& closure)
-      : closure_(std::forward<Closure>(closure)) {}
-  CancelablePeriodicTask(const CancelablePeriodicTask&) = delete;
-  CancelablePeriodicTask& operator=(const CancelablePeriodicTask&) = delete;
-  ~CancelablePeriodicTask() override = default;
-
- private:
-  bool Run() override {
-    // See QueuedTask::Run documentaion for return values meaning.
-    if (BaseCancelableTask::Canceled())
-      return true;  // Caller retains ownership of `this`, and will destroy it.
-    // Run the actual task.
-    auto delay = closure_();
-    // Convert closure_() return type into uint32_t.
-    uint32_t delay_ms = 0;
-    if (rtc::IsValueInRangeForNumericType<uint32_t>(delay)) {
-      delay_ms = static_cast<uint32_t>(delay);
-    } else {
-      // Log and recover in production.
-      RTC_LOG(LS_ERROR) << "Invalid delay until next run: " << delay;
-      delay_ms = rtc::saturated_cast<uint32_t>(delay);
-      // But crash in debug.
-      RTC_DCHECK(false);
-    }
-    // Reschedule.
-    auto owned_task = absl::WrapUnique(this);
-    if (delay_ms == 0)
-      TaskQueue::Current()->PostTask(std::move(owned_task));
-    else
-      TaskQueue::Current()->PostDelayedTask(std::move(owned_task), delay_ms);
-    return false;  // Caller will release ownership of `this`.
-  }
-
-  Closure closure_;
-};
-}  // namespace cancelable_periodic_task_internal
-
-template <typename Closure>
-std::unique_ptr<BaseCancelableTask> CreateCancelablePeriodicTask(
-    Closure&& closure) {
-  using CleanedClosure = typename std::remove_cv<
-      typename std::remove_reference<Closure>::type>::type;
-  return absl::make_unique<cancelable_periodic_task_internal::
-                               CancelablePeriodicTask<CleanedClosure>>(
-      std::forward<CleanedClosure>(closure));
-}
-
-}  // namespace rtc
-
-#endif  // RTC_BASE_CANCELABLE_PERIODIC_TASK_H_
diff --git a/rtc_base/cancelable_periodic_task_unittest.cc b/rtc_base/cancelable_periodic_task_unittest.cc
deleted file mode 100644
index badd623..0000000
--- a/rtc_base/cancelable_periodic_task_unittest.cc
+++ /dev/null
@@ -1,228 +0,0 @@
-/*
- *  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/cancelable_periodic_task.h"
-
-#include "rtc_base/event.h"
-#include "test/gmock.h"
-
-namespace {
-
-using ::testing::AtLeast;
-using ::testing::Invoke;
-using ::testing::NiceMock;
-using ::testing::MockFunction;
-using ::testing::Return;
-
-constexpr int kTimeoutMs = 1000;
-
-class MockClosure {
- public:
-  MOCK_METHOD0(Call, int());
-  MOCK_METHOD0(Delete, void());
-};
-
-class MoveOnlyClosure {
- public:
-  explicit MoveOnlyClosure(MockClosure* mock) : mock_(mock) {}
-  MoveOnlyClosure(const MoveOnlyClosure&) = delete;
-  MoveOnlyClosure(MoveOnlyClosure&& other) : mock_(other.mock_) {
-    other.mock_ = nullptr;
-  }
-  ~MoveOnlyClosure() {
-    if (mock_)
-      mock_->Delete();
-  }
-  int operator()() { return mock_->Call(); }
-
- private:
-  MockClosure* mock_;
-};
-
-class CopyableClosure {
- public:
-  explicit CopyableClosure(MockClosure* mock) : mock_(mock) {}
-  CopyableClosure(const CopyableClosure& other) : mock_(other.mock_) {}
-  ~CopyableClosure() {
-    if (mock_) {
-      mock_->Delete();
-      mock_ = nullptr;
-    }
-  }
-  int operator()() { return mock_->Call(); }
-
- private:
-  MockClosure* mock_;
-};
-
-TEST(CancelablePeriodicTaskTest, CanCallCancelOnEmptyHandle) {
-  rtc::CancelableTaskHandle handle;
-  handle.Cancel();
-}
-
-TEST(CancelablePeriodicTaskTest, CancelTaskBeforeItRuns) {
-  rtc::Event done;
-  MockClosure mock;
-  EXPECT_CALL(mock, Call).Times(0);
-  EXPECT_CALL(mock, Delete).WillOnce(Invoke([&done] { done.Set(); }));
-
-  rtc::TaskQueue task_queue("queue");
-
-  auto task = rtc::CreateCancelablePeriodicTask(MoveOnlyClosure(&mock));
-  rtc::CancelableTaskHandle handle = task->GetCancellationHandle();
-  task_queue.PostTask([handle] { handle.Cancel(); });
-  task_queue.PostTask(std::move(task));
-
-  EXPECT_TRUE(done.Wait(kTimeoutMs));
-}
-
-TEST(CancelablePeriodicTaskTest, CancelDelayedTaskBeforeItRuns) {
-  rtc::Event done;
-  MockClosure mock;
-  EXPECT_CALL(mock, Call).Times(0);
-  EXPECT_CALL(mock, Delete).WillOnce(Invoke([&done] { done.Set(); }));
-
-  rtc::TaskQueue task_queue("queue");
-
-  auto task = rtc::CreateCancelablePeriodicTask(MoveOnlyClosure(&mock));
-  rtc::CancelableTaskHandle handle = task->GetCancellationHandle();
-  task_queue.PostDelayedTask(std::move(task), 100);
-  task_queue.PostTask([handle] { handle.Cancel(); });
-
-  EXPECT_TRUE(done.Wait(kTimeoutMs));
-}
-
-TEST(CancelablePeriodicTaskTest, CancelTaskAfterItRuns) {
-  rtc::Event done;
-  MockClosure mock;
-  EXPECT_CALL(mock, Call).WillOnce(Return(100));
-  EXPECT_CALL(mock, Delete).WillOnce(Invoke([&done] { done.Set(); }));
-
-  rtc::TaskQueue task_queue("queue");
-
-  auto task = rtc::CreateCancelablePeriodicTask(MoveOnlyClosure(&mock));
-  rtc::CancelableTaskHandle handle = task->GetCancellationHandle();
-  task_queue.PostTask(std::move(task));
-  task_queue.PostTask([handle] { handle.Cancel(); });
-
-  EXPECT_TRUE(done.Wait(kTimeoutMs));
-}
-
-TEST(CancelablePeriodicTaskTest, ZeroReturnValueRepostsTheTask) {
-  NiceMock<MockClosure> closure;
-  rtc::Event done;
-  EXPECT_CALL(closure, Call()).WillOnce(Return(0)).WillOnce(Invoke([&done] {
-    done.Set();
-    return kTimeoutMs;
-  }));
-  rtc::TaskQueue task_queue("queue");
-  task_queue.PostTask(
-      rtc::CreateCancelablePeriodicTask(MoveOnlyClosure(&closure)));
-  EXPECT_TRUE(done.Wait(kTimeoutMs));
-}
-
-TEST(CancelablePeriodicTaskTest, StartPeriodicTask) {
-  MockFunction<int()> closure;
-  rtc::Event done;
-  EXPECT_CALL(closure, Call())
-      .WillOnce(Return(20))
-      .WillOnce(Return(20))
-      .WillOnce(Invoke([&done] {
-        done.Set();
-        return kTimeoutMs;
-      }));
-  rtc::TaskQueue task_queue("queue");
-  task_queue.PostTask(
-      rtc::CreateCancelablePeriodicTask(closure.AsStdFunction()));
-  EXPECT_TRUE(done.Wait(kTimeoutMs));
-}
-
-// Validates perfect forwarding doesn't keep reference to deleted copy.
-TEST(CancelablePeriodicTaskTest, CreateWithCopyOfAClosure) {
-  rtc::Event done;
-  MockClosure mock;
-  EXPECT_CALL(mock, Call).WillOnce(Invoke([&done] {
-    done.Set();
-    return kTimeoutMs;
-  }));
-  EXPECT_CALL(mock, Delete).Times(AtLeast(2));
-  CopyableClosure closure(&mock);
-  std::unique_ptr<rtc::BaseCancelableTask> task;
-  {
-    CopyableClosure copy = closure;
-    task = rtc::CreateCancelablePeriodicTask(copy);
-  }
-
-  rtc::TaskQueue task_queue("queue");
-  task_queue.PostTask(std::move(task));
-  EXPECT_TRUE(done.Wait(kTimeoutMs));
-}
-
-TEST(CancelablePeriodicTaskTest, DeletingHandleDoesntStopTheTask) {
-  rtc::Event run;
-  rtc::TaskQueue task_queue("queue");
-  auto task = rtc::CreateCancelablePeriodicTask(([&] {
-    run.Set();
-    return kTimeoutMs;
-  }));
-  rtc::CancelableTaskHandle handle = task->GetCancellationHandle();
-  handle = {};  // delete the handle.
-  task_queue.PostTask(std::move(task));
-  EXPECT_TRUE(run.Wait(kTimeoutMs));
-}
-
-// Example to test there are no thread races and use after free for suggested
-// typical usage of the CancelablePeriodicTask
-TEST(CancelablePeriodicTaskTest, Example) {
-  class ObjectOnTaskQueue {
-   public:
-    void DoPeriodicTask() {}
-    int TimeUntilNextRunMs() { return 100; }
-
-    rtc::CancelableTaskHandle StartPeriodicTask(rtc::TaskQueue* task_queue) {
-      auto periodic_task = rtc::CreateCancelablePeriodicTask([this] {
-        DoPeriodicTask();
-        return TimeUntilNextRunMs();
-      });
-      rtc::CancelableTaskHandle handle = periodic_task->GetCancellationHandle();
-      task_queue->PostTask(std::move(periodic_task));
-      return handle;
-    }
-  };
-
-  rtc::TaskQueue task_queue("queue");
-
-  auto object = absl::make_unique<ObjectOnTaskQueue>();
-  // Create and start the periodic task.
-  rtc::CancelableTaskHandle handle = object->StartPeriodicTask(&task_queue);
-
-  // Restart the task
-  task_queue.PostTask([handle] { handle.Cancel(); });
-  handle = object->StartPeriodicTask(&task_queue);
-
-  // Stop the task and destroy the object.
-  struct Destructor {
-    void operator()() {
-      // Cancel must be run on the task_queue, but if task failed to start
-      // because of task queue destruction, there is no need to run Cancel.
-      handle.Cancel();
-    }
-    // Destruction will happen either on the task queue or because task
-    // queue is destroyed.
-
-    std::unique_ptr<ObjectOnTaskQueue> object;
-    rtc::CancelableTaskHandle handle;
-  };
-  task_queue.PostTask(Destructor{std::move(object), std::move(handle)});
-  // Do not wait for the Destructor closure in order to create a race between
-  // task queue destruction and running the Desctructor closure.
-}
-
-}  // namespace
diff --git a/rtc_base/cancelable_task_handle.cc b/rtc_base/cancelable_task_handle.cc
deleted file mode 100644
index 372e766..0000000
--- a/rtc_base/cancelable_task_handle.cc
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- *  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/cancelable_task_handle.h"
-
-#include <utility>
-
-#include "rtc_base/refcounter.h"
-#include "rtc_base/sequenced_task_checker.h"
-#include "rtc_base/thread_annotations.h"
-#include "rtc_base/thread_checker.h"
-
-namespace rtc {
-
-class CancelableTaskHandle::CancellationToken {
- public:
-  CancellationToken() : canceled_(false), ref_count_(0) { checker_.Detach(); }
-  CancellationToken(const CancellationToken&) = delete;
-  CancellationToken& operator=(const CancellationToken&) = delete;
-
-  void Cancel() {
-    RTC_DCHECK_RUN_ON(&checker_);
-    canceled_ = true;
-  }
-
-  bool Canceled() {
-    RTC_DCHECK_RUN_ON(&checker_);
-    return canceled_;
-  }
-
-  void AddRef() { ref_count_.IncRef(); }
-
-  void Release() {
-    if (ref_count_.DecRef() == rtc::RefCountReleaseStatus::kDroppedLastRef)
-      delete this;
-  }
-
- private:
-  ~CancellationToken() = default;
-
-  rtc::SequencedTaskChecker checker_;
-  bool canceled_ RTC_GUARDED_BY(checker_);
-  webrtc::webrtc_impl::RefCounter ref_count_;
-};
-
-CancelableTaskHandle::CancelableTaskHandle() = default;
-CancelableTaskHandle::CancelableTaskHandle(const CancelableTaskHandle&) =
-    default;
-CancelableTaskHandle::CancelableTaskHandle(CancelableTaskHandle&&) = default;
-CancelableTaskHandle& CancelableTaskHandle::operator=(
-    const CancelableTaskHandle&) = default;
-CancelableTaskHandle& CancelableTaskHandle::operator=(CancelableTaskHandle&&) =
-    default;
-CancelableTaskHandle::~CancelableTaskHandle() = default;
-
-void CancelableTaskHandle::Cancel() const {
-  if (cancellation_token_.get() != nullptr)
-    cancellation_token_->Cancel();
-}
-
-CancelableTaskHandle::CancelableTaskHandle(
-    rtc::scoped_refptr<CancellationToken> cancellation_token)
-    : cancellation_token_(std::move(cancellation_token)) {}
-
-BaseCancelableTask::~BaseCancelableTask() = default;
-
-CancelableTaskHandle BaseCancelableTask::GetCancellationHandle() const {
-  return CancelableTaskHandle(cancellation_token_);
-}
-
-BaseCancelableTask::BaseCancelableTask()
-    : cancellation_token_(new CancelableTaskHandle::CancellationToken) {}
-
-bool BaseCancelableTask::Canceled() const {
-  return cancellation_token_->Canceled();
-}
-
-}  // namespace rtc
diff --git a/rtc_base/cancelable_task_handle.h b/rtc_base/cancelable_task_handle.h
deleted file mode 100644
index 3b1f0d5..0000000
--- a/rtc_base/cancelable_task_handle.h
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- *  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_CANCELABLE_TASK_HANDLE_H_
-#define RTC_BASE_CANCELABLE_TASK_HANDLE_H_
-
-#include "rtc_base/scoped_ref_ptr.h"
-#include "rtc_base/task_queue.h"
-
-namespace rtc {
-
-class BaseCancelableTask;
-
-// Allows to cancel a cancelable task. Non-empty handle can be acquired by
-// calling GetCancellationHandle() on a cancelable task.
-class CancelableTaskHandle {
- public:
-  // This class is copyable and cheaply movable.
-  CancelableTaskHandle();
-  CancelableTaskHandle(const CancelableTaskHandle&);
-  CancelableTaskHandle(CancelableTaskHandle&&);
-  CancelableTaskHandle& operator=(const CancelableTaskHandle&);
-  CancelableTaskHandle& operator=(CancelableTaskHandle&&);
-  // Deleting the handler doesn't Cancel the task.
-  ~CancelableTaskHandle();
-
-  // Prevents the cancelable task to run.
-  // Must be executed on the same task queue as the task itself.
-  void Cancel() const;
-
- private:
-  friend class BaseCancelableTask;
-  class CancellationToken;
-  explicit CancelableTaskHandle(
-      rtc::scoped_refptr<CancellationToken> cancelation_token);
-
-  rtc::scoped_refptr<CancellationToken> cancellation_token_;
-};
-
-class BaseCancelableTask : public QueuedTask {
- public:
-  ~BaseCancelableTask() override;
-
-  CancelableTaskHandle GetCancellationHandle() const;
-
- protected:
-  BaseCancelableTask();
-
-  bool Canceled() const;
-
- private:
-  rtc::scoped_refptr<CancelableTaskHandle::CancellationToken>
-      cancellation_token_;
-};
-
-}  // namespace rtc
-
-#endif  // RTC_BASE_CANCELABLE_TASK_HANDLE_H_
diff --git a/rtc_base/constructormagic.h b/rtc_base/constructor_magic.h
similarity index 91%
rename from rtc_base/constructormagic.h
rename to rtc_base/constructor_magic.h
index 6b6e83c..e63c2ff 100644
--- a/rtc_base/constructormagic.h
+++ b/rtc_base/constructor_magic.h
@@ -8,8 +8,8 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#ifndef RTC_BASE_CONSTRUCTORMAGIC_H_
-#define RTC_BASE_CONSTRUCTORMAGIC_H_
+#ifndef RTC_BASE_CONSTRUCTOR_MAGIC_H_
+#define RTC_BASE_CONSTRUCTOR_MAGIC_H_
 
 // Put this in the declarations for a class to be unassignable.
 #define RTC_DISALLOW_ASSIGN(TypeName) \
@@ -31,4 +31,4 @@
   TypeName() = delete;                               \
   RTC_DISALLOW_COPY_AND_ASSIGN(TypeName)
 
-#endif  // RTC_BASE_CONSTRUCTORMAGIC_H_
+#endif  // RTC_BASE_CONSTRUCTOR_MAGIC_H_
diff --git a/rtc_base/copyonwritebuffer.cc b/rtc_base/copy_on_write_buffer.cc
similarity index 98%
rename from rtc_base/copyonwritebuffer.cc
rename to rtc_base/copy_on_write_buffer.cc
index 8f5126a..de003f2 100644
--- a/rtc_base/copyonwritebuffer.cc
+++ b/rtc_base/copy_on_write_buffer.cc
@@ -8,7 +8,7 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#include "rtc_base/copyonwritebuffer.h"
+#include "rtc_base/copy_on_write_buffer.h"
 
 #include <stddef.h>
 
diff --git a/rtc_base/copyonwritebuffer.h b/rtc_base/copy_on_write_buffer.h
similarity index 97%
rename from rtc_base/copyonwritebuffer.h
rename to rtc_base/copy_on_write_buffer.h
index cc174df..d0954ad 100644
--- a/rtc_base/copyonwritebuffer.h
+++ b/rtc_base/copy_on_write_buffer.h
@@ -8,8 +8,8 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#ifndef RTC_BASE_COPYONWRITEBUFFER_H_
-#define RTC_BASE_COPYONWRITEBUFFER_H_
+#ifndef RTC_BASE_COPY_ON_WRITE_BUFFER_H_
+#define RTC_BASE_COPY_ON_WRITE_BUFFER_H_
 
 #include <stdint.h>
 #include <algorithm>
@@ -18,10 +18,10 @@
 #include <type_traits>
 #include <utility>
 
+#include "api/scoped_refptr.h"
 #include "rtc_base/buffer.h"
 #include "rtc_base/checks.h"
-#include "rtc_base/refcountedobject.h"
-#include "rtc_base/scoped_ref_ptr.h"
+#include "rtc_base/ref_counted_object.h"
 
 namespace rtc {
 
@@ -243,4 +243,4 @@
 
 }  // namespace rtc
 
-#endif  // RTC_BASE_COPYONWRITEBUFFER_H_
+#endif  // RTC_BASE_COPY_ON_WRITE_BUFFER_H_
diff --git a/rtc_base/copyonwritebuffer_unittest.cc b/rtc_base/copy_on_write_buffer_unittest.cc
similarity index 98%
rename from rtc_base/copyonwritebuffer_unittest.cc
rename to rtc_base/copy_on_write_buffer_unittest.cc
index 24a57d4..fc569bd 100644
--- a/rtc_base/copyonwritebuffer_unittest.cc
+++ b/rtc_base/copy_on_write_buffer_unittest.cc
@@ -8,8 +8,11 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#include "rtc_base/copyonwritebuffer.h"
-#include "rtc_base/gunit.h"
+#include "rtc_base/copy_on_write_buffer.h"
+
+#include <cstdint>
+
+#include "test/gtest.h"
 
 namespace rtc {
 
diff --git a/rtc_base/cpu_time.cc b/rtc_base/cpu_time.cc
index ad91eca..b95bcb1 100644
--- a/rtc_base/cpu_time.cc
+++ b/rtc_base/cpu_time.cc
@@ -9,8 +9,9 @@
  */
 
 #include "rtc_base/cpu_time.h"
+
 #include "rtc_base/logging.h"
-#include "rtc_base/timeutils.h"
+#include "rtc_base/time_utils.h"
 
 #if defined(WEBRTC_LINUX)
 #include <time.h>
diff --git a/rtc_base/cpu_time_unittest.cc b/rtc_base/cpu_time_unittest.cc
index f473069..b5e0f67 100644
--- a/rtc_base/cpu_time_unittest.cc
+++ b/rtc_base/cpu_time_unittest.cc
@@ -9,11 +9,9 @@
  */
 
 #include "rtc_base/cpu_time.h"
-#include <algorithm>
-#include <memory>
+
 #include "rtc_base/platform_thread.h"
-#include "rtc_base/timeutils.h"
-#include "system_wrappers/include/cpu_info.h"
+#include "rtc_base/time_utils.h"
 #include "system_wrappers/include/sleep.h"
 #include "test/gtest.h"
 
diff --git a/rtc_base/crc32_unittest.cc b/rtc_base/crc32_unittest.cc
index 752bc9f..60997b2 100644
--- a/rtc_base/crc32_unittest.cc
+++ b/rtc_base/crc32_unittest.cc
@@ -9,10 +9,11 @@
  */
 
 #include "rtc_base/crc32.h"
-#include "rtc_base/gunit.h"
 
 #include <string>
 
+#include "test/gtest.h"
+
 namespace rtc {
 
 TEST(Crc32Test, TestBasic) {
diff --git a/rtc_base/criticalsection.cc b/rtc_base/critical_section.cc
similarity index 96%
rename from rtc_base/criticalsection.cc
rename to rtc_base/critical_section.cc
index 4e00be9..2100fe9 100644
--- a/rtc_base/criticalsection.cc
+++ b/rtc_base/critical_section.cc
@@ -8,11 +8,11 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#include "rtc_base/criticalsection.h"
+#include "rtc_base/critical_section.h"
 
 #include <time.h>
 
-#include "rtc_base/atomicops.h"
+#include "rtc_base/atomic_ops.h"
 #include "rtc_base/checks.h"
 #include "rtc_base/platform_thread_types.h"
 #include "rtc_base/system/unused.h"
@@ -34,6 +34,10 @@
   pthread_mutexattr_t mutex_attribute;
   pthread_mutexattr_init(&mutex_attribute);
   pthread_mutexattr_settype(&mutex_attribute, PTHREAD_MUTEX_RECURSIVE);
+#if defined(WEBRTC_MAC)
+  pthread_mutexattr_setpolicy_np(&mutex_attribute,
+                                 _PTHREAD_MUTEX_POLICY_FAIRSHARE);
+#endif
   pthread_mutex_init(&mutex_, &mutex_attribute);
   pthread_mutexattr_destroy(&mutex_attribute);
 #endif
diff --git a/rtc_base/criticalsection.h b/rtc_base/critical_section.h
similarity index 95%
rename from rtc_base/criticalsection.h
rename to rtc_base/critical_section.h
index f25e7d0..d575b97 100644
--- a/rtc_base/criticalsection.h
+++ b/rtc_base/critical_section.h
@@ -8,11 +8,11 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#ifndef RTC_BASE_CRITICALSECTION_H_
-#define RTC_BASE_CRITICALSECTION_H_
+#ifndef RTC_BASE_CRITICAL_SECTION_H_
+#define RTC_BASE_CRITICAL_SECTION_H_
 
 #include "rtc_base/checks.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 #include "rtc_base/platform_thread_types.h"
 #include "rtc_base/thread_annotations.h"
 
@@ -34,7 +34,7 @@
 #endif
 
 // See notes in the 'Performance' unit test for the effects of this flag.
-#define USE_NATIVE_MUTEX_ON_MAC 0
+#define USE_NATIVE_MUTEX_ON_MAC 1
 
 #if defined(WEBRTC_MAC) && !USE_NATIVE_MUTEX_ON_MAC
 #include <dispatch/dispatch.h>
@@ -52,7 +52,7 @@
 
 // Locking methods (Enter, TryEnter, Leave)are const to permit protecting
 // members inside a const context without requiring mutable CriticalSections
-// everywhere.
+// everywhere. CriticalSection is reentrant lock.
 class RTC_LOCKABLE CriticalSection {
  public:
   CriticalSection();
@@ -157,4 +157,4 @@
 
 }  // namespace rtc
 
-#endif  // RTC_BASE_CRITICALSECTION_H_
+#endif  // RTC_BASE_CRITICAL_SECTION_H_
diff --git a/rtc_base/criticalsection_unittest.cc b/rtc_base/critical_section_unittest.cc
similarity index 91%
rename from rtc_base/criticalsection_unittest.cc
rename to rtc_base/critical_section_unittest.cc
index 6016f85..5405c61 100644
--- a/rtc_base/criticalsection_unittest.cc
+++ b/rtc_base/critical_section_unittest.cc
@@ -8,18 +8,24 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
+#include <stddef.h>
+#include <stdint.h>
 #include <memory>
 #include <set>
+#include <utility>
 #include <vector>
 
 #include "rtc_base/arraysize.h"
-#include "rtc_base/atomicops.h"
+#include "rtc_base/atomic_ops.h"
 #include "rtc_base/checks.h"
-#include "rtc_base/criticalsection.h"
+#include "rtc_base/critical_section.h"
 #include "rtc_base/event.h"
-#include "rtc_base/gunit.h"
+#include "rtc_base/location.h"
+#include "rtc_base/message_handler.h"
+#include "rtc_base/message_queue.h"
 #include "rtc_base/platform_thread.h"
 #include "rtc_base/thread.h"
+#include "test/gtest.h"
 
 namespace rtc {
 
@@ -366,25 +372,33 @@
   int my_id_ = 0;
 };
 
-// Comparison of output of this test as tested on a MacBook Pro Retina, 15-inch,
-// Mid 2014, 2,8 GHz Intel Core i7, 16 GB 1600 MHz DDR3,
-// running OS X El Capitan, 10.11.2.
+// Comparison of output of this test as tested on a MacBook Pro, 13-inch,
+// 2017, 3,5 GHz Intel Core i7, 16 GB 2133 MHz LPDDR3,
+// running macOS Mojave, 10.14.3.
 //
-// Native mutex implementation:
+// Native mutex implementation using fair policy (previously macOS default):
 // Approximate CPU usage:
-//   System: ~16%
-//   User mode: ~1.3%
-//   Idle: ~82%
+// real    4m54.612s
+// user    1m20.575s
+// sys     3m48.872s
 // Unit test output:
-// [       OK ] CriticalSectionTest.Performance (234545 ms)
+// [       OK ] CriticalSectionTest.Performance (294375 ms)
+//
+// Native mutex implementation using first fit policy (current macOS default):
+// Approximate CPU usage:
+// real    0m11.535s
+// user    0m12.738s
+// sys     0m31.207s
+// Unit test output:
+// [       OK ] CriticalSectionTest.Performance (11444 ms)
 //
 // Special partially spin lock based implementation:
 // Approximate CPU usage:
-//   System: ~75%
-//   User mode: ~16%
-//   Idle: ~8%
+// real    0m2.113s
+// user    0m3.014s
+// sys     0m4.495s
 // Unit test output:
-// [       OK ] CriticalSectionTest.Performance (2107 ms)
+// [       OK ] CriticalSectionTest.Performance (1885 ms)
 //
 // The test is disabled by default to avoid unecessarily loading the bots.
 TEST(CriticalSectionTest, DISABLED_Performance) {
diff --git a/rtc_base/cryptstring.cc b/rtc_base/crypt_string.cc
similarity index 96%
rename from rtc_base/cryptstring.cc
rename to rtc_base/crypt_string.cc
index 2c7c0c7..ed0ff16 100644
--- a/rtc_base/cryptstring.cc
+++ b/rtc_base/crypt_string.cc
@@ -8,7 +8,7 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#include "rtc_base/cryptstring.h"
+#include "rtc_base/crypt_string.h"
 
 namespace rtc {
 
@@ -69,4 +69,4 @@
   memcpy(&dest->front(), password_.data(), password_.size());
 }
 
-};  // namespace rtc
+}  // namespace rtc
diff --git a/rtc_base/cryptstring.h b/rtc_base/crypt_string.h
similarity index 95%
rename from rtc_base/cryptstring.h
rename to rtc_base/crypt_string.h
index d0e36cb..8aa757c 100644
--- a/rtc_base/cryptstring.h
+++ b/rtc_base/crypt_string.h
@@ -8,8 +8,8 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#ifndef RTC_BASE_CRYPTSTRING_H_
-#define RTC_BASE_CRYPTSTRING_H_
+#ifndef RTC_BASE_CRYPT_STRING_H_
+#define RTC_BASE_CRYPT_STRING_H_
 
 #include <string.h>
 
@@ -83,4 +83,4 @@
 
 }  // namespace rtc
 
-#endif  // RTC_BASE_CRYPTSTRING_H_
+#endif  // RTC_BASE_CRYPT_STRING_H_
diff --git a/rtc_base/data_rate_limiter_unittest.cc b/rtc_base/data_rate_limiter_unittest.cc
index 8c410fe..efd4728 100644
--- a/rtc_base/data_rate_limiter_unittest.cc
+++ b/rtc_base/data_rate_limiter_unittest.cc
@@ -9,7 +9,8 @@
  */
 
 #include "rtc_base/data_rate_limiter.h"
-#include "rtc_base/gunit.h"
+
+#include "test/gtest.h"
 
 namespace rtc {
 
diff --git a/rtc_base/event_tracer.cc b/rtc_base/event_tracer.cc
index af88c9d..bcc8252 100644
--- a/rtc_base/event_tracer.cc
+++ b/rtc_base/event_tracer.cc
@@ -16,16 +16,16 @@
 #include <string>
 #include <vector>
 
-#include "rtc_base/atomicops.h"
+#include "rtc_base/atomic_ops.h"
 #include "rtc_base/checks.h"
-#include "rtc_base/criticalsection.h"
+#include "rtc_base/critical_section.h"
 #include "rtc_base/event.h"
 #include "rtc_base/logging.h"
 #include "rtc_base/platform_thread.h"
 #include "rtc_base/platform_thread_types.h"
 #include "rtc_base/thread_annotations.h"
 #include "rtc_base/thread_checker.h"
-#include "rtc_base/timeutils.h"
+#include "rtc_base/time_utils.h"
 #include "rtc_base/trace_event.h"
 
 // This is a guesstimate that should be enough in most cases.
diff --git a/rtc_base/event_unittest.cc b/rtc_base/event_unittest.cc
index a65111b..3111887 100644
--- a/rtc_base/event_unittest.cc
+++ b/rtc_base/event_unittest.cc
@@ -9,8 +9,9 @@
  */
 
 #include "rtc_base/event.h"
-#include "rtc_base/gunit.h"
+
 #include "rtc_base/platform_thread.h"
+#include "test/gtest.h"
 
 namespace rtc {
 
diff --git a/rtc_base/experiments/BUILD.gn b/rtc_base/experiments/BUILD.gn
index d36a43e..80fa70b 100644
--- a/rtc_base/experiments/BUILD.gn
+++ b/rtc_base/experiments/BUILD.gn
@@ -20,6 +20,24 @@
   ]
 }
 
+rtc_static_library("audio_allocation_settings") {
+  sources = [
+    "audio_allocation_settings.cc",
+    "audio_allocation_settings.h",
+  ]
+  defines = []
+  if (rtc_opus_support_120ms_ptime) {
+    defines += [ "WEBRTC_OPUS_SUPPORT_120MS_PTIME=1" ]
+  } else {
+    defines += [ "WEBRTC_OPUS_SUPPORT_120MS_PTIME=0" ]
+  }
+  deps = [
+    ":field_trial_parser",
+    "../:rtc_base_approved",
+    "../../system_wrappers:field_trial",
+  ]
+}
+
 rtc_static_library("field_trial_parser") {
   sources = [
     "field_trial_parser.cc",
@@ -37,18 +55,6 @@
   ]
 }
 
-rtc_static_library("congestion_controller_experiment") {
-  sources = [
-    "congestion_controller_experiment.cc",
-    "congestion_controller_experiment.h",
-  ]
-  deps = [
-    "../:rtc_base_approved",
-    "../../system_wrappers:field_trial",
-    "//third_party/abseil-cpp/absl/types:optional",
-  ]
-}
-
 rtc_static_library("quality_scaling_experiment") {
   sources = [
     "quality_scaling_experiment.cc",
@@ -109,29 +115,47 @@
   ]
 }
 
+rtc_static_library("rate_control_settings") {
+  sources = [
+    "rate_control_settings.cc",
+    "rate_control_settings.h",
+  ]
+  deps = [
+    ":field_trial_parser",
+    "../:rtc_base_approved",
+    "../../api/transport:field_trial_based_config",
+    "../../api/transport:webrtc_key_value_config",
+    "../../api/video_codecs:video_codecs_api",
+    "../../system_wrappers:field_trial",
+    "//third_party/abseil-cpp/absl/memory:memory",
+    "//third_party/abseil-cpp/absl/types:optional",
+  ]
+}
+
 if (rtc_include_tests) {
   rtc_source_set("experiments_unittests") {
     testonly = true
 
     sources = [
-      "congestion_controller_experiment_unittest.cc",
       "cpu_speed_experiment_unittest.cc",
       "field_trial_parser_unittest.cc",
       "field_trial_units_unittest.cc",
       "normalize_simulcast_size_experiment_unittest.cc",
       "quality_scaling_experiment_unittest.cc",
+      "rate_control_settings_unittest.cc",
       "rtt_mult_experiment_unittest.cc",
     ]
     deps = [
-      ":congestion_controller_experiment",
       ":cpu_speed_experiment",
       ":field_trial_parser",
       ":normalize_simulcast_size_experiment",
       ":quality_scaling_experiment",
+      ":rate_control_settings",
       ":rtt_mult_experiment",
       "..:gunit_helpers",
       "../:rtc_base_tests_main",
       "../:rtc_base_tests_utils",
+      "../../api/video_codecs:video_codecs_api",
       "../../system_wrappers:field_trial",
       "../../test:field_trial",
       "../../test:test_support",
diff --git a/rtc_base/experiments/OWNERS b/rtc_base/experiments/OWNERS
index 9c55872..c31e020 100644
--- a/rtc_base/experiments/OWNERS
+++ b/rtc_base/experiments/OWNERS
@@ -1,4 +1,5 @@
 per-file alr_experiment*=sprang@webrtc.org
+per-file audio_allocation_settings*=srte@webrtc.org
 per-file congestion_controller_experiment*=srte@webrtc.org
 per-file cpu_speed_experiment*=asapersson@webrtc.org
 per-file field_trial*=srte@webrtc.org
@@ -6,3 +7,5 @@
 per-file normalize_simulcast_size_experiment*=asapersson@webrtc.org
 per-file quality_scaling_experiment*=asapersson@webrtc.org
 per-file rtt_mult_experiment*=mhoro@webrtc.org
+per-file rate_control_settings*=sprang@webrtc.org
+per-file rate_control_settings*=srte@webrtc.org
diff --git a/rtc_base/experiments/audio_allocation_settings.cc b/rtc_base/experiments/audio_allocation_settings.cc
new file mode 100644
index 0000000..a505357
--- /dev/null
+++ b/rtc_base/experiments/audio_allocation_settings.cc
@@ -0,0 +1,149 @@
+/*
+ *  Copyright 2019 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+#include "rtc_base/experiments/audio_allocation_settings.h"
+#include "system_wrappers/include/field_trial.h"
+
+namespace webrtc {
+namespace {
+// For SendSideBwe, Opus bitrate should be in the range between 6000 and 32000.
+const int kOpusMinBitrateBps = 6000;
+const int kOpusBitrateFbBps = 32000;
+// OverheadPerPacket = Ipv4(20B) + UDP(8B) + SRTP(10B) + RTP(12)
+constexpr int kOverheadPerPacket = 20 + 8 + 10 + 12;
+}  // namespace
+AudioAllocationSettings::AudioAllocationSettings()
+    : audio_send_side_bwe_("Enabled"),
+      allocate_audio_without_feedback_("Enabled"),
+      force_no_audio_feedback_("Enabled"),
+      audio_feedback_to_improve_video_bwe_("Enabled"),
+      send_side_bwe_with_overhead_("Enabled"),
+      default_min_bitrate_("min", DataRate::bps(kOpusMinBitrateBps)),
+      default_max_bitrate_("max", DataRate::bps(kOpusBitrateFbBps)),
+      priority_bitrate_("prio", DataRate::Zero()) {
+  ParseFieldTrial({&audio_send_side_bwe_},
+                  field_trial::FindFullName("WebRTC-Audio-SendSideBwe"));
+  ParseFieldTrial({&allocate_audio_without_feedback_},
+                  field_trial::FindFullName("WebRTC-Audio-ABWENoTWCC"));
+  ParseFieldTrial({&force_no_audio_feedback_},
+                  field_trial::FindFullName("WebRTC-Audio-ForceNoTWCC"));
+  ParseFieldTrial(
+      {&audio_feedback_to_improve_video_bwe_},
+      field_trial::FindFullName("WebRTC-Audio-SendSideBwe-For-Video"));
+
+  ParseFieldTrial({&send_side_bwe_with_overhead_},
+                  field_trial::FindFullName("WebRTC-SendSideBwe-WithOverhead"));
+  ParseFieldTrial(
+      {&default_min_bitrate_, &default_max_bitrate_, &priority_bitrate_},
+      field_trial::FindFullName("WebRTC-Audio-Allocation"));
+
+  // TODO(mflodman): Keep testing this and set proper values.
+  // Note: This is an early experiment currently only supported by Opus.
+  if (send_side_bwe_with_overhead_) {
+    constexpr int kMaxPacketSizeMs = WEBRTC_OPUS_SUPPORT_120MS_PTIME ? 120 : 60;
+    min_overhead_bps_ = kOverheadPerPacket * 8 * 1000 / kMaxPacketSizeMs;
+  }
+}
+
+AudioAllocationSettings::~AudioAllocationSettings() {}
+
+bool AudioAllocationSettings::ForceNoAudioFeedback() const {
+  return force_no_audio_feedback_;
+}
+
+bool AudioAllocationSettings::IgnoreSeqNumIdChange() const {
+  return !audio_send_side_bwe_;
+}
+
+bool AudioAllocationSettings::ConfigureRateAllocationRange() const {
+  return audio_send_side_bwe_;
+}
+
+bool AudioAllocationSettings::ShouldSendTransportSequenceNumber(
+    int transport_seq_num_extension_header_id) const {
+  if (force_no_audio_feedback_)
+    return false;
+  return audio_send_side_bwe_ && !allocate_audio_without_feedback_ &&
+         transport_seq_num_extension_header_id != 0;
+}
+
+bool AudioAllocationSettings::UpdateAudioTargetBitrate(
+    int transport_seq_num_extension_header_id) const {
+  // If other side does not support audio TWCC and WebRTC-Audio-ABWENoTWCC is
+  // not enabled, do not update target audio bitrate if we are in
+  // WebRTC-Audio-SendSideBwe-For-Video experiment
+  if (allocate_audio_without_feedback_ ||
+      transport_seq_num_extension_header_id != 0)
+    return true;
+  if (audio_feedback_to_improve_video_bwe_)
+    return false;
+  return true;
+}
+
+bool AudioAllocationSettings::IncludeAudioInAllocationOnStart(
+    int min_bitrate_bps,
+    int max_bitrate_bps,
+    bool has_dscp,
+    int transport_seq_num_extension_header_id) const {
+  if (has_dscp || min_bitrate_bps == -1 || max_bitrate_bps == -1)
+    return false;
+  if (transport_seq_num_extension_header_id != 0 && !force_no_audio_feedback_)
+    return true;
+  if (allocate_audio_without_feedback_)
+    return true;
+  if (audio_send_side_bwe_)
+    return false;
+  return true;
+}
+
+bool AudioAllocationSettings::IncludeAudioInAllocationOnReconfigure(
+    int min_bitrate_bps,
+    int max_bitrate_bps,
+    bool has_dscp,
+    int transport_seq_num_extension_header_id) const {
+  // TODO(srte): Make this match include_audio_in_allocation_on_start.
+  if (has_dscp || min_bitrate_bps == -1 || max_bitrate_bps == -1)
+    return false;
+  if (transport_seq_num_extension_header_id != 0)
+    return true;
+  if (audio_send_side_bwe_)
+    return false;
+  return true;
+}
+
+int AudioAllocationSettings::MinBitrateBps() const {
+  return default_min_bitrate_->bps() + min_overhead_bps_;
+}
+
+int AudioAllocationSettings::MaxBitrateBps(
+    absl::optional<int> rtp_parameter_max_bitrate_bps) const {
+  // We assume that the max is a hard limit on the payload bitrate, so we add
+  // min_overhead_bps to it to ensure that, when overhead is deducted, the
+  // payload rate never goes beyond the limit.  Note: this also means that if a
+  // higher overhead is forced, we cannot reach the limit.
+  // TODO(minyue): Reconsider this when the signaling to BWE is done
+  // through a dedicated API.
+
+  // This means that when RtpParameters is reset, we may change the
+  // encoder's bit rate immediately (through ReconfigureAudioSendStream()),
+  // meanwhile change the cap to the output of BWE.
+  if (rtp_parameter_max_bitrate_bps)
+    return *rtp_parameter_max_bitrate_bps + min_overhead_bps_;
+  return default_max_bitrate_->bps() + min_overhead_bps_;
+}
+DataRate AudioAllocationSettings::DefaultPriorityBitrate() const {
+  DataRate max_overhead = DataRate::Zero();
+  if (send_side_bwe_with_overhead_) {
+    const TimeDelta kMinPacketDuration = TimeDelta::ms(20);
+    max_overhead = DataSize::bytes(kOverheadPerPacket) / kMinPacketDuration;
+  }
+  return priority_bitrate_.Get() + max_overhead;
+}
+
+}  // namespace webrtc
diff --git a/rtc_base/experiments/audio_allocation_settings.h b/rtc_base/experiments/audio_allocation_settings.h
new file mode 100644
index 0000000..f05b4a3
--- /dev/null
+++ b/rtc_base/experiments/audio_allocation_settings.h
@@ -0,0 +1,97 @@
+/*
+ *  Copyright 2019 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+#ifndef RTC_BASE_EXPERIMENTS_AUDIO_ALLOCATION_SETTINGS_H_
+#define RTC_BASE_EXPERIMENTS_AUDIO_ALLOCATION_SETTINGS_H_
+
+#include "rtc_base/experiments/field_trial_parser.h"
+#include "rtc_base/experiments/field_trial_units.h"
+namespace webrtc {
+// This class encapsulates the logic that controls how allocation of audio
+// bitrate is done. This is primarily based on field trials, but also on the
+// values of audio parameters.
+class AudioAllocationSettings {
+ public:
+  AudioAllocationSettings();
+  ~AudioAllocationSettings();
+  // Returns true if audio feedback should be force disabled.
+  bool ForceNoAudioFeedback() const;
+  // Returns true if changes in transport sequence number id should be ignored
+  // as a trigger for reconfiguration.
+  bool IgnoreSeqNumIdChange() const;
+  // Returns true if the bitrate allocation range should be configured.
+  bool ConfigureRateAllocationRange() const;
+  // Returns true if sent audio packets should have transport wide sequence
+  // numbers.
+  // |transport_seq_num_extension_header_id| the extension header id for
+  // transport sequence numbers. Set to 0 if not the extension is not
+  // configured.
+  bool ShouldSendTransportSequenceNumber(
+      int transport_seq_num_extension_header_id) const;
+  // Returns true if target bitrate for audio streams should be updated.
+  // |transport_seq_num_extension_header_id| the extension header id for
+  // transport sequence numbers. Set to 0 if not the extension is not
+  // configured.
+  bool UpdateAudioTargetBitrate(
+      int transport_seq_num_extension_header_id) const;
+  // Returns true if audio should be added to rate allocation when the audio
+  // stream is started.
+  // |min_bitrate_bps| the configured min bitrate, set to -1 if unset.
+  // |max_bitrate_bps| the configured max bitrate, set to -1 if unset.
+  // |has_dscp| true is dscp is enabled.
+  // |transport_seq_num_extension_header_id| the extension header id for
+  // transport sequence numbers. Set to 0 if not the extension is not
+  // configured.
+  bool IncludeAudioInAllocationOnStart(
+      int min_bitrate_bps,
+      int max_bitrate_bps,
+      bool has_dscp,
+      int transport_seq_num_extension_header_id) const;
+  // Returns true if audio should be added to rate allocation when the audio
+  // stream is reconfigured.
+  // |min_bitrate_bps| the configured min bitrate, set to -1 if unset.
+  // |max_bitrate_bps| the configured max bitrate, set to -1 if unset.
+  // |has_dscp| true is dscp is enabled.
+  // |transport_seq_num_extension_header_id| the extension header id for
+  // transport sequence numbers. Set to 0 if not the extension is not
+  // configured.
+  bool IncludeAudioInAllocationOnReconfigure(
+      int min_bitrate_bps,
+      int max_bitrate_bps,
+      bool has_dscp,
+      int transport_seq_num_extension_header_id) const;
+
+  // Returns the min bitrate for audio rate allocation, potentially including
+  // overhead.
+  int MinBitrateBps() const;
+  // Returns the max bitrate for audio rate allocation, potentially including
+  // overhead. |rtp_parameter_max_bitrate_bps| max bitrate as configured in rtp
+  // parameters, excluding overhead.
+  int MaxBitrateBps(absl::optional<int> rtp_parameter_max_bitrate_bps) const;
+  // Indicates the default priority bitrate for audio streams. The bitrate
+  // allocator will prioritize audio until it reaches this bitrate and will
+  // divide bitrate evently between audio and video above this bitrate.
+  DataRate DefaultPriorityBitrate() const;
+
+ private:
+  FieldTrialFlag audio_send_side_bwe_;
+  FieldTrialFlag allocate_audio_without_feedback_;
+  FieldTrialFlag force_no_audio_feedback_;
+  FieldTrialFlag audio_feedback_to_improve_video_bwe_;
+  FieldTrialFlag send_side_bwe_with_overhead_;
+  int min_overhead_bps_ = 0;
+  // Default bitrates to use as range if there's no user configured
+  // bitrate range but audio bitrate allocation is enabled.
+  FieldTrialParameter<DataRate> default_min_bitrate_;
+  FieldTrialParameter<DataRate> default_max_bitrate_;
+  FieldTrialParameter<DataRate> priority_bitrate_;
+};
+}  // namespace webrtc
+
+#endif  // RTC_BASE_EXPERIMENTS_AUDIO_ALLOCATION_SETTINGS_H_
diff --git a/rtc_base/experiments/congestion_controller_experiment.cc b/rtc_base/experiments/congestion_controller_experiment.cc
deleted file mode 100644
index 2b7d776..0000000
--- a/rtc_base/experiments/congestion_controller_experiment.cc
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- *  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/congestion_controller_experiment.h"
-
-#include <string>
-
-#include "system_wrappers/include/field_trial.h"
-
-namespace webrtc {
-namespace {
-
-const char kControllerExperiment[] = "WebRTC-BweCongestionController";
-}  // namespace
-
-bool CongestionControllerExperiment::BbrControllerEnabled() {
-  std::string trial_string =
-      webrtc::field_trial::FindFullName(kControllerExperiment);
-  return trial_string.find("Enabled,BBR") == 0;
-}
-
-bool CongestionControllerExperiment::InjectedControllerEnabled() {
-  std::string trial_string =
-      webrtc::field_trial::FindFullName(kControllerExperiment);
-  return trial_string.find("Enabled,Injected") == 0;
-}
-}  // namespace webrtc
diff --git a/rtc_base/experiments/congestion_controller_experiment.h b/rtc_base/experiments/congestion_controller_experiment.h
deleted file mode 100644
index 1f2d8ae..0000000
--- a/rtc_base/experiments/congestion_controller_experiment.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- *  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_CONGESTION_CONTROLLER_EXPERIMENT_H_
-#define RTC_BASE_EXPERIMENTS_CONGESTION_CONTROLLER_EXPERIMENT_H_
-
-namespace webrtc {
-class CongestionControllerExperiment {
- public:
-  static bool BbrControllerEnabled();
-  static bool InjectedControllerEnabled();
-};
-
-}  // namespace webrtc
-
-#endif  // RTC_BASE_EXPERIMENTS_CONGESTION_CONTROLLER_EXPERIMENT_H_
diff --git a/rtc_base/experiments/congestion_controller_experiment_unittest.cc b/rtc_base/experiments/congestion_controller_experiment_unittest.cc
deleted file mode 100644
index 7f929e6..0000000
--- a/rtc_base/experiments/congestion_controller_experiment_unittest.cc
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- *  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/congestion_controller_experiment.h"
-#include "rtc_base/gunit.h"
-#include "test/field_trial.h"
-
-namespace webrtc {
-TEST(CongestionControllerExperimentTest, BbrDisabledByDefault) {
-  webrtc::test::ScopedFieldTrials field_trials("");
-  EXPECT_FALSE(CongestionControllerExperiment::BbrControllerEnabled());
-}
-
-TEST(CongestionControllerExperimentTest, BbrEnabledByFieldTrial) {
-  webrtc::test::ScopedFieldTrials field_trials(
-      "WebRTC-BweCongestionController/Enabled,BBR/");
-  EXPECT_TRUE(CongestionControllerExperiment::BbrControllerEnabled());
-}
-}  // namespace webrtc
diff --git a/rtc_base/experiments/cpu_speed_experiment.cc b/rtc_base/experiments/cpu_speed_experiment.cc
index f39540c..114c27f 100644
--- a/rtc_base/experiments/cpu_speed_experiment.cc
+++ b/rtc_base/experiments/cpu_speed_experiment.cc
@@ -10,6 +10,7 @@
 
 #include "rtc_base/experiments/cpu_speed_experiment.h"
 
+#include <stdio.h>
 #include <string>
 
 #include "rtc_base/logging.h"
diff --git a/rtc_base/experiments/field_trial_parser.cc b/rtc_base/experiments/field_trial_parser.cc
index 936487c..f823b48 100644
--- a/rtc_base/experiments/field_trial_parser.cc
+++ b/rtc_base/experiments/field_trial_parser.cc
@@ -41,9 +41,15 @@
     std::initializer_list<FieldTrialParameterInterface*> fields,
     std::string trial_string) {
   std::map<std::string, FieldTrialParameterInterface*> field_map;
+  FieldTrialParameterInterface* keyless_field = nullptr;
   for (FieldTrialParameterInterface* field : fields) {
     field->MarkAsUsed();
-    field_map[field->Key()] = field;
+    if (field->Key().empty()) {
+      RTC_DCHECK(!keyless_field);
+      keyless_field = field;
+    } else {
+      field_map[field->Key()] = field;
+    }
   }
   size_t i = 0;
   while (i < trial_string.length()) {
@@ -62,6 +68,11 @@
         RTC_LOG(LS_WARNING) << "Failed to read field with key: '" << key
                             << "' in trial: \"" << trial_string << "\"";
       }
+    } else if (!opt_value && keyless_field && !key.empty()) {
+      if (!keyless_field->Parse(key)) {
+        RTC_LOG(LS_WARNING) << "Failed to read empty key field with value '"
+                            << key << "' in trial: \"" << trial_string << "\"";
+      }
     } else {
       RTC_LOG(LS_INFO) << "No field with key: '" << key
                        << "' (found in trial: \"" << trial_string << "\")";
diff --git a/rtc_base/experiments/field_trial_parser.h b/rtc_base/experiments/field_trial_parser.h
index 8bdd9b5..0330f19 100644
--- a/rtc_base/experiments/field_trial_parser.h
+++ b/rtc_base/experiments/field_trial_parser.h
@@ -55,7 +55,7 @@
 };
 
 // ParseFieldTrial function parses the given string and fills the given fields
-// with extrated values if available.
+// with extracted values if available.
 void ParseFieldTrial(
     std::initializer_list<FieldTrialParameterInterface*> fields,
     std::string raw_string);
diff --git a/rtc_base/experiments/field_trial_parser_unittest.cc b/rtc_base/experiments/field_trial_parser_unittest.cc
index 0d067f5..806b895 100644
--- a/rtc_base/experiments/field_trial_parser_unittest.cc
+++ b/rtc_base/experiments/field_trial_parser_unittest.cc
@@ -112,6 +112,14 @@
   EXPECT_EQ(low.Get(), 20);
   EXPECT_EQ(high.Get(), 20);
 }
+TEST(FieldTrialParserTest, ReadsValuesFromFieldWithoutKey) {
+  FieldTrialFlag enabled("Enabled");
+  FieldTrialParameter<int> req("", 10);
+  ParseFieldTrial({&enabled, &req}, "Enabled,20");
+  EXPECT_EQ(req.Get(), 20);
+  ParseFieldTrial({&req}, "30");
+  EXPECT_EQ(req.Get(), 30);
+}
 TEST(FieldTrialParserTest, ParsesOptionalParameters) {
   FieldTrialOptional<int> max_count("c", absl::nullopt);
   ParseFieldTrial({&max_count}, "");
diff --git a/rtc_base/experiments/field_trial_units_unittest.cc b/rtc_base/experiments/field_trial_units_unittest.cc
index 57022c2..94cbdb8 100644
--- a/rtc_base/experiments/field_trial_units_unittest.cc
+++ b/rtc_base/experiments/field_trial_units_unittest.cc
@@ -9,9 +9,10 @@
  */
 #include <string>
 
+#include "absl/types/optional.h"
 #include "rtc_base/experiments/field_trial_parser.h"
 #include "rtc_base/experiments/field_trial_units.h"
-#include "rtc_base/gunit.h"
+#include "test/gtest.h"
 
 namespace webrtc {
 namespace {
diff --git a/rtc_base/experiments/jitter_upper_bound_experiment.cc b/rtc_base/experiments/jitter_upper_bound_experiment.cc
index b3e9230..84a17bf 100644
--- a/rtc_base/experiments/jitter_upper_bound_experiment.cc
+++ b/rtc_base/experiments/jitter_upper_bound_experiment.cc
@@ -10,7 +10,7 @@
 
 #include "rtc_base/experiments/jitter_upper_bound_experiment.h"
 
-#include <algorithm>
+#include <stdio.h>
 #include <string>
 
 #include "rtc_base/logging.h"
diff --git a/rtc_base/experiments/normalize_simulcast_size_experiment.cc b/rtc_base/experiments/normalize_simulcast_size_experiment.cc
index 9ce5f57..ddf0683 100644
--- a/rtc_base/experiments/normalize_simulcast_size_experiment.cc
+++ b/rtc_base/experiments/normalize_simulcast_size_experiment.cc
@@ -10,6 +10,7 @@
 
 #include "rtc_base/experiments/normalize_simulcast_size_experiment.h"
 
+#include <stdio.h>
 #include <string>
 
 #include "rtc_base/logging.h"
diff --git a/rtc_base/experiments/normalize_simulcast_size_experiment_unittest.cc b/rtc_base/experiments/normalize_simulcast_size_experiment_unittest.cc
index c37b809..34e0742 100644
--- a/rtc_base/experiments/normalize_simulcast_size_experiment_unittest.cc
+++ b/rtc_base/experiments/normalize_simulcast_size_experiment_unittest.cc
@@ -10,8 +10,8 @@
 
 #include "rtc_base/experiments/normalize_simulcast_size_experiment.h"
 
-#include "rtc_base/gunit.h"
 #include "test/field_trial.h"
+#include "test/gtest.h"
 
 namespace webrtc {
 
diff --git a/rtc_base/experiments/quality_scaling_experiment.cc b/rtc_base/experiments/quality_scaling_experiment.cc
index c13de3f..4a50115 100644
--- a/rtc_base/experiments/quality_scaling_experiment.cc
+++ b/rtc_base/experiments/quality_scaling_experiment.cc
@@ -9,6 +9,7 @@
  */
 #include "rtc_base/experiments/quality_scaling_experiment.h"
 
+#include <stdio.h>
 #include <string>
 
 #include "rtc_base/logging.h"
diff --git a/rtc_base/experiments/quality_scaling_experiment_unittest.cc b/rtc_base/experiments/quality_scaling_experiment_unittest.cc
index 15aadd6..7a345b6 100644
--- a/rtc_base/experiments/quality_scaling_experiment_unittest.cc
+++ b/rtc_base/experiments/quality_scaling_experiment_unittest.cc
@@ -10,8 +10,8 @@
 
 #include "rtc_base/experiments/quality_scaling_experiment.h"
 
-#include "rtc_base/gunit.h"
 #include "test/field_trial.h"
+#include "test/gtest.h"
 
 namespace webrtc {
 namespace {
diff --git a/rtc_base/experiments/rate_control_settings.cc b/rtc_base/experiments/rate_control_settings.cc
new file mode 100644
index 0000000..4e2d745
--- /dev/null
+++ b/rtc_base/experiments/rate_control_settings.cc
@@ -0,0 +1,219 @@
+/*
+ *  Copyright (c) 2019 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "rtc_base/experiments/rate_control_settings.h"
+
+#include <inttypes.h>
+#include <stdio.h>
+
+#include <string>
+
+#include "api/transport/field_trial_based_config.h"
+#include "rtc_base/logging.h"
+#include "rtc_base/numerics/safe_conversions.h"
+
+namespace webrtc {
+
+namespace {
+
+const char* kCongestionWindowFieldTrialName = "WebRTC-CwndExperiment";
+const int kDefaultAcceptedQueueMs = 250;
+
+const char* kCongestionWindowPushbackFieldTrialName =
+    "WebRTC-CongestionWindowPushback";
+const int kDefaultMinPushbackTargetBitrateBps = 30000;
+
+const char kVp8TrustedRateControllerFieldTrialName[] =
+    "WebRTC-LibvpxVp8TrustedRateController";
+const char kVp9TrustedRateControllerFieldTrialName[] =
+    "WebRTC-LibvpxVp9TrustedRateController";
+
+const char* kVideoHysteresisFieldTrialname =
+    "WebRTC-SimulcastUpswitchHysteresisPercent";
+const double kDefaultVideoHysteresisFactor = 1.0;
+const char* kScreenshareHysteresisFieldTrialname =
+    "WebRTC-SimulcastScreenshareUpswitchHysteresisPercent";
+// Default to 35% hysteresis for simulcast screenshare.
+const double kDefaultScreenshareHysteresisFactor = 1.35;
+
+absl::optional<int> MaybeReadCwndExperimentParameter(
+    const WebRtcKeyValueConfig* const key_value_config) {
+  int64_t accepted_queue_ms;
+  std::string experiment_string =
+      key_value_config->Lookup(kCongestionWindowFieldTrialName);
+  int parsed_values =
+      sscanf(experiment_string.c_str(), "Enabled-%" PRId64, &accepted_queue_ms);
+  if (parsed_values == 1) {
+    RTC_CHECK_GE(accepted_queue_ms, 0)
+        << "Accepted must be greater than or equal to 0.";
+    return rtc::checked_cast<int>(accepted_queue_ms);
+  } else if (experiment_string.find("Enabled") == 0) {
+    return kDefaultAcceptedQueueMs;
+  }
+  return absl::nullopt;
+}
+
+absl::optional<int> MaybeReadCongestionWindowPushbackExperimentParameter(
+    const WebRtcKeyValueConfig* const key_value_config) {
+  uint32_t min_pushback_target_bitrate_bps;
+  std::string experiment_string =
+      key_value_config->Lookup(kCongestionWindowPushbackFieldTrialName);
+  int parsed_values = sscanf(experiment_string.c_str(), "Enabled-%" PRIu32,
+                             &min_pushback_target_bitrate_bps);
+  if (parsed_values == 1) {
+    RTC_CHECK_GE(min_pushback_target_bitrate_bps, 0)
+        << "Min pushback target bitrate must be greater than or equal to 0.";
+    return rtc::checked_cast<int>(min_pushback_target_bitrate_bps);
+  } else if (experiment_string.find("Enabled") == 0) {
+    return kDefaultMinPushbackTargetBitrateBps;
+  }
+  return absl::nullopt;
+}
+
+bool IsEnabled(const WebRtcKeyValueConfig* const key_value_config,
+               absl::string_view key) {
+  return key_value_config->Lookup(key).find("Enabled") == 0;
+}
+
+double ParseHysteresisFactor(const WebRtcKeyValueConfig* const key_value_config,
+                             absl::string_view key,
+                             double default_value) {
+  std::string group_name = key_value_config->Lookup(key);
+  int percent = 0;
+  if (!group_name.empty() && sscanf(group_name.c_str(), "%d", &percent) == 1 &&
+      percent >= 0) {
+    return 1.0 + (percent / 100.0);
+  }
+  return default_value;
+}
+
+}  // namespace
+
+RateControlSettings::RateControlSettings(
+    const WebRtcKeyValueConfig* const key_value_config)
+    : congestion_window_("cwnd",
+                         MaybeReadCwndExperimentParameter(key_value_config)),
+      congestion_window_pushback_(
+          "cwnd_pushback",
+          MaybeReadCongestionWindowPushbackExperimentParameter(
+              key_value_config)),
+      pacing_factor_("pacing_factor"),
+      alr_probing_("alr_probing", false),
+      trust_vp8_(
+          "trust_vp8",
+          IsEnabled(key_value_config, kVp8TrustedRateControllerFieldTrialName)),
+      trust_vp9_(
+          "trust_vp9",
+          IsEnabled(key_value_config, kVp9TrustedRateControllerFieldTrialName)),
+      video_hysteresis_("video_hysteresis",
+                        ParseHysteresisFactor(key_value_config,
+                                              kVideoHysteresisFieldTrialname,
+                                              kDefaultVideoHysteresisFactor)),
+      screenshare_hysteresis_(
+          "screenshare_hysteresis",
+          ParseHysteresisFactor(key_value_config,
+                                kScreenshareHysteresisFieldTrialname,
+                                kDefaultScreenshareHysteresisFactor)),
+      probe_max_allocation_("probe_max_allocation", true),
+      bitrate_adjuster_("bitrate_adjuster", false),
+      vp8_s0_boost_("vp8_s0_boost", true) {
+  ParseFieldTrial({&congestion_window_, &congestion_window_pushback_,
+                   &pacing_factor_, &alr_probing_, &trust_vp8_, &trust_vp9_,
+                   &video_hysteresis_, &screenshare_hysteresis_,
+                   &probe_max_allocation_, &bitrate_adjuster_, &vp8_s0_boost_},
+                  key_value_config->Lookup("WebRTC-VideoRateControl"));
+}
+
+RateControlSettings::~RateControlSettings() = default;
+RateControlSettings::RateControlSettings(RateControlSettings&&) = default;
+
+RateControlSettings RateControlSettings::ParseFromFieldTrials() {
+  FieldTrialBasedConfig field_trial_config;
+  return RateControlSettings(&field_trial_config);
+}
+
+RateControlSettings RateControlSettings::ParseFromKeyValueConfig(
+    const WebRtcKeyValueConfig* const key_value_config) {
+  FieldTrialBasedConfig field_trial_config;
+  return RateControlSettings(key_value_config ? key_value_config
+                                              : &field_trial_config);
+}
+
+bool RateControlSettings::UseCongestionWindow() const {
+  return congestion_window_;
+}
+
+int64_t RateControlSettings::GetCongestionWindowAdditionalTimeMs() const {
+  return congestion_window_.GetOptional().value_or(kDefaultAcceptedQueueMs);
+}
+
+bool RateControlSettings::UseCongestionWindowPushback() const {
+  return congestion_window_ && congestion_window_pushback_;
+}
+
+uint32_t RateControlSettings::CongestionWindowMinPushbackTargetBitrateBps()
+    const {
+  return congestion_window_pushback_.GetOptional().value_or(
+      kDefaultMinPushbackTargetBitrateBps);
+}
+
+absl::optional<double> RateControlSettings::GetPacingFactor() const {
+  return pacing_factor_.GetOptional();
+}
+
+bool RateControlSettings::UseAlrProbing() const {
+  return alr_probing_.Get();
+}
+
+bool RateControlSettings::LibvpxVp8TrustedRateController() const {
+  return trust_vp8_.Get();
+}
+
+bool RateControlSettings::Vp8BoostBaseLayerQuality() const {
+  return vp8_s0_boost_.Get();
+}
+
+bool RateControlSettings::LibvpxVp9TrustedRateController() const {
+  return trust_vp9_.Get();
+}
+
+double RateControlSettings::GetSimulcastHysteresisFactor(
+    VideoCodecMode mode) const {
+  if (mode == VideoCodecMode::kScreensharing) {
+    return GetSimulcastScreenshareHysteresisFactor();
+  }
+  return GetSimulcastVideoHysteresisFactor();
+}
+
+double RateControlSettings::GetSimulcastHysteresisFactor(
+    VideoEncoderConfig::ContentType content_type) const {
+  if (content_type == VideoEncoderConfig::ContentType::kScreen) {
+    return GetSimulcastScreenshareHysteresisFactor();
+  }
+  return GetSimulcastVideoHysteresisFactor();
+}
+
+double RateControlSettings::GetSimulcastVideoHysteresisFactor() const {
+  return video_hysteresis_.Get();
+}
+
+double RateControlSettings::GetSimulcastScreenshareHysteresisFactor() const {
+  return screenshare_hysteresis_.Get();
+}
+
+bool RateControlSettings::TriggerProbeOnMaxAllocatedBitrateChange() const {
+  return probe_max_allocation_.Get();
+}
+
+bool RateControlSettings::UseEncoderBitrateAdjuster() const {
+  return bitrate_adjuster_.Get();
+}
+
+}  // namespace webrtc
diff --git a/rtc_base/experiments/rate_control_settings.h b/rtc_base/experiments/rate_control_settings.h
new file mode 100644
index 0000000..0898f9b
--- /dev/null
+++ b/rtc_base/experiments/rate_control_settings.h
@@ -0,0 +1,78 @@
+/*
+ *  Copyright (c) 2019 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef RTC_BASE_EXPERIMENTS_RATE_CONTROL_SETTINGS_H_
+#define RTC_BASE_EXPERIMENTS_RATE_CONTROL_SETTINGS_H_
+
+#include "absl/types/optional.h"
+#include "api/transport/webrtc_key_value_config.h"
+#include "api/video_codecs/video_codec.h"
+#include "api/video_codecs/video_encoder_config.h"
+#include "rtc_base/experiments/field_trial_parser.h"
+#include "rtc_base/experiments/field_trial_units.h"
+
+namespace webrtc {
+
+class RateControlSettings final {
+ public:
+  ~RateControlSettings();
+  RateControlSettings(RateControlSettings&&);
+
+  static RateControlSettings ParseFromFieldTrials();
+  static RateControlSettings ParseFromKeyValueConfig(
+      const WebRtcKeyValueConfig* const key_value_config);
+
+  // When CongestionWindowPushback is enabled, the pacer is oblivious to
+  // the congestion window. The relation between outstanding data and
+  // the congestion window affects encoder allocations directly.
+  bool UseCongestionWindow() const;
+  int64_t GetCongestionWindowAdditionalTimeMs() const;
+  bool UseCongestionWindowPushback() const;
+  uint32_t CongestionWindowMinPushbackTargetBitrateBps() const;
+
+  absl::optional<double> GetPacingFactor() const;
+  bool UseAlrProbing() const;
+
+  bool LibvpxVp8TrustedRateController() const;
+  bool Vp8BoostBaseLayerQuality() const;
+  bool LibvpxVp9TrustedRateController() const;
+
+  // TODO(bugs.webrtc.org/10272): Remove one of these when we have merged
+  // VideoCodecMode and VideoEncoderConfig::ContentType.
+  double GetSimulcastHysteresisFactor(VideoCodecMode mode) const;
+  double GetSimulcastHysteresisFactor(
+      VideoEncoderConfig::ContentType content_type) const;
+
+  bool TriggerProbeOnMaxAllocatedBitrateChange() const;
+  bool UseEncoderBitrateAdjuster() const;
+
+ private:
+  explicit RateControlSettings(
+      const WebRtcKeyValueConfig* const key_value_config);
+
+  double GetSimulcastVideoHysteresisFactor() const;
+  double GetSimulcastScreenshareHysteresisFactor() const;
+
+  FieldTrialOptional<int> congestion_window_;
+  FieldTrialOptional<int> congestion_window_pushback_;
+  FieldTrialOptional<double> pacing_factor_;
+  FieldTrialParameter<bool> alr_probing_;
+  FieldTrialParameter<bool> trust_vp8_;
+  FieldTrialParameter<bool> trust_vp9_;
+  FieldTrialParameter<double> video_hysteresis_;
+  FieldTrialParameter<double> screenshare_hysteresis_;
+  FieldTrialParameter<bool> probe_max_allocation_;
+  FieldTrialParameter<bool> bitrate_adjuster_;
+  FieldTrialParameter<bool> vp8_s0_boost_;
+};
+
+}  // namespace webrtc
+
+#endif  // RTC_BASE_EXPERIMENTS_RATE_CONTROL_SETTINGS_H_
diff --git a/rtc_base/experiments/rate_control_settings_unittest.cc b/rtc_base/experiments/rate_control_settings_unittest.cc
new file mode 100644
index 0000000..0d8c376
--- /dev/null
+++ b/rtc_base/experiments/rate_control_settings_unittest.cc
@@ -0,0 +1,143 @@
+/*
+ *  Copyright 2019 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "rtc_base/experiments/rate_control_settings.h"
+
+#include "api/video_codecs/video_codec.h"
+#include "api/video_codecs/video_encoder_config.h"
+#include "test/field_trial.h"
+#include "test/gtest.h"
+
+namespace webrtc {
+
+namespace {
+
+TEST(RateControlSettingsTest, CongestionWindow) {
+  EXPECT_FALSE(
+      RateControlSettings::ParseFromFieldTrials().UseCongestionWindow());
+
+  test::ScopedFieldTrials field_trials("WebRTC-VideoRateControl/cwnd:100/");
+  const RateControlSettings settings_after =
+      RateControlSettings::ParseFromFieldTrials();
+  EXPECT_TRUE(settings_after.UseCongestionWindow());
+  EXPECT_EQ(settings_after.GetCongestionWindowAdditionalTimeMs(), 100);
+}
+
+TEST(RateControlSettingsTest, CongestionWindowPushback) {
+  EXPECT_FALSE(RateControlSettings::ParseFromFieldTrials()
+                   .UseCongestionWindowPushback());
+
+  test::ScopedFieldTrials field_trials(
+      "WebRTC-VideoRateControl/cwnd:100,cwnd_pushback:100000/");
+  const RateControlSettings settings_after =
+      RateControlSettings::ParseFromFieldTrials();
+  EXPECT_TRUE(settings_after.UseCongestionWindowPushback());
+  EXPECT_EQ(settings_after.CongestionWindowMinPushbackTargetBitrateBps(),
+            100000u);
+}
+
+TEST(RateControlSettingsTest, PacingFactor) {
+  EXPECT_FALSE(RateControlSettings::ParseFromFieldTrials().GetPacingFactor());
+
+  test::ScopedFieldTrials field_trials(
+      "WebRTC-VideoRateControl/pacing_factor:1.2/");
+  const RateControlSettings settings_after =
+      RateControlSettings::ParseFromFieldTrials();
+  // Need to explicitly dereference the absl::optional
+  // for the EXPECT_DOUBLE_EQ to compile.
+  ASSERT_TRUE(settings_after.GetPacingFactor());
+  EXPECT_DOUBLE_EQ(*settings_after.GetPacingFactor(), 1.2);
+}
+
+TEST(RateControlSettingsTest, AlrProbing) {
+  EXPECT_FALSE(RateControlSettings::ParseFromFieldTrials().UseAlrProbing());
+
+  test::ScopedFieldTrials field_trials(
+      "WebRTC-VideoRateControl/alr_probing:1/");
+  EXPECT_TRUE(RateControlSettings::ParseFromFieldTrials().UseAlrProbing());
+}
+
+TEST(RateControlSettingsTest, LibvpxTrustedRateController) {
+  const RateControlSettings settings_before =
+      RateControlSettings::ParseFromFieldTrials();
+  EXPECT_FALSE(settings_before.LibvpxVp8TrustedRateController());
+  EXPECT_FALSE(settings_before.LibvpxVp9TrustedRateController());
+
+  test::ScopedFieldTrials field_trials(
+      "WebRTC-VideoRateControl/trust_vp8:1,trust_vp9:1/");
+  const RateControlSettings settings_after =
+      RateControlSettings::ParseFromFieldTrials();
+  EXPECT_TRUE(settings_after.LibvpxVp8TrustedRateController());
+  EXPECT_TRUE(settings_after.LibvpxVp9TrustedRateController());
+}
+
+TEST(RateControlSettingsTest, GetSimulcastHysteresisFactor) {
+  const RateControlSettings settings_before =
+      RateControlSettings::ParseFromFieldTrials();
+  EXPECT_DOUBLE_EQ(settings_before.GetSimulcastHysteresisFactor(
+                       VideoCodecMode::kRealtimeVideo),
+                   1.0);
+  EXPECT_DOUBLE_EQ(settings_before.GetSimulcastHysteresisFactor(
+                       VideoEncoderConfig::ContentType::kRealtimeVideo),
+                   1.0);
+  EXPECT_DOUBLE_EQ(settings_before.GetSimulcastHysteresisFactor(
+                       VideoCodecMode::kScreensharing),
+                   1.35);
+  EXPECT_DOUBLE_EQ(settings_before.GetSimulcastHysteresisFactor(
+                       VideoEncoderConfig::ContentType::kScreen),
+                   1.35);
+
+  test::ScopedFieldTrials field_trials(
+      "WebRTC-VideoRateControl/"
+      "video_hysteresis:1.2,screenshare_hysteresis:1.4/");
+  const RateControlSettings settings_after =
+      RateControlSettings::ParseFromFieldTrials();
+
+  EXPECT_DOUBLE_EQ(settings_after.GetSimulcastHysteresisFactor(
+                       VideoCodecMode::kRealtimeVideo),
+                   1.2);
+  EXPECT_DOUBLE_EQ(settings_after.GetSimulcastHysteresisFactor(
+                       VideoEncoderConfig::ContentType::kRealtimeVideo),
+                   1.2);
+  EXPECT_DOUBLE_EQ(settings_after.GetSimulcastHysteresisFactor(
+                       VideoCodecMode::kScreensharing),
+                   1.4);
+  EXPECT_DOUBLE_EQ(settings_after.GetSimulcastHysteresisFactor(
+                       VideoEncoderConfig::ContentType::kScreen),
+                   1.4);
+}
+
+TEST(RateControlSettingsTest, TriggerProbeOnMaxAllocatedBitrateChange) {
+  EXPECT_TRUE(RateControlSettings::ParseFromFieldTrials()
+                  .TriggerProbeOnMaxAllocatedBitrateChange());
+
+  test::ScopedFieldTrials field_trials(
+      "WebRTC-VideoRateControl/probe_max_allocation:0/");
+  EXPECT_FALSE(RateControlSettings::ParseFromFieldTrials()
+                   .TriggerProbeOnMaxAllocatedBitrateChange());
+}
+
+TEST(RateControlSettingsTest, UseEncoderBitrateAdjuster) {
+  // Should be off by default.
+  EXPECT_FALSE(
+      RateControlSettings::ParseFromFieldTrials().UseEncoderBitrateAdjuster());
+
+  {
+    // Can be turned on via field trial.
+    test::ScopedFieldTrials field_trials(
+        "WebRTC-VideoRateControl/bitrate_adjuster:true/");
+    EXPECT_TRUE(RateControlSettings::ParseFromFieldTrials()
+                    .UseEncoderBitrateAdjuster());
+  }
+}
+
+}  // namespace
+
+}  // namespace webrtc
diff --git a/rtc_base/experiments/rtt_mult_experiment.cc b/rtc_base/experiments/rtt_mult_experiment.cc
index f8f7f2a..beb577c 100644
--- a/rtc_base/experiments/rtt_mult_experiment.cc
+++ b/rtc_base/experiments/rtt_mult_experiment.cc
@@ -9,6 +9,7 @@
  */
 #include "rtc_base/experiments/rtt_mult_experiment.h"
 
+#include <stdio.h>
 #include <algorithm>
 #include <string>
 
diff --git a/rtc_base/experiments/rtt_mult_experiment_unittest.cc b/rtc_base/experiments/rtt_mult_experiment_unittest.cc
index 0cd86d1..9442cea 100644
--- a/rtc_base/experiments/rtt_mult_experiment_unittest.cc
+++ b/rtc_base/experiments/rtt_mult_experiment_unittest.cc
@@ -9,8 +9,9 @@
  */
 
 #include "rtc_base/experiments/rtt_mult_experiment.h"
-#include "rtc_base/gunit.h"
+
 #include "test/field_trial.h"
+#include "test/gtest.h"
 
 namespace webrtc {
 
diff --git a/rtc_base/fakeclock.cc b/rtc_base/fake_clock.cc
similarity index 94%
rename from rtc_base/fakeclock.cc
rename to rtc_base/fake_clock.cc
index f63b85c..6b7d96b 100644
--- a/rtc_base/fakeclock.cc
+++ b/rtc_base/fake_clock.cc
@@ -8,10 +8,10 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#include "rtc_base/fakeclock.h"
+#include "rtc_base/fake_clock.h"
 
 #include "rtc_base/checks.h"
-#include "rtc_base/messagequeue.h"
+#include "rtc_base/message_queue.h"
 
 namespace rtc {
 
diff --git a/rtc_base/fakeclock.h b/rtc_base/fake_clock.h
similarity index 87%
rename from rtc_base/fakeclock.h
rename to rtc_base/fake_clock.h
index 2da8c61..5ccf370 100644
--- a/rtc_base/fakeclock.h
+++ b/rtc_base/fake_clock.h
@@ -8,12 +8,15 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#ifndef RTC_BASE_FAKECLOCK_H_
-#define RTC_BASE_FAKECLOCK_H_
+#ifndef RTC_BASE_FAKE_CLOCK_H_
+#define RTC_BASE_FAKE_CLOCK_H_
+
+#include <stdint.h>
 
 #include "api/units/time_delta.h"
-#include "rtc_base/criticalsection.h"
-#include "rtc_base/timeutils.h"
+#include "rtc_base/critical_section.h"
+#include "rtc_base/thread_annotations.h"
+#include "rtc_base/time_utils.h"
 
 namespace rtc {
 
@@ -69,4 +72,4 @@
 
 }  // namespace rtc
 
-#endif  // RTC_BASE_FAKECLOCK_H_
+#endif  // RTC_BASE_FAKE_CLOCK_H_
diff --git a/rtc_base/fake_mdns_responder.h b/rtc_base/fake_mdns_responder.h
index 1e60a5d..4290876 100644
--- a/rtc_base/fake_mdns_responder.h
+++ b/rtc_base/fake_mdns_responder.h
@@ -15,9 +15,11 @@
 #include <memory>
 #include <string>
 
+#include "rtc_base/async_invoker.h"
+#include "rtc_base/ip_address.h"
+#include "rtc_base/location.h"
 #include "rtc_base/mdns_responder_interface.h"
-
-#include "rtc_base/helpers.h"
+#include "rtc_base/thread.h"
 
 namespace webrtc {
 
@@ -50,6 +52,15 @@
                                [callback, result]() { callback(result); });
   }
 
+  rtc::IPAddress GetMappedAddressForName(const std::string& name) const {
+    for (const auto& addr_name_pair : addr_name_map_) {
+      if (addr_name_pair.second == name) {
+        return addr_name_pair.first;
+      }
+    }
+    return rtc::IPAddress();
+  }
+
  private:
   uint32_t next_available_id_ = 0;
   std::map<rtc::IPAddress, std::string> addr_name_map_;
diff --git a/rtc_base/fakenetwork.h b/rtc_base/fake_network.h
similarity index 85%
rename from rtc_base/fakenetwork.h
rename to rtc_base/fake_network.h
index cb890ec..1da9814 100644
--- a/rtc_base/fakenetwork.h
+++ b/rtc_base/fake_network.h
@@ -8,8 +8,8 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#ifndef RTC_BASE_FAKENETWORK_H_
-#define RTC_BASE_FAKENETWORK_H_
+#ifndef RTC_BASE_FAKE_NETWORK_H_
+#define RTC_BASE_FAKE_NETWORK_H_
 
 #include <memory>
 #include <string>
@@ -19,10 +19,10 @@
 #include "absl/memory/memory.h"
 #include "rtc_base/checks.h"
 #include "rtc_base/fake_mdns_responder.h"
-#include "rtc_base/messagehandler.h"
+#include "rtc_base/message_handler.h"
 #include "rtc_base/network.h"
-#include "rtc_base/socketaddress.h"
-#include "rtc_base/stringencode.h"
+#include "rtc_base/socket_address.h"
+#include "rtc_base/string_encode.h"
 #include "rtc_base/thread.h"
 
 namespace rtc {
@@ -65,7 +65,7 @@
     DoUpdateNetworks();
   }
 
-  virtual void StartUpdating() {
+  void StartUpdating() override {
     ++start_count_;
     if (start_count_ == 1) {
       sent_first_update_ = false;
@@ -77,25 +77,30 @@
     }
   }
 
-  virtual void StopUpdating() { --start_count_; }
+  void StopUpdating() override { --start_count_; }
 
   // MessageHandler interface.
-  virtual void OnMessage(Message* msg) { DoUpdateNetworks(); }
+  void OnMessage(Message* msg) override { DoUpdateNetworks(); }
 
-  void CreateMdnsResponder() {
+  void CreateMdnsResponder(rtc::Thread* network_thread) {
     if (mdns_responder_ == nullptr) {
       mdns_responder_ =
-          absl::make_unique<webrtc::FakeMdnsResponder>(rtc::Thread::Current());
+          absl::make_unique<webrtc::FakeMdnsResponder>(network_thread);
     }
   }
 
   using NetworkManagerBase::set_enumeration_permission;
   using NetworkManagerBase::set_default_local_addresses;
 
+  // rtc::NetworkManager override.
   webrtc::MdnsResponderInterface* GetMdnsResponder() const override {
     return mdns_responder_.get();
   }
 
+  webrtc::FakeMdnsResponder* GetMdnsResponderForTesting() const {
+    return mdns_responder_.get();
+  }
+
  private:
   void DoUpdateNetworks() {
     if (start_count_ == 0)
@@ -129,12 +134,9 @@
   int start_count_ = 0;
   bool sent_first_update_ = false;
 
-  IPAddress default_local_ipv4_address_;
-  IPAddress default_local_ipv6_address_;
-
   std::unique_ptr<webrtc::FakeMdnsResponder> mdns_responder_;
 };
 
 }  // namespace rtc
 
-#endif  // RTC_BASE_FAKENETWORK_H_
+#endif  // RTC_BASE_FAKE_NETWORK_H_
diff --git a/rtc_base/fakesslidentity.cc b/rtc_base/fake_ssl_identity.cc
similarity index 96%
rename from rtc_base/fakesslidentity.cc
rename to rtc_base/fake_ssl_identity.cc
index 62ac9dd..480922c 100644
--- a/rtc_base/fakesslidentity.cc
+++ b/rtc_base/fake_ssl_identity.cc
@@ -8,15 +8,14 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#include "rtc_base/fakesslidentity.h"
+#include "rtc_base/fake_ssl_identity.h"
 
-#include <algorithm>
 #include <string>
 #include <utility>
 
 #include "absl/memory/memory.h"
 #include "rtc_base/checks.h"
-#include "rtc_base/messagedigest.h"
+#include "rtc_base/message_digest.h"
 
 namespace rtc {
 
@@ -76,6 +75,7 @@
 
 FakeSSLIdentity::FakeSSLIdentity(const std::vector<std::string>& pem_strings) {
   std::vector<std::unique_ptr<SSLCertificate>> certs;
+  certs.reserve(pem_strings.size());
   for (const std::string& pem_string : pem_strings) {
     certs.push_back(absl::make_unique<FakeSSLCertificate>(pem_string));
   }
diff --git a/rtc_base/fakesslidentity.h b/rtc_base/fake_ssl_identity.h
similarity index 92%
rename from rtc_base/fakesslidentity.h
rename to rtc_base/fake_ssl_identity.h
index b19cbfb..c3a8d1f 100644
--- a/rtc_base/fakesslidentity.h
+++ b/rtc_base/fake_ssl_identity.h
@@ -8,14 +8,14 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#ifndef RTC_BASE_FAKESSLIDENTITY_H_
-#define RTC_BASE_FAKESSLIDENTITY_H_
+#ifndef RTC_BASE_FAKE_SSL_IDENTITY_H_
+#define RTC_BASE_FAKE_SSL_IDENTITY_H_
 
 #include <memory>
 #include <vector>
 
-#include "rtc_base/sslcertificate.h"
-#include "rtc_base/sslidentity.h"
+#include "rtc_base/ssl_certificate.h"
+#include "rtc_base/ssl_identity.h"
 
 namespace rtc {
 
@@ -78,4 +78,4 @@
 
 }  // namespace rtc
 
-#endif  // RTC_BASE_FAKESSLIDENTITY_H_
+#endif  // RTC_BASE_FAKE_SSL_IDENTITY_H_
diff --git a/rtc_base/file.cc b/rtc_base/file.cc
deleted file mode 100644
index a793500..0000000
--- a/rtc_base/file.cc
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- *  Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
- *
- *  Use of this source code is governed by a BSD-style license
- *  that can be found in the LICENSE file in the root of the source
- *  tree. An additional intellectual property rights grant can be found
- *  in the file PATENTS.  All contributing project authors may
- *  be found in the AUTHORS file in the root of the source tree.
- */
-
-#include "rtc_base/file.h"
-
-namespace rtc {
-
-File::File(PlatformFile file) : file_(file) {}
-
-File::File() : file_(kInvalidPlatformFileValue) {}
-
-File::~File() {
-  Close();
-}
-
-// static
-File File::Open(const std::string& path) {
-  return File(OpenPlatformFile(path));
-}
-
-// static
-File File::Create(const std::string& path) {
-  return File(CreatePlatformFile(path));
-}
-
-// static
-bool File::Remove(const std::string& path) {
-  return RemoveFile(path);
-}
-
-File::File(File&& other) : file_(other.file_) {
-  other.file_ = kInvalidPlatformFileValue;
-}
-
-File& File::operator=(File&& other) {
-  Close();
-  file_ = other.file_;
-  other.file_ = kInvalidPlatformFileValue;
-  return *this;
-}
-
-bool File::IsOpen() {
-  return file_ != kInvalidPlatformFileValue;
-}
-
-}  // namespace rtc
diff --git a/rtc_base/file.h b/rtc_base/file.h
deleted file mode 100644
index bc0974a..0000000
--- a/rtc_base/file.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- *  Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
- *
- *  Use of this source code is governed by a BSD-style license
- *  that can be found in the LICENSE file in the root of the source
- *  tree. An additional intellectual property rights grant can be found
- *  in the file PATENTS.  All contributing project authors may
- *  be found in the AUTHORS file in the root of the source tree.
- */
-
-#ifndef RTC_BASE_FILE_H_
-#define RTC_BASE_FILE_H_
-
-#include <stddef.h>
-#include <stdint.h>
-#include <string>
-
-#include "rtc_base/constructormagic.h"
-#include "rtc_base/platform_file.h"
-
-namespace rtc {
-
-// This class wraps the platform specific APIs for simple file interactions.
-//
-// The various read and write methods are best effort, i.e. if an underlying
-// call does not manage to read/write all the data more calls will be performed,
-// until an error is detected or all data is read/written.
-class File {
- public:
-  // Wraps the given PlatformFile. This class is then responsible for closing
-  // the file, which will be done in the destructor if Close is never called.
-  explicit File(PlatformFile);
-  // The default constructor produces a closed file.
-  File();
-  ~File();
-
-  File(File&& other);
-  File& operator=(File&& other);
-
-  // Open and Create give files with both reading and writing enabled.
-  static File Open(const std::string& path);
-  // If the file already exists it will be overwritten.
-  static File Create(const std::string& path);
-
-  // Remove a file in the file system.
-  static bool Remove(const std::string& path);
-
-  size_t Write(const uint8_t* data, size_t length);
-  size_t Read(uint8_t* buffer, size_t length);
-
-  // The current position in the file after a call to these methods is platform
-  // dependent (MSVC gives position offset+length, most other
-  // compilers/platforms do not alter the position), i.e. do not depend on it,
-  // do a Seek before any subsequent Read/Write.
-  size_t WriteAt(const uint8_t* data, size_t length, size_t offset);
-  size_t ReadAt(uint8_t* buffer, size_t length, size_t offset);
-
-  // Attempt to position the file at the given offset from the start.
-  // Returns true if successful, false otherwise.
-  bool Seek(size_t offset);
-
-  // Attempt to close the file. Returns true if successful, false otherwise,
-  // most notably when the file is already closed.
-  bool Close();
-
-  bool IsOpen();
-
- private:
-  PlatformFile file_;
-  RTC_DISALLOW_COPY_AND_ASSIGN(File);
-};
-
-}  // namespace rtc
-
-#endif  // RTC_BASE_FILE_H_
diff --git a/rtc_base/file_posix.cc b/rtc_base/file_posix.cc
deleted file mode 100644
index 4920192..0000000
--- a/rtc_base/file_posix.cc
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- *  Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
- *
- *  Use of this source code is governed by a BSD-style license
- *  that can be found in the LICENSE file in the root of the source
- *  tree. An additional intellectual property rights grant can be found
- *  in the file PATENTS.  All contributing project authors may
- *  be found in the AUTHORS file in the root of the source tree.
- */
-
-#include <errno.h>
-#include <fcntl.h>
-#include <stddef.h>
-#include <stdint.h>
-#include <unistd.h>
-#include <limits>
-
-#include "rtc_base/checks.h"
-#include "rtc_base/file.h"
-#include "rtc_base/platform_file.h"
-
-namespace rtc {
-
-size_t File::Write(const uint8_t* data, size_t length) {
-  size_t total_written = 0;
-  do {
-    ssize_t written;
-    do {
-      written = ::write(file_, data + total_written, length - total_written);
-    } while (written == -1 && errno == EINTR);
-    if (written == -1)
-      break;
-    total_written += written;
-  } while (total_written < length);
-  return total_written;
-}
-
-size_t File::Read(uint8_t* buffer, size_t length) {
-  size_t total_read = 0;
-  do {
-    ssize_t read;
-    do {
-      read = ::read(file_, buffer + total_read, length - total_read);
-    } while (read == -1 && errno == EINTR);
-    if (read == -1)
-      break;
-    total_read += read;
-  } while (total_read < length);
-  return total_read;
-}
-
-size_t File::WriteAt(const uint8_t* data, size_t length, size_t offset) {
-  size_t total_written = 0;
-  do {
-    ssize_t written;
-    do {
-      written = ::pwrite(file_, data + total_written, length - total_written,
-                         offset + total_written);
-    } while (written == -1 && errno == EINTR);
-    if (written == -1)
-      break;
-    total_written += written;
-  } while (total_written < length);
-  return total_written;
-}
-
-size_t File::ReadAt(uint8_t* buffer, size_t length, size_t offset) {
-  size_t total_read = 0;
-  do {
-    ssize_t read;
-    do {
-      read = ::pread(file_, buffer + total_read, length - total_read,
-                     offset + total_read);
-    } while (read == -1 && errno == EINTR);
-    if (read == -1)
-      break;
-    total_read += read;
-  } while (total_read < length);
-  return total_read;
-}
-
-bool File::Seek(size_t offset) {
-  RTC_DCHECK_LE(offset, std::numeric_limits<off_t>::max());
-  return lseek(file_, static_cast<off_t>(offset), SEEK_SET) != -1;
-}
-
-bool File::Close() {
-  if (file_ == rtc::kInvalidPlatformFileValue)
-    return false;
-  bool ret = close(file_) == 0;
-  file_ = rtc::kInvalidPlatformFileValue;
-  return ret;
-}
-
-}  // namespace rtc
diff --git a/rtc_base/filerotatingstream.cc b/rtc_base/file_rotating_stream.cc
similarity index 67%
rename from rtc_base/filerotatingstream.cc
rename to rtc_base/file_rotating_stream.cc
index b1dc5ff..86b852f 100644
--- a/rtc_base/filerotatingstream.cc
+++ b/rtc_base/file_rotating_stream.cc
@@ -8,7 +8,7 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#include "rtc_base/filerotatingstream.h"
+#include "rtc_base/file_rotating_stream.h"
 
 #include <algorithm>
 #include <cstdio>
@@ -17,7 +17,7 @@
 
 #if defined(WEBRTC_WIN)
 #include <windows.h>
-#include "rtc_base/stringutils.h"
+#include "rtc_base/string_utils.h"
 #else
 #include <dirent.h>
 #include <sys/stat.h>
@@ -25,6 +25,7 @@
 #endif  // WEBRTC_WIN
 
 #include "absl/strings/match.h"
+#include "absl/types/optional.h"
 #include "rtc_base/checks.h"
 #include "rtc_base/logging.h"
 
@@ -35,6 +36,8 @@
 
 namespace {
 
+const char kCallSessionLogPrefix[] = "webrtc_log";
+
 std::string AddTrailingPathDelimiterIfNeeded(std::string directory);
 
 // |dir| must have a trailing delimiter. |prefix| must not include wild card
@@ -167,68 +170,30 @@
 }  // namespace
 
 FileRotatingStream::FileRotatingStream(const std::string& dir_path,
-                                       const std::string& file_prefix)
-    : FileRotatingStream(dir_path, file_prefix, 0, 0, kRead) {}
-
-FileRotatingStream::FileRotatingStream(const std::string& dir_path,
                                        const std::string& file_prefix,
                                        size_t max_file_size,
                                        size_t num_files)
-    : FileRotatingStream(dir_path,
-                         file_prefix,
-                         max_file_size,
-                         num_files,
-                         kWrite) {
-  RTC_DCHECK_GT(max_file_size, 0);
-  RTC_DCHECK_GT(num_files, 1);
-}
-
-FileRotatingStream::FileRotatingStream(const std::string& dir_path,
-                                       const std::string& file_prefix,
-                                       size_t max_file_size,
-                                       size_t num_files,
-                                       Mode mode)
     : dir_path_(AddTrailingPathDelimiterIfNeeded(dir_path)),
       file_prefix_(file_prefix),
-      mode_(mode),
-      file_stream_(nullptr),
       max_file_size_(max_file_size),
       current_file_index_(0),
       rotation_index_(0),
       current_bytes_written_(0),
       disable_buffering_(false) {
+  RTC_DCHECK_GT(max_file_size, 0);
+  RTC_DCHECK_GT(num_files, 1);
   RTC_DCHECK(IsFolder(dir_path));
-  switch (mode) {
-    case kWrite: {
-      file_names_.clear();
-      for (size_t i = 0; i < num_files; ++i) {
-        file_names_.push_back(GetFilePath(i, num_files));
-      }
-      rotation_index_ = num_files - 1;
-      break;
-    }
-    case kRead: {
-      file_names_ = GetFilesWithPrefix(dir_path_, file_prefix_);
-      std::sort(file_names_.begin(), file_names_.end());
-      if (file_names_.size() > 0) {
-        // |file_names_| is sorted newest first, so read from the end.
-        current_file_index_ = file_names_.size() - 1;
-      }
-      break;
-    }
+  file_names_.clear();
+  for (size_t i = 0; i < num_files; ++i) {
+    file_names_.push_back(GetFilePath(i, num_files));
   }
+  rotation_index_ = num_files - 1;
 }
 
 FileRotatingStream::~FileRotatingStream() {}
 
 StreamState FileRotatingStream::GetState() const {
-  if (mode_ == kRead && current_file_index_ < file_names_.size()) {
-    return SS_OPEN;
-  }
-  if (!file_stream_) {
-    return SS_CLOSED;
-  }
-  return file_stream_->GetState();
+  return (file_.is_open() ? SS_OPEN : SS_CLOSED);
 }
 
 StreamResult FileRotatingStream::Read(void* buffer,
@@ -236,60 +201,15 @@
                                       size_t* read,
                                       int* error) {
   RTC_DCHECK(buffer);
-  if (mode_ != kRead) {
-    return SR_EOS;
-  }
-  if (current_file_index_ >= file_names_.size()) {
-    return SR_EOS;
-  }
-  // We will have no file stream initially, and when we are finished with the
-  // previous file.
-  if (!file_stream_) {
-    if (!OpenCurrentFile()) {
-      return SR_ERROR;
-    }
-  }
-  int local_error = 0;
-  if (!error) {
-    error = &local_error;
-  }
-  StreamResult result = file_stream_->Read(buffer, buffer_len, read, error);
-  if (result == SR_EOS || result == SR_ERROR) {
-    if (result == SR_ERROR) {
-      RTC_LOG(LS_ERROR) << "Failed to read from: "
-                        << file_names_[current_file_index_]
-                        << "Error: " << error;
-    }
-    // Reached the end of the file, read next file. If there is an error return
-    // the error status but allow for a next read by reading next file.
-    CloseCurrentFile();
-    if (current_file_index_ == 0) {
-      // Just finished reading the last file, signal EOS by setting index.
-      current_file_index_ = file_names_.size();
-    } else {
-      --current_file_index_;
-    }
-    if (read) {
-      *read = 0;
-    }
-    return result == SR_EOS ? SR_SUCCESS : result;
-  } else if (result == SR_SUCCESS) {
-    // Succeeded, continue reading from this file.
-    return SR_SUCCESS;
-  } else {
-    RTC_NOTREACHED();
-  }
-  return result;
+  RTC_NOTREACHED();
+  return SR_EOS;
 }
 
 StreamResult FileRotatingStream::Write(const void* data,
                                        size_t data_len,
                                        size_t* written,
                                        int* error) {
-  if (mode_ != kWrite) {
-    return SR_EOS;
-  }
-  if (!file_stream_) {
+  if (!file_.is_open()) {
     std::fprintf(stderr, "Open() must be called before Write.\n");
     return SR_ERROR;
   }
@@ -297,42 +217,31 @@
   RTC_DCHECK_LT(current_bytes_written_, max_file_size_);
   size_t remaining_bytes = max_file_size_ - current_bytes_written_;
   size_t write_length = std::min(data_len, remaining_bytes);
-  size_t local_written = 0;
-  if (!written) {
-    written = &local_written;
-  }
-  StreamResult result = file_stream_->Write(data, write_length, written, error);
-  current_bytes_written_ += *written;
 
+  if (!file_.Write(data, write_length)) {
+    return SR_ERROR;
+  }
+  if (disable_buffering_ && !file_.Flush()) {
+    return SR_ERROR;
+  }
+
+  current_bytes_written_ += write_length;
+  if (written) {
+    *written = write_length;
+  }
   // If we're done with this file, rotate it out.
   if (current_bytes_written_ >= max_file_size_) {
     RTC_DCHECK_EQ(current_bytes_written_, max_file_size_);
     RotateFiles();
   }
-  return result;
+  return SR_SUCCESS;
 }
 
 bool FileRotatingStream::Flush() {
-  if (!file_stream_) {
+  if (!file_.is_open()) {
     return false;
   }
-  return file_stream_->Flush();
-}
-
-bool FileRotatingStream::GetSize(size_t* size) const {
-  if (mode_ != kRead) {
-    // Not possible to get accurate size on disk when writing because of
-    // potential buffering.
-    return false;
-  }
-  RTC_DCHECK(size);
-  *size = 0;
-  size_t total_size = 0;
-  for (auto file_name : file_names_) {
-    total_size += GetFileSize(file_name).value_or(0);
-  }
-  *size = total_size;
-  return true;
+  return file_.Flush();
 }
 
 void FileRotatingStream::Close() {
@@ -340,33 +249,20 @@
 }
 
 bool FileRotatingStream::Open() {
-  switch (mode_) {
-    case kRead:
-      // Defer opening to when we first read since we want to return read error
-      // if we fail to open next file.
-      return true;
-    case kWrite: {
-      // Delete existing files when opening for write.
-      std::vector<std::string> matching_files =
-          GetFilesWithPrefix(dir_path_, file_prefix_);
-      for (const auto& matching_file : matching_files) {
-        if (!DeleteFile(matching_file)) {
-          std::fprintf(stderr, "Failed to delete: %s\n", matching_file.c_str());
-        }
-      }
-      return OpenCurrentFile();
+  // Delete existing files when opening for write.
+  std::vector<std::string> matching_files =
+      GetFilesWithPrefix(dir_path_, file_prefix_);
+  for (const auto& matching_file : matching_files) {
+    if (!DeleteFile(matching_file)) {
+      std::fprintf(stderr, "Failed to delete: %s\n", matching_file.c_str());
     }
   }
-  return false;
+  return OpenCurrentFile();
 }
 
 bool FileRotatingStream::DisableBuffering() {
   disable_buffering_ = true;
-  if (!file_stream_) {
-    std::fprintf(stderr, "Open() must be called before DisableBuffering().\n");
-    return false;
-  }
-  return file_stream_->DisableBuffering();
+  return true;
 }
 
 std::string FileRotatingStream::GetFilePath(size_t index) const {
@@ -380,41 +276,28 @@
   // Opens the appropriate file in the appropriate mode.
   RTC_DCHECK_LT(current_file_index_, file_names_.size());
   std::string file_path = file_names_[current_file_index_];
-  file_stream_.reset(new FileStream());
-  const char* mode = nullptr;
-  switch (mode_) {
-    case kWrite:
-      mode = "w+";
-      // We should always we writing to the zero-th file.
-      RTC_DCHECK_EQ(current_file_index_, 0);
-      break;
-    case kRead:
-      mode = "r";
-      break;
-  }
-  int error = 0;
-  if (!file_stream_->Open(file_path, mode, &error)) {
-    std::fprintf(stderr, "Failed to open: %s Error: %i\n", file_path.c_str(),
+
+  // We should always be writing to the zero-th file.
+  RTC_DCHECK_EQ(current_file_index_, 0);
+  int error;
+  file_ = webrtc::FileWrapper::OpenWriteOnly(file_path, &error);
+  if (!file_.is_open()) {
+    std::fprintf(stderr, "Failed to open: %s Error: %d\n", file_path.c_str(),
                  error);
-    file_stream_.reset();
     return false;
   }
-  if (disable_buffering_) {
-    file_stream_->DisableBuffering();
-  }
   return true;
 }
 
 void FileRotatingStream::CloseCurrentFile() {
-  if (!file_stream_) {
+  if (!file_.is_open()) {
     return;
   }
   current_bytes_written_ = 0;
-  file_stream_.reset();
+  file_.Close();
 }
 
 void FileRotatingStream::RotateFiles() {
-  RTC_DCHECK_EQ(mode_, kWrite);
   CloseCurrentFile();
   // Rotates the files by deleting the file at |rotation_index_|, which is the
   // oldest file and then renaming the newer files to have an incremented index.
@@ -456,16 +339,10 @@
 }
 
 CallSessionFileRotatingStream::CallSessionFileRotatingStream(
-    const std::string& dir_path)
-    : FileRotatingStream(dir_path, kLogPrefix),
-      max_total_log_size_(0),
-      num_rotations_(0) {}
-
-CallSessionFileRotatingStream::CallSessionFileRotatingStream(
     const std::string& dir_path,
     size_t max_total_log_size)
     : FileRotatingStream(dir_path,
-                         kLogPrefix,
+                         kCallSessionLogPrefix,
                          max_total_log_size / 2,
                          GetNumRotatingLogFiles(max_total_log_size) + 1),
       max_total_log_size_(max_total_log_size),
@@ -473,7 +350,6 @@
   RTC_DCHECK_GE(max_total_log_size, 4);
 }
 
-const char* CallSessionFileRotatingStream::kLogPrefix = "webrtc_log";
 const size_t CallSessionFileRotatingStream::kRotatingLogFileDefaultSize =
     1024 * 1024;
 
@@ -507,4 +383,46 @@
                   (max_total_log_size / 2) / kRotatingLogFileDefaultSize);
 }
 
+FileRotatingStreamReader::FileRotatingStreamReader(
+    const std::string& dir_path,
+    const std::string& file_prefix) {
+  file_names_ = GetFilesWithPrefix(AddTrailingPathDelimiterIfNeeded(dir_path),
+                                   file_prefix);
+
+  // Plain sort of the file names would sort by age, i.e., oldest last. Using
+  // std::greater gives us the desired chronological older, oldest first.
+  std::sort(file_names_.begin(), file_names_.end(),
+            std::greater<std::string>());
+}
+
+FileRotatingStreamReader::~FileRotatingStreamReader() = default;
+
+size_t FileRotatingStreamReader::GetSize() const {
+  size_t total_size = 0;
+  for (const auto& file_name : file_names_) {
+    total_size += GetFileSize(file_name).value_or(0);
+  }
+  return total_size;
+}
+
+size_t FileRotatingStreamReader::ReadAll(void* buffer, size_t size) const {
+  size_t done = 0;
+  for (const auto& file_name : file_names_) {
+    if (done < size) {
+      webrtc::FileWrapper f = webrtc::FileWrapper::OpenReadOnly(file_name);
+      if (!f.is_open()) {
+        break;
+      }
+      done += f.Read(static_cast<char*>(buffer) + done, size - done);
+    } else {
+      break;
+    }
+  }
+  return done;
+}
+
+CallSessionFileRotatingStreamReader::CallSessionFileRotatingStreamReader(
+    const std::string& dir_path)
+    : FileRotatingStreamReader(dir_path, kCallSessionLogPrefix) {}
+
 }  // namespace rtc
diff --git a/rtc_base/filerotatingstream.h b/rtc_base/file_rotating_stream.h
similarity index 81%
rename from rtc_base/filerotatingstream.h
rename to rtc_base/file_rotating_stream.h
index c75ee15..78e2983 100644
--- a/rtc_base/filerotatingstream.h
+++ b/rtc_base/file_rotating_stream.h
@@ -8,16 +8,17 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#ifndef RTC_BASE_FILEROTATINGSTREAM_H_
-#define RTC_BASE_FILEROTATINGSTREAM_H_
+#ifndef RTC_BASE_FILE_ROTATING_STREAM_H_
+#define RTC_BASE_FILE_ROTATING_STREAM_H_
 
 #include <stddef.h>
 #include <memory>
 #include <string>
 #include <vector>
 
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 #include "rtc_base/stream.h"
+#include "rtc_base/system/file_wrapper.h"
 
 namespace rtc {
 
@@ -52,8 +53,6 @@
                      size_t* written,
                      int* error) override;
   bool Flush() override;
-  // Returns the total file size currently used on disk.
-  bool GetSize(size_t* size) const override;
   void Close() override;
 
   // Opens the appropriate file(s). Call this before using the stream.
@@ -83,14 +82,6 @@
   virtual void OnRotation() {}
 
  private:
-  enum Mode { kRead, kWrite };
-
-  FileRotatingStream(const std::string& dir_path,
-                     const std::string& file_prefix,
-                     size_t max_file_size,
-                     size_t num_files,
-                     Mode mode);
-
   bool OpenCurrentFile();
   void CloseCurrentFile();
 
@@ -107,10 +98,9 @@
 
   const std::string dir_path_;
   const std::string file_prefix_;
-  const Mode mode_;
 
-  // FileStream is used to write to the current file.
-  std::unique_ptr<FileStream> file_stream_;
+  // File we're currently writing to.
+  webrtc::FileWrapper file_;
   // Convenience storage for file names so we don't generate them over and over.
   std::vector<std::string> file_names_;
   size_t max_file_size_;
@@ -127,7 +117,7 @@
 };
 
 // CallSessionFileRotatingStream is meant to be used in situations where we will
-// have limited disk space. Its purpose is to read and write logs up to a
+// have limited disk space. Its purpose is to write logs up to a
 // maximum size. Once the maximum size is exceeded, logs from the middle are
 // deleted whereas logs from the beginning and end are preserved. The reason for
 // this is because we anticipate that in WebRTC the beginning and end of the
@@ -140,11 +130,11 @@
 // (earliest) file on rotate, and that that file's size is bigger.
 //
 // Open() must be called before using this stream.
+
+// To read the logs produced by this class, one can use the companion class
+// CallSessionFileRotatingStreamReader.
 class CallSessionFileRotatingStream : public FileRotatingStream {
  public:
-  // Use this constructor for reading a directory previously written to with
-  // this stream.
-  explicit CallSessionFileRotatingStream(const std::string& dir_path);
   // Use this constructor for writing to a directory. Files in the directory
   // matching what's used by the stream will be deleted. |max_total_log_size|
   // must be at least 4.
@@ -158,7 +148,6 @@
  private:
   static size_t GetRotatingLogSize(size_t max_total_log_size);
   static size_t GetNumRotatingLogFiles(size_t max_total_log_size);
-  static const char* kLogPrefix;
   static const size_t kRotatingLogFileDefaultSize;
 
   const size_t max_total_log_size_;
@@ -167,6 +156,27 @@
   RTC_DISALLOW_COPY_AND_ASSIGN(CallSessionFileRotatingStream);
 };
 
+// This is a convenience class, to read all files produced by a
+// FileRotatingStream, all in one go. Typical use calls GetSize and ReadData
+// only once. The list of file names to read is based on the contents of the log
+// directory at construction time.
+class FileRotatingStreamReader {
+ public:
+  FileRotatingStreamReader(const std::string& dir_path,
+                           const std::string& file_prefix);
+  ~FileRotatingStreamReader();
+  size_t GetSize() const;
+  size_t ReadAll(void* buffer, size_t size) const;
+
+ private:
+  std::vector<std::string> file_names_;
+};
+
+class CallSessionFileRotatingStreamReader : public FileRotatingStreamReader {
+ public:
+  CallSessionFileRotatingStreamReader(const std::string& dir_path);
+};
+
 }  // namespace rtc
 
-#endif  // RTC_BASE_FILEROTATINGSTREAM_H_
+#endif  // RTC_BASE_FILE_ROTATING_STREAM_H_
diff --git a/rtc_base/filerotatingstream_unittest.cc b/rtc_base/file_rotating_stream_unittest.cc
similarity index 82%
rename from rtc_base/filerotatingstream_unittest.cc
rename to rtc_base/file_rotating_stream_unittest.cc
index 172be57..22e247f 100644
--- a/rtc_base/filerotatingstream_unittest.cc
+++ b/rtc_base/file_rotating_stream_unittest.cc
@@ -8,13 +8,14 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
+#include <string.h>
+#include <cstdint>
 #include <memory>
 
 #include "rtc_base/arraysize.h"
-#include "rtc_base/checks.h"
-#include "rtc_base/filerotatingstream.h"
-#include "rtc_base/gunit.h"
-#include "test/testsupport/fileutils.h"
+#include "rtc_base/file_rotating_stream.h"
+#include "test/gtest.h"
+#include "test/testsupport/file_utils.h"
 
 namespace rtc {
 
@@ -79,32 +80,24 @@
                         const size_t expected_length,
                         const std::string& dir_path,
                         const char* file_prefix) {
-    std::unique_ptr<FileRotatingStream> stream;
-    stream.reset(new FileRotatingStream(dir_path, file_prefix));
-    ASSERT_TRUE(stream->Open());
-    size_t read = 0;
-    size_t stream_size = 0;
-    EXPECT_TRUE(stream->GetSize(&stream_size));
+    FileRotatingStreamReader reader(dir_path, file_prefix);
+    EXPECT_EQ(reader.GetSize(), expected_length);
     std::unique_ptr<uint8_t[]> buffer(new uint8_t[expected_length]);
-    EXPECT_EQ(SR_SUCCESS,
-              stream->ReadAll(buffer.get(), expected_length, &read, nullptr));
+    memset(buffer.get(), 0, expected_length);
+    EXPECT_EQ(expected_length, reader.ReadAll(buffer.get(), expected_length));
     EXPECT_EQ(0, memcmp(expected_contents, buffer.get(), expected_length));
-    EXPECT_EQ(SR_EOS, stream->ReadAll(buffer.get(), 1, nullptr, nullptr));
-    EXPECT_EQ(stream_size, read);
   }
 
   void VerifyFileContents(const char* expected_contents,
                           const size_t expected_length,
                           const std::string& file_path) {
-    std::unique_ptr<uint8_t[]> buffer(new uint8_t[expected_length]);
-    FileStream stream;
-    ASSERT_TRUE(stream.Open(file_path, "r", nullptr));
-    EXPECT_EQ(rtc::SR_SUCCESS,
-              stream.ReadAll(buffer.get(), expected_length, nullptr, nullptr));
-    EXPECT_EQ(0, memcmp(expected_contents, buffer.get(), expected_length));
-    size_t file_size = 0;
-    EXPECT_TRUE(stream.GetSize(&file_size));
-    EXPECT_EQ(file_size, expected_length);
+    std::unique_ptr<uint8_t[]> buffer(new uint8_t[expected_length + 1]);
+    webrtc::FileWrapper f = webrtc::FileWrapper::OpenReadOnly(file_path);
+    ASSERT_TRUE(f.is_open());
+    size_t size_read = f.Read(buffer.get(), expected_length + 1);
+    EXPECT_EQ(size_read, expected_length);
+    EXPECT_EQ(0, memcmp(expected_contents, buffer.get(),
+                        std::min(expected_length, size_read)));
   }
 
   std::unique_ptr<FileRotatingStream> stream_;
@@ -134,11 +127,10 @@
   WriteAndFlush("a", 0);
 
   std::string logfile_path = stream_->GetFilePath(0);
-  FileStream stream;
-  ASSERT_TRUE(stream.Open(logfile_path, "r", nullptr));
-  size_t file_size = 0;
-  EXPECT_TRUE(stream.GetSize(&file_size));
-  EXPECT_EQ(0u, file_size);
+  webrtc::FileWrapper f = webrtc::FileWrapper::OpenReadOnly(logfile_path);
+  ASSERT_TRUE(f.is_open());
+  char buf[1];
+  EXPECT_EQ(0u, f.Read(buf, sizeof(buf)));
 }
 
 // Tests that a write operation followed by a read returns the expected data
@@ -292,18 +284,12 @@
   void VerifyStreamRead(const char* expected_contents,
                         const size_t expected_length,
                         const std::string& dir_path) {
-    std::unique_ptr<CallSessionFileRotatingStream> stream(
-        new CallSessionFileRotatingStream(dir_path));
-    ASSERT_TRUE(stream->Open());
-    size_t read = 0;
-    size_t stream_size = 0;
-    EXPECT_TRUE(stream->GetSize(&stream_size));
+    CallSessionFileRotatingStreamReader reader(dir_path);
+    EXPECT_EQ(reader.GetSize(), expected_length);
     std::unique_ptr<uint8_t[]> buffer(new uint8_t[expected_length]);
-    EXPECT_EQ(SR_SUCCESS,
-              stream->ReadAll(buffer.get(), expected_length, &read, nullptr));
+    memset(buffer.get(), 0, expected_length);
+    EXPECT_EQ(expected_length, reader.ReadAll(buffer.get(), expected_length));
     EXPECT_EQ(0, memcmp(expected_contents, buffer.get(), expected_length));
-    EXPECT_EQ(SR_EOS, stream->ReadAll(buffer.get(), 1, nullptr, nullptr));
-    EXPECT_EQ(stream_size, read);
   }
 
   std::unique_ptr<CallSessionFileRotatingStream> stream_;
@@ -350,17 +336,25 @@
               stream_->WriteAll(buffer.get(), buffer_size, nullptr, nullptr));
   }
 
-  stream_.reset(new CallSessionFileRotatingStream(dir_path_));
-  ASSERT_TRUE(stream_->Open());
-  std::unique_ptr<uint8_t[]> expected_buffer(new uint8_t[buffer_size]);
-  int expected_vals[] = {0, 1, 2, 6, 7};
+  const int expected_vals[] = {0, 1, 2, 6, 7};
+  const size_t expected_size = buffer_size * arraysize(expected_vals);
+
+  CallSessionFileRotatingStreamReader reader(dir_path_);
+  EXPECT_EQ(reader.GetSize(), expected_size);
+  std::unique_ptr<uint8_t[]> contents(new uint8_t[expected_size + 1]);
+  EXPECT_EQ(reader.ReadAll(contents.get(), expected_size + 1), expected_size);
   for (size_t i = 0; i < arraysize(expected_vals); ++i) {
-    memset(expected_buffer.get(), expected_vals[i], buffer_size);
-    EXPECT_EQ(SR_SUCCESS,
-              stream_->ReadAll(buffer.get(), buffer_size, nullptr, nullptr));
-    EXPECT_EQ(0, memcmp(buffer.get(), expected_buffer.get(), buffer_size));
+    const uint8_t* block = contents.get() + i * buffer_size;
+    bool match = true;
+    for (size_t j = 0; j < buffer_size; j++) {
+      if (block[j] != expected_vals[i]) {
+        match = false;
+        break;
+      }
+    }
+    // EXPECT call at end of loop, to limit the number of messages on failure.
+    EXPECT_TRUE(match);
   }
-  EXPECT_EQ(SR_EOS, stream_->ReadAll(buffer.get(), 1, nullptr, nullptr));
 }
 
 // Tests that writing and reading to a stream where only the first file is
@@ -377,17 +371,26 @@
               stream_->WriteAll(buffer.get(), buffer_size, nullptr, nullptr));
   }
 
-  stream_.reset(new CallSessionFileRotatingStream(dir_path_));
-  ASSERT_TRUE(stream_->Open());
-  std::unique_ptr<uint8_t[]> expected_buffer(new uint8_t[buffer_size]);
-  int expected_vals[] = {0, 1};
+  const int expected_vals[] = {0, 1};
+  const size_t expected_size = buffer_size * arraysize(expected_vals);
+
+  CallSessionFileRotatingStreamReader reader(dir_path_);
+  EXPECT_EQ(reader.GetSize(), expected_size);
+  std::unique_ptr<uint8_t[]> contents(new uint8_t[expected_size + 1]);
+  EXPECT_EQ(reader.ReadAll(contents.get(), expected_size + 1), expected_size);
+
   for (size_t i = 0; i < arraysize(expected_vals); ++i) {
-    memset(expected_buffer.get(), expected_vals[i], buffer_size);
-    EXPECT_EQ(SR_SUCCESS,
-              stream_->ReadAll(buffer.get(), buffer_size, nullptr, nullptr));
-    EXPECT_EQ(0, memcmp(buffer.get(), expected_buffer.get(), buffer_size));
+    const uint8_t* block = contents.get() + i * buffer_size;
+    bool match = true;
+    for (size_t j = 0; j < buffer_size; j++) {
+      if (block[j] != expected_vals[i]) {
+        match = false;
+        break;
+      }
+    }
+    // EXPECT call at end of loop, to limit the number of messages on failure.
+    EXPECT_TRUE(match);
   }
-  EXPECT_EQ(SR_EOS, stream_->ReadAll(buffer.get(), 1, nullptr, nullptr));
 }
 
 }  // namespace rtc
diff --git a/rtc_base/file_unittest.cc b/rtc_base/file_unittest.cc
deleted file mode 100644
index 5a72e5d..0000000
--- a/rtc_base/file_unittest.cc
+++ /dev/null
@@ -1,175 +0,0 @@
-/*
- *  Copyright 2016 The WebRTC Project Authors. All rights reserved.
- *
- *  Use of this source code is governed by a BSD-style license
- *  that can be found in the LICENSE file in the root of the source
- *  tree. An additional intellectual property rights grant can be found
- *  in the file PATENTS.  All contributing project authors may
- *  be found in the AUTHORS file in the root of the source tree.
- */
-
-#include <limits>
-#include <memory>
-#include <string>
-
-#include "rtc_base/file.h"
-#include "rtc_base/gunit.h"
-#include "test/testsupport/fileutils.h"
-
-#if defined(WEBRTC_WIN)
-
-#include "rtc_base/win32.h"
-
-#else  // if defined(WEBRTC_WIN)
-
-#include <errno.h>
-
-#endif
-
-namespace rtc {
-
-int LastError() {
-#if defined(WEBRTC_WIN)
-  return ::GetLastError();
-#else
-  return errno;
-#endif
-}
-
-bool VerifyBuffer(uint8_t* buffer, size_t length, uint8_t start_value) {
-  for (size_t i = 0; i < length; ++i) {
-    uint8_t val = start_value++;
-    EXPECT_EQ(val, buffer[i]);
-    if (buffer[i] != val)
-      return false;
-  }
-  // Prevent the same buffer from being verified multiple times simply
-  // because some operation that should have written to it failed
-  memset(buffer, 0, length);
-  return true;
-}
-
-class FileTest : public ::testing::Test {
- protected:
-  std::string path_;
-  void SetUp() override {
-    path_ = webrtc::test::TempFilename(webrtc::test::OutputPath(), "test_file");
-    ASSERT_FALSE(path_.empty());
-  }
-  void TearDown() override { RemoveFile(path_); }
-};
-
-TEST_F(FileTest, DefaultConstructor) {
-  File file;
-  uint8_t buffer[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
-
-  EXPECT_FALSE(file.IsOpen());
-  EXPECT_EQ(0u, file.Write(buffer, 10));
-  EXPECT_FALSE(file.Seek(0));
-  EXPECT_EQ(0u, file.Read(buffer, 10));
-  EXPECT_EQ(0u, file.WriteAt(buffer, 10, 0));
-  EXPECT_EQ(0u, file.ReadAt(buffer, 10, 0));
-  EXPECT_FALSE(file.Close());
-}
-
-TEST_F(FileTest, DoubleClose) {
-  File file = File::Open(path_);
-  ASSERT_TRUE(file.IsOpen()) << "Error: " << LastError();
-
-  EXPECT_TRUE(file.Close());
-  EXPECT_FALSE(file.Close());
-}
-
-TEST_F(FileTest, SimpleReadWrite) {
-  File file = File::Open(path_);
-  ASSERT_TRUE(file.IsOpen()) << "Error: " << LastError();
-
-  uint8_t data[100] = {0};
-  uint8_t out[100] = {0};
-  for (int i = 0; i < 100; ++i) {
-    data[i] = i;
-  }
-
-  EXPECT_EQ(10u, file.Write(data, 10));
-
-  EXPECT_TRUE(file.Seek(0));
-  EXPECT_EQ(10u, file.Read(out, 10));
-  EXPECT_TRUE(VerifyBuffer(out, 10, 0));
-
-  EXPECT_TRUE(file.Seek(0));
-  EXPECT_EQ(100u, file.Write(data, 100));
-
-  EXPECT_TRUE(file.Seek(0));
-  EXPECT_EQ(100u, file.Read(out, 100));
-  EXPECT_TRUE(VerifyBuffer(out, 100, 0));
-
-  EXPECT_TRUE(file.Seek(1));
-  EXPECT_EQ(50u, file.Write(data, 50));
-  EXPECT_EQ(50u, file.Write(data + 50, 50));
-
-  EXPECT_TRUE(file.Seek(1));
-  EXPECT_EQ(100u, file.Read(out, 100));
-  EXPECT_TRUE(VerifyBuffer(out, 100, 0));
-}
-
-TEST_F(FileTest, ReadWriteClose) {
-  File file = File::Open(path_);
-  ASSERT_TRUE(file.IsOpen()) << "Error: " << LastError();
-
-  uint8_t data[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
-  uint8_t out[10] = {0};
-  EXPECT_EQ(10u, file.Write(data, 10));
-  EXPECT_TRUE(file.Close());
-
-  File file2 = File::Open(path_);
-  ASSERT_TRUE(file2.IsOpen()) << "Error: " << LastError();
-  EXPECT_EQ(10u, file2.Read(out, 10));
-  EXPECT_TRUE(VerifyBuffer(out, 10, 0));
-}
-
-TEST_F(FileTest, RandomAccessRead) {
-  File file = File::Open(path_);
-  ASSERT_TRUE(file.IsOpen()) << "Error: " << LastError();
-
-  uint8_t data[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
-  uint8_t out[10] = {0};
-  EXPECT_EQ(10u, file.Write(data, 10));
-
-  EXPECT_EQ(4u, file.ReadAt(out, 4, 0));
-  EXPECT_TRUE(VerifyBuffer(out, 4, 0));
-
-  EXPECT_EQ(4u, file.ReadAt(out, 4, 4));
-  EXPECT_TRUE(VerifyBuffer(out, 4, 4));
-
-  EXPECT_EQ(5u, file.ReadAt(out, 5, 5));
-  EXPECT_TRUE(VerifyBuffer(out, 5, 5));
-}
-
-TEST_F(FileTest, RandomAccessReadWrite) {
-  File file = File::Open(path_);
-  ASSERT_TRUE(file.IsOpen()) << "Error: " << LastError();
-
-  uint8_t data[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
-  uint8_t out[10] = {0};
-  EXPECT_EQ(10u, file.Write(data, 10));
-  EXPECT_TRUE(file.Seek(4));
-
-  EXPECT_EQ(4u, file.WriteAt(data, 4, 4));
-  EXPECT_EQ(4u, file.ReadAt(out, 4, 4));
-  EXPECT_TRUE(VerifyBuffer(out, 4, 0));
-
-  EXPECT_EQ(2u, file.WriteAt(data, 2, 8));
-  EXPECT_EQ(2u, file.ReadAt(out, 2, 8));
-  EXPECT_TRUE(VerifyBuffer(out, 2, 0));
-}
-
-TEST_F(FileTest, ShouldBeAbleToRemoveFile) {
-  {
-    File file = File::Open(path_);
-    ASSERT_TRUE(file.IsOpen()) << "Error: " << LastError();
-  }
-
-  ASSERT_TRUE(File::Remove(path_)) << "Error: " << LastError();
-}
-
-}  // namespace rtc
diff --git a/rtc_base/file_win.cc b/rtc_base/file_win.cc
deleted file mode 100644
index d7580aa..0000000
--- a/rtc_base/file_win.cc
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- *  Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
- *
- *  Use of this source code is governed by a BSD-style license
- *  that can be found in the LICENSE file in the root of the source
- *  tree. An additional intellectual property rights grant can be found
- *  in the file PATENTS.  All contributing project authors may
- *  be found in the AUTHORS file in the root of the source tree.
- */
-
-#include "rtc_base/file.h"
-
-#include <io.h>
-#include <windows.h>
-
-#include <limits>
-
-#include "rtc_base/checks.h"
-
-namespace rtc {
-
-size_t File::Write(const uint8_t* data, size_t length) {
-  RTC_DCHECK_LT(length, std::numeric_limits<DWORD>::max());
-  size_t total_written = 0;
-  do {
-    DWORD written;
-    if (!::WriteFile(file_, data + total_written,
-                     static_cast<DWORD>(length - total_written), &written,
-                     nullptr)) {
-      break;
-    }
-    total_written += written;
-  } while (total_written < length);
-  return total_written;
-}
-
-size_t File::Read(uint8_t* buffer, size_t length) {
-  RTC_DCHECK_LT(length, std::numeric_limits<DWORD>::max());
-  size_t total_read = 0;
-  do {
-    DWORD read;
-    if (!::ReadFile(file_, buffer + total_read,
-                    static_cast<DWORD>(length - total_read), &read, nullptr)) {
-      break;
-    }
-    total_read += read;
-  } while (total_read < length);
-  return total_read;
-}
-
-size_t File::WriteAt(const uint8_t* data, size_t length, size_t offset) {
-  RTC_DCHECK_LT(length, std::numeric_limits<DWORD>::max());
-  size_t total_written = 0;
-  do {
-    DWORD written;
-
-    LARGE_INTEGER offset_li;
-    offset_li.QuadPart = offset + total_written;
-
-    OVERLAPPED overlapped = {0};
-    overlapped.Offset = offset_li.LowPart;
-    overlapped.OffsetHigh = offset_li.HighPart;
-
-    if (!::WriteFile(file_, data + total_written,
-                     static_cast<DWORD>(length - total_written), &written,
-                     &overlapped)) {
-      break;
-    }
-
-    total_written += written;
-  } while (total_written < length);
-  return total_written;
-}
-
-size_t File::ReadAt(uint8_t* buffer, size_t length, size_t offset) {
-  RTC_DCHECK_LT(length, std::numeric_limits<DWORD>::max());
-  size_t total_read = 0;
-  do {
-    DWORD read;
-
-    LARGE_INTEGER offset_li;
-    offset_li.QuadPart = offset + total_read;
-
-    OVERLAPPED overlapped = {0};
-    overlapped.Offset = offset_li.LowPart;
-    overlapped.OffsetHigh = offset_li.HighPart;
-
-    if (!::ReadFile(file_, buffer + total_read,
-                    static_cast<DWORD>(length - total_read), &read,
-                    &overlapped)) {
-      break;
-    }
-
-    total_read += read;
-  } while (total_read < length);
-  return total_read;
-}
-
-bool File::Seek(size_t offset) {
-  LARGE_INTEGER distance;
-  distance.QuadPart = offset;
-  return SetFilePointerEx(file_, distance, nullptr, FILE_BEGIN) != 0;
-}
-
-bool File::Close() {
-  if (file_ == kInvalidPlatformFileValue)
-    return false;
-  bool ret = CloseHandle(file_) != 0;
-  file_ = kInvalidPlatformFileValue;
-  return ret;
-}
-
-}  // namespace rtc
diff --git a/rtc_base/firewallsocketserver.cc b/rtc_base/firewall_socket_server.cc
similarity index 97%
rename from rtc_base/firewallsocketserver.cc
rename to rtc_base/firewall_socket_server.cc
index 2a28124..ec5a857 100644
--- a/rtc_base/firewallsocketserver.cc
+++ b/rtc_base/firewall_socket_server.cc
@@ -8,11 +8,15 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#include "rtc_base/firewallsocketserver.h"
+#include "rtc_base/firewall_socket_server.h"
 
+#include <errno.h>
+#include <stddef.h>
+#include <stdint.h>
 #include <algorithm>
+#include <string>
 
-#include "rtc_base/asyncsocket.h"
+#include "rtc_base/async_socket.h"
 #include "rtc_base/checks.h"
 #include "rtc_base/logging.h"
 
diff --git a/rtc_base/firewallsocketserver.h b/rtc_base/firewall_socket_server.h
similarity index 91%
rename from rtc_base/firewallsocketserver.h
rename to rtc_base/firewall_socket_server.h
index 0e96823..9536bd2 100644
--- a/rtc_base/firewallsocketserver.h
+++ b/rtc_base/firewall_socket_server.h
@@ -8,12 +8,17 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#ifndef RTC_BASE_FIREWALLSOCKETSERVER_H_
-#define RTC_BASE_FIREWALLSOCKETSERVER_H_
+#ifndef RTC_BASE_FIREWALL_SOCKET_SERVER_H_
+#define RTC_BASE_FIREWALL_SOCKET_SERVER_H_
 
 #include <vector>
-#include "rtc_base/criticalsection.h"
-#include "rtc_base/socketserver.h"
+
+#include "rtc_base/async_socket.h"
+#include "rtc_base/critical_section.h"
+#include "rtc_base/ip_address.h"
+#include "rtc_base/socket.h"
+#include "rtc_base/socket_address.h"
+#include "rtc_base/socket_server.h"
 
 namespace rtc {
 
@@ -124,4 +129,4 @@
 
 }  // namespace rtc
 
-#endif  // RTC_BASE_FIREWALLSOCKETSERVER_H_
+#endif  // RTC_BASE_FIREWALL_SOCKET_SERVER_H_
diff --git a/rtc_base/flags.cc b/rtc_base/flags.cc
index bcce0da..6a87eb4 100644
--- a/rtc_base/flags.cc
+++ b/rtc_base/flags.cc
@@ -23,7 +23,7 @@
 #include <shellapi.h> // must come after windows.h
 // clang-format on
 
-#include "rtc_base/stringutils.h"  // For ToUtf8
+#include "rtc_base/string_utils.h"  // For ToUtf8
 #endif
 
 namespace {
diff --git a/rtc_base/flags.h b/rtc_base/flags.h
index a08bfd2..e152e2a 100644
--- a/rtc_base/flags.h
+++ b/rtc_base/flags.h
@@ -25,7 +25,7 @@
 #include "rtc_base/checks.h"
 
 #if defined(WEBRTC_WIN)
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 #endif
 
 namespace rtc {
diff --git a/rtc_base/function_view_unittest.cc b/rtc_base/function_view_unittest.cc
index d0cfeb3..d91bac0 100644
--- a/rtc_base/function_view_unittest.cc
+++ b/rtc_base/function_view_unittest.cc
@@ -12,7 +12,7 @@
 #include <utility>
 
 #include "rtc_base/function_view.h"
-#include "rtc_base/gunit.h"
+#include "test/gtest.h"
 
 namespace rtc {
 
@@ -97,6 +97,7 @@
 TEST(FunctionViewTest, MoveConstructorIsCopy) {
   auto f17 = [] { return 17; };
   rtc::FunctionView<int()> fv1(f17);
+  // NOLINTNEXTLINE(performance-move-const-arg)
   rtc::FunctionView<int()> fv2(std::move(fv1));
   EXPECT_EQ(17, fv1());
   EXPECT_EQ(17, fv2());
@@ -121,7 +122,7 @@
   rtc::FunctionView<int()> fv2(f23);
   EXPECT_EQ(17, fv1());
   EXPECT_EQ(23, fv2());
-  fv2 = std::move(fv1);
+  fv2 = std::move(fv1);  // NOLINT(performance-move-const-arg)
   EXPECT_EQ(17, fv1());
   EXPECT_EQ(17, fv2());
 }
diff --git a/rtc_base/gunit.cc b/rtc_base/gunit.cc
index 0dd8f12..83ee807 100644
--- a/rtc_base/gunit.cc
+++ b/rtc_base/gunit.cc
@@ -12,17 +12,18 @@
 
 #include <string>
 
-#include "rtc_base/stringutils.h"
+#include "absl/strings/match.h"
 
-::testing::AssertionResult AssertStartsWith(const char* str_expr,
+::testing::AssertionResult AssertStartsWith(const char* text_expr,
                                             const char* prefix_expr,
-                                            const std::string& str,
-                                            const std::string& prefix) {
-  if (rtc::starts_with(str.c_str(), prefix.c_str())) {
+                                            absl::string_view text,
+                                            absl::string_view prefix) {
+  if (absl::StartsWith(text, prefix)) {
     return ::testing::AssertionSuccess();
   } else {
     return ::testing::AssertionFailure()
-           << str_expr << "\nwhich is\n\"" << str << "\"\ndoes not start with\n"
+           << text_expr << "\nwhich is\n\"" << text
+           << "\"\ndoes not start with\n"
            << prefix_expr << "\nwhich is\n\"" << prefix << "\"";
   }
 }
diff --git a/rtc_base/gunit.h b/rtc_base/gunit.h
index 910fbf3..d499125 100644
--- a/rtc_base/gunit.h
+++ b/rtc_base/gunit.h
@@ -11,7 +11,7 @@
 #ifndef RTC_BASE_GUNIT_H_
 #define RTC_BASE_GUNIT_H_
 
-#include "rtc_base/fakeclock.h"
+#include "rtc_base/fake_clock.h"
 #include "rtc_base/logging.h"
 #include "rtc_base/thread.h"
 #include "test/gtest.h"
@@ -153,11 +153,11 @@
   } else                                                 \
     GTEST_CONCAT_TOKEN_(gunit_label_, __LINE__) : ASSERT_EQ(v1, v2)
 
-// Usage: EXPECT_PRED_FORMAT2(AssertStartsWith, str, "prefix");
-testing::AssertionResult AssertStartsWith(const char* str_expr,
+// Usage: EXPECT_PRED_FORMAT2(AssertStartsWith, text, "prefix");
+testing::AssertionResult AssertStartsWith(const char* text_expr,
                                           const char* prefix_expr,
-                                          const std::string& str,
-                                          const std::string& prefix);
+                                          absl::string_view text,
+                                          absl::string_view prefix);
 
 // Usage: EXPECT_PRED_FORMAT2(AssertStringContains, str, "substring");
 testing::AssertionResult AssertStringContains(const char* str_expr,
diff --git a/rtc_base/helpers.cc b/rtc_base/helpers.cc
index b9372b9..d8ea89f 100644
--- a/rtc_base/helpers.cc
+++ b/rtc_base/helpers.cc
@@ -10,15 +10,13 @@
 
 #include "rtc_base/helpers.h"
 
+#include <openssl/rand.h>
+#include <cstdint>
 #include <limits>
 #include <memory>
 
-#include <openssl/rand.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.
 #undef max
diff --git a/rtc_base/helpers_unittest.cc b/rtc_base/helpers_unittest.cc
index 3e8729c..1feb9de 100644
--- a/rtc_base/helpers_unittest.cc
+++ b/rtc_base/helpers_unittest.cc
@@ -8,12 +8,12 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
+#include <string.h>
 #include <string>
 
 #include "rtc_base/buffer.h"
-#include "rtc_base/gunit.h"
 #include "rtc_base/helpers.h"
-#include "rtc_base/ssladapter.h"
+#include "test/gtest.h"
 
 namespace rtc {
 
diff --git a/rtc_base/httpcommon.cc b/rtc_base/http_common.cc
similarity index 98%
rename from rtc_base/httpcommon.cc
rename to rtc_base/http_common.cc
index 4fa5f41..0456eea 100644
--- a/rtc_base/httpcommon.cc
+++ b/rtc_base/http_common.cc
@@ -14,24 +14,22 @@
 #include <windows.h>
 #include <winsock2.h>
 #include <ws2tcpip.h>
+
 #define SECURITY_WIN32
 #include <security.h>
 #endif
 
 #include <ctype.h>  // for isspace
 #include <stdio.h>  // for sprintf
-#include <algorithm>
 #include <utility>  // for pair
 #include <vector>
 
 #include "absl/strings/match.h"
-#include "rtc_base/arraysize.h"
-#include "rtc_base/checks.h"
-#include "rtc_base/cryptstring.h"  // for CryptString
-#include "rtc_base/httpcommon.h"
+#include "rtc_base/crypt_string.h"  // for CryptString
+#include "rtc_base/http_common.h"
 #include "rtc_base/logging.h"
-#include "rtc_base/messagedigest.h"
-#include "rtc_base/socketaddress.h"
+#include "rtc_base/message_digest.h"
+#include "rtc_base/socket_address.h"
 #include "rtc_base/strings/string_builder.h"
 #include "rtc_base/third_party/base64/base64.h"  // for Base64
 #include "rtc_base/zero_memory.h"                // for ExplicitZeroMemory
diff --git a/rtc_base/httpcommon.h b/rtc_base/http_common.h
similarity index 94%
rename from rtc_base/httpcommon.h
rename to rtc_base/http_common.h
index fbad280..edf161f 100644
--- a/rtc_base/httpcommon.h
+++ b/rtc_base/http_common.h
@@ -8,8 +8,8 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#ifndef RTC_BASE_HTTPCOMMON_H_
-#define RTC_BASE_HTTPCOMMON_H_
+#ifndef RTC_BASE_HTTP_COMMON_H_
+#define RTC_BASE_HTTP_COMMON_H_
 
 #include <string>
 
@@ -49,4 +49,4 @@
 
 }  // namespace rtc
 
-#endif  // RTC_BASE_HTTPCOMMON_H_
+#endif  // RTC_BASE_HTTP_COMMON_H_
diff --git a/rtc_base/ifaddrs-android.cc b/rtc_base/ifaddrs_android.cc
similarity index 99%
rename from rtc_base/ifaddrs-android.cc
rename to rtc_base/ifaddrs_android.cc
index cc6cdab..94b8669 100644
--- a/rtc_base/ifaddrs-android.cc
+++ b/rtc_base/ifaddrs_android.cc
@@ -9,7 +9,7 @@
  */
 
 #if defined(WEBRTC_ANDROID)
-#include "rtc_base/ifaddrs-android.h"
+#include "rtc_base/ifaddrs_android.h"
 #include <errno.h>
 #include <linux/netlink.h>
 #include <linux/rtnetlink.h>
diff --git a/rtc_base/ifaddrs-android.h b/rtc_base/ifaddrs_android.h
similarity index 100%
rename from rtc_base/ifaddrs-android.h
rename to rtc_base/ifaddrs_android.h
diff --git a/rtc_base/ifaddrs_converter.h b/rtc_base/ifaddrs_converter.h
index 35bef5b..bd6957d 100644
--- a/rtc_base/ifaddrs_converter.h
+++ b/rtc_base/ifaddrs_converter.h
@@ -12,12 +12,12 @@
 #define RTC_BASE_IFADDRS_CONVERTER_H_
 
 #if defined(WEBRTC_ANDROID)
-#include "rtc_base/ifaddrs-android.h"
+#include "rtc_base/ifaddrs_android.h"
 #else
 #include <ifaddrs.h>
 #endif  // WEBRTC_ANDROID
 
-#include "rtc_base/ipaddress.h"
+#include "rtc_base/ip_address.h"
 
 namespace rtc {
 
diff --git a/rtc_base/ipaddress.cc b/rtc_base/ip_address.cc
similarity index 98%
rename from rtc_base/ipaddress.cc
rename to rtc_base/ip_address.cc
index 027a7b2..ff0be13 100644
--- a/rtc_base/ipaddress.cc
+++ b/rtc_base/ip_address.cc
@@ -20,10 +20,10 @@
 #include <netdb.h>
 #endif
 
-#include "rtc_base/byteorder.h"
-#include "rtc_base/ipaddress.h"
-#include "rtc_base/nethelpers.h"
-#include "rtc_base/stringutils.h"
+#include "rtc_base/byte_order.h"
+#include "rtc_base/ip_address.h"
+#include "rtc_base/net_helpers.h"
+#include "rtc_base/string_utils.h"
 
 #if defined(WEBRTC_WIN)
 #include "rtc_base/win32.h"
diff --git a/rtc_base/ipaddress.h b/rtc_base/ip_address.h
similarity index 97%
rename from rtc_base/ipaddress.h
rename to rtc_base/ip_address.h
index 614fd8f..49dea68 100644
--- a/rtc_base/ipaddress.h
+++ b/rtc_base/ip_address.h
@@ -8,8 +8,8 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#ifndef RTC_BASE_IPADDRESS_H_
-#define RTC_BASE_IPADDRESS_H_
+#ifndef RTC_BASE_IP_ADDRESS_H_
+#define RTC_BASE_IP_ADDRESS_H_
 
 #if defined(WEBRTC_POSIX)
 #include <arpa/inet.h>
@@ -23,9 +23,8 @@
 #endif
 #include <string.h>
 #include <string>
-#include <vector>
 
-#include "rtc_base/byteorder.h"
+#include "rtc_base/byte_order.h"
 #if defined(WEBRTC_WIN)
 #include "rtc_base/win32.h"
 #endif
@@ -190,4 +189,4 @@
 
 }  // namespace rtc
 
-#endif  // RTC_BASE_IPADDRESS_H_
+#endif  // RTC_BASE_IP_ADDRESS_H_
diff --git a/rtc_base/ipaddress_unittest.cc b/rtc_base/ip_address_unittest.cc
similarity index 99%
rename from rtc_base/ipaddress_unittest.cc
rename to rtc_base/ip_address_unittest.cc
index 30312d0..c93244d 100644
--- a/rtc_base/ipaddress_unittest.cc
+++ b/rtc_base/ip_address_unittest.cc
@@ -8,8 +8,9 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#include "rtc_base/ipaddress.h"
-#include "rtc_base/gunit.h"
+#include "rtc_base/ip_address.h"
+
+#include "test/gtest.h"
 
 namespace rtc {
 
diff --git a/rtc_base/java/src/org/webrtc/Logging.java b/rtc_base/java/src/org/webrtc/Logging.java
index aafdbe8..5dac688 100644
--- a/rtc_base/java/src/org/webrtc/Logging.java
+++ b/rtc_base/java/src/org/webrtc/Logging.java
@@ -10,12 +10,12 @@
 
 package org.webrtc;
 
+import android.support.annotation.Nullable;
 import java.io.PrintWriter;
 import java.io.StringWriter;
 import java.util.EnumSet;
 import java.util.logging.Level;
 import java.util.logging.Logger;
-import javax.annotation.Nullable;
 import org.webrtc.Loggable;
 
 /**
@@ -88,7 +88,7 @@
   }
 
   // Keep in sync with webrtc/rtc_base/logging.h:LoggingSeverity.
-  public enum Severity { LS_SENSITIVE, LS_VERBOSE, LS_INFO, LS_WARNING, LS_ERROR, LS_NONE }
+  public enum Severity { LS_VERBOSE, LS_INFO, LS_WARNING, LS_ERROR, LS_NONE }
 
   public static void enableLogThreads() {
     nativeEnableLogThreads();
diff --git a/rtc_base/java/src/org/webrtc/ThreadUtils.java b/rtc_base/java/src/org/webrtc/ThreadUtils.java
index a403870..d60230a 100644
--- a/rtc_base/java/src/org/webrtc/ThreadUtils.java
+++ b/rtc_base/java/src/org/webrtc/ThreadUtils.java
@@ -13,10 +13,10 @@
 import android.os.Handler;
 import android.os.Looper;
 import android.os.SystemClock;
+import android.support.annotation.Nullable;
 import java.util.concurrent.Callable;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
-import javax.annotation.Nullable;
 
 public class ThreadUtils {
   /**
diff --git a/rtc_base/keep_ref_until_done.h b/rtc_base/keep_ref_until_done.h
index 9ba0e87..7bebd82 100644
--- a/rtc_base/keep_ref_until_done.h
+++ b/rtc_base/keep_ref_until_done.h
@@ -11,10 +11,10 @@
 #ifndef RTC_BASE_KEEP_REF_UNTIL_DONE_H_
 #define RTC_BASE_KEEP_REF_UNTIL_DONE_H_
 
+#include "api/scoped_refptr.h"
 #include "rtc_base/bind.h"
 #include "rtc_base/callback.h"
-#include "rtc_base/refcount.h"
-#include "rtc_base/scoped_ref_ptr.h"
+#include "rtc_base/ref_count.h"
 
 namespace rtc {
 
diff --git a/rtc_base/key_derivation.cc b/rtc_base/key_derivation.cc
index 288e407..6c9a254 100644
--- a/rtc_base/key_derivation.cc
+++ b/rtc_base/key_derivation.cc
@@ -11,6 +11,7 @@
 #include "rtc_base/key_derivation.h"
 
 #include "absl/memory/memory.h"
+#include "rtc_base/checks.h"
 #include "rtc_base/openssl_key_derivation_hkdf.h"
 
 namespace rtc {
diff --git a/rtc_base/key_derivation.h b/rtc_base/key_derivation.h
index fa329ae..f35e7ff 100644
--- a/rtc_base/key_derivation.h
+++ b/rtc_base/key_derivation.h
@@ -11,12 +11,14 @@
 #ifndef RTC_BASE_KEY_DERIVATION_H_
 #define RTC_BASE_KEY_DERIVATION_H_
 
+#include <stddef.h>
+#include <stdint.h>
 #include <memory>
 
 #include "absl/types/optional.h"
 #include "api/array_view.h"
 #include "rtc_base/buffer.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace rtc {
 
diff --git a/rtc_base/location.cc b/rtc_base/location.cc
index c95ad9c..d3c911f 100644
--- a/rtc_base/location.cc
+++ b/rtc_base/location.cc
@@ -10,6 +10,8 @@
 
 #include "rtc_base/location.h"
 
+#include <stdio.h>
+
 namespace rtc {
 
 Location::Location(const char* function_name, const char* file_and_line)
diff --git a/rtc_base/logsinks.cc b/rtc_base/log_sinks.cc
similarity index 98%
rename from rtc_base/logsinks.cc
rename to rtc_base/log_sinks.cc
index c01bafb..db12e9f 100644
--- a/rtc_base/logsinks.cc
+++ b/rtc_base/log_sinks.cc
@@ -8,7 +8,7 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#include "rtc_base/logsinks.h"
+#include "rtc_base/log_sinks.h"
 
 #include <string.h>
 #include <cstdio>
diff --git a/rtc_base/logsinks.h b/rtc_base/log_sinks.h
similarity index 92%
rename from rtc_base/logsinks.h
rename to rtc_base/log_sinks.h
index d0867a2..9e35748 100644
--- a/rtc_base/logsinks.h
+++ b/rtc_base/log_sinks.h
@@ -8,15 +8,15 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#ifndef RTC_BASE_LOGSINKS_H_
-#define RTC_BASE_LOGSINKS_H_
+#ifndef RTC_BASE_LOG_SINKS_H_
+#define RTC_BASE_LOG_SINKS_H_
 
 #include <stddef.h>
 #include <memory>
 #include <string>
 
-#include "rtc_base/constructormagic.h"
-#include "rtc_base/filerotatingstream.h"
+#include "rtc_base/constructor_magic.h"
+#include "rtc_base/file_rotating_stream.h"
 #include "rtc_base/logging.h"
 
 namespace rtc {
@@ -69,4 +69,4 @@
 
 }  // namespace rtc
 
-#endif  // RTC_BASE_LOGSINKS_H_
+#endif  // RTC_BASE_LOG_SINKS_H_
diff --git a/rtc_base/logging.cc b/rtc_base/logging.cc
index 8d6afbc..f78cd88 100644
--- a/rtc_base/logging.cc
+++ b/rtc_base/logging.cc
@@ -35,14 +35,14 @@
 #include <vector>
 
 #include "rtc_base/checks.h"
-#include "rtc_base/criticalsection.h"
+#include "rtc_base/critical_section.h"
 #include "rtc_base/logging.h"
 #include "rtc_base/platform_thread_types.h"
-#include "rtc_base/stringencode.h"
+#include "rtc_base/string_encode.h"
+#include "rtc_base/string_utils.h"
 #include "rtc_base/strings/string_builder.h"
-#include "rtc_base/stringutils.h"
 #include "rtc_base/thread_annotations.h"
-#include "rtc_base/timeutils.h"
+#include "rtc_base/time_utils.h"
 
 namespace rtc {
 namespace {
@@ -308,8 +308,6 @@
       LogThreads();
 
       // Logging levels
-    } else if (token == "sensitive") {
-      current_level = LS_SENSITIVE;
     } else if (token == "verbose") {
       current_level = LS_VERBOSE;
     } else if (token == "info") {
@@ -402,13 +400,6 @@
   // from the shell.
   int prio;
   switch (severity) {
-    case LS_SENSITIVE:
-      __android_log_write(ANDROID_LOG_INFO, tag, "SENSITIVE");
-      if (log_to_stderr) {
-        fprintf(stderr, "SENSITIVE");
-        fflush(stderr);
-      }
-      return;
     case LS_VERBOSE:
       prio = ANDROID_LOG_VERBOSE;
       break;
@@ -540,9 +531,11 @@
       case LogArgType::kLongDouble:
         log_message.stream() << va_arg(args, long double);
         break;
-      case LogArgType::kCharP:
-        log_message.stream() << va_arg(args, const char*);
+      case LogArgType::kCharP: {
+        const char* s = va_arg(args, const char*);
+        log_message.stream() << (s ? s : "(null)");
         break;
+      }
       case LogArgType::kStdString:
         log_message.stream() << *va_arg(args, const std::string*);
         break;
diff --git a/rtc_base/logging.h b/rtc_base/logging.h
index c7d083e..5cd4f72 100644
--- a/rtc_base/logging.h
+++ b/rtc_base/logging.h
@@ -52,7 +52,7 @@
 #include <utility>
 
 #include "absl/strings/string_view.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 #include "rtc_base/deprecation.h"
 #include "rtc_base/strings/string_builder.h"
 #include "rtc_base/system/inline.h"
@@ -73,8 +73,6 @@
 
 // Note that the non-standard LoggingSeverity aliases exist because they are
 // still in broad use.  The meanings of the levels are:
-//  LS_SENSITIVE: Information which should only be logged with the consent
-//   of the user, due to privacy concerns.
 //  LS_VERBOSE: This level is for data which we do not want to appear in the
 //   normal debug log, but should appear in diagnostic logs.
 //  LS_INFO: Chatty level used in debugging for all sorts of things, the default
@@ -83,7 +81,6 @@
 //  LS_ERROR: Something that should not have occurred.
 //  LS_NONE: Don't log.
 enum LoggingSeverity {
-  LS_SENSITIVE,
   LS_VERBOSE,
   LS_INFO,
   LS_WARNING,
@@ -361,11 +358,6 @@
   }
 };
 
-// TODO(bugs.webrtc.org/9278): Remove this once it's no longer used.
-struct LogMessageVoidify {
-  void operator&(std::ostream&) {}  // no-presubmit-check TODO(webrtc:8982)
-};
-
 }  // namespace webrtc_logging_impl
 
 // Direct use of this class is deprecated; please use the logging macros
@@ -512,13 +504,6 @@
 // Logging Helpers
 //////////////////////////////////////////////////////////////////////
 
-// DEPRECATED.
-// TODO(bugs.webrtc.org/9278): Remove once there are no more users.
-#define RTC_LOG_SEVERITY_PRECONDITION(sev) \
-  (rtc::LogMessage::IsNoop(sev))           \
-      ? static_cast<void>(0)               \
-      : rtc::webrtc_logging_impl::LogMessageVoidify()&
-
 #define RTC_LOG_FILE_LINE(sev, file, line)      \
   rtc::webrtc_logging_impl::LogCall() &         \
       rtc::webrtc_logging_impl::LogStreamer<>() \
diff --git a/rtc_base/logging_unittest.cc b/rtc_base/logging_unittest.cc
index 4de1cf2..e49440d 100644
--- a/rtc_base/logging_unittest.cc
+++ b/rtc_base/logging_unittest.cc
@@ -9,13 +9,17 @@
  */
 
 #include "rtc_base/logging.h"
+
+#include <string.h>
+#include <algorithm>
+
 #include "rtc_base/arraysize.h"
 #include "rtc_base/checks.h"
 #include "rtc_base/event.h"
-#include "rtc_base/gunit.h"
 #include "rtc_base/platform_thread.h"
 #include "rtc_base/stream.h"
-#include "test/testsupport/fileutils.h"
+#include "rtc_base/time_utils.h"
+#include "test/gtest.h"
 
 namespace rtc {
 
@@ -36,10 +40,6 @@
                      size_t* written,
                      int* error) override;
   void Close() override;
-  bool SetPosition(size_t position) override;
-  bool GetPosition(size_t* position) const override;
-  bool GetSize(size_t* size) const override;
-  bool ReserveSize(size_t size) override;
 
  private:
   std::string& str_;
@@ -90,32 +90,6 @@
 
 void StringStream::Close() {}
 
-bool StringStream::SetPosition(size_t position) {
-  if (position > str_.size())
-    return false;
-  read_pos_ = position;
-  return true;
-}
-
-bool StringStream::GetPosition(size_t* position) const {
-  if (position)
-    *position = read_pos_;
-  return true;
-}
-
-bool StringStream::GetSize(size_t* size) const {
-  if (size)
-    *size = str_.size();
-  return true;
-}
-
-bool StringStream::ReserveSize(size_t size) {
-  if (read_only_)
-    return false;
-  str_.reserve(size);
-  return true;
-}
-
 }  // namespace
 
 template <typename Base>
@@ -188,13 +162,14 @@
   std::string s1 = "char*";
   std::string s2 = "std::string";
   std::string s3 = "absl::stringview";
-
+  const char* null_string = nullptr;
   void* p = reinterpret_cast<void*>(0xabcd);
 
   // Log all suported types(except doubles/floats) as a sanity-check.
   RTC_LOG(LS_INFO) << "|" << i << "|" << l << "|" << ll << "|" << u << "|" << ul
                    << "|" << ull << "|" << s1.c_str() << "|" << s2 << "|"
-                   << absl::string_view(s3) << "|" << p << "|";
+                   << absl::string_view(s3) << "|" << p << "|" << null_string
+                   << "|";
 
   // Signed integers
   EXPECT_NE(std::string::npos, str.find("|1|"));
@@ -214,6 +189,9 @@
   // void*
   EXPECT_NE(std::string::npos, str.find("|abcd|"));
 
+  // null char*
+  EXPECT_NE(std::string::npos, str.find("|(null)|"));
+
   LogMessage::RemoveLogToStream(&stream);
   EXPECT_EQ(LS_NONE, LogMessage::GetLogToStream(&stream));
   EXPECT_EQ(sev, LogMessage::GetLogToStream(nullptr));
@@ -284,10 +262,7 @@
   void Start() { thread_.Start(); }
 
  private:
-  void Run() {
-    // LS_SENSITIVE by default to avoid cluttering up any real logging going on.
-    RTC_LOG(LS_SENSITIVE) << "RTC_LOG";
-  }
+  void Run() { RTC_LOG(LS_VERBOSE) << "RTC_LOG"; }
 
   static void ThreadEntry(void* p) { static_cast<LogThread*>(p)->Run(); }
 
@@ -308,9 +283,9 @@
   std::string s1, s2, s3;
   LogSinkImpl<StringStream> stream1(&s1), stream2(&s2), stream3(&s3);
   for (int i = 0; i < 1000; ++i) {
-    LogMessage::AddLogToStream(&stream1, LS_INFO);
-    LogMessage::AddLogToStream(&stream2, LS_VERBOSE);
-    LogMessage::AddLogToStream(&stream3, LS_SENSITIVE);
+    LogMessage::AddLogToStream(&stream1, LS_WARNING);
+    LogMessage::AddLogToStream(&stream2, LS_INFO);
+    LogMessage::AddLogToStream(&stream3, LS_VERBOSE);
     LogMessage::RemoveLogToStream(&stream1);
     LogMessage::RemoveLogToStream(&stream2);
     LogMessage::RemoveLogToStream(&stream3);
@@ -367,12 +342,10 @@
 TEST(LogTest, Perf) {
   std::string str;
   LogSinkImpl<StringStream> stream(&str);
-  LogMessage::AddLogToStream(&stream, LS_SENSITIVE);
+  LogMessage::AddLogToStream(&stream, LS_VERBOSE);
 
   const std::string message(80, 'X');
-  {
-    LogMessageForTesting sanity_check_msg(__FILE__, __LINE__, LS_SENSITIVE);
-  }
+  { LogMessageForTesting sanity_check_msg(__FILE__, __LINE__, LS_VERBOSE); }
 
   // We now know how many bytes the logging framework will tag onto every msg.
   const size_t logging_overhead = str.size();
@@ -383,7 +356,7 @@
 
   int64_t start = TimeMillis(), finish;
   for (int i = 0; i < kRepetitions; ++i) {
-    LogMessageForTesting(__FILE__, __LINE__, LS_SENSITIVE).stream() << message;
+    LogMessageForTesting(__FILE__, __LINE__, LS_VERBOSE).stream() << message;
   }
   finish = TimeMillis();
 
diff --git a/rtc_base/macifaddrs_converter.cc b/rtc_base/mac_ifaddrs_converter.cc
similarity index 100%
rename from rtc_base/macifaddrs_converter.cc
rename to rtc_base/mac_ifaddrs_converter.cc
diff --git a/rtc_base/macutils.cc b/rtc_base/mac_utils.cc
similarity index 95%
rename from rtc_base/macutils.cc
rename to rtc_base/mac_utils.cc
index 2b8700f..390f183 100644
--- a/rtc_base/macutils.cc
+++ b/rtc_base/mac_utils.cc
@@ -15,8 +15,7 @@
 
 #include "rtc_base/checks.h"
 #include "rtc_base/logging.h"
-#include "rtc_base/macutils.h"
-#include "rtc_base/stringutils.h"
+#include "rtc_base/mac_utils.h"
 
 namespace rtc {
 
diff --git a/rtc_base/macutils.h b/rtc_base/mac_utils.h
similarity index 86%
rename from rtc_base/macutils.h
rename to rtc_base/mac_utils.h
index b22e5f9..ae97c3a 100644
--- a/rtc_base/macutils.h
+++ b/rtc_base/mac_utils.h
@@ -8,8 +8,8 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#ifndef RTC_BASE_MACUTILS_H_
-#define RTC_BASE_MACUTILS_H_
+#ifndef RTC_BASE_MAC_UTILS_H_
+#define RTC_BASE_MAC_UTILS_H_
 
 #include <CoreFoundation/CoreFoundation.h>
 #include <string>
@@ -19,4 +19,4 @@
 bool ToUtf16(const std::string& str8, CFStringRef* str16);
 }  // namespace rtc
 
-#endif  // RTC_BASE_MACUTILS_H_
+#endif  // RTC_BASE_MAC_UTILS_H_
diff --git a/rtc_base/mdns_responder_interface.h b/rtc_base/mdns_responder_interface.h
index 71938b2..96280a7 100644
--- a/rtc_base/mdns_responder_interface.h
+++ b/rtc_base/mdns_responder_interface.h
@@ -14,7 +14,7 @@
 #include <functional>
 #include <string>
 
-#include "rtc_base/ipaddress.h"
+#include "rtc_base/ip_address.h"
 
 namespace webrtc {
 
diff --git a/rtc_base/memory/aligned_array.h b/rtc_base/memory/aligned_array.h
index dcdef12..c67d87d 100644
--- a/rtc_base/memory/aligned_array.h
+++ b/rtc_base/memory/aligned_array.h
@@ -11,6 +11,8 @@
 #ifndef RTC_BASE_MEMORY_ALIGNED_ARRAY_H_
 #define RTC_BASE_MEMORY_ALIGNED_ARRAY_H_
 
+#include <stddef.h>
+
 #include "rtc_base/checks.h"
 #include "rtc_base/memory/aligned_malloc.h"
 
diff --git a/rtc_base/memory_stream.cc b/rtc_base/memory_stream.cc
index 541de07..a30aacd 100644
--- a/rtc_base/memory_stream.cc
+++ b/rtc_base/memory_stream.cc
@@ -8,8 +8,11 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
+#include <errno.h>
+#include <string.h>
 #include <algorithm>
 
+#include "rtc_base/checks.h"
 #include "rtc_base/memory_stream.h"
 
 namespace rtc {
@@ -88,6 +91,10 @@
   return true;
 }
 
+void MemoryStream::Rewind() {
+  seek_position_ = 0;
+}
+
 bool MemoryStream::GetSize(size_t* size) const {
   if (size)
     *size = data_length_;
diff --git a/rtc_base/memory_stream.h b/rtc_base/memory_stream.h
index 936f71b..bdcc40d 100644
--- a/rtc_base/memory_stream.h
+++ b/rtc_base/memory_stream.h
@@ -11,6 +11,8 @@
 #ifndef RTC_BASE_MEMORY_STREAM_H_
 #define RTC_BASE_MEMORY_STREAM_H_
 
+#include <stddef.h>
+
 #include "rtc_base/stream.h"
 
 namespace rtc {
@@ -34,10 +36,12 @@
                      size_t* bytes_written,
                      int* error) override;
   void Close() override;
-  bool SetPosition(size_t position) override;
-  bool GetPosition(size_t* position) const override;
-  bool GetSize(size_t* size) const override;
-  bool ReserveSize(size_t size) override;
+  bool GetSize(size_t* size) const;
+  bool ReserveSize(size_t size);
+
+  bool SetPosition(size_t position);
+  bool GetPosition(size_t* position) const;
+  void Rewind();
 
   char* GetBuffer() { return buffer_; }
   const char* GetBuffer() const { return buffer_; }
diff --git a/rtc_base/memory_usage.cc b/rtc_base/memory_usage.cc
index 9cd36d3..20db9f3 100644
--- a/rtc_base/memory_usage.cc
+++ b/rtc_base/memory_usage.cc
@@ -13,15 +13,13 @@
 #if defined(WEBRTC_LINUX)
 #include <unistd.h>
 #include <cstdio>
-#include <cstdlib>
-#include <cstring>
 #elif defined(WEBRTC_MAC)
 #include <mach/mach.h>
 #elif defined(WEBRTC_WIN)
 // clang-format off
 // clang formating would change include order.
 #include <windows.h>
-#include <psapi.h> // must come after windows.h
+#include <psapi.h>  // must come after windows.h
 // clang-format on
 #endif
 
diff --git a/rtc_base/memory_usage_unittest.cc b/rtc_base/memory_usage_unittest.cc
index 9c82f98..a928efb 100644
--- a/rtc_base/memory_usage_unittest.cc
+++ b/rtc_base/memory_usage_unittest.cc
@@ -9,7 +9,7 @@
  */
 
 #include "rtc_base/memory_usage.h"
-#include <cstdio>
+
 #include "test/gtest.h"
 
 namespace rtc {
diff --git a/rtc_base/message_buffer_reader.h b/rtc_base/message_buffer_reader.h
index baba89e..32b8f33 100644
--- a/rtc_base/message_buffer_reader.h
+++ b/rtc_base/message_buffer_reader.h
@@ -11,7 +11,7 @@
 #ifndef RTC_BASE_MESSAGE_BUFFER_READER_H_
 #define RTC_BASE_MESSAGE_BUFFER_READER_H_
 
-#include "rtc_base/bytebuffer.h"
+#include "rtc_base/byte_buffer.h"
 
 namespace webrtc {
 
diff --git a/rtc_base/messagedigest.cc b/rtc_base/message_digest.cc
similarity index 98%
rename from rtc_base/messagedigest.cc
rename to rtc_base/message_digest.cc
index 5a0d16a..b1d4a48 100644
--- a/rtc_base/messagedigest.cc
+++ b/rtc_base/message_digest.cc
@@ -8,14 +8,14 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#include "rtc_base/messagedigest.h"
+#include "rtc_base/message_digest.h"
 
 #include <string.h>
 #include <cstdint>
 #include <memory>
 
-#include "rtc_base/openssldigest.h"
-#include "rtc_base/stringencode.h"
+#include "rtc_base/openssl_digest.h"
+#include "rtc_base/string_encode.h"
 
 namespace rtc {
 
diff --git a/rtc_base/messagedigest.h b/rtc_base/message_digest.h
similarity index 97%
rename from rtc_base/messagedigest.h
rename to rtc_base/message_digest.h
index 757f914..bbb22cf 100644
--- a/rtc_base/messagedigest.h
+++ b/rtc_base/message_digest.h
@@ -8,8 +8,8 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#ifndef RTC_BASE_MESSAGEDIGEST_H_
-#define RTC_BASE_MESSAGEDIGEST_H_
+#ifndef RTC_BASE_MESSAGE_DIGEST_H_
+#define RTC_BASE_MESSAGE_DIGEST_H_
 
 #include <stddef.h>
 #include <string>
@@ -126,4 +126,4 @@
 
 }  // namespace rtc
 
-#endif  // RTC_BASE_MESSAGEDIGEST_H_
+#endif  // RTC_BASE_MESSAGE_DIGEST_H_
diff --git a/rtc_base/messagedigest_unittest.cc b/rtc_base/message_digest_unittest.cc
similarity index 98%
rename from rtc_base/messagedigest_unittest.cc
rename to rtc_base/message_digest_unittest.cc
index 5524b18..85e9bbd 100644
--- a/rtc_base/messagedigest_unittest.cc
+++ b/rtc_base/message_digest_unittest.cc
@@ -8,9 +8,10 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#include "rtc_base/messagedigest.h"
-#include "rtc_base/gunit.h"
-#include "rtc_base/stringencode.h"
+#include "rtc_base/message_digest.h"
+
+#include "rtc_base/string_encode.h"
+#include "test/gtest.h"
 
 namespace rtc {
 
diff --git a/rtc_base/messagehandler.cc b/rtc_base/message_handler.cc
similarity index 87%
rename from rtc_base/messagehandler.cc
rename to rtc_base/message_handler.cc
index 7376def..0e6c237 100644
--- a/rtc_base/messagehandler.cc
+++ b/rtc_base/message_handler.cc
@@ -8,8 +8,8 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#include "rtc_base/messagehandler.h"
-#include "rtc_base/messagequeue.h"
+#include "rtc_base/message_handler.h"
+#include "rtc_base/message_queue.h"
 
 namespace rtc {
 
diff --git a/rtc_base/messagehandler.h b/rtc_base/message_handler.h
similarity index 86%
rename from rtc_base/messagehandler.h
rename to rtc_base/message_handler.h
index 0c40853..015255e 100644
--- a/rtc_base/messagehandler.h
+++ b/rtc_base/message_handler.h
@@ -8,12 +8,12 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#ifndef RTC_BASE_MESSAGEHANDLER_H_
-#define RTC_BASE_MESSAGEHANDLER_H_
+#ifndef RTC_BASE_MESSAGE_HANDLER_H_
+#define RTC_BASE_MESSAGE_HANDLER_H_
 
 #include <utility>
 
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace rtc {
 
@@ -55,7 +55,8 @@
 template <class FunctorT>
 class FunctorMessageHandler<void, FunctorT> : public MessageHandler {
  public:
-  explicit FunctorMessageHandler(const FunctorT& functor) : functor_(functor) {}
+  explicit FunctorMessageHandler(FunctorT&& functor)
+      : functor_(std::forward<FunctorT>(functor)) {}
   virtual void OnMessage(Message* msg) { functor_(); }
   void result() const {}
   void MoveResult() {}
@@ -66,4 +67,4 @@
 
 }  // namespace rtc
 
-#endif  // RTC_BASE_MESSAGEHANDLER_H_
+#endif  // RTC_BASE_MESSAGE_HANDLER_H_
diff --git a/rtc_base/messagequeue.cc b/rtc_base/message_queue.cc
similarity index 99%
rename from rtc_base/messagequeue.cc
rename to rtc_base/message_queue.cc
index 204952a..abb01b3 100644
--- a/rtc_base/messagequeue.cc
+++ b/rtc_base/message_queue.cc
@@ -11,12 +11,12 @@
 #include <string>
 #include <utility>
 
-#include "rtc_base/atomicops.h"
+#include "rtc_base/atomic_ops.h"
 #include "rtc_base/checks.h"
 #include "rtc_base/logging.h"
-#include "rtc_base/messagequeue.h"
+#include "rtc_base/message_queue.h"
 #include "rtc_base/thread.h"
-#include "rtc_base/timeutils.h"
+#include "rtc_base/time_utils.h"
 #include "rtc_base/trace_event.h"
 
 namespace rtc {
diff --git a/rtc_base/messagequeue.h b/rtc_base/message_queue.h
similarity index 97%
rename from rtc_base/messagequeue.h
rename to rtc_base/message_queue.h
index c1b9b5a..5a6bd0a 100644
--- a/rtc_base/messagequeue.h
+++ b/rtc_base/message_queue.h
@@ -8,8 +8,8 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#ifndef RTC_BASE_MESSAGEQUEUE_H_
-#define RTC_BASE_MESSAGEQUEUE_H_
+#ifndef RTC_BASE_MESSAGE_QUEUE_H_
+#define RTC_BASE_MESSAGE_QUEUE_H_
 
 #include <string.h>
 
@@ -19,12 +19,12 @@
 #include <queue>
 #include <vector>
 
-#include "rtc_base/constructormagic.h"
-#include "rtc_base/criticalsection.h"
+#include "api/scoped_refptr.h"
+#include "rtc_base/constructor_magic.h"
+#include "rtc_base/critical_section.h"
 #include "rtc_base/location.h"
-#include "rtc_base/messagehandler.h"
-#include "rtc_base/scoped_ref_ptr.h"
-#include "rtc_base/socketserver.h"
+#include "rtc_base/message_handler.h"
+#include "rtc_base/socket_server.h"
 #include "rtc_base/third_party/sigslot/sigslot.h"
 #include "rtc_base/thread_annotations.h"
 
@@ -330,4 +330,4 @@
 
 }  // namespace rtc
 
-#endif  // RTC_BASE_MESSAGEQUEUE_H_
+#endif  // RTC_BASE_MESSAGE_QUEUE_H_
diff --git a/rtc_base/messagequeue_unittest.cc b/rtc_base/message_queue_unittest.cc
similarity index 96%
rename from rtc_base/messagequeue_unittest.cc
rename to rtc_base/message_queue_unittest.cc
index d8e8b11..657949c 100644
--- a/rtc_base/messagequeue_unittest.cc
+++ b/rtc_base/message_queue_unittest.cc
@@ -8,22 +8,23 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#include "rtc_base/messagequeue.h"
+#include "rtc_base/message_queue.h"
 
 #include <functional>
 
-#include "rtc_base/atomicops.h"
+#include "rtc_base/atomic_ops.h"
 #include "rtc_base/bind.h"
 #include "rtc_base/event.h"
 #include "rtc_base/gunit.h"
 #include "rtc_base/logging.h"
-#include "rtc_base/nullsocketserver.h"
-#include "rtc_base/refcount.h"
-#include "rtc_base/refcountedobject.h"
+#include "rtc_base/null_socket_server.h"
+#include "rtc_base/ref_count.h"
+#include "rtc_base/ref_counted_object.h"
 #include "rtc_base/thread.h"
-#include "rtc_base/timeutils.h"
+#include "rtc_base/time_utils.h"
 
-using namespace rtc;
+namespace rtc {
+namespace {
 
 class MessageQueueTest : public testing::Test, public MessageQueue {
  public:
@@ -231,3 +232,6 @@
   t->Post(RTC_FROM_HERE, &handler, 0,
           new ScopedRefMessageData<RefCountedHandler>(inner_handler));
 }
+
+}  // namespace
+}  // namespace rtc
diff --git a/rtc_base/module.mk b/rtc_base/module.mk
index 8364fe5..61f2dd1 100644
--- a/rtc_base/module.mk
+++ b/rtc_base/module.mk
@@ -6,14 +6,13 @@
 
 rtc_base_approved_generic_CXX_OBJECTS = \
 	rtc_base/third_party/base64/base64.o \
-	rtc_base/bitbuffer.o \
-	rtc_base/bitrateallocationstrategy.o \
-	rtc_base/bufferqueue.o \
-	rtc_base/bytebuffer.o \
-	rtc_base/copyonwritebuffer.o \
-	rtc_base/criticalsection.o \
+	rtc_base/bit_buffer.o \
+	rtc_base/bitrate_allocation_strategy.o \
+	rtc_base/buffer_queue.o \
+	rtc_base/byte_buffer.o \
+	rtc_base/copy_on_write_buffer.o \
+	rtc_base/critical_section.o \
 	rtc_base/event_tracer.o \
-	rtc_base/file.o \
 	rtc_base/flags.o \
 	rtc_base/location.o \
 	rtc_base/numerics/histogram_percentile_counter.o \
@@ -23,21 +22,23 @@
 	rtc_base/race_checker.o \
 	rtc_base/random.o \
 	rtc_base/rate_statistics.o \
-	rtc_base/ratetracker.o \
+	rtc_base/rate_tracker.o \
 	rtc_base/string_to_number.o \
-	rtc_base/stringencode.o \
+	rtc_base/string_encode.o \
 	rtc_base/thread_checker_impl.o \
-	rtc_base/timestampaligner.o \
-	rtc_base/timeutils.o \
+	rtc_base/timestamp_aligner.o \
+	rtc_base/time_utils.o \
 	rtc_base/zero_memory.o \
-	rtc_base/file_posix.o \
 	rtc_base/event.o \
 	rtc_base/logging.o \
 
 # requires libevent at link
 task_queue_impl_CXX_OBJECTS = \
-	rtc_base/task_queue_libevent.o \
-	rtc_base/task_queue_posix.o
+	api/task_queue/default_task_queue_factory_libevent.o \
+	api/task_queue/global_task_queue_factory.o \
+	api/task_queue/task_queue_base.o \
+	rtc_base/task_queue.o \
+	rtc_base/task_queue_libevent.o
 
 rtc_base_CXX_OBJECTS = \
 	rtc_base/checks.o \
@@ -48,7 +49,7 @@
 
 stringutils_CXX_OBJECTS = \
 	rtc_base/strings/string_builder.o \
-	rtc_base/stringutils.o
+	rtc_base/string_utils.o
 
 CXX_STATIC_LIBRARY(rtc_base/librtc_base.pic.a): \
 	CPPFLAGS+= -DWEBRTC_POSIX -DWEBRTC_LINUX
diff --git a/rtc_base/natserver.cc b/rtc_base/nat_server.cc
similarity index 98%
rename from rtc_base/natserver.cc
rename to rtc_base/nat_server.cc
index b005eca..2b614e8 100644
--- a/rtc_base/natserver.cc
+++ b/rtc_base/nat_server.cc
@@ -12,9 +12,9 @@
 
 #include "rtc_base/checks.h"
 #include "rtc_base/logging.h"
-#include "rtc_base/natserver.h"
-#include "rtc_base/natsocketfactory.h"
-#include "rtc_base/socketadapters.h"
+#include "rtc_base/nat_server.h"
+#include "rtc_base/nat_socket_factory.h"
+#include "rtc_base/socket_adapters.h"
 
 namespace rtc {
 
diff --git a/rtc_base/natserver.h b/rtc_base/nat_server.h
similarity index 92%
rename from rtc_base/natserver.h
rename to rtc_base/nat_server.h
index d16b537..46f01e9 100644
--- a/rtc_base/natserver.h
+++ b/rtc_base/nat_server.h
@@ -8,18 +8,18 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#ifndef RTC_BASE_NATSERVER_H_
-#define RTC_BASE_NATSERVER_H_
+#ifndef RTC_BASE_NAT_SERVER_H_
+#define RTC_BASE_NAT_SERVER_H_
 
 #include <map>
 #include <set>
 
-#include "rtc_base/asyncudpsocket.h"
-#include "rtc_base/constructormagic.h"
-#include "rtc_base/nattypes.h"
-#include "rtc_base/proxyserver.h"
-#include "rtc_base/socketaddresspair.h"
-#include "rtc_base/socketfactory.h"
+#include "rtc_base/async_udp_socket.h"
+#include "rtc_base/constructor_magic.h"
+#include "rtc_base/nat_types.h"
+#include "rtc_base/proxy_server.h"
+#include "rtc_base/socket_address_pair.h"
+#include "rtc_base/socket_factory.h"
 #include "rtc_base/thread.h"
 
 namespace rtc {
@@ -126,4 +126,4 @@
 
 }  // namespace rtc
 
-#endif  // RTC_BASE_NATSERVER_H_
+#endif  // RTC_BASE_NAT_SERVER_H_
diff --git a/rtc_base/natsocketfactory.cc b/rtc_base/nat_socket_factory.cc
similarity index 99%
rename from rtc_base/natsocketfactory.cc
rename to rtc_base/nat_socket_factory.cc
index a707ce0..6d44651 100644
--- a/rtc_base/natsocketfactory.cc
+++ b/rtc_base/nat_socket_factory.cc
@@ -8,13 +8,13 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#include "rtc_base/natsocketfactory.h"
+#include "rtc_base/nat_socket_factory.h"
 
 #include "rtc_base/arraysize.h"
 #include "rtc_base/checks.h"
 #include "rtc_base/logging.h"
-#include "rtc_base/natserver.h"
-#include "rtc_base/virtualsocketserver.h"
+#include "rtc_base/nat_server.h"
+#include "rtc_base/virtual_socket_server.h"
 
 namespace rtc {
 
diff --git a/rtc_base/natsocketfactory.h b/rtc_base/nat_socket_factory.h
similarity index 92%
rename from rtc_base/natsocketfactory.h
rename to rtc_base/nat_socket_factory.h
index 97961d4..9b5cb5a 100644
--- a/rtc_base/natsocketfactory.h
+++ b/rtc_base/nat_socket_factory.h
@@ -8,18 +8,23 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#ifndef RTC_BASE_NATSOCKETFACTORY_H_
-#define RTC_BASE_NATSOCKETFACTORY_H_
+#ifndef RTC_BASE_NAT_SOCKET_FACTORY_H_
+#define RTC_BASE_NAT_SOCKET_FACTORY_H_
 
+#include <stddef.h>
 #include <map>
 #include <memory>
 #include <set>
-#include <string>
 
-#include "rtc_base/constructormagic.h"
-#include "rtc_base/natserver.h"
-#include "rtc_base/socketaddress.h"
-#include "rtc_base/socketserver.h"
+#include "rtc_base/async_socket.h"
+#include "rtc_base/constructor_magic.h"
+#include "rtc_base/message_queue.h"
+#include "rtc_base/nat_server.h"
+#include "rtc_base/nat_types.h"
+#include "rtc_base/socket.h"
+#include "rtc_base/socket_address.h"
+#include "rtc_base/socket_factory.h"
+#include "rtc_base/socket_server.h"
 
 namespace rtc {
 
@@ -80,6 +85,7 @@
 class NATSocketServer : public SocketServer, public NATInternalSocketFactory {
  public:
   class Translator;
+
   // holds a list of NATs
   class TranslatorMap : private std::map<SocketAddress, Translator*> {
    public:
@@ -169,4 +175,4 @@
                             SocketAddress* remote_addr);
 }  // namespace rtc
 
-#endif  // RTC_BASE_NATSOCKETFACTORY_H_
+#endif  // RTC_BASE_NAT_SOCKET_FACTORY_H_
diff --git a/rtc_base/nattypes.cc b/rtc_base/nat_types.cc
similarity index 97%
rename from rtc_base/nattypes.cc
rename to rtc_base/nat_types.cc
index a7af57d..50d7de0 100644
--- a/rtc_base/nattypes.cc
+++ b/rtc_base/nat_types.cc
@@ -8,7 +8,7 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#include "rtc_base/nattypes.h"
+#include "rtc_base/nat_types.h"
 
 #include "rtc_base/checks.h"
 
diff --git a/rtc_base/nattypes.h b/rtc_base/nat_types.h
similarity index 92%
rename from rtc_base/nattypes.h
rename to rtc_base/nat_types.h
index 1d816ac..60e7fbd 100644
--- a/rtc_base/nattypes.h
+++ b/rtc_base/nat_types.h
@@ -8,8 +8,8 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#ifndef RTC_BASE_NATTYPES_H_
-#define RTC_BASE_NATTYPES_H_
+#ifndef RTC_BASE_NAT_TYPES_H_
+#define RTC_BASE_NAT_TYPES_H_
 
 namespace rtc {
 
@@ -44,4 +44,4 @@
 
 }  // namespace rtc
 
-#endif  // RTC_BASE_NATTYPES_H_
+#endif  // RTC_BASE_NAT_TYPES_H_
diff --git a/rtc_base/nat_unittest.cc b/rtc_base/nat_unittest.cc
index ee94427..7a0761e 100644
--- a/rtc_base/nat_unittest.cc
+++ b/rtc_base/nat_unittest.cc
@@ -8,23 +8,37 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
+#include <string.h>
 #include <algorithm>
 #include <memory>
 #include <string>
+#include <vector>
 
 #include "absl/memory/memory.h"
-#include "rtc_base/asynctcpsocket.h"
+#include "rtc_base/async_packet_socket.h"
+#include "rtc_base/async_socket.h"
+#include "rtc_base/async_tcp_socket.h"
+#include "rtc_base/async_udp_socket.h"
 #include "rtc_base/gunit.h"
+#include "rtc_base/ip_address.h"
 #include "rtc_base/logging.h"
-#include "rtc_base/natserver.h"
-#include "rtc_base/natsocketfactory.h"
-#include "rtc_base/nethelpers.h"
+#include "rtc_base/nat_server.h"
+#include "rtc_base/nat_socket_factory.h"
+#include "rtc_base/nat_types.h"
+#include "rtc_base/net_helpers.h"
 #include "rtc_base/network.h"
-#include "rtc_base/physicalsocketserver.h"
-#include "rtc_base/testclient.h"
-#include "rtc_base/virtualsocketserver.h"
+#include "rtc_base/physical_socket_server.h"
+#include "rtc_base/socket_address.h"
+#include "rtc_base/socket_factory.h"
+#include "rtc_base/socket_server.h"
+#include "rtc_base/test_client.h"
+#include "rtc_base/third_party/sigslot/sigslot.h"
+#include "rtc_base/thread.h"
+#include "rtc_base/virtual_socket_server.h"
+#include "test/gtest.h"
 
-using namespace rtc;
+namespace rtc {
+namespace {
 
 bool CheckReceive(TestClient* client,
                   bool should_receive,
@@ -207,7 +221,6 @@
 
 void TestPhysicalInternal(const SocketAddress& int_addr) {
   BasicNetworkManager network_manager;
-  network_manager.set_ipv6_enabled(true);
   network_manager.StartUpdating();
   // Process pending messages so the network list is updated.
   Thread::Current()->ProcessMessages(0);
@@ -387,4 +400,6 @@
   out->Send(buf, len);
   EXPECT_TRUE(in->CheckNextPacket(buf, len, &trans_addr));
 }
-// #endif
+
+}  // namespace
+}  // namespace rtc
diff --git a/rtc_base/nethelper.cc b/rtc_base/net_helper.cc
similarity index 94%
rename from rtc_base/nethelper.cc
rename to rtc_base/net_helper.cc
index e654fe3..7dcb599 100644
--- a/rtc_base/nethelper.cc
+++ b/rtc_base/net_helper.cc
@@ -8,10 +8,10 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#include "rtc_base/nethelper.h"
+#include "rtc_base/net_helper.h"
 
 #include "rtc_base/checks.h"
-#include "rtc_base/ipaddress.h"
+#include "rtc_base/ip_address.h"
 
 namespace cricket {
 
diff --git a/rtc_base/nethelper.h b/rtc_base/net_helper.h
similarity index 90%
rename from rtc_base/nethelper.h
rename to rtc_base/net_helper.h
index f956138..e42502b 100644
--- a/rtc_base/nethelper.h
+++ b/rtc_base/net_helper.h
@@ -7,8 +7,8 @@
  *  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_NETHELPER_H_
-#define RTC_BASE_NETHELPER_H_
+#ifndef RTC_BASE_NET_HELPER_H_
+#define RTC_BASE_NET_HELPER_H_
 
 #include <string>
 
@@ -29,4 +29,4 @@
 
 }  // namespace cricket
 
-#endif  // RTC_BASE_NETHELPER_H_
+#endif  // RTC_BASE_NET_HELPER_H_
diff --git a/rtc_base/nethelpers.cc b/rtc_base/net_helpers.cc
similarity index 98%
rename from rtc_base/nethelpers.cc
rename to rtc_base/net_helpers.cc
index 1bba3b4..c662f1a 100644
--- a/rtc_base/nethelpers.cc
+++ b/rtc_base/net_helpers.cc
@@ -8,7 +8,7 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#include "rtc_base/nethelpers.h"
+#include "rtc_base/net_helpers.h"
 
 #include <memory>
 
@@ -19,14 +19,14 @@
 #endif
 #if defined(WEBRTC_POSIX) && !defined(__native_client__)
 #if defined(WEBRTC_ANDROID)
-#include "rtc_base/ifaddrs-android.h"
+#include "rtc_base/ifaddrs_android.h"
 #else
 #include <ifaddrs.h>
 #endif
 #endif  // defined(WEBRTC_POSIX) && !defined(__native_client__)
 
 #include "rtc_base/logging.h"
-#include "rtc_base/signalthread.h"
+#include "rtc_base/signal_thread.h"
 #include "rtc_base/third_party/sigslot/sigslot.h"  // for signal_with_thread...
 
 namespace rtc {
diff --git a/rtc_base/nethelpers.h b/rtc_base/net_helpers.h
similarity index 86%
rename from rtc_base/nethelpers.h
rename to rtc_base/net_helpers.h
index 138f958..6f75318 100644
--- a/rtc_base/nethelpers.h
+++ b/rtc_base/net_helpers.h
@@ -8,8 +8,8 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#ifndef RTC_BASE_NETHELPERS_H_
-#define RTC_BASE_NETHELPERS_H_
+#ifndef RTC_BASE_NET_HELPERS_H_
+#define RTC_BASE_NET_HELPERS_H_
 
 #if defined(WEBRTC_POSIX)
 #include <sys/socket.h>
@@ -19,10 +19,10 @@
 
 #include <vector>
 
-#include "rtc_base/asyncresolverinterface.h"
-#include "rtc_base/ipaddress.h"
-#include "rtc_base/signalthread.h"
-#include "rtc_base/socketaddress.h"
+#include "rtc_base/async_resolver_interface.h"
+#include "rtc_base/ip_address.h"
+#include "rtc_base/signal_thread.h"
+#include "rtc_base/socket_address.h"
 
 namespace rtc {
 
@@ -60,4 +60,4 @@
 bool HasIPv6Enabled();
 }  // namespace rtc
 
-#endif  // RTC_BASE_NETHELPERS_H_
+#endif  // RTC_BASE_NET_HELPERS_H_
diff --git a/rtc_base/network.cc b/rtc_base/network.cc
index 5c7b019..9c9bc57 100644
--- a/rtc_base/network.cc
+++ b/rtc_base/network.cc
@@ -36,11 +36,11 @@
 
 #include "rtc_base/checks.h"
 #include "rtc_base/logging.h"
-#include "rtc_base/networkmonitor.h"
+#include "rtc_base/network_monitor.h"
 #include "rtc_base/socket.h"  // includes something that makes windows happy
-#include "rtc_base/stringencode.h"
+#include "rtc_base/string_encode.h"
+#include "rtc_base/string_utils.h"
 #include "rtc_base/strings/string_builder.h"
-#include "rtc_base/stringutils.h"
 #include "rtc_base/thread.h"
 
 namespace rtc {
@@ -235,7 +235,8 @@
   if (MatchTypeNameWithIndexPattern(network_name, "rmnet") ||
       MatchTypeNameWithIndexPattern(network_name, "rmnet_data") ||
       MatchTypeNameWithIndexPattern(network_name, "v4-rmnet") ||
-      MatchTypeNameWithIndexPattern(network_name, "v4-rmnet_data")) {
+      MatchTypeNameWithIndexPattern(network_name, "v4-rmnet_data") ||
+      MatchTypeNameWithIndexPattern(network_name, "clat")) {
     return ADAPTER_TYPE_CELLULAR;
   }
   if (MatchTypeNameWithIndexPattern(network_name, "wlan")) {
@@ -264,8 +265,7 @@
 }
 
 NetworkManagerBase::NetworkManagerBase()
-    : enumeration_permission_(NetworkManager::ENUMERATION_ALLOWED),
-      ipv6_enabled_(true) {}
+    : enumeration_permission_(NetworkManager::ENUMERATION_ALLOWED) {}
 
 NetworkManagerBase::~NetworkManagerBase() {
   for (const auto& kv : networks_map_) {
@@ -284,22 +284,20 @@
     ipv4_any_address_network_.reset(
         new rtc::Network("any", "any", ipv4_any_address, 0, ADAPTER_TYPE_ANY));
     ipv4_any_address_network_->set_default_local_address_provider(this);
+    ipv4_any_address_network_->set_mdns_responder_provider(this);
     ipv4_any_address_network_->AddIP(ipv4_any_address);
-    ipv4_any_address_network_->SetMdnsResponder(GetMdnsResponder());
   }
   networks->push_back(ipv4_any_address_network_.get());
 
-  if (ipv6_enabled()) {
-    if (!ipv6_any_address_network_) {
-      const rtc::IPAddress ipv6_any_address(in6addr_any);
-      ipv6_any_address_network_.reset(new rtc::Network(
-          "any", "any", ipv6_any_address, 0, ADAPTER_TYPE_ANY));
-      ipv6_any_address_network_->set_default_local_address_provider(this);
-      ipv6_any_address_network_->AddIP(ipv6_any_address);
-      ipv6_any_address_network_->SetMdnsResponder(GetMdnsResponder());
-    }
-    networks->push_back(ipv6_any_address_network_.get());
+  if (!ipv6_any_address_network_) {
+    const rtc::IPAddress ipv6_any_address(in6addr_any);
+    ipv6_any_address_network_.reset(
+        new rtc::Network("any", "any", ipv6_any_address, 0, ADAPTER_TYPE_ANY));
+    ipv6_any_address_network_->set_default_local_address_provider(this);
+    ipv6_any_address_network_->set_mdns_responder_provider(this);
+    ipv6_any_address_network_->AddIP(ipv6_any_address);
   }
+  networks->push_back(ipv6_any_address_network_.get());
 }
 
 void NetworkManagerBase::GetNetworks(NetworkList* result) const {
@@ -386,7 +384,7 @@
         delete net;
       }
     }
-    networks_map_[key]->SetMdnsResponder(GetMdnsResponder());
+    networks_map_[key]->set_mdns_responder_provider(this);
   }
   // It may still happen that the merged list is a subset of |networks_|.
   // To detect this change, we compare their sizes.
@@ -520,10 +518,6 @@
         cursor->ifa_addr->sa_family != AF_INET6) {
       continue;
     }
-    // Skip IPv6 if not enabled.
-    if (cursor->ifa_addr->sa_family == AF_INET6 && !ipv6_enabled()) {
-      continue;
-    }
     // Convert to InterfaceAddress.
     if (!ifaddrs_converter->ConvertIfAddrsToIPAddress(cursor, &ip, &mask)) {
       continue;
@@ -699,22 +693,20 @@
             break;
           }
           case AF_INET6: {
-            if (ipv6_enabled()) {
-              sockaddr_in6* v6_addr =
-                  reinterpret_cast<sockaddr_in6*>(address->Address.lpSockaddr);
-              scope_id = v6_addr->sin6_scope_id;
-              ip = IPAddress(v6_addr->sin6_addr);
+            sockaddr_in6* v6_addr =
+                reinterpret_cast<sockaddr_in6*>(address->Address.lpSockaddr);
+            scope_id = v6_addr->sin6_scope_id;
+            ip = IPAddress(v6_addr->sin6_addr);
 
-              if (IsIgnoredIPv6(InterfaceAddress(ip))) {
-                continue;
-              }
-
-              break;
-            } else {
+            if (IsIgnoredIPv6(InterfaceAddress(ip))) {
               continue;
             }
+
+            break;
           }
-          default: { continue; }
+          default: {
+            continue;
+          }
         }
 
         IPAddress prefix;
@@ -750,6 +742,7 @@
           std::unique_ptr<Network> network(new Network(
               name, description, prefix, prefix_length, adapter_type));
           network->set_default_local_address_provider(this);
+          network->set_mdns_responder_provider(this);
           network->set_scope_id(scope_id);
           network->AddIP(ip);
           bool ignored = IsIgnoredNetwork(*network);
@@ -1060,6 +1053,13 @@
   return static_cast<IPAddress>(selected_ip);
 }
 
+webrtc::MdnsResponderInterface* Network::GetMdnsResponder() const {
+  if (mdns_responder_provider_ == nullptr) {
+    return nullptr;
+  }
+  return mdns_responder_provider_->GetMdnsResponder();
+}
+
 uint16_t Network::GetCost() const {
   AdapterType type = IsVpn() ? underlying_type_for_vpn_ : type_;
   return ComputeNetworkCostByType(type);
diff --git a/rtc_base/network.h b/rtc_base/network.h
index 8b1a5fc..d202f6e 100644
--- a/rtc_base/network.h
+++ b/rtc_base/network.h
@@ -19,10 +19,10 @@
 #include <string>
 #include <vector>
 
-#include "rtc_base/ipaddress.h"
+#include "rtc_base/ip_address.h"
 #include "rtc_base/mdns_responder_interface.h"
-#include "rtc_base/messagehandler.h"
-#include "rtc_base/networkmonitor.h"
+#include "rtc_base/message_handler.h"
+#include "rtc_base/network_monitor.h"
 #include "rtc_base/third_party/sigslot/sigslot.h"
 
 #if defined(WEBRTC_POSIX)
@@ -57,12 +57,24 @@
 class DefaultLocalAddressProvider {
  public:
   virtual ~DefaultLocalAddressProvider() = default;
+
   // The default local address is the local address used in multi-homed endpoint
   // when the any address (0.0.0.0 or ::) is used as the local address. It's
   // important to check the return value as a IP family may not be enabled.
   virtual bool GetDefaultLocalAddress(int family, IPAddress* ipaddr) const = 0;
 };
 
+class MdnsResponderProvider {
+ public:
+  virtual ~MdnsResponderProvider() = default;
+
+  // Returns the mDNS responder that can be used to obfuscate the local IP
+  // addresses of ICE host candidates by mDNS hostnames.
+  //
+  // The provider MUST outlive the mDNS responder.
+  virtual webrtc::MdnsResponderInterface* GetMdnsResponder() const = 0;
+};
+
 // Generic network manager interface. It provides list of local
 // networks.
 //
@@ -72,7 +84,8 @@
 //
 // This allows constructing a NetworkManager subclass on one thread and
 // passing it into an object that uses it on a different thread.
-class NetworkManager : public DefaultLocalAddressProvider {
+class NetworkManager : public DefaultLocalAddressProvider,
+                       public MdnsResponderProvider {
  public:
   typedef std::vector<Network*> NetworkList;
 
@@ -139,9 +152,8 @@
     }
   };
 
-  // Returns the mDNS responder that can be used to obfuscate the local IP
-  // addresses of ICE host candidates by mDNS hostnames.
-  virtual webrtc::MdnsResponderInterface* GetMdnsResponder() const;
+  // MdnsResponderProvider interface.
+  webrtc::MdnsResponderInterface* GetMdnsResponder() const override;
 };
 
 // Base class for NetworkManager implementations.
@@ -153,12 +165,6 @@
   void GetNetworks(NetworkList* networks) const override;
   void GetAnyAddressNetworks(NetworkList* networks) override;
 
-  // Defaults to true.
-  // TODO(deadbeef): Remove this. Nothing but tests use this; IPv6 is enabled
-  // by default everywhere else.
-  bool ipv6_enabled() const { return ipv6_enabled_; }
-  void set_ipv6_enabled(bool enabled) { ipv6_enabled_ = enabled; }
-
   EnumerationPermission enumeration_permission() const override;
 
   bool GetDefaultLocalAddress(int family, IPAddress* ipaddr) const override;
@@ -194,7 +200,6 @@
   NetworkList networks_;
 
   NetworkMap networks_map_;
-  bool ipv6_enabled_;
 
   std::unique_ptr<rtc::Network> ipv4_any_address_network_;
   std::unique_ptr<rtc::Network> ipv6_any_address_network_;
@@ -310,7 +315,11 @@
     default_local_address_provider_ = provider;
   }
 
-  // Returns the name of the interface this network is associated wtih.
+  void set_mdns_responder_provider(const MdnsResponderProvider* provider) {
+    mdns_responder_provider_ = provider;
+  }
+
+  // Returns the name of the interface this network is associated with.
   const std::string& name() const { return name_; }
 
   // Returns the OS-assigned name for this network. This is useful for
@@ -329,7 +338,7 @@
   // Returns the Network's current idea of the 'best' IP it has.
   // Or return an unset IP if this network has no active addresses.
   // Here is the rule on how we mark the IPv6 address as ignorable for WebRTC.
-  // 1) return all global temporary dynamic and non-deprecrated ones.
+  // 1) return all global temporary dynamic and non-deprecated ones.
   // 2) if #1 not available, return global ones.
   // 3) if #2 not available, use ULA ipv6 as last resort. (ULA stands
   // for unique local address, which is not route-able in open
@@ -361,19 +370,11 @@
   const std::vector<InterfaceAddress>& GetIPs() const { return ips_; }
   // Clear the network's list of addresses.
   void ClearIPs() { ips_.clear(); }
-  // Sets the mDNS responder that can be used to obfuscate the local IP
+  // Returns the mDNS responder that can be used to obfuscate the local IP
   // addresses of host candidates by mDNS names in ICE gathering. After a
   // name-address mapping is created by the mDNS responder, queries for the
   // created name will be resolved by the responder.
-  //
-  // The mDNS responder, if not null, should outlive this rtc::Network.
-  void SetMdnsResponder(webrtc::MdnsResponderInterface* mdns_responder) {
-    mdns_responder_ = mdns_responder;
-  }
-  // Returns the mDNS responder, which is null by default.
-  webrtc::MdnsResponderInterface* GetMdnsResponder() const {
-    return mdns_responder_;
-  }
+  webrtc::MdnsResponderInterface* GetMdnsResponder() const;
 
   // Returns the scope-id of the network's address.
   // Should only be relevant for link-local IPv6 addresses.
@@ -440,13 +441,13 @@
 
  private:
   const DefaultLocalAddressProvider* default_local_address_provider_ = nullptr;
+  const MdnsResponderProvider* mdns_responder_provider_ = nullptr;
   std::string name_;
   std::string description_;
   IPAddress prefix_;
   int prefix_length_;
   std::string key_;
   std::vector<InterfaceAddress> ips_;
-  webrtc::MdnsResponderInterface* mdns_responder_ = nullptr;
   int scope_id_;
   bool ignored_;
   AdapterType type_;
diff --git a/rtc_base/networkmonitor.cc b/rtc_base/network_monitor.cc
similarity index 98%
rename from rtc_base/networkmonitor.cc
rename to rtc_base/network_monitor.cc
index 0185eab..4eb5290 100644
--- a/rtc_base/networkmonitor.cc
+++ b/rtc_base/network_monitor.cc
@@ -8,7 +8,7 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#include "rtc_base/networkmonitor.h"
+#include "rtc_base/network_monitor.h"
 
 #include <stdint.h>
 
diff --git a/rtc_base/networkmonitor.h b/rtc_base/network_monitor.h
similarity index 96%
rename from rtc_base/networkmonitor.h
rename to rtc_base/network_monitor.h
index 1ad7663..ed4464d 100644
--- a/rtc_base/networkmonitor.h
+++ b/rtc_base/network_monitor.h
@@ -8,8 +8,8 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#ifndef RTC_BASE_NETWORKMONITOR_H_
-#define RTC_BASE_NETWORKMONITOR_H_
+#ifndef RTC_BASE_NETWORK_MONITOR_H_
+#define RTC_BASE_NETWORK_MONITOR_H_
 
 #include "rtc_base/network_constants.h"
 #include "rtc_base/third_party/sigslot/sigslot.h"
@@ -120,4 +120,4 @@
 
 }  // namespace rtc
 
-#endif  // RTC_BASE_NETWORKMONITOR_H_
+#endif  // RTC_BASE_NETWORK_MONITOR_H_
diff --git a/rtc_base/networkroute.h b/rtc_base/network_route.h
similarity index 67%
rename from rtc_base/networkroute.h
rename to rtc_base/network_route.h
index 31c0831..6a8f183 100644
--- a/rtc_base/networkroute.h
+++ b/rtc_base/network_route.h
@@ -8,8 +8,8 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#ifndef RTC_BASE_NETWORKROUTE_H_
-#define RTC_BASE_NETWORKROUTE_H_
+#ifndef RTC_BASE_NETWORK_ROUTE_H_
+#define RTC_BASE_NETWORK_ROUTE_H_
 
 #include <stdint.h>
 
@@ -27,17 +27,7 @@
   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.
-  bool operator==(const NetworkRoute& nr) const {
-    return connected == nr.connected &&
-           local_network_id == nr.local_network_id &&
-           remote_network_id == nr.remote_network_id;
-  }
-
-  bool operator!=(const NetworkRoute& nr) const { return !(*this == nr); }
 };
 }  // namespace rtc
 
-#endif  // RTC_BASE_NETWORKROUTE_H_
+#endif  // RTC_BASE_NETWORK_ROUTE_H_
diff --git a/rtc_base/network_unittest.cc b/rtc_base/network_unittest.cc
index cf1cecc..1ba573e 100644
--- a/rtc_base/network_unittest.cc
+++ b/rtc_base/network_unittest.cc
@@ -16,8 +16,8 @@
 #include <vector>
 
 #include "rtc_base/checks.h"
-#include "rtc_base/nethelpers.h"
-#include "rtc_base/networkmonitor.h"
+#include "rtc_base/net_helpers.h"
+#include "rtc_base/network_monitor.h"
 #if defined(WEBRTC_POSIX)
 #include <net/if.h>
 #include <sys/types.h>
@@ -179,6 +179,48 @@
     return addr_list;
   }
 
+  struct sockaddr_in* CreateIpv4Addr(const std::string& ip_string) {
+    struct sockaddr_in* ipv4_addr =
+        static_cast<struct sockaddr_in*>(malloc(sizeof(struct sockaddr_in)));
+    memset(ipv4_addr, 0, sizeof(struct sockaddr_in));
+    ipv4_addr->sin_family = AF_INET;
+    IPAddress ip;
+    IPFromString(ip_string, &ip);
+    ipv4_addr->sin_addr = ip.ipv4_address();
+    return ipv4_addr;
+  }
+
+  // Pointers created here need to be released via ReleaseIfAddrs.
+  struct ifaddrs* AddIpv4Address(struct ifaddrs* list,
+                                 char* if_name,
+                                 const std::string& ipv4_address,
+                                 const std::string& ipv4_netmask) {
+    struct ifaddrs* if_addr = new struct ifaddrs;
+    memset(if_addr, 0, sizeof(struct ifaddrs));
+    if_addr->ifa_name = if_name;
+    if_addr->ifa_addr =
+        reinterpret_cast<struct sockaddr*>(CreateIpv4Addr(ipv4_address));
+    if_addr->ifa_netmask =
+        reinterpret_cast<struct sockaddr*>(CreateIpv4Addr(ipv4_netmask));
+    if_addr->ifa_next = list;
+    if_addr->ifa_flags = IFF_RUNNING;
+    return if_addr;
+  }
+
+  struct ifaddrs* InstallIpv4Network(char* if_name,
+                                     const std::string& ipv4_address,
+                                     const std::string& ipv4_mask,
+                                     BasicNetworkManager& network_manager) {
+    ifaddrs* addr_list = nullptr;
+    addr_list = AddIpv4Address(addr_list, if_name, ipv4_address, ipv4_mask);
+    NetworkManager::NetworkList result;
+    bool changed;
+    NetworkManager::Stats stats;
+    CallConvertIfAddrs(network_manager, addr_list, true, &result);
+    network_manager.MergeNetworkList(result, &changed, &stats);
+    return addr_list;
+  }
+
   void ReleaseIfAddrs(struct ifaddrs* list) {
     struct ifaddrs* if_addr = list;
     while (if_addr != nullptr) {
@@ -624,22 +666,10 @@
   manager.DumpNetworks();
 }
 
-// Test that we can toggle IPv6 on and off.
-// Crashes on Linux. See webrtc:4923.
-#if defined(WEBRTC_LINUX)
-#define MAYBE_TestIPv6Toggle DISABLED_TestIPv6Toggle
-#else
-#define MAYBE_TestIPv6Toggle TestIPv6Toggle
-#endif
-TEST_F(NetworkTest, MAYBE_TestIPv6Toggle) {
+TEST_F(NetworkTest, TestIPv6Toggle) {
   BasicNetworkManager manager;
   bool ipv6_found = false;
   NetworkManager::NetworkList list;
-#if !defined(WEBRTC_WIN)
-  // There should be at least one IPv6 network (fe80::/64 should be in there).
-  // TODO(thaloun): Disabling this test on windows for the moment as the test
-  // machines don't seem to have IPv6 installed on them at all.
-  manager.set_ipv6_enabled(true);
   list = GetNetworks(manager, true);
   for (NetworkManager::NetworkList::iterator it = list.begin();
        it != list.end(); ++it) {
@@ -653,22 +683,6 @@
        it != list.end(); ++it) {
     delete (*it);
   }
-#endif
-  ipv6_found = false;
-  manager.set_ipv6_enabled(false);
-  list = GetNetworks(manager, true);
-  for (NetworkManager::NetworkList::iterator it = list.begin();
-       it != list.end(); ++it) {
-    if ((*it)->prefix().family() == AF_INET6) {
-      ipv6_found = true;
-      break;
-    }
-  }
-  EXPECT_FALSE(ipv6_found);
-  for (NetworkManager::NetworkList::iterator it = list.begin();
-       it != list.end(); ++it) {
-    delete (*it);
-  }
 }
 
 // Test that when network interfaces are sorted and given preference values,
@@ -830,6 +844,8 @@
 // a few cases. Note that UNKNOWN type for non-matching strings has been tested
 // in the above test.
 TEST_F(NetworkTest, TestGetAdapterTypeFromNameMatching) {
+  std::string ipv4_address1 = "192.0.0.121";
+  std::string ipv4_mask = "255.255.255.0";
   std::string ipv6_address1 = "1000:2000:3000:4000:0:0:0:1";
   std::string ipv6_address2 = "1000:2000:3000:8000:0:0:0:1";
   std::string ipv6_mask = "FFFF:FFFF:FFFF:FFFF::";
@@ -850,7 +866,7 @@
   ReleaseIfAddrs(addr_list);
 
   strcpy(if_name, "eth0");
-  addr_list = InstallIpv6Network(if_name, ipv6_address1, ipv6_mask, manager);
+  addr_list = InstallIpv4Network(if_name, ipv4_address1, ipv4_mask, manager);
   EXPECT_EQ(ADAPTER_TYPE_ETHERNET, GetAdapterType(manager));
   ClearNetworks(manager);
   ReleaseIfAddrs(addr_list);
@@ -886,6 +902,12 @@
   EXPECT_EQ(ADAPTER_TYPE_CELLULAR, GetAdapterType(manager));
   ClearNetworks(manager);
   ReleaseIfAddrs(addr_list);
+
+  strcpy(if_name, "clat4");
+  addr_list = InstallIpv4Network(if_name, ipv4_address1, ipv4_mask, manager);
+  EXPECT_EQ(ADAPTER_TYPE_CELLULAR, GetAdapterType(manager));
+  ClearNetworks(manager);
+  ReleaseIfAddrs(addr_list);
 #else
   // TODO(deadbeef): If not iOS or Android, "wlan0" should be treated as
   // "unknown"? Why? This should be fixed if there's no good reason.
diff --git a/rtc_base/nullsocketserver.cc b/rtc_base/null_socket_server.cc
similarity index 95%
rename from rtc_base/nullsocketserver.cc
rename to rtc_base/null_socket_server.cc
index ec042dd..f446b3d 100644
--- a/rtc_base/nullsocketserver.cc
+++ b/rtc_base/null_socket_server.cc
@@ -8,7 +8,7 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#include "rtc_base/nullsocketserver.h"
+#include "rtc_base/null_socket_server.h"
 #include "rtc_base/checks.h"
 
 namespace rtc {
diff --git a/rtc_base/nullsocketserver.h b/rtc_base/null_socket_server.h
similarity index 81%
rename from rtc_base/nullsocketserver.h
rename to rtc_base/null_socket_server.h
index 47a7fa6..da22c79 100644
--- a/rtc_base/nullsocketserver.h
+++ b/rtc_base/null_socket_server.h
@@ -8,13 +8,13 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#ifndef RTC_BASE_NULLSOCKETSERVER_H_
-#define RTC_BASE_NULLSOCKETSERVER_H_
+#ifndef RTC_BASE_NULL_SOCKET_SERVER_H_
+#define RTC_BASE_NULL_SOCKET_SERVER_H_
 
-#include "rtc_base/asyncsocket.h"
+#include "rtc_base/async_socket.h"
 #include "rtc_base/event.h"
 #include "rtc_base/socket.h"
-#include "rtc_base/socketserver.h"
+#include "rtc_base/socket_server.h"
 
 namespace rtc {
 
@@ -35,4 +35,4 @@
 
 }  // namespace rtc
 
-#endif  // RTC_BASE_NULLSOCKETSERVER_H_
+#endif  // RTC_BASE_NULL_SOCKET_SERVER_H_
diff --git a/rtc_base/nullsocketserver_unittest.cc b/rtc_base/null_socket_server_unittest.cc
similarity index 82%
rename from rtc_base/nullsocketserver_unittest.cc
rename to rtc_base/null_socket_server_unittest.cc
index f1d65ea..8268911 100644
--- a/rtc_base/nullsocketserver_unittest.cc
+++ b/rtc_base/null_socket_server_unittest.cc
@@ -8,8 +8,18 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#include "rtc_base/nullsocketserver.h"
+#include "rtc_base/null_socket_server.h"
+
+#include <stdint.h>
+#include <memory>
+
 #include "rtc_base/gunit.h"
+#include "rtc_base/location.h"
+#include "rtc_base/message_handler.h"
+#include "rtc_base/message_queue.h"
+#include "rtc_base/thread.h"
+#include "rtc_base/time_utils.h"
+#include "test/gtest.h"
 
 namespace rtc {
 
diff --git a/rtc_base/numerics/histogram_percentile_counter.h b/rtc_base/numerics/histogram_percentile_counter.h
index 7e5743f..f52513c 100644
--- a/rtc_base/numerics/histogram_percentile_counter.h
+++ b/rtc_base/numerics/histogram_percentile_counter.h
@@ -11,6 +11,7 @@
 #ifndef RTC_BASE_NUMERICS_HISTOGRAM_PERCENTILE_COUNTER_H_
 #define RTC_BASE_NUMERICS_HISTOGRAM_PERCENTILE_COUNTER_H_
 
+#include <stddef.h>
 #include <stdint.h>
 #include <map>
 #include <vector>
diff --git a/rtc_base/numerics/histogram_percentile_counter_unittest.cc b/rtc_base/numerics/histogram_percentile_counter_unittest.cc
index a004dba..6fdaa36 100644
--- a/rtc_base/numerics/histogram_percentile_counter_unittest.cc
+++ b/rtc_base/numerics/histogram_percentile_counter_unittest.cc
@@ -10,6 +10,7 @@
 
 #include "rtc_base/numerics/histogram_percentile_counter.h"
 
+#include <cstdint>
 #include <utility>
 #include <vector>
 
diff --git a/rtc_base/numerics/mathutils.h b/rtc_base/numerics/math_utils.h
similarity index 91%
rename from rtc_base/numerics/mathutils.h
rename to rtc_base/numerics/math_utils.h
index 5036c8f..8a91958 100644
--- a/rtc_base/numerics/mathutils.h
+++ b/rtc_base/numerics/math_utils.h
@@ -8,8 +8,8 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#ifndef RTC_BASE_NUMERICS_MATHUTILS_H_
-#define RTC_BASE_NUMERICS_MATHUTILS_H_
+#ifndef RTC_BASE_NUMERICS_MATH_UTILS_H_
+#define RTC_BASE_NUMERICS_MATH_UTILS_H_
 
 #include <math.h>
 #include <type_traits>
@@ -36,4 +36,4 @@
   return static_cast<unsigned_type>(x) - static_cast<unsigned_type>(y);
 }
 
-#endif  // RTC_BASE_NUMERICS_MATHUTILS_H_
+#endif  // RTC_BASE_NUMERICS_MATH_UTILS_H_
diff --git a/rtc_base/numerics/mod_ops.h b/rtc_base/numerics/mod_ops.h
index 90d3ed8..65618b4 100644
--- a/rtc_base/numerics/mod_ops.h
+++ b/rtc_base/numerics/mod_ops.h
@@ -12,7 +12,6 @@
 #define RTC_BASE_NUMERICS_MOD_OPS_H_
 
 #include <algorithm>
-#include <limits>
 #include <type_traits>
 
 #include "rtc_base/checks.h"
diff --git a/rtc_base/numerics/mod_ops_unittest.cc b/rtc_base/numerics/mod_ops_unittest.cc
index 7b03e65..3bd2034 100644
--- a/rtc_base/numerics/mod_ops_unittest.cc
+++ b/rtc_base/numerics/mod_ops_unittest.cc
@@ -9,6 +9,9 @@
  */
 
 #include "rtc_base/numerics/mod_ops.h"
+
+#include <stdint.h>
+
 #include "test/gtest.h"
 
 namespace webrtc {
diff --git a/rtc_base/numerics/moving_average.h b/rtc_base/numerics/moving_average.h
index 770e47d..1ae26ff 100644
--- a/rtc_base/numerics/moving_average.h
+++ b/rtc_base/numerics/moving_average.h
@@ -11,6 +11,8 @@
 #ifndef RTC_BASE_NUMERICS_MOVING_AVERAGE_H_
 #define RTC_BASE_NUMERICS_MOVING_AVERAGE_H_
 
+#include <stddef.h>
+#include <stdint.h>
 #include <vector>
 
 #include "absl/types/optional.h"
diff --git a/rtc_base/numerics/moving_max_counter.h b/rtc_base/numerics/moving_max_counter.h
index 6c6286d..ca956e9 100644
--- a/rtc_base/numerics/moving_max_counter.h
+++ b/rtc_base/numerics/moving_max_counter.h
@@ -19,7 +19,7 @@
 
 #include "absl/types/optional.h"
 #include "rtc_base/checks.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace rtc {
 
diff --git a/rtc_base/numerics/moving_median_filter.h b/rtc_base/numerics/moving_median_filter.h
index b5c5fce..b4d8741 100644
--- a/rtc_base/numerics/moving_median_filter.h
+++ b/rtc_base/numerics/moving_median_filter.h
@@ -11,10 +11,11 @@
 #ifndef RTC_BASE_NUMERICS_MOVING_MEDIAN_FILTER_H_
 #define RTC_BASE_NUMERICS_MOVING_MEDIAN_FILTER_H_
 
+#include <stddef.h>
 #include <list>
 
 #include "rtc_base/checks.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 #include "rtc_base/numerics/percentile_filter.h"
 
 namespace webrtc {
diff --git a/rtc_base/numerics/moving_median_filter_unittest.cc b/rtc_base/numerics/moving_median_filter_unittest.cc
index 5a6eb3d..41684b2 100644
--- a/rtc_base/numerics/moving_median_filter_unittest.cc
+++ b/rtc_base/numerics/moving_median_filter_unittest.cc
@@ -9,6 +9,9 @@
  */
 
 #include "rtc_base/numerics/moving_median_filter.h"
+
+#include <stdint.h>
+
 #include "test/gtest.h"
 
 namespace webrtc {
diff --git a/rtc_base/numerics/percentile_filter.h b/rtc_base/numerics/percentile_filter.h
index cba4463..4781963 100644
--- a/rtc_base/numerics/percentile_filter.h
+++ b/rtc_base/numerics/percentile_filter.h
@@ -12,7 +12,6 @@
 #define RTC_BASE_NUMERICS_PERCENTILE_FILTER_H_
 
 #include <stdint.h>
-
 #include <iterator>
 #include <set>
 
diff --git a/rtc_base/numerics/percentile_filter_unittest.cc b/rtc_base/numerics/percentile_filter_unittest.cc
index 11fb4a5..8ed6d67 100644
--- a/rtc_base/numerics/percentile_filter_unittest.cc
+++ b/rtc_base/numerics/percentile_filter_unittest.cc
@@ -8,11 +8,13 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
+#include <stdlib.h>
 #include <algorithm>
 #include <climits>
+#include <cstdint>
 #include <random>
 
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 #include "rtc_base/numerics/percentile_filter.h"
 #include "test/gtest.h"
 
@@ -32,9 +34,9 @@
   RTC_DISALLOW_COPY_AND_ASSIGN(PercentileFilterTest);
 };
 
-INSTANTIATE_TEST_CASE_P(PercentileFilterTests,
-                        PercentileFilterTest,
-                        ::testing::Values(0.0f, 0.1f, 0.5f, 0.9f, 1.0f));
+INSTANTIATE_TEST_SUITE_P(PercentileFilterTests,
+                         PercentileFilterTest,
+                         ::testing::Values(0.0f, 0.1f, 0.5f, 0.9f, 1.0f));
 
 TEST(PercentileFilterTest, MinFilter) {
   PercentileFilter<int64_t> filter(0.0f);
diff --git a/rtc_base/numerics/safe_minmax.h b/rtc_base/numerics/safe_minmax.h
index 8d00afb..6c41dfd 100644
--- a/rtc_base/numerics/safe_minmax.h
+++ b/rtc_base/numerics/safe_minmax.h
@@ -42,7 +42,7 @@
 //
 //   2. is no larger than the largest of the three argument types; and
 //
-//   3. has the same signedness as the type of the third argument, if this is
+//   3. has the same signedness as the type of the first argument, if this is
 //      possible without violating the First or Second Law.
 //
 // There is always at least one type that meets criteria 1 and 2. If more than
diff --git a/rtc_base/numerics/sample_counter.cc b/rtc_base/numerics/sample_counter.cc
index bab47f1..7f76b74 100644
--- a/rtc_base/numerics/sample_counter.cc
+++ b/rtc_base/numerics/sample_counter.cc
@@ -57,6 +57,13 @@
   return max_;
 }
 
+absl::optional<int64_t> SampleCounter::Sum(int64_t min_required_samples) const {
+  RTC_DCHECK_GT(min_required_samples, 0);
+  if (num_samples_ < min_required_samples)
+    return absl::nullopt;
+  return sum_;
+}
+
 int64_t SampleCounter::NumSamples() const {
   return num_samples_;
 }
diff --git a/rtc_base/numerics/sample_counter.h b/rtc_base/numerics/sample_counter.h
index 18bd36b..93d39c3 100644
--- a/rtc_base/numerics/sample_counter.h
+++ b/rtc_base/numerics/sample_counter.h
@@ -26,6 +26,7 @@
   void Add(int sample);
   absl::optional<int> Avg(int64_t min_required_samples) const;
   absl::optional<int> Max() const;
+  absl::optional<int64_t> Sum(int64_t min_required_samples) const;
   int64_t NumSamples() const;
   void Reset();
   // Adds all the samples from the |other| SampleCounter as if they were all
diff --git a/rtc_base/numerics/sample_counter_unittest.cc b/rtc_base/numerics/sample_counter_unittest.cc
index 4085370..e87c809 100644
--- a/rtc_base/numerics/sample_counter_unittest.cc
+++ b/rtc_base/numerics/sample_counter_unittest.cc
@@ -10,8 +10,7 @@
 
 #include "rtc_base/numerics/sample_counter.h"
 
-#include <utility>
-#include <vector>
+#include <initializer_list>
 
 #include "test/gmock.h"
 #include "test/gtest.h"
@@ -34,6 +33,7 @@
     counter.Add(value);
   }
   EXPECT_THAT(counter.Avg(kMinSamples), Eq(absl::nullopt));
+  EXPECT_THAT(counter.Sum(kMinSamples), Eq(absl::nullopt));
   EXPECT_THAT(counter.Max(), Eq(5));
 }
 
@@ -44,6 +44,7 @@
     counter.Add(value);
   }
   EXPECT_THAT(counter.Avg(kMinSamples), Eq(3));
+  EXPECT_THAT(counter.Sum(kMinSamples), Eq(15));
   EXPECT_THAT(counter.Max(), Eq(5));
 }
 
diff --git a/rtc_base/numerics/samples_stats_counter.cc b/rtc_base/numerics/samples_stats_counter.cc
new file mode 100644
index 0000000..1348cba
--- /dev/null
+++ b/rtc_base/numerics/samples_stats_counter.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 "rtc_base/numerics/samples_stats_counter.h"
+
+#include <algorithm>
+#include <cmath>
+
+namespace webrtc {
+
+SamplesStatsCounter::SamplesStatsCounter() = default;
+SamplesStatsCounter::~SamplesStatsCounter() = default;
+SamplesStatsCounter::SamplesStatsCounter(const SamplesStatsCounter&) = default;
+SamplesStatsCounter& SamplesStatsCounter::operator=(
+    const SamplesStatsCounter&) = default;
+SamplesStatsCounter::SamplesStatsCounter(SamplesStatsCounter&&) = default;
+SamplesStatsCounter& SamplesStatsCounter::operator=(SamplesStatsCounter&&) =
+    default;
+
+void SamplesStatsCounter::AddSample(double value) {
+  samples_.push_back(value);
+  sorted_ = false;
+  if (value > max_) {
+    max_ = value;
+  }
+  if (value < min_) {
+    min_ = value;
+  }
+  sum_ += value;
+  sum_squared_ += value * value;
+}
+
+double SamplesStatsCounter::GetPercentile(double percentile) {
+  RTC_DCHECK(!IsEmpty());
+  RTC_CHECK_GE(percentile, 0);
+  RTC_CHECK_LE(percentile, 1);
+  if (!sorted_) {
+    std::sort(samples_.begin(), samples_.end());
+    sorted_ = true;
+  }
+  const double raw_rank = percentile * (samples_.size() - 1);
+  double int_part;
+  double fract_part = std::modf(raw_rank, &int_part);
+  size_t rank = static_cast<size_t>(int_part);
+  if (fract_part >= 1.0) {
+    // It can happen due to floating point calculation error.
+    rank++;
+    fract_part -= 1.0;
+  }
+
+  RTC_DCHECK_GE(rank, 0);
+  RTC_DCHECK_LT(rank, samples_.size());
+  RTC_DCHECK_GE(fract_part, 0);
+  RTC_DCHECK_LT(fract_part, 1);
+  RTC_DCHECK(rank + fract_part == raw_rank);
+
+  const double low = samples_[rank];
+  const double high = samples_[std::min(rank + 1, samples_.size() - 1)];
+  return low + fract_part * (high - low);
+}
+
+}  // namespace webrtc
diff --git a/rtc_base/numerics/samples_stats_counter.h b/rtc_base/numerics/samples_stats_counter.h
new file mode 100644
index 0000000..a982b2e
--- /dev/null
+++ b/rtc_base/numerics/samples_stats_counter.h
@@ -0,0 +1,86 @@
+/*
+ *  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 RTC_BASE_NUMERICS_SAMPLES_STATS_COUNTER_H_
+#define RTC_BASE_NUMERICS_SAMPLES_STATS_COUNTER_H_
+
+#include <math.h>
+#include <limits>
+#include <vector>
+
+#include "rtc_base/checks.h"
+
+namespace webrtc {
+
+class SamplesStatsCounter {
+ public:
+  SamplesStatsCounter();
+  ~SamplesStatsCounter();
+  SamplesStatsCounter(const SamplesStatsCounter&);
+  SamplesStatsCounter& operator=(const SamplesStatsCounter&);
+  SamplesStatsCounter(SamplesStatsCounter&&);
+  SamplesStatsCounter& operator=(SamplesStatsCounter&&);
+
+  // Adds sample to the stats in amortized O(1) time.
+  void AddSample(double value);
+
+  // Returns if there are any values in O(1) time.
+  bool IsEmpty() const { return samples_.empty(); }
+
+  // Returns min in O(1) time. This function may not be called if there are no
+  // samples.
+  double GetMin() const {
+    RTC_DCHECK(!IsEmpty());
+    return min_;
+  }
+  // Returns max in O(1) time. This function may not be called if there are no
+  // samples.
+  double GetMax() const {
+    RTC_DCHECK(!IsEmpty());
+    return max_;
+  }
+  // Returns average in O(1) time. This function may not be called if there are
+  // no samples.
+  double GetAverage() const {
+    RTC_DCHECK(!IsEmpty());
+    return sum_ / samples_.size();
+  }
+  // Returns variance in O(1) time. This function may not be called if there are
+  // no samples.
+  double GetVariance() const {
+    RTC_DCHECK(!IsEmpty());
+    return sum_squared_ / samples_.size() - GetAverage() * GetAverage();
+  }
+  // Returns standard deviation in O(1) time. This function may not be called if
+  // there are no samples.
+  double GetStandardDeviation() const {
+    RTC_DCHECK(!IsEmpty());
+    return sqrt(GetVariance());
+  }
+  // Returns percentile in O(nlogn) on first call and in O(1) after, if no
+  // additions were done. This function may not be called if there are no
+  // samples.
+  //
+  // |percentile| has to be in [0; 1]. 0 percentile is the min in the array and
+  // 1 percentile is the max in the array.
+  double GetPercentile(double percentile);
+
+ private:
+  std::vector<double> samples_;
+  double min_ = std::numeric_limits<double>::max();
+  double max_ = std::numeric_limits<double>::min();
+  double sum_ = 0;
+  double sum_squared_ = 0;
+  bool sorted_ = false;
+};
+
+}  // namespace webrtc
+
+#endif  // RTC_BASE_NUMERICS_SAMPLES_STATS_COUNTER_H_
diff --git a/rtc_base/numerics/samples_stats_counter_unittest.cc b/rtc_base/numerics/samples_stats_counter_unittest.cc
new file mode 100644
index 0000000..e6d9f67
--- /dev/null
+++ b/rtc_base/numerics/samples_stats_counter_unittest.cc
@@ -0,0 +1,78 @@
+/*
+ *  Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "rtc_base/numerics/samples_stats_counter.h"
+
+#include <math.h>
+#include <algorithm>
+#include <vector>
+
+#include "test/gtest.h"
+
+namespace webrtc {
+namespace {
+
+SamplesStatsCounter CreateStatsFilledWithIntsFrom1ToN(int n) {
+  std::vector<double> data;
+  for (int i = 1; i <= n; i++) {
+    data.push_back(i);
+  }
+  std::random_shuffle(data.begin(), data.end());
+
+  SamplesStatsCounter stats;
+  for (double v : data) {
+    stats.AddSample(v);
+  }
+  return stats;
+}
+
+}  // namespace
+
+TEST(SamplesStatsCounter, FullSimpleTest) {
+  SamplesStatsCounter stats = CreateStatsFilledWithIntsFrom1ToN(100);
+
+  EXPECT_TRUE(!stats.IsEmpty());
+  EXPECT_DOUBLE_EQ(stats.GetMin(), 1.0);
+  EXPECT_DOUBLE_EQ(stats.GetMax(), 100.0);
+  EXPECT_DOUBLE_EQ(stats.GetAverage(), 50.5);
+  for (int i = 1; i <= 100; i++) {
+    double p = i / 100.0;
+    EXPECT_GE(stats.GetPercentile(p), i);
+    EXPECT_LT(stats.GetPercentile(p), i + 1);
+  }
+}
+
+TEST(SamplesStatsCounter, VarianceAndDeviation) {
+  SamplesStatsCounter stats;
+  stats.AddSample(2);
+  stats.AddSample(2);
+  stats.AddSample(-1);
+  stats.AddSample(5);
+
+  EXPECT_DOUBLE_EQ(stats.GetAverage(), 2.0);
+  EXPECT_DOUBLE_EQ(stats.GetVariance(), 4.5);
+  EXPECT_DOUBLE_EQ(stats.GetStandardDeviation(), sqrt(4.5));
+}
+
+TEST(SamplesStatsCounter, FractionPercentile) {
+  SamplesStatsCounter stats = CreateStatsFilledWithIntsFrom1ToN(5);
+
+  EXPECT_DOUBLE_EQ(stats.GetPercentile(0.5), 3);
+}
+
+TEST(SamplesStatsCounter, TestBorderValues) {
+  SamplesStatsCounter stats = CreateStatsFilledWithIntsFrom1ToN(5);
+
+  EXPECT_GE(stats.GetPercentile(0.01), 1);
+  EXPECT_LT(stats.GetPercentile(0.01), 2);
+  EXPECT_DOUBLE_EQ(stats.GetPercentile(1.0), 5);
+}
+
+}  // namespace webrtc
diff --git a/rtc_base/numerics/sequence_number_util.h b/rtc_base/numerics/sequence_number_util.h
index c55513a..9a7361d 100644
--- a/rtc_base/numerics/sequence_number_util.h
+++ b/rtc_base/numerics/sequence_number_util.h
@@ -11,12 +11,13 @@
 #ifndef RTC_BASE_NUMERICS_SEQUENCE_NUMBER_UTIL_H_
 #define RTC_BASE_NUMERICS_SEQUENCE_NUMBER_UTIL_H_
 
+#include <stdint.h>
 #include <limits>
 #include <type_traits>
 
 #include "absl/types/optional.h"
+#include "rtc_base/checks.h"
 #include "rtc_base/numerics/mod_ops.h"
-#include "rtc_base/numerics/safe_compare.h"
 
 namespace webrtc {
 
diff --git a/rtc_base/numerics/sequence_number_util_unittest.cc b/rtc_base/numerics/sequence_number_util_unittest.cc
index beb2b52..881e017 100644
--- a/rtc_base/numerics/sequence_number_util_unittest.cc
+++ b/rtc_base/numerics/sequence_number_util_unittest.cc
@@ -8,6 +8,8 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
+#include <cstdint>
+#include <iterator>
 #include <set>
 
 #include "rtc_base/numerics/sequence_number_util.h"
diff --git a/rtc_base/onetimeevent.h b/rtc_base/one_time_event.h
similarity index 89%
rename from rtc_base/onetimeevent.h
rename to rtc_base/one_time_event.h
index f649f15..c5ccbf6 100644
--- a/rtc_base/onetimeevent.h
+++ b/rtc_base/one_time_event.h
@@ -8,10 +8,10 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#ifndef RTC_BASE_ONETIMEEVENT_H_
-#define RTC_BASE_ONETIMEEVENT_H_
+#ifndef RTC_BASE_ONE_TIME_EVENT_H_
+#define RTC_BASE_ONE_TIME_EVENT_H_
 
-#include "rtc_base/criticalsection.h"
+#include "rtc_base/critical_section.h"
 
 namespace webrtc {
 // Provides a simple way to perform an operation (such as logging) one
@@ -57,4 +57,4 @@
 
 }  // namespace webrtc
 
-#endif  // RTC_BASE_ONETIMEEVENT_H_
+#endif  // RTC_BASE_ONE_TIME_EVENT_H_
diff --git a/rtc_base/onetimeevent_unittest.cc b/rtc_base/one_time_event_unittest.cc
similarity index 92%
rename from rtc_base/onetimeevent_unittest.cc
rename to rtc_base/one_time_event_unittest.cc
index 49cae07..39fd8f9 100644
--- a/rtc_base/onetimeevent_unittest.cc
+++ b/rtc_base/one_time_event_unittest.cc
@@ -8,8 +8,9 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#include "rtc_base/onetimeevent.h"
-#include "rtc_base/gunit.h"
+#include "rtc_base/one_time_event.h"
+
+#include "test/gtest.h"
 
 namespace webrtc {
 
diff --git a/rtc_base/openssladapter.cc b/rtc_base/openssl_adapter.cc
similarity index 94%
rename from rtc_base/openssladapter.cc
rename to rtc_base/openssl_adapter.cc
index fcfa53b..388b9a0 100644
--- a/rtc_base/openssladapter.cc
+++ b/rtc_base/openssl_adapter.cc
@@ -8,7 +8,7 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#include "rtc_base/openssladapter.h"
+#include "rtc_base/openssl_adapter.h"
 
 #include <errno.h>
 
@@ -26,39 +26,11 @@
 #include "rtc_base/location.h"
 #include "rtc_base/logging.h"
 #include "rtc_base/numerics/safe_conversions.h"
-#include "rtc_base/opensslcertificate.h"
-#include "rtc_base/opensslutility.h"
-#include "rtc_base/stringencode.h"
+#include "rtc_base/openssl_certificate.h"
+#include "rtc_base/openssl_utility.h"
+#include "rtc_base/string_encode.h"
 #include "rtc_base/thread.h"
 
-#ifndef OPENSSL_IS_BORINGSSL
-
-// TODO(benwright): Use a nicer abstraction for mutex.
-
-#if defined(WEBRTC_WIN)
-#define MUTEX_TYPE HANDLE
-#define MUTEX_SETUP(x) (x) = CreateMutex(nullptr, FALSE, nullptr)
-#define MUTEX_CLEANUP(x) CloseHandle(x)
-#define MUTEX_LOCK(x) WaitForSingleObject((x), INFINITE)
-#define MUTEX_UNLOCK(x) ReleaseMutex(x)
-#define THREAD_ID GetCurrentThreadId()
-#elif defined(WEBRTC_POSIX)
-#define MUTEX_TYPE pthread_mutex_t
-#define MUTEX_SETUP(x) pthread_mutex_init(&(x), nullptr)
-#define MUTEX_CLEANUP(x) pthread_mutex_destroy(&(x))
-#define MUTEX_LOCK(x) pthread_mutex_lock(&(x))
-#define MUTEX_UNLOCK(x) pthread_mutex_unlock(&(x))
-#define THREAD_ID pthread_self()
-#else
-#error You must define mutex operations appropriate for your platform!
-#endif
-
-struct CRYPTO_dynlock_value {
-  MUTEX_TYPE mutex;
-};
-
-#endif  // #ifndef OPENSSL_IS_BORINGSSL
-
 //////////////////////////////////////////////////////////////////////
 // SocketBIO
 //////////////////////////////////////////////////////////////////////
@@ -881,17 +853,8 @@
 }
 
 SSL_CTX* OpenSSLAdapter::CreateContext(SSLMode mode, bool enable_cache) {
-  // Use (D)TLS 1.2.
-  // Note: BoringSSL supports a range of versions by setting max/min version
-  // (Default V1.0 to V1.2). However (D)TLSv1_2_client_method functions used
-  // below in OpenSSL only support V1.2.
-  SSL_CTX* ctx = nullptr;
-#ifdef OPENSSL_IS_BORINGSSL
-  ctx = SSL_CTX_new(mode == SSL_MODE_DTLS ? DTLS_method() : TLS_method());
-#else
-  ctx = SSL_CTX_new(mode == SSL_MODE_DTLS ? DTLSv1_2_client_method()
-                                          : TLSv1_2_client_method());
-#endif  // OPENSSL_IS_BORINGSSL
+  SSL_CTX* ctx =
+      SSL_CTX_new(mode == SSL_MODE_DTLS ? DTLS_method() : TLS_method());
   if (ctx == nullptr) {
     unsigned long error = ERR_get_error();  // NOLINT: type used by OpenSSL.
     RTC_LOG(LS_WARNING) << "SSL_CTX creation failed: " << '"'
diff --git a/rtc_base/openssladapter.h b/rtc_base/openssl_adapter.h
similarity index 93%
rename from rtc_base/openssladapter.h
rename to rtc_base/openssl_adapter.h
index 2e3a355..7219671 100644
--- a/rtc_base/openssladapter.h
+++ b/rtc_base/openssl_adapter.h
@@ -8,8 +8,8 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#ifndef RTC_BASE_OPENSSLADAPTER_H_
-#define RTC_BASE_OPENSSLADAPTER_H_
+#ifndef RTC_BASE_OPENSSL_ADAPTER_H_
+#define RTC_BASE_OPENSSL_ADAPTER_H_
 
 #include <stddef.h>
 #include <stdint.h>
@@ -17,18 +17,18 @@
 #include <string>
 #include <vector>
 
-#include "rtc_base/asyncsocket.h"
+#include "rtc_base/async_socket.h"
 #include "rtc_base/buffer.h"
-#include "rtc_base/messagehandler.h"
-#include "rtc_base/messagequeue.h"
-#include "rtc_base/opensslidentity.h"
-#include "rtc_base/opensslsessioncache.h"
+#include "rtc_base/message_handler.h"
+#include "rtc_base/message_queue.h"
+#include "rtc_base/openssl_identity.h"
+#include "rtc_base/openssl_session_cache.h"
 #include "rtc_base/socket.h"
-#include "rtc_base/socketaddress.h"
-#include "rtc_base/ssladapter.h"
-#include "rtc_base/sslcertificate.h"
-#include "rtc_base/sslidentity.h"
-#include "rtc_base/sslstreamadapter.h"
+#include "rtc_base/socket_address.h"
+#include "rtc_base/ssl_adapter.h"
+#include "rtc_base/ssl_certificate.h"
+#include "rtc_base/ssl_identity.h"
+#include "rtc_base/ssl_stream_adapter.h"
 
 namespace rtc {
 
@@ -189,4 +189,4 @@
 
 }  // namespace rtc
 
-#endif  // RTC_BASE_OPENSSLADAPTER_H_
+#endif  // RTC_BASE_OPENSSL_ADAPTER_H_
diff --git a/rtc_base/openssladapter_unittest.cc b/rtc_base/openssl_adapter_unittest.cc
similarity index 98%
rename from rtc_base/openssladapter_unittest.cc
rename to rtc_base/openssl_adapter_unittest.cc
index 4db00e5..2b171e6 100644
--- a/rtc_base/openssladapter_unittest.cc
+++ b/rtc_base/openssl_adapter_unittest.cc
@@ -13,9 +13,9 @@
 #include <vector>
 
 #include "absl/memory/memory.h"
-#include "rtc_base/asyncsocket.h"
+#include "rtc_base/async_socket.h"
 #include "rtc_base/gunit.h"
-#include "rtc_base/openssladapter.h"
+#include "rtc_base/openssl_adapter.h"
 #include "test/gmock.h"
 
 namespace rtc {
diff --git a/rtc_base/opensslcertificate.cc b/rtc_base/openssl_certificate.cc
similarity index 97%
rename from rtc_base/opensslcertificate.cc
rename to rtc_base/openssl_certificate.cc
index 4e61b86..c22e5fb 100644
--- a/rtc_base/opensslcertificate.cc
+++ b/rtc_base/openssl_certificate.cc
@@ -8,7 +8,7 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#include "rtc_base/opensslcertificate.h"
+#include "rtc_base/openssl_certificate.h"
 
 #if defined(WEBRTC_WIN)
 // Must be included first before openssl headers.
@@ -24,10 +24,10 @@
 #include "rtc_base/checks.h"
 #include "rtc_base/helpers.h"
 #include "rtc_base/logging.h"
-#include "rtc_base/messagedigest.h"
-#include "rtc_base/openssldigest.h"
-#include "rtc_base/opensslidentity.h"
-#include "rtc_base/opensslutility.h"
+#include "rtc_base/message_digest.h"
+#include "rtc_base/openssl_digest.h"
+#include "rtc_base/openssl_identity.h"
+#include "rtc_base/openssl_utility.h"
 
 namespace rtc {
 namespace {
diff --git a/rtc_base/opensslcertificate.h b/rtc_base/openssl_certificate.h
similarity index 90%
rename from rtc_base/opensslcertificate.h
rename to rtc_base/openssl_certificate.h
index 088725c..9b61eee 100644
--- a/rtc_base/opensslcertificate.h
+++ b/rtc_base/openssl_certificate.h
@@ -8,8 +8,8 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#ifndef RTC_BASE_OPENSSLCERTIFICATE_H_
-#define RTC_BASE_OPENSSLCERTIFICATE_H_
+#ifndef RTC_BASE_OPENSSL_CERTIFICATE_H_
+#define RTC_BASE_OPENSSL_CERTIFICATE_H_
 
 #include <openssl/ossl_typ.h>
 
@@ -18,9 +18,9 @@
 #include <string>
 
 #include "rtc_base/buffer.h"
-#include "rtc_base/constructormagic.h"
-#include "rtc_base/sslcertificate.h"
-#include "rtc_base/sslidentity.h"
+#include "rtc_base/constructor_magic.h"
+#include "rtc_base/ssl_certificate.h"
+#include "rtc_base/ssl_identity.h"
 
 namespace rtc {
 
@@ -75,4 +75,4 @@
 
 }  // namespace rtc
 
-#endif  // RTC_BASE_OPENSSLCERTIFICATE_H_
+#endif  // RTC_BASE_OPENSSL_CERTIFICATE_H_
diff --git a/rtc_base/openssldigest.cc b/rtc_base/openssl_digest.cc
similarity index 98%
rename from rtc_base/openssldigest.cc
rename to rtc_base/openssl_digest.cc
index da90b65..1cf5bc0 100644
--- a/rtc_base/openssldigest.cc
+++ b/rtc_base/openssl_digest.cc
@@ -8,7 +8,7 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#include "rtc_base/openssldigest.h"
+#include "rtc_base/openssl_digest.h"
 
 #include "rtc_base/checks.h"  // RTC_DCHECK, RTC_CHECK
 #include "rtc_base/openssl.h"
diff --git a/rtc_base/openssldigest.h b/rtc_base/openssl_digest.h
similarity index 89%
rename from rtc_base/openssldigest.h
rename to rtc_base/openssl_digest.h
index 82dc9a9..ee39eb8 100644
--- a/rtc_base/openssldigest.h
+++ b/rtc_base/openssl_digest.h
@@ -8,14 +8,14 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#ifndef RTC_BASE_OPENSSLDIGEST_H_
-#define RTC_BASE_OPENSSLDIGEST_H_
+#ifndef RTC_BASE_OPENSSL_DIGEST_H_
+#define RTC_BASE_OPENSSL_DIGEST_H_
 
-#include <openssl/base.h>
+#include <openssl/ossl_typ.h>
 #include <stddef.h>
 #include <string>
 
-#include "rtc_base/messagedigest.h"
+#include "rtc_base/message_digest.h"
 
 namespace rtc {
 
@@ -46,4 +46,4 @@
 
 }  // namespace rtc
 
-#endif  // RTC_BASE_OPENSSLDIGEST_H_
+#endif  // RTC_BASE_OPENSSL_DIGEST_H_
diff --git a/rtc_base/opensslidentity.cc b/rtc_base/openssl_identity.cc
similarity index 99%
rename from rtc_base/opensslidentity.cc
rename to rtc_base/openssl_identity.cc
index 9850c85..531c971 100644
--- a/rtc_base/opensslidentity.cc
+++ b/rtc_base/openssl_identity.cc
@@ -8,7 +8,7 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#include "rtc_base/opensslidentity.h"
+#include "rtc_base/openssl_identity.h"
 
 #include <memory>
 #include <utility>
@@ -32,7 +32,7 @@
 #include "rtc_base/logging.h"
 #include "rtc_base/numerics/safe_conversions.h"
 #include "rtc_base/openssl.h"
-#include "rtc_base/opensslutility.h"
+#include "rtc_base/openssl_utility.h"
 
 namespace rtc {
 
diff --git a/rtc_base/opensslidentity.h b/rtc_base/openssl_identity.h
similarity index 92%
rename from rtc_base/opensslidentity.h
rename to rtc_base/openssl_identity.h
index fcf7deb..f0c4fb8 100644
--- a/rtc_base/opensslidentity.h
+++ b/rtc_base/openssl_identity.h
@@ -8,8 +8,8 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#ifndef RTC_BASE_OPENSSLIDENTITY_H_
-#define RTC_BASE_OPENSSLIDENTITY_H_
+#ifndef RTC_BASE_OPENSSL_IDENTITY_H_
+#define RTC_BASE_OPENSSL_IDENTITY_H_
 
 #include <openssl/ossl_typ.h>
 
@@ -18,10 +18,10 @@
 #include <string>
 
 #include "rtc_base/checks.h"
-#include "rtc_base/constructormagic.h"
-#include "rtc_base/opensslcertificate.h"
-#include "rtc_base/sslcertificate.h"
-#include "rtc_base/sslidentity.h"
+#include "rtc_base/constructor_magic.h"
+#include "rtc_base/openssl_certificate.h"
+#include "rtc_base/ssl_certificate.h"
+#include "rtc_base/ssl_identity.h"
 
 namespace rtc {
 
@@ -98,4 +98,4 @@
 
 }  // namespace rtc
 
-#endif  // RTC_BASE_OPENSSLIDENTITY_H_
+#endif  // RTC_BASE_OPENSSL_IDENTITY_H_
diff --git a/rtc_base/openssl_key_derivation_hkdf.cc b/rtc_base/openssl_key_derivation_hkdf.cc
index 52af667..6b75e62 100644
--- a/rtc_base/openssl_key_derivation_hkdf.cc
+++ b/rtc_base/openssl_key_derivation_hkdf.cc
@@ -10,19 +10,57 @@
 
 #include "rtc_base/openssl_key_derivation_hkdf.h"
 
-#include <openssl/digest.h>
-#include <openssl/err.h>
-#include <openssl/hkdf.h>
-#include <openssl/sha.h>
-
 #include <algorithm>
 #include <utility>
 
+#include <openssl/ossl_typ.h>
+#ifdef OPENSSL_IS_BORINGSSL
+#include <openssl/digest.h>
+#include <openssl/hkdf.h>
+#else
+#include <openssl/evp.h>
+#include <openssl/kdf.h>
+#endif
+#include <openssl/err.h>
+#include <openssl/sha.h>
+
 #include "rtc_base/buffer.h"
 #include "rtc_base/openssl.h"
 
 namespace rtc {
 
+#ifndef OPENSSL_IS_BORINGSSL
+namespace {
+
+// HKDF is static within OpenSSL and hence not accessible to the caller.
+// This internal implementation allows for compatibility with BoringSSL.
+static int HKDF(uint8_t* out_key,
+                size_t out_len,
+                const EVP_MD* digest,
+                const uint8_t* secret,
+                size_t secret_len,
+                const uint8_t* salt,
+                size_t salt_len,
+                const uint8_t* info,
+                size_t info_len) {
+  EVP_PKEY_CTX* pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_HKDF, NULL);
+
+  if (EVP_PKEY_derive_init(pctx) <= 0 ||
+      EVP_PKEY_CTX_set_hkdf_md(pctx, digest) <= 0 ||
+      EVP_PKEY_CTX_set1_hkdf_salt(pctx, salt, salt_len) <= 0 ||
+      EVP_PKEY_CTX_set1_hkdf_key(pctx, secret, secret_len) <= 0 ||
+      EVP_PKEY_CTX_add1_hkdf_info(pctx, info, info_len) <= 0 ||
+      EVP_PKEY_derive(pctx, out_key, &out_len) <= 0) {
+    EVP_PKEY_CTX_free(pctx);
+    return 0;
+  }
+  EVP_PKEY_CTX_free(pctx);
+  return 1;
+}
+
+}  // namespace
+#endif
+
 OpenSSLKeyDerivationHKDF::OpenSSLKeyDerivationHKDF() = default;
 OpenSSLKeyDerivationHKDF::~OpenSSLKeyDerivationHKDF() = default;
 
diff --git a/rtc_base/openssl_key_derivation_hkdf.h b/rtc_base/openssl_key_derivation_hkdf.h
index ebf43cf..7f88252 100644
--- a/rtc_base/openssl_key_derivation_hkdf.h
+++ b/rtc_base/openssl_key_derivation_hkdf.h
@@ -11,7 +11,7 @@
 #ifndef RTC_BASE_OPENSSL_KEY_DERIVATION_HKDF_H_
 #define RTC_BASE_OPENSSL_KEY_DERIVATION_HKDF_H_
 
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 #include "rtc_base/key_derivation.h"
 
 namespace rtc {
diff --git a/rtc_base/opensslsessioncache.cc b/rtc_base/openssl_session_cache.cc
similarity index 94%
rename from rtc_base/opensslsessioncache.cc
rename to rtc_base/openssl_session_cache.cc
index 2e37d55..270abe8 100644
--- a/rtc_base/opensslsessioncache.cc
+++ b/rtc_base/openssl_session_cache.cc
@@ -8,7 +8,7 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#include "rtc_base/opensslsessioncache.h"
+#include "rtc_base/openssl_session_cache.h"
 #include "rtc_base/checks.h"
 #include "rtc_base/openssl.h"
 
@@ -22,7 +22,7 @@
 }
 
 OpenSSLSessionCache::~OpenSSLSessionCache() {
-  for (auto it : sessions_) {
+  for (const auto& it : sessions_) {
     SSL_SESSION_free(it.second);
   }
   SSL_CTX_free(ssl_ctx_);
diff --git a/rtc_base/opensslsessioncache.h b/rtc_base/openssl_session_cache.h
similarity index 92%
rename from rtc_base/opensslsessioncache.h
rename to rtc_base/openssl_session_cache.h
index c74b7bf..e53e41a 100644
--- a/rtc_base/opensslsessioncache.h
+++ b/rtc_base/openssl_session_cache.h
@@ -8,15 +8,15 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#ifndef RTC_BASE_OPENSSLSESSIONCACHE_H_
-#define RTC_BASE_OPENSSLSESSIONCACHE_H_
+#ifndef RTC_BASE_OPENSSL_SESSION_CACHE_H_
+#define RTC_BASE_OPENSSL_SESSION_CACHE_H_
 
 #include <openssl/ossl_typ.h>
 #include <map>
 #include <string>
 
-#include "rtc_base/constructormagic.h"
-#include "rtc_base/sslstreamadapter.h"
+#include "rtc_base/constructor_magic.h"
+#include "rtc_base/ssl_stream_adapter.h"
 
 #ifndef OPENSSL_IS_BORINGSSL
 typedef struct ssl_session_st SSL_SESSION;
@@ -64,4 +64,4 @@
 
 }  // namespace rtc
 
-#endif  // RTC_BASE_OPENSSLSESSIONCACHE_H_
+#endif  // RTC_BASE_OPENSSL_SESSION_CACHE_H_
diff --git a/rtc_base/opensslsessioncache_unittest.cc b/rtc_base/openssl_session_cache_unittest.cc
similarity index 98%
rename from rtc_base/opensslsessioncache_unittest.cc
rename to rtc_base/openssl_session_cache_unittest.cc
index 6489b2b..366fc26 100644
--- a/rtc_base/opensslsessioncache_unittest.cc
+++ b/rtc_base/openssl_session_cache_unittest.cc
@@ -16,7 +16,7 @@
 
 #include "rtc_base/gunit.h"
 #include "rtc_base/openssl.h"
-#include "rtc_base/opensslsessioncache.h"
+#include "rtc_base/openssl_session_cache.h"
 
 namespace rtc {
 
diff --git a/rtc_base/opensslstreamadapter.cc b/rtc_base/openssl_stream_adapter.cc
similarity index 88%
rename from rtc_base/opensslstreamadapter.cc
rename to rtc_base/openssl_stream_adapter.cc
index 727cb84..5131b30 100644
--- a/rtc_base/opensslstreamadapter.cc
+++ b/rtc_base/openssl_stream_adapter.cc
@@ -8,7 +8,7 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#include "rtc_base/opensslstreamadapter.h"
+#include "rtc_base/openssl_stream_adapter.h"
 
 #include <openssl/bio.h>
 #include <openssl/crypto.h>
@@ -25,29 +25,33 @@
 #include <utility>
 #include <vector>
 
+#include "absl/memory/memory.h"
 #include "rtc_base/checks.h"
 #include "rtc_base/logging.h"
 #include "rtc_base/numerics/safe_conversions.h"
 #include "rtc_base/openssl.h"
-#include "rtc_base/openssladapter.h"
-#include "rtc_base/openssldigest.h"
-#include "rtc_base/opensslidentity.h"
-#include "rtc_base/sslcertificate.h"
+#include "rtc_base/openssl_adapter.h"
+#include "rtc_base/openssl_digest.h"
+#include "rtc_base/openssl_identity.h"
+#include "rtc_base/ssl_certificate.h"
 #include "rtc_base/stream.h"
-#include "rtc_base/stringutils.h"
 #include "rtc_base/thread.h"
-#include "rtc_base/timeutils.h"
-
-namespace {
-bool g_use_time_callback_for_testing = false;
-}
-
-namespace rtc {
+#include "rtc_base/time_utils.h"
+#include "system_wrappers/include/field_trial.h"
 
 #if (OPENSSL_VERSION_NUMBER < 0x10100000L)
 #error "webrtc requires at least OpenSSL version 1.1.0, to support DTLS-SRTP"
 #endif
 
+// Defines for the TLS Cipher Suite Map.
+#define DEFINE_CIPHER_ENTRY_SSL3(name) \
+  { SSL3_CK_##name, "TLS_" #name }
+#define DEFINE_CIPHER_ENTRY_TLS1(name) \
+  { TLS1_CK_##name, "TLS_" #name }
+
+namespace rtc {
+namespace {
+
 // SRTP cipher suite table. |internal_name| is used to construct a
 // colon-separated profile strings which is needed by
 // SSL_CTX_set_tlsext_use_srtp().
@@ -56,37 +60,23 @@
   const int id;
 };
 
-// This isn't elegant, but it's better than an external reference
-static SrtpCipherMapEntry SrtpCipherMap[] = {
-    {"SRTP_AES128_CM_SHA1_80", SRTP_AES128_CM_SHA1_80},
-    {"SRTP_AES128_CM_SHA1_32", SRTP_AES128_CM_SHA1_32},
-    {"SRTP_AEAD_AES_128_GCM", SRTP_AEAD_AES_128_GCM},
-    {"SRTP_AEAD_AES_256_GCM", SRTP_AEAD_AES_256_GCM},
-    {nullptr, 0}};
-
-#ifdef OPENSSL_IS_BORINGSSL
-// Not used in production code. Actual time should be relative to Jan 1, 1970.
-static void TimeCallbackForTesting(const SSL* ssl, struct timeval* out_clock) {
-  int64_t time = TimeNanos();
-  out_clock->tv_sec = time / kNumNanosecsPerSec;
-  out_clock->tv_usec = (time % kNumNanosecsPerSec) / kNumNanosecsPerMicrosec;
-}
-#else  // #ifdef OPENSSL_IS_BORINGSSL
-
 // Cipher name table. Maps internal OpenSSL cipher ids to the RFC name.
 struct SslCipherMapEntry {
   uint32_t openssl_id;
   const char* rfc_name;
 };
 
-#define DEFINE_CIPHER_ENTRY_SSL3(name) \
-  { SSL3_CK_##name, "TLS_" #name }
-#define DEFINE_CIPHER_ENTRY_TLS1(name) \
-  { TLS1_CK_##name, "TLS_" #name }
+// This isn't elegant, but it's better than an external reference
+constexpr SrtpCipherMapEntry kSrtpCipherMap[] = {
+    {"SRTP_AES128_CM_SHA1_80", SRTP_AES128_CM_SHA1_80},
+    {"SRTP_AES128_CM_SHA1_32", SRTP_AES128_CM_SHA1_32},
+    {"SRTP_AEAD_AES_128_GCM", SRTP_AEAD_AES_128_GCM},
+    {"SRTP_AEAD_AES_256_GCM", SRTP_AEAD_AES_256_GCM}};
 
+#ifndef OPENSSL_IS_BORINGSSL
 // The "SSL_CIPHER_standard_name" function is only available in OpenSSL when
 // compiled with tracing, so we need to define the mapping manually here.
-static const SslCipherMapEntry kSslCipherMap[] = {
+constexpr SslCipherMapEntry kSslCipherMap[] = {
     // TLS v1.0 ciphersuites from RFC2246.
     DEFINE_CIPHER_ENTRY_SSL3(RSA_RC4_128_SHA),
     {SSL3_CK_RSA_DES_192_CBC3_SHA, "TLS_RSA_WITH_3DES_EDE_CBC_SHA"},
@@ -145,15 +135,19 @@
     {0, nullptr}};
 #endif  // #ifndef OPENSSL_IS_BORINGSSL
 
-#if defined(_MSC_VER)
-#pragma warning(push)
-#pragma warning(disable : 4309)
-#pragma warning(disable : 4310)
-#endif  // defined(_MSC_VER)
+#ifdef OPENSSL_IS_BORINGSSL
+// Enabled by EnableTimeCallbackForTesting. Should never be set in production
+// code.
+bool g_use_time_callback_for_testing = false;
+// Not used in production code. Actual time should be relative to Jan 1, 1970.
+void TimeCallbackForTesting(const SSL* ssl, struct timeval* out_clock) {
+  int64_t time = TimeNanos();
+  out_clock->tv_sec = time / kNumNanosecsPerSec;
+  out_clock->tv_usec = (time % kNumNanosecsPerSec) / kNumNanosecsPerMicrosec;
+}
+#endif
 
-#if defined(_MSC_VER)
-#pragma warning(pop)
-#endif  // defined(_MSC_VER)
+}  // namespace
 
 //////////////////////////////////////////////////////////////////////
 // StreamBIO
@@ -281,7 +275,9 @@
       ssl_(nullptr),
       ssl_ctx_(nullptr),
       ssl_mode_(SSL_MODE_TLS),
-      ssl_max_version_(SSL_PROTOCOL_TLS_12) {}
+      ssl_max_version_(SSL_PROTOCOL_TLS_12),
+      support_legacy_tls_protocols_flag_(
+          webrtc::field_trial::IsEnabled("WebRTC-LegacyTlsProtocols")) {}
 
 OpenSSLStreamAdapter::~OpenSSLStreamAdapter() {
   Cleanup(0);
@@ -382,8 +378,9 @@
 }
 
 int OpenSSLStreamAdapter::GetSslVersion() const {
-  if (state_ != SSL_CONNECTED)
+  if (state_ != SSL_CONNECTED) {
     return -1;
+  }
 
   int ssl_version = SSL_version(ssl_);
   if (ssl_mode_ == SSL_MODE_DTLS) {
@@ -422,29 +419,26 @@
 
 bool OpenSSLStreamAdapter::SetDtlsSrtpCryptoSuites(
     const std::vector<int>& ciphers) {
-  std::string internal_ciphers;
-
   if (state_ != SSL_NONE) {
     return false;
   }
 
-  for (std::vector<int>::const_iterator cipher = ciphers.begin();
-       cipher != ciphers.end(); ++cipher) {
+  std::string internal_ciphers;
+  for (const int cipher : ciphers) {
     bool found = false;
-    for (SrtpCipherMapEntry* entry = SrtpCipherMap; entry->internal_name;
-         ++entry) {
-      if (*cipher == entry->id) {
+    for (const auto& entry : kSrtpCipherMap) {
+      if (cipher == entry.id) {
         found = true;
         if (!internal_ciphers.empty()) {
           internal_ciphers += ":";
         }
-        internal_ciphers += entry->internal_name;
+        internal_ciphers += entry.internal_name;
         break;
       }
     }
 
     if (!found) {
-      RTC_LOG(LS_ERROR) << "Could not find cipher: " << *cipher;
+      RTC_LOG(LS_ERROR) << "Could not find cipher: " << cipher;
       return false;
     }
   }
@@ -624,8 +618,9 @@
 
   ssl_read_needs_write_ = false;
 
-  int code = SSL_read(ssl_, data, checked_cast<int>(data_len));
-  int ssl_error = SSL_get_error(ssl_, code);
+  const int code = SSL_read(ssl_, data, checked_cast<int>(data_len));
+  const int ssl_error = SSL_get_error(ssl_, code);
+
   switch (ssl_error) {
     case SSL_ERROR_NONE:
       RTC_LOG(LS_VERBOSE) << " -- success";
@@ -676,10 +671,10 @@
 
   while (left) {
     // This should always succeed
-    int toread = (sizeof(buf) < left) ? sizeof(buf) : left;
-    int code = SSL_read(ssl_, buf, toread);
+    const int toread = (sizeof(buf) < left) ? sizeof(buf) : left;
+    const int code = SSL_read(ssl_, buf, toread);
 
-    int ssl_error = SSL_get_error(ssl_, code);
+    const int ssl_error = SSL_get_error(ssl_, code);
     RTC_DCHECK(ssl_error == SSL_ERROR_NONE);
 
     if (ssl_error != SSL_ERROR_NONE) {
@@ -820,20 +815,6 @@
   SSL_set_mode(ssl_, SSL_MODE_ENABLE_PARTIAL_WRITE |
                          SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
 
-#if !defined(OPENSSL_IS_BORINGSSL)
-  // Specify an ECDH group for ECDHE ciphers, otherwise OpenSSL cannot
-  // negotiate them when acting as the server. Use NIST's P-256 which is
-  // commonly supported. BoringSSL doesn't need explicit configuration and has
-  // a reasonable default set.
-  EC_KEY* ecdh = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
-  if (ecdh == nullptr) {
-    return -1;
-  }
-  SSL_set_options(ssl_, SSL_OP_SINGLE_ECDH_USE);
-  SSL_set_tmp_ecdh(ssl_, ecdh);
-  EC_KEY_free(ecdh);
-#endif
-
   // Do the connect
   return ContinueSSL();
 }
@@ -845,9 +826,10 @@
   // Clear the DTLS timer
   Thread::Current()->Clear(this, MSG_TIMEOUT);
 
-  int code = (role_ == SSL_CLIENT) ? SSL_connect(ssl_) : SSL_accept(ssl_);
-  int ssl_error;
-  switch (ssl_error = SSL_get_error(ssl_, code)) {
+  const int code = (role_ == SSL_CLIENT) ? SSL_connect(ssl_) : SSL_accept(ssl_);
+  const int ssl_error = SSL_get_error(ssl_, code);
+
+  switch (ssl_error) {
     case SSL_ERROR_NONE:
       RTC_LOG(LS_VERBOSE) << " -- success";
       // By this point, OpenSSL should have given us a certificate, or errored
@@ -967,74 +949,42 @@
 }
 
 SSL_CTX* OpenSSLStreamAdapter::SetupSSLContext() {
-  SSL_CTX* ctx = nullptr;
-
-#ifdef OPENSSL_IS_BORINGSSL
-  ctx = SSL_CTX_new(ssl_mode_ == SSL_MODE_DTLS ? DTLS_method() : TLS_method());
-// Version limiting for BoringSSL will be done below.
-#else
-  const SSL_METHOD* method;
-  switch (ssl_max_version_) {
-    case SSL_PROTOCOL_TLS_10:
-    case SSL_PROTOCOL_TLS_11:
-      // OpenSSL doesn't support setting min/max versions, so we always use
-      // (D)TLS 1.0 if a max. version below the max. available is requested.
-      if (ssl_mode_ == SSL_MODE_DTLS) {
-        if (role_ == SSL_CLIENT) {
-          method = DTLSv1_client_method();
-        } else {
-          method = DTLSv1_server_method();
-        }
-      } else {
-        if (role_ == SSL_CLIENT) {
-          method = TLSv1_client_method();
-        } else {
-          method = TLSv1_server_method();
-        }
-      }
-      break;
-    case SSL_PROTOCOL_TLS_12:
-    default:
-      if (ssl_mode_ == SSL_MODE_DTLS) {
-        if (role_ == SSL_CLIENT) {
-          method = DTLS_client_method();
-        } else {
-          method = DTLS_server_method();
-        }
-      } else {
-        if (role_ == SSL_CLIENT) {
-          method = TLS_client_method();
-        } else {
-          method = TLS_server_method();
-        }
-      }
-      break;
-  }
-  ctx = SSL_CTX_new(method);
-#endif  // OPENSSL_IS_BORINGSSL
-
+  SSL_CTX* ctx =
+      SSL_CTX_new(ssl_mode_ == SSL_MODE_DTLS ? DTLS_method() : TLS_method());
   if (ctx == nullptr) {
     return nullptr;
   }
 
-#ifdef OPENSSL_IS_BORINGSSL
-  SSL_CTX_set_min_proto_version(
-      ctx, ssl_mode_ == SSL_MODE_DTLS ? DTLS1_VERSION : TLS1_VERSION);
-  switch (ssl_max_version_) {
-    case SSL_PROTOCOL_TLS_10:
-      SSL_CTX_set_max_proto_version(
-          ctx, ssl_mode_ == SSL_MODE_DTLS ? DTLS1_VERSION : TLS1_VERSION);
-      break;
-    case SSL_PROTOCOL_TLS_11:
-      SSL_CTX_set_max_proto_version(
-          ctx, ssl_mode_ == SSL_MODE_DTLS ? DTLS1_VERSION : TLS1_1_VERSION);
-      break;
-    case SSL_PROTOCOL_TLS_12:
-    default:
-      SSL_CTX_set_max_proto_version(
-          ctx, ssl_mode_ == SSL_MODE_DTLS ? DTLS1_2_VERSION : TLS1_2_VERSION);
-      break;
+  if (support_legacy_tls_protocols_flag_) {
+    // TODO(https://bugs.webrtc.org/10261): Completely remove this branch in
+    // M75.
+    SSL_CTX_set_min_proto_version(
+        ctx, ssl_mode_ == SSL_MODE_DTLS ? DTLS1_VERSION : TLS1_VERSION);
+    switch (ssl_max_version_) {
+      case SSL_PROTOCOL_TLS_10:
+        SSL_CTX_set_max_proto_version(
+            ctx, ssl_mode_ == SSL_MODE_DTLS ? DTLS1_VERSION : TLS1_VERSION);
+        break;
+      case SSL_PROTOCOL_TLS_11:
+        SSL_CTX_set_max_proto_version(
+            ctx, ssl_mode_ == SSL_MODE_DTLS ? DTLS1_VERSION : TLS1_1_VERSION);
+        break;
+      case SSL_PROTOCOL_TLS_12:
+      default:
+        SSL_CTX_set_max_proto_version(
+            ctx, ssl_mode_ == SSL_MODE_DTLS ? DTLS1_2_VERSION : TLS1_2_VERSION);
+        break;
+    }
+  } else {
+    // TODO(https://bugs.webrtc.org/10261): Make this the default in M75.
+    SSL_CTX_set_min_proto_version(
+        ctx, ssl_mode_ == SSL_MODE_DTLS ? DTLS1_2_VERSION : TLS1_2_VERSION);
+    SSL_CTX_set_max_proto_version(
+        ctx, ssl_mode_ == SSL_MODE_DTLS ? DTLS1_2_VERSION : TLS1_2_VERSION);
   }
+
+#ifdef OPENSSL_IS_BORINGSSL
+  // SSL_CTX_set_current_time_cb is only supported in BoringSSL.
   if (g_use_time_callback_for_testing) {
     SSL_CTX_set_current_time_cb(ctx, &TimeCallbackForTesting);
   }
@@ -1137,7 +1087,7 @@
   // Record the peer's certificate.
   X509* cert = X509_STORE_CTX_get0_cert(store);
   stream->peer_cert_chain_.reset(
-      new SSLCertChain(new OpenSSLCertificate(cert)));
+      new SSLCertChain(absl::make_unique<OpenSSLCertificate>(cert)));
 #endif
 
   // If the peer certificate digest isn't known yet, we'll wait to verify
diff --git a/rtc_base/opensslstreamadapter.h b/rtc_base/openssl_stream_adapter.h
similarity index 94%
rename from rtc_base/opensslstreamadapter.h
rename to rtc_base/openssl_stream_adapter.h
index e012d17..bca2fde 100644
--- a/rtc_base/opensslstreamadapter.h
+++ b/rtc_base/openssl_stream_adapter.h
@@ -8,8 +8,8 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#ifndef RTC_BASE_OPENSSLSTREAMADAPTER_H_
-#define RTC_BASE_OPENSSLSTREAMADAPTER_H_
+#ifndef RTC_BASE_OPENSSL_STREAM_ADAPTER_H_
+#define RTC_BASE_OPENSSL_STREAM_ADAPTER_H_
 
 #include <openssl/ossl_typ.h>
 
@@ -20,10 +20,10 @@
 #include <vector>
 
 #include "rtc_base/buffer.h"
-#include "rtc_base/messagequeue.h"
-#include "rtc_base/opensslidentity.h"
-#include "rtc_base/sslidentity.h"
-#include "rtc_base/sslstreamadapter.h"
+#include "rtc_base/message_queue.h"
+#include "rtc_base/openssl_identity.h"
+#include "rtc_base/ssl_identity.h"
+#include "rtc_base/ssl_stream_adapter.h"
 #include "rtc_base/stream.h"
 
 namespace rtc {
@@ -217,10 +217,13 @@
   // A 50-ms initial timeout ensures rapid setup on fast connections, but may
   // be too aggressive for low bandwidth links.
   int dtls_handshake_timeout_ms_ = 50;
+
+  // TODO(https://bugs.webrtc.org/10261): Completely remove this option in M75.
+  const bool support_legacy_tls_protocols_flag_;
 };
 
 /////////////////////////////////////////////////////////////////////////////
 
 }  // namespace rtc
 
-#endif  // RTC_BASE_OPENSSLSTREAMADAPTER_H_
+#endif  // RTC_BASE_OPENSSL_STREAM_ADAPTER_H_
diff --git a/rtc_base/opensslutility.cc b/rtc_base/openssl_utility.cc
similarity index 96%
rename from rtc_base/opensslutility.cc
rename to rtc_base/openssl_utility.cc
index a3f3347..9749912 100644
--- a/rtc_base/opensslutility.cc
+++ b/rtc_base/openssl_utility.cc
@@ -8,7 +8,7 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#include "rtc_base/opensslutility.h"
+#include "rtc_base/openssl_utility.h"
 #if defined(WEBRTC_WIN)
 // Must be included first before openssl headers.
 #include "rtc_base/win32.h"  // NOLINT
@@ -24,9 +24,9 @@
 #include "rtc_base/arraysize.h"
 #include "rtc_base/logging.h"
 #include "rtc_base/numerics/safe_conversions.h"
-#include "rtc_base/opensslcertificate.h"
+#include "rtc_base/openssl_certificate.h"
 #ifndef WEBRTC_EXCLUDE_BUILT_IN_SSL_ROOT_CERTS
-#include "rtc_base/sslroots.h"
+#include "rtc_base/ssl_roots.h"
 #endif  // WEBRTC_EXCLUDE_BUILT_IN_SSL_ROOT_CERTS
 
 namespace rtc {
diff --git a/rtc_base/opensslutility.h b/rtc_base/openssl_utility.h
similarity index 92%
rename from rtc_base/opensslutility.h
rename to rtc_base/openssl_utility.h
index 77ed0b1..a2e49df 100644
--- a/rtc_base/opensslutility.h
+++ b/rtc_base/openssl_utility.h
@@ -8,8 +8,8 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#ifndef RTC_BASE_OPENSSLUTILITY_H_
-#define RTC_BASE_OPENSSLUTILITY_H_
+#ifndef RTC_BASE_OPENSSL_UTILITY_H_
+#define RTC_BASE_OPENSSL_UTILITY_H_
 
 #include <openssl/ossl_typ.h>
 #include <string>
@@ -37,4 +37,4 @@
 }  // namespace openssl
 }  // namespace rtc
 
-#endif  // RTC_BASE_OPENSSLUTILITY_H_
+#endif  // RTC_BASE_OPENSSL_UTILITY_H_
diff --git a/rtc_base/opensslutility_unittest.cc b/rtc_base/openssl_utility_unittest.cc
similarity index 99%
rename from rtc_base/opensslutility_unittest.cc
rename to rtc_base/openssl_utility_unittest.cc
index 2f952ae..9c9b971 100644
--- a/rtc_base/opensslutility_unittest.cc
+++ b/rtc_base/openssl_utility_unittest.cc
@@ -32,8 +32,8 @@
 #include "rtc_base/gunit.h"
 #include "rtc_base/numerics/safe_conversions.h"
 #include "rtc_base/openssl.h"
-#include "rtc_base/opensslutility.h"
-#include "rtc_base/sslroots.h"
+#include "rtc_base/openssl_utility.h"
+#include "rtc_base/ssl_roots.h"
 #include "test/gmock.h"
 
 namespace rtc {
diff --git a/rtc_base/physicalsocketserver.cc b/rtc_base/physical_socket_server.cc
similarity index 99%
rename from rtc_base/physicalsocketserver.cc
rename to rtc_base/physical_socket_server.cc
index 4ad2857..4845a73 100644
--- a/rtc_base/physicalsocketserver.cc
+++ b/rtc_base/physical_socket_server.cc
@@ -7,7 +7,7 @@
  *  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/physicalsocketserver.h"
+#include "rtc_base/physical_socket_server.h"
 
 #if defined(_MSC_VER) && _MSC_VER < 1300
 #pragma warning(disable : 4786)
@@ -44,12 +44,12 @@
 #include <map>
 
 #include "rtc_base/arraysize.h"
-#include "rtc_base/byteorder.h"
+#include "rtc_base/byte_order.h"
 #include "rtc_base/checks.h"
 #include "rtc_base/logging.h"
-#include "rtc_base/networkmonitor.h"
-#include "rtc_base/nullsocketserver.h"
-#include "rtc_base/timeutils.h"
+#include "rtc_base/network_monitor.h"
+#include "rtc_base/null_socket_server.h"
+#include "rtc_base/time_utils.h"
 
 #if defined(WEBRTC_WIN)
 #define LAST_SYSTEM_ERROR (::GetLastError())
diff --git a/rtc_base/physicalsocketserver.h b/rtc_base/physical_socket_server.h
similarity index 96%
rename from rtc_base/physicalsocketserver.h
rename to rtc_base/physical_socket_server.h
index ee4f936..b2dfb3f 100644
--- a/rtc_base/physicalsocketserver.h
+++ b/rtc_base/physical_socket_server.h
@@ -8,8 +8,8 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#ifndef RTC_BASE_PHYSICALSOCKETSERVER_H_
-#define RTC_BASE_PHYSICALSOCKETSERVER_H_
+#ifndef RTC_BASE_PHYSICAL_SOCKET_SERVER_H_
+#define RTC_BASE_PHYSICAL_SOCKET_SERVER_H_
 
 #if defined(WEBRTC_POSIX) && defined(WEBRTC_LINUX)
 #include <sys/epoll.h>
@@ -20,9 +20,9 @@
 #include <set>
 #include <vector>
 
-#include "rtc_base/criticalsection.h"
-#include "rtc_base/nethelpers.h"
-#include "rtc_base/socketserver.h"
+#include "rtc_base/critical_section.h"
+#include "rtc_base/net_helpers.h"
+#include "rtc_base/socket_server.h"
 
 #if defined(WEBRTC_POSIX)
 typedef int SOCKET;
@@ -268,4 +268,4 @@
 
 }  // namespace rtc
 
-#endif  // RTC_BASE_PHYSICALSOCKETSERVER_H_
+#endif  // RTC_BASE_PHYSICAL_SOCKET_SERVER_H_
diff --git a/rtc_base/physicalsocketserver_unittest.cc b/rtc_base/physical_socket_server_unittest.cc
similarity index 98%
rename from rtc_base/physicalsocketserver_unittest.cc
rename to rtc_base/physical_socket_server_unittest.cc
index 4b36cd5..aed8bf3 100644
--- a/rtc_base/physicalsocketserver_unittest.cc
+++ b/rtc_base/physical_socket_server_unittest.cc
@@ -9,16 +9,18 @@
  */
 
 #include <signal.h>
-#include <stdarg.h>
+#include <algorithm>
 #include <memory>
 
 #include "rtc_base/gunit.h"
+#include "rtc_base/ip_address.h"
 #include "rtc_base/logging.h"
-#include "rtc_base/networkmonitor.h"
-#include "rtc_base/physicalsocketserver.h"
+#include "rtc_base/network_monitor.h"
+#include "rtc_base/physical_socket_server.h"
 #include "rtc_base/socket_unittest.h"
-#include "rtc_base/testutils.h"
+#include "rtc_base/test_utils.h"
 #include "rtc_base/thread.h"
+#include "test/gtest.h"
 
 namespace rtc {
 
diff --git a/rtc_base/platform_file.cc b/rtc_base/platform_file.cc
index baefb22..f9317d3 100644
--- a/rtc_base/platform_file.cc
+++ b/rtc_base/platform_file.cc
@@ -13,7 +13,7 @@
 #if defined(WEBRTC_WIN)
 #include <io.h>
 
-#include "rtc_base/stringutils.h"  // For ToUtf16
+#include "rtc_base/string_utils.h"  // For ToUtf16
 #else
 #include <fcntl.h>
 #include <sys/stat.h>
diff --git a/rtc_base/platform_file_unittest.cc b/rtc_base/platform_file_unittest.cc
index 4e72400..396286a 100644
--- a/rtc_base/platform_file_unittest.cc
+++ b/rtc_base/platform_file_unittest.cc
@@ -10,7 +10,7 @@
 
 #include "rtc_base/platform_file.h"
 #include "test/gtest.h"
-#include "test/testsupport/fileutils.h"
+#include "test/testsupport/file_utils.h"
 
 namespace rtc {
 
diff --git a/rtc_base/platform_thread.cc b/rtc_base/platform_thread.cc
index ba84b6a..19da912 100644
--- a/rtc_base/platform_thread.cc
+++ b/rtc_base/platform_thread.cc
@@ -17,9 +17,9 @@
 #include <time.h>
 #include <algorithm>
 
-#include "rtc_base/atomicops.h"
+#include "rtc_base/atomic_ops.h"
 #include "rtc_base/checks.h"
-#include "rtc_base/timeutils.h"
+#include "rtc_base/time_utils.h"
 
 namespace rtc {
 namespace {
@@ -39,10 +39,8 @@
 
 PlatformThread::PlatformThread(ThreadRunFunctionDeprecated func,
                                void* obj,
-                               const char* thread_name)
-    : run_function_deprecated_(func),
-      obj_(obj),
-      name_(thread_name ? thread_name : "webrtc") {
+                               absl::string_view thread_name)
+    : run_function_deprecated_(func), obj_(obj), name_(thread_name) {
   RTC_DCHECK(func);
   RTC_DCHECK(name_.length() < 64);
   spawned_thread_checker_.DetachFromThread();
@@ -50,7 +48,7 @@
 
 PlatformThread::PlatformThread(ThreadRunFunction func,
                                void* obj,
-                               const char* thread_name,
+                               absl::string_view thread_name,
                                ThreadPriority priority /*= kNormalPriority*/)
     : run_function_(func), priority_(priority), obj_(obj), name_(thread_name) {
   RTC_DCHECK(func);
@@ -240,11 +238,7 @@
   // thread priorities.
   return true;
 #else
-#ifdef WEBRTC_THREAD_RR
-  const int policy = SCHED_RR;
-#else
   const int policy = SCHED_FIFO;
-#endif
   const int min_prio = sched_get_priority_min(policy);
   const int max_prio = sched_get_priority_max(policy);
   if (min_prio == -1 || max_prio == -1) {
diff --git a/rtc_base/platform_thread.h b/rtc_base/platform_thread.h
index 47c23dc..99c5f90 100644
--- a/rtc_base/platform_thread.h
+++ b/rtc_base/platform_thread.h
@@ -16,7 +16,8 @@
 #endif
 #include <string>
 
-#include "rtc_base/constructormagic.h"
+#include "absl/strings/string_view.h"
+#include "rtc_base/constructor_magic.h"
 #include "rtc_base/platform_thread_types.h"
 #include "rtc_base/thread_checker.h"
 
@@ -51,10 +52,10 @@
  public:
   PlatformThread(ThreadRunFunctionDeprecated func,
                  void* obj,
-                 const char* thread_name);
+                 absl::string_view thread_name);
   PlatformThread(ThreadRunFunction func,
                  void* obj,
-                 const char* thread_name,
+                 absl::string_view thread_name,
                  ThreadPriority priority = kNormalPriority);
   virtual ~PlatformThread();
 
diff --git a/rtc_base/platform_thread_types.h b/rtc_base/platform_thread_types.h
index 0bc42eb..6b9101e 100644
--- a/rtc_base/platform_thread_types.h
+++ b/rtc_base/platform_thread_types.h
@@ -25,6 +25,9 @@
 #elif defined(WEBRTC_POSIX)
 #include <pthread.h>
 #include <unistd.h>
+#if defined(WEBRTC_MAC)
+#include <pthread_spis.h>
+#endif
 #endif
 // clang-format on
 
diff --git a/rtc_base/protobuf_utils.h b/rtc_base/protobuf_utils.h
index 8fbc060..786365d 100644
--- a/rtc_base/protobuf_utils.h
+++ b/rtc_base/protobuf_utils.h
@@ -13,12 +13,6 @@
 #ifndef RTC_BASE_PROTOBUF_UTILS_H_
 #define RTC_BASE_PROTOBUF_UTILS_H_
 
-namespace webrtc {
-
-using ProtoString = std::string;
-
-}  // namespace webrtc
-
 #if WEBRTC_ENABLE_PROTOBUF
 
 #include "third_party/protobuf/src/google/protobuf/message_lite.h"
diff --git a/rtc_base/proxyinfo.cc b/rtc_base/proxy_info.cc
similarity index 95%
rename from rtc_base/proxyinfo.cc
rename to rtc_base/proxy_info.cc
index c394487..23d60af 100644
--- a/rtc_base/proxyinfo.cc
+++ b/rtc_base/proxy_info.cc
@@ -8,7 +8,7 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#include "rtc_base/proxyinfo.h"
+#include "rtc_base/proxy_info.h"
 
 namespace rtc {
 
diff --git a/rtc_base/proxyinfo.h b/rtc_base/proxy_info.h
similarity index 82%
rename from rtc_base/proxyinfo.h
rename to rtc_base/proxy_info.h
index 1947669..6fded09 100644
--- a/rtc_base/proxyinfo.h
+++ b/rtc_base/proxy_info.h
@@ -8,12 +8,12 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#ifndef RTC_BASE_PROXYINFO_H_
-#define RTC_BASE_PROXYINFO_H_
+#ifndef RTC_BASE_PROXY_INFO_H_
+#define RTC_BASE_PROXY_INFO_H_
 
 #include <string>
-#include "rtc_base/cryptstring.h"
-#include "rtc_base/socketaddress.h"
+#include "rtc_base/crypt_string.h"
+#include "rtc_base/socket_address.h"
 
 namespace rtc {
 
@@ -35,4 +35,4 @@
 
 }  // namespace rtc
 
-#endif  // RTC_BASE_PROXYINFO_H_
+#endif  // RTC_BASE_PROXY_INFO_H_
diff --git a/rtc_base/proxyserver.cc b/rtc_base/proxy_server.cc
similarity index 98%
rename from rtc_base/proxyserver.cc
rename to rtc_base/proxy_server.cc
index 71c4879..3420404 100644
--- a/rtc_base/proxyserver.cc
+++ b/rtc_base/proxy_server.cc
@@ -8,13 +8,14 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#include "rtc_base/proxyserver.h"
+#include "rtc_base/proxy_server.h"
 
+#include <stddef.h>
 #include <algorithm>
 
 #include "rtc_base/checks.h"
 #include "rtc_base/logging.h"
-#include "rtc_base/socketfactory.h"
+#include "rtc_base/socket_factory.h"
 
 namespace rtc {
 
diff --git a/rtc_base/proxyserver.h b/rtc_base/proxy_server.h
similarity index 92%
rename from rtc_base/proxyserver.h
rename to rtc_base/proxy_server.h
index 37cadd0..ef4a3c7 100644
--- a/rtc_base/proxyserver.h
+++ b/rtc_base/proxy_server.h
@@ -8,15 +8,15 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#ifndef RTC_BASE_PROXYSERVER_H_
-#define RTC_BASE_PROXYSERVER_H_
+#ifndef RTC_BASE_PROXY_SERVER_H_
+#define RTC_BASE_PROXY_SERVER_H_
 
 #include <list>
 #include <memory>
-#include "rtc_base/asyncsocket.h"
-#include "rtc_base/constructormagic.h"
-#include "rtc_base/socketadapters.h"
-#include "rtc_base/socketaddress.h"
+#include "rtc_base/async_socket.h"
+#include "rtc_base/constructor_magic.h"
+#include "rtc_base/server_socket_adapters.h"
+#include "rtc_base/socket_address.h"
 #include "rtc_base/stream.h"
 
 namespace rtc {
@@ -101,4 +101,4 @@
 
 }  // namespace rtc
 
-#endif  // RTC_BASE_PROXYSERVER_H_
+#endif  // RTC_BASE_PROXY_SERVER_H_
diff --git a/rtc_base/proxy_unittest.cc b/rtc_base/proxy_unittest.cc
index 0101893..229891d 100644
--- a/rtc_base/proxy_unittest.cc
+++ b/rtc_base/proxy_unittest.cc
@@ -11,11 +11,11 @@
 #include <memory>
 #include <string>
 #include "rtc_base/gunit.h"
-#include "rtc_base/proxyserver.h"
-#include "rtc_base/socketadapters.h"
-#include "rtc_base/testclient.h"
-#include "rtc_base/testechoserver.h"
-#include "rtc_base/virtualsocketserver.h"
+#include "rtc_base/proxy_server.h"
+#include "rtc_base/socket_adapters.h"
+#include "rtc_base/test_client.h"
+#include "rtc_base/test_echo_server.h"
+#include "rtc_base/virtual_socket_server.h"
 
 using rtc::Socket;
 using rtc::SocketAddress;
diff --git a/rtc_base/random.h b/rtc_base/random.h
index e1c3bb7..31de6e1 100644
--- a/rtc_base/random.h
+++ b/rtc_base/random.h
@@ -15,7 +15,7 @@
 #include <limits>
 
 #include "rtc_base/checks.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
diff --git a/rtc_base/random_unittest.cc b/rtc_base/random_unittest.cc
index d05a16b..8f32657 100644
--- a/rtc_base/random_unittest.cc
+++ b/rtc_base/random_unittest.cc
@@ -13,7 +13,7 @@
 #include <limits>
 #include <vector>
 
-#include "rtc_base/numerics/mathutils.h"  // unsigned difference
+#include "rtc_base/numerics/math_utils.h"  // unsigned difference
 #include "rtc_base/random.h"
 #include "test/gtest.h"
 
diff --git a/rtc_base/rate_limiter.cc b/rtc_base/rate_limiter.cc
index 5c7bdef..7394c3e 100644
--- a/rtc_base/rate_limiter.cc
+++ b/rtc_base/rate_limiter.cc
@@ -17,7 +17,7 @@
 
 namespace webrtc {
 
-RateLimiter::RateLimiter(const Clock* clock, int64_t max_window_ms)
+RateLimiter::RateLimiter(Clock* clock, int64_t max_window_ms)
     : clock_(clock),
       current_rate_(max_window_ms, RateStatistics::kBpsScale),
       window_size_ms_(max_window_ms),
diff --git a/rtc_base/rate_limiter.h b/rtc_base/rate_limiter.h
index 43ef88d..1c956d7 100644
--- a/rtc_base/rate_limiter.h
+++ b/rtc_base/rate_limiter.h
@@ -14,8 +14,8 @@
 #include <stddef.h>
 #include <stdint.h>
 
-#include "rtc_base/constructormagic.h"
-#include "rtc_base/criticalsection.h"
+#include "rtc_base/constructor_magic.h"
+#include "rtc_base/critical_section.h"
 #include "rtc_base/rate_statistics.h"
 #include "rtc_base/thread_annotations.h"
 
@@ -28,7 +28,7 @@
 // methods will acquire (the same) lock befeore executing.
 class RateLimiter {
  public:
-  RateLimiter(const Clock* clock, int64_t max_window_ms);
+  RateLimiter(Clock* clock, int64_t max_window_ms);
   ~RateLimiter();
 
   // Try to use rate to send bytes. Returns true on success and if so updates
@@ -44,7 +44,7 @@
   bool SetWindowSize(int64_t window_size_ms);
 
  private:
-  const Clock* const clock_;
+  Clock* const clock_;
   rtc::CriticalSection lock_;
   RateStatistics current_rate_ RTC_GUARDED_BY(lock_);
   int64_t window_size_ms_ RTC_GUARDED_BY(lock_);
diff --git a/rtc_base/rate_limiter_unittest.cc b/rtc_base/rate_limiter_unittest.cc
index ac0625f..cb9b5b4 100644
--- a/rtc_base/rate_limiter_unittest.cc
+++ b/rtc_base/rate_limiter_unittest.cc
@@ -8,13 +8,11 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#include <algorithm>
 #include <memory>
 
 #include "rtc_base/event.h"
 #include "rtc_base/platform_thread.h"
 #include "rtc_base/rate_limiter.h"
-#include "rtc_base/task_queue.h"
 #include "system_wrappers/include/clock.h"
 #include "test/gtest.h"
 
diff --git a/rtc_base/rate_statistics_unittest.cc b/rtc_base/rate_statistics_unittest.cc
index 62f1486..822767e 100644
--- a/rtc_base/rate_statistics_unittest.cc
+++ b/rtc_base/rate_statistics_unittest.cc
@@ -8,7 +8,7 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#include <algorithm>
+#include <cstdlib>
 
 #include "rtc_base/rate_statistics.h"
 #include "test/gtest.h"
diff --git a/rtc_base/ratetracker.cc b/rtc_base/rate_tracker.cc
similarity index 98%
rename from rtc_base/ratetracker.cc
rename to rtc_base/rate_tracker.cc
index 7c96ca9..771dc6c 100644
--- a/rtc_base/ratetracker.cc
+++ b/rtc_base/rate_tracker.cc
@@ -8,12 +8,12 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#include "rtc_base/ratetracker.h"
+#include "rtc_base/rate_tracker.h"
 
 #include <algorithm>
 
 #include "rtc_base/checks.h"
-#include "rtc_base/timeutils.h"
+#include "rtc_base/time_utils.h"
 
 namespace rtc {
 
diff --git a/rtc_base/ratetracker.h b/rtc_base/rate_tracker.h
similarity index 95%
rename from rtc_base/ratetracker.h
rename to rtc_base/rate_tracker.h
index ac9b88a..e9be522 100644
--- a/rtc_base/ratetracker.h
+++ b/rtc_base/rate_tracker.h
@@ -8,8 +8,8 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#ifndef RTC_BASE_RATETRACKER_H_
-#define RTC_BASE_RATETRACKER_H_
+#ifndef RTC_BASE_RATE_TRACKER_H_
+#define RTC_BASE_RATE_TRACKER_H_
 
 #include <stdint.h>
 #include <stdlib.h>
@@ -66,4 +66,4 @@
 
 }  // namespace rtc
 
-#endif  // RTC_BASE_RATETRACKER_H_
+#endif  // RTC_BASE_RATE_TRACKER_H_
diff --git a/rtc_base/ratetracker_unittest.cc b/rtc_base/rate_tracker_unittest.cc
similarity index 98%
rename from rtc_base/ratetracker_unittest.cc
rename to rtc_base/rate_tracker_unittest.cc
index 58102df..7a2c1ad 100644
--- a/rtc_base/ratetracker_unittest.cc
+++ b/rtc_base/rate_tracker_unittest.cc
@@ -8,8 +8,9 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#include "rtc_base/ratetracker.h"
-#include "rtc_base/gunit.h"
+#include "rtc_base/rate_tracker.h"
+
+#include "test/gtest.h"
 
 namespace rtc {
 namespace {
diff --git a/rtc_base/refcount.h b/rtc_base/ref_count.h
similarity index 96%
rename from rtc_base/refcount.h
rename to rtc_base/ref_count.h
index fb0971c..d8d652a 100644
--- a/rtc_base/refcount.h
+++ b/rtc_base/ref_count.h
@@ -7,8 +7,8 @@
  *  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_REFCOUNT_H_
-#define RTC_BASE_REFCOUNT_H_
+#ifndef RTC_BASE_REF_COUNT_H_
+#define RTC_BASE_REF_COUNT_H_
 
 namespace rtc {
 
@@ -64,4 +64,4 @@
 
 }  // namespace rtc
 
-#endif  // RTC_BASE_REFCOUNT_H_
+#endif  // RTC_BASE_REF_COUNT_H_
diff --git a/rtc_base/refcountedobject.h b/rtc_base/ref_counted_object.h
similarity index 87%
rename from rtc_base/refcountedobject.h
rename to rtc_base/ref_counted_object.h
index da3ed9f..ce18379 100644
--- a/rtc_base/refcountedobject.h
+++ b/rtc_base/ref_counted_object.h
@@ -7,14 +7,15 @@
  *  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_REFCOUNTEDOBJECT_H_
-#define RTC_BASE_REFCOUNTEDOBJECT_H_
+#ifndef RTC_BASE_REF_COUNTED_OBJECT_H_
+#define RTC_BASE_REF_COUNTED_OBJECT_H_
 
+#include <type_traits>
 #include <utility>
 
-#include "rtc_base/constructormagic.h"
-#include "rtc_base/refcount.h"
-#include "rtc_base/refcounter.h"
+#include "rtc_base/constructor_magic.h"
+#include "rtc_base/ref_count.h"
+#include "rtc_base/ref_counter.h"
 
 namespace rtc {
 
@@ -60,4 +61,4 @@
 
 }  // namespace rtc
 
-#endif  // RTC_BASE_REFCOUNTEDOBJECT_H_
+#endif  // RTC_BASE_REF_COUNTED_OBJECT_H_
diff --git a/rtc_base/refcountedobject_unittest.cc b/rtc_base/ref_counted_object_unittest.cc
similarity index 92%
rename from rtc_base/refcountedobject_unittest.cc
rename to rtc_base/ref_counted_object_unittest.cc
index 4744525..00a9295 100644
--- a/rtc_base/refcountedobject_unittest.cc
+++ b/rtc_base/ref_counted_object_unittest.cc
@@ -8,11 +8,14 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
+#include <memory>
 #include <string>
+#include <utility>
 
-#include "rtc_base/gunit.h"
-#include "rtc_base/refcount.h"
-#include "rtc_base/refcountedobject.h"
+#include "api/scoped_refptr.h"
+#include "rtc_base/ref_count.h"
+#include "rtc_base/ref_counted_object.h"
+#include "test/gtest.h"
 
 namespace rtc {
 
diff --git a/rtc_base/refcounter.h b/rtc_base/ref_counter.h
similarity index 73%
rename from rtc_base/refcounter.h
rename to rtc_base/ref_counter.h
index 3906529..600dda8 100644
--- a/rtc_base/refcounter.h
+++ b/rtc_base/ref_counter.h
@@ -7,11 +7,11 @@
  *  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_REFCOUNTER_H_
-#define RTC_BASE_REFCOUNTER_H_
+#ifndef RTC_BASE_REF_COUNTER_H_
+#define RTC_BASE_REF_COUNTER_H_
 
-#include "rtc_base/atomicops.h"
-#include "rtc_base/refcount.h"
+#include "rtc_base/atomic_ops.h"
+#include "rtc_base/ref_count.h"
 
 namespace webrtc {
 namespace webrtc_impl {
@@ -23,9 +23,11 @@
 
   void IncRef() { rtc::AtomicOps::Increment(&ref_count_); }
 
-  // TODO(nisse): Switch return type to RefCountReleaseStatus?
-  // Returns true if this was the last reference, and the resource protected by
-  // the reference counter can be deleted.
+  // Returns kDroppedLastRef if this call dropped the last reference; the caller
+  // should therefore free the resource protected by the reference counter.
+  // Otherwise, returns kOtherRefsRemained (note that in case of multithreading,
+  // some other caller may have dropped the last reference by the time this call
+  // returns; all we know is that we didn't do it).
   rtc::RefCountReleaseStatus DecRef() {
     return (rtc::AtomicOps::Decrement(&ref_count_) == 0)
                ? rtc::RefCountReleaseStatus::kDroppedLastRef
@@ -49,4 +51,4 @@
 }  // namespace webrtc_impl
 }  // namespace webrtc
 
-#endif  // RTC_BASE_REFCOUNTER_H_
+#endif  // RTC_BASE_REF_COUNTER_H_
diff --git a/rtc_base/rollingaccumulator.h b/rtc_base/rolling_accumulator.h
similarity index 95%
rename from rtc_base/rollingaccumulator.h
rename to rtc_base/rolling_accumulator.h
index f6215c5..dacceff 100644
--- a/rtc_base/rollingaccumulator.h
+++ b/rtc_base/rolling_accumulator.h
@@ -8,14 +8,15 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#ifndef RTC_BASE_ROLLINGACCUMULATOR_H_
-#define RTC_BASE_ROLLINGACCUMULATOR_H_
+#ifndef RTC_BASE_ROLLING_ACCUMULATOR_H_
+#define RTC_BASE_ROLLING_ACCUMULATOR_H_
 
+#include <stddef.h>
 #include <algorithm>
 #include <vector>
 
 #include "rtc_base/checks.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace rtc {
 
@@ -163,4 +164,4 @@
 
 }  // namespace rtc
 
-#endif  // RTC_BASE_ROLLINGACCUMULATOR_H_
+#endif  // RTC_BASE_ROLLING_ACCUMULATOR_H_
diff --git a/rtc_base/rollingaccumulator_unittest.cc b/rtc_base/rolling_accumulator_unittest.cc
similarity index 97%
rename from rtc_base/rollingaccumulator_unittest.cc
rename to rtc_base/rolling_accumulator_unittest.cc
index 91ed853..7d5e70d 100644
--- a/rtc_base/rollingaccumulator_unittest.cc
+++ b/rtc_base/rolling_accumulator_unittest.cc
@@ -8,8 +8,9 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#include "rtc_base/rollingaccumulator.h"
-#include "rtc_base/gunit.h"
+#include "rtc_base/rolling_accumulator.h"
+
+#include "test/gtest.h"
 
 namespace rtc {
 
diff --git a/rtc_base/rtccertificate.cc b/rtc_base/rtc_certificate.cc
similarity index 92%
rename from rtc_base/rtccertificate.cc
rename to rtc_base/rtc_certificate.cc
index 875068f..46f6c31 100644
--- a/rtc_base/rtccertificate.cc
+++ b/rtc_base/rtc_certificate.cc
@@ -10,13 +10,13 @@
 
 #include <memory>
 
-#include "rtc_base/rtccertificate.h"
+#include "rtc_base/rtc_certificate.h"
 
 #include "rtc_base/checks.h"
-#include "rtc_base/refcountedobject.h"
-#include "rtc_base/sslcertificate.h"
-#include "rtc_base/sslidentity.h"
-#include "rtc_base/timeutils.h"
+#include "rtc_base/ref_counted_object.h"
+#include "rtc_base/ssl_certificate.h"
+#include "rtc_base/ssl_identity.h"
+#include "rtc_base/time_utils.h"
 
 namespace rtc {
 
diff --git a/rtc_base/rtccertificate.h b/rtc_base/rtc_certificate.h
similarity index 94%
rename from rtc_base/rtccertificate.h
rename to rtc_base/rtc_certificate.h
index 561ea0f..d98c4ea 100644
--- a/rtc_base/rtccertificate.h
+++ b/rtc_base/rtc_certificate.h
@@ -8,15 +8,15 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#ifndef RTC_BASE_RTCCERTIFICATE_H_
-#define RTC_BASE_RTCCERTIFICATE_H_
+#ifndef RTC_BASE_RTC_CERTIFICATE_H_
+#define RTC_BASE_RTC_CERTIFICATE_H_
 
 #include <stdint.h>
 #include <memory>
 #include <string>
 
-#include "rtc_base/refcount.h"
-#include "rtc_base/scoped_ref_ptr.h"
+#include "api/scoped_refptr.h"
+#include "rtc_base/ref_count.h"
 
 namespace rtc {
 
@@ -90,4 +90,4 @@
 
 }  // namespace rtc
 
-#endif  // RTC_BASE_RTCCERTIFICATE_H_
+#endif  // RTC_BASE_RTC_CERTIFICATE_H_
diff --git a/rtc_base/rtccertificategenerator.cc b/rtc_base/rtc_certificate_generator.cc
similarity index 96%
rename from rtc_base/rtccertificategenerator.cc
rename to rtc_base/rtc_certificate_generator.cc
index 114b35c..08cd199 100644
--- a/rtc_base/rtccertificategenerator.cc
+++ b/rtc_base/rtc_certificate_generator.cc
@@ -8,7 +8,7 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#include "rtc_base/rtccertificategenerator.h"
+#include "rtc_base/rtc_certificate_generator.h"
 
 #include <time.h>
 #include <algorithm>
@@ -17,10 +17,10 @@
 
 #include "rtc_base/checks.h"
 #include "rtc_base/location.h"
-#include "rtc_base/messagehandler.h"
-#include "rtc_base/messagequeue.h"
-#include "rtc_base/refcountedobject.h"
-#include "rtc_base/sslidentity.h"
+#include "rtc_base/message_handler.h"
+#include "rtc_base/message_queue.h"
+#include "rtc_base/ref_counted_object.h"
+#include "rtc_base/ssl_identity.h"
 
 namespace rtc {
 
diff --git a/rtc_base/rtccertificategenerator.h b/rtc_base/rtc_certificate_generator.h
similarity index 91%
rename from rtc_base/rtccertificategenerator.h
rename to rtc_base/rtc_certificate_generator.h
index fed075e..8cabca4 100644
--- a/rtc_base/rtccertificategenerator.h
+++ b/rtc_base/rtc_certificate_generator.h
@@ -8,16 +8,16 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#ifndef RTC_BASE_RTCCERTIFICATEGENERATOR_H_
-#define RTC_BASE_RTCCERTIFICATEGENERATOR_H_
+#ifndef RTC_BASE_RTC_CERTIFICATE_GENERATOR_H_
+#define RTC_BASE_RTC_CERTIFICATE_GENERATOR_H_
 
 #include <stdint.h>
 
 #include "absl/types/optional.h"
-#include "rtc_base/refcount.h"
-#include "rtc_base/rtccertificate.h"
-#include "rtc_base/scoped_ref_ptr.h"
-#include "rtc_base/sslidentity.h"
+#include "api/scoped_refptr.h"
+#include "rtc_base/ref_count.h"
+#include "rtc_base/rtc_certificate.h"
+#include "rtc_base/ssl_identity.h"
 #include "rtc_base/thread.h"
 
 namespace rtc {
@@ -84,4 +84,4 @@
 
 }  // namespace rtc
 
-#endif  // RTC_BASE_RTCCERTIFICATEGENERATOR_H_
+#endif  // RTC_BASE_RTC_CERTIFICATE_GENERATOR_H_
diff --git a/rtc_base/rtccertificategenerator_unittest.cc b/rtc_base/rtc_certificate_generator_unittest.cc
similarity index 97%
rename from rtc_base/rtccertificategenerator_unittest.cc
rename to rtc_base/rtc_certificate_generator_unittest.cc
index 3929128..69c8597 100644
--- a/rtc_base/rtccertificategenerator_unittest.cc
+++ b/rtc_base/rtc_certificate_generator_unittest.cc
@@ -8,16 +8,16 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#include "rtc_base/rtccertificategenerator.h"
+#include "rtc_base/rtc_certificate_generator.h"
 
 #include <memory>
 
 #include "absl/types/optional.h"
 #include "rtc_base/checks.h"
 #include "rtc_base/gunit.h"
-#include "rtc_base/logging.h"
-#include "rtc_base/refcountedobject.h"
+#include "rtc_base/ref_counted_object.h"
 #include "rtc_base/thread.h"
+#include "test/gtest.h"
 
 namespace rtc {
 
diff --git a/rtc_base/rtccertificate_unittest.cc b/rtc_base/rtc_certificate_unittest.cc
similarity index 95%
rename from rtc_base/rtccertificate_unittest.cc
rename to rtc_base/rtc_certificate_unittest.cc
index bb88d8a..ab242bb 100644
--- a/rtc_base/rtccertificate_unittest.cc
+++ b/rtc_base/rtc_certificate_unittest.cc
@@ -8,18 +8,16 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
+#include <time.h>
 #include <memory>
 #include <utility>
 
 #include "rtc_base/checks.h"
-#include "rtc_base/fakesslidentity.h"
-#include "rtc_base/gunit.h"
-#include "rtc_base/logging.h"
 #include "rtc_base/numerics/safe_conversions.h"
-#include "rtc_base/rtccertificate.h"
-#include "rtc_base/sslidentity.h"
-#include "rtc_base/thread.h"
-#include "rtc_base/timeutils.h"
+#include "rtc_base/rtc_certificate.h"
+#include "rtc_base/ssl_identity.h"
+#include "rtc_base/time_utils.h"
+#include "test/gtest.h"
 
 namespace rtc {
 
diff --git a/rtc_base/sanitizer_unittest.cc b/rtc_base/sanitizer_unittest.cc
index 8dc6068..ffbfed7 100644
--- a/rtc_base/sanitizer_unittest.cc
+++ b/rtc_base/sanitizer_unittest.cc
@@ -10,8 +10,10 @@
 
 #include "rtc_base/sanitizer.h"
 
-#include "rtc_base/gunit.h"
+#include <stdint.h>
+
 #include "rtc_base/logging.h"
+#include "test/gtest.h"
 
 #if RTC_HAS_MSAN
 #include <sanitizer/msan_interface.h>
diff --git a/rtc_base/scoped_ref_ptr.h b/rtc_base/scoped_ref_ptr.h
deleted file mode 100644
index b961ff5..0000000
--- a/rtc_base/scoped_ref_ptr.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- *  Copyright 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
- *  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_SCOPED_REF_PTR_H_
-#define RTC_BASE_SCOPED_REF_PTR_H_
-
-// TODO(bugs.webrtc.org/9887): This is a forward header for backwards
-// compatibility. Remove when downstream clients are updated.
-
-#include "api/scoped_refptr.h"
-
-#endif  // RTC_BASE_SCOPED_REF_PTR_H_
diff --git a/rtc_base/sequenced_task_checker.h b/rtc_base/sequenced_task_checker.h
index eb15198..e5443af 100644
--- a/rtc_base/sequenced_task_checker.h
+++ b/rtc_base/sequenced_task_checker.h
@@ -17,7 +17,7 @@
 #define ENABLE_SEQUENCED_TASK_CHECKER RTC_DCHECK_IS_ON
 
 #include "rtc_base/checks.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 #include "rtc_base/sequenced_task_checker_impl.h"
 #include "rtc_base/thread_annotations.h"
 
diff --git a/rtc_base/sequenced_task_checker_impl.cc b/rtc_base/sequenced_task_checker_impl.cc
index 717cb95..678f91d 100644
--- a/rtc_base/sequenced_task_checker_impl.cc
+++ b/rtc_base/sequenced_task_checker_impl.cc
@@ -14,19 +14,19 @@
 #include <dispatch/dispatch.h>
 #endif
 
+#include "api/task_queue/task_queue_base.h"
 #include "rtc_base/checks.h"
 #include "rtc_base/sequenced_task_checker.h"
-#include "rtc_base/task_queue.h"
 
 namespace rtc {
 
 SequencedTaskCheckerImpl::SequencedTaskCheckerImpl()
-    : attached_(true), valid_queue_(TaskQueue::Current()) {}
+    : attached_(true), valid_queue_(webrtc::TaskQueueBase::Current()) {}
 
 SequencedTaskCheckerImpl::~SequencedTaskCheckerImpl() {}
 
 bool SequencedTaskCheckerImpl::CalledSequentially() const {
-  QueueId current_queue = TaskQueue::Current();
+  QueueId current_queue = webrtc::TaskQueueBase::Current();
 #if defined(WEBRTC_MAC)
   // If we're not running on a TaskQueue, use the system dispatch queue
   // label as an identifier.
diff --git a/rtc_base/sequenced_task_checker_impl.h b/rtc_base/sequenced_task_checker_impl.h
index 293b1ac..bd53961 100644
--- a/rtc_base/sequenced_task_checker_impl.h
+++ b/rtc_base/sequenced_task_checker_impl.h
@@ -11,12 +11,11 @@
 #ifndef RTC_BASE_SEQUENCED_TASK_CHECKER_IMPL_H_
 #define RTC_BASE_SEQUENCED_TASK_CHECKER_IMPL_H_
 
-#include "rtc_base/criticalsection.h"
+#include "rtc_base/critical_section.h"
 #include "rtc_base/thread_checker.h"
 
 namespace rtc {
 
-class TaskQueue;
 // Real implementation of SequencedTaskChecker, for use in debug mode, or
 // for temporary use in release mode.
 //
diff --git a/rtc_base/sequenced_task_checker_unittest.cc b/rtc_base/sequenced_task_checker_unittest.cc
index 7b7247c..b3df2fa 100644
--- a/rtc_base/sequenced_task_checker_unittest.cc
+++ b/rtc_base/sequenced_task_checker_unittest.cc
@@ -10,8 +10,11 @@
 
 #include "rtc_base/sequenced_task_checker.h"
 
+#include <memory>
+#include <utility>
+
 #include "rtc_base/checks.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 #include "rtc_base/event.h"
 #include "rtc_base/platform_thread.h"
 #include "rtc_base/task_queue.h"
diff --git a/rtc_base/server_socket_adapters.cc b/rtc_base/server_socket_adapters.cc
new file mode 100644
index 0000000..887ca87
--- /dev/null
+++ b/rtc_base/server_socket_adapters.cc
@@ -0,0 +1,185 @@
+/*
+ *  Copyright 2004 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 <string>
+
+#include "rtc_base/byte_buffer.h"
+#include "rtc_base/server_socket_adapters.h"
+
+namespace rtc {
+
+AsyncProxyServerSocket::AsyncProxyServerSocket(AsyncSocket* socket,
+                                               size_t buffer_size)
+    : BufferedReadAdapter(socket, buffer_size) {}
+
+AsyncProxyServerSocket::~AsyncProxyServerSocket() = default;
+
+AsyncSSLServerSocket::AsyncSSLServerSocket(AsyncSocket* socket)
+    : BufferedReadAdapter(socket, 1024) {
+  BufferInput(true);
+}
+
+void AsyncSSLServerSocket::ProcessInput(char* data, size_t* len) {
+  // We only accept client hello messages.
+  const ArrayView<const uint8_t> client_hello =
+      AsyncSSLSocket::SslClientHello();
+  if (*len < client_hello.size()) {
+    return;
+  }
+
+  if (memcmp(client_hello.data(), data, client_hello.size()) != 0) {
+    Close();
+    SignalCloseEvent(this, 0);
+    return;
+  }
+
+  *len -= client_hello.size();
+
+  // Clients should not send more data until the handshake is completed.
+  RTC_DCHECK(*len == 0);
+
+  const ArrayView<const uint8_t> server_hello =
+      AsyncSSLSocket::SslServerHello();
+  // Send a server hello back to the client.
+  DirectSend(server_hello.data(), server_hello.size());
+
+  // Handshake completed for us, redirect input to our parent.
+  BufferInput(false);
+}
+
+AsyncSocksProxyServerSocket::AsyncSocksProxyServerSocket(AsyncSocket* socket)
+    : AsyncProxyServerSocket(socket, kBufferSize), state_(SS_HELLO) {
+  BufferInput(true);
+}
+
+void AsyncSocksProxyServerSocket::ProcessInput(char* data, size_t* len) {
+  RTC_DCHECK(state_ < SS_CONNECT_PENDING);
+
+  ByteBufferReader response(data, *len);
+  if (state_ == SS_HELLO) {
+    HandleHello(&response);
+  } else if (state_ == SS_AUTH) {
+    HandleAuth(&response);
+  } else if (state_ == SS_CONNECT) {
+    HandleConnect(&response);
+  }
+
+  // Consume parsed data
+  *len = response.Length();
+  memmove(data, response.Data(), *len);
+}
+
+void AsyncSocksProxyServerSocket::DirectSend(const ByteBufferWriter& buf) {
+  BufferedReadAdapter::DirectSend(buf.Data(), buf.Length());
+}
+
+void AsyncSocksProxyServerSocket::HandleHello(ByteBufferReader* request) {
+  uint8_t ver, num_methods;
+  if (!request->ReadUInt8(&ver) || !request->ReadUInt8(&num_methods)) {
+    Error(0);
+    return;
+  }
+
+  if (ver != 5) {
+    Error(0);
+    return;
+  }
+
+  // Handle either no-auth (0) or user/pass auth (2)
+  uint8_t method = 0xFF;
+  if (num_methods > 0 && !request->ReadUInt8(&method)) {
+    Error(0);
+    return;
+  }
+
+  SendHelloReply(method);
+  if (method == 0) {
+    state_ = SS_CONNECT;
+  } else if (method == 2) {
+    state_ = SS_AUTH;
+  } else {
+    state_ = SS_ERROR;
+  }
+}
+
+void AsyncSocksProxyServerSocket::SendHelloReply(uint8_t method) {
+  ByteBufferWriter response;
+  response.WriteUInt8(5);       // Socks Version
+  response.WriteUInt8(method);  // Auth method
+  DirectSend(response);
+}
+
+void AsyncSocksProxyServerSocket::HandleAuth(ByteBufferReader* request) {
+  uint8_t ver, user_len, pass_len;
+  std::string user, pass;
+  if (!request->ReadUInt8(&ver) || !request->ReadUInt8(&user_len) ||
+      !request->ReadString(&user, user_len) || !request->ReadUInt8(&pass_len) ||
+      !request->ReadString(&pass, pass_len)) {
+    Error(0);
+    return;
+  }
+
+  SendAuthReply(0);
+  state_ = SS_CONNECT;
+}
+
+void AsyncSocksProxyServerSocket::SendAuthReply(uint8_t result) {
+  ByteBufferWriter response;
+  response.WriteUInt8(1);  // Negotiation Version
+  response.WriteUInt8(result);
+  DirectSend(response);
+}
+
+void AsyncSocksProxyServerSocket::HandleConnect(ByteBufferReader* request) {
+  uint8_t ver, command, reserved, addr_type;
+  uint32_t ip;
+  uint16_t port;
+  if (!request->ReadUInt8(&ver) || !request->ReadUInt8(&command) ||
+      !request->ReadUInt8(&reserved) || !request->ReadUInt8(&addr_type) ||
+      !request->ReadUInt32(&ip) || !request->ReadUInt16(&port)) {
+    Error(0);
+    return;
+  }
+
+  if (ver != 5 || command != 1 || reserved != 0 || addr_type != 1) {
+    Error(0);
+    return;
+  }
+
+  SignalConnectRequest(this, SocketAddress(ip, port));
+  state_ = SS_CONNECT_PENDING;
+}
+
+void AsyncSocksProxyServerSocket::SendConnectResult(int result,
+                                                    const SocketAddress& addr) {
+  if (state_ != SS_CONNECT_PENDING)
+    return;
+
+  ByteBufferWriter response;
+  response.WriteUInt8(5);              // Socks version
+  response.WriteUInt8((result != 0));  // 0x01 is generic error
+  response.WriteUInt8(0);              // reserved
+  response.WriteUInt8(1);              // IPv4 address
+  response.WriteUInt32(addr.ip());
+  response.WriteUInt16(addr.port());
+  DirectSend(response);
+  BufferInput(false);
+  state_ = SS_TUNNEL;
+}
+
+void AsyncSocksProxyServerSocket::Error(int error) {
+  state_ = SS_ERROR;
+  BufferInput(false);
+  Close();
+  SetError(SOCKET_EACCES);
+  SignalCloseEvent(this, error);
+}
+
+}  // namespace rtc
diff --git a/rtc_base/server_socket_adapters.h b/rtc_base/server_socket_adapters.h
new file mode 100644
index 0000000..a534eea
--- /dev/null
+++ b/rtc_base/server_socket_adapters.h
@@ -0,0 +1,72 @@
+/*
+ *  Copyright 2004 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_SERVER_SOCKET_ADAPTERS_H_
+#define RTC_BASE_SERVER_SOCKET_ADAPTERS_H_
+
+#include "rtc_base/socket_adapters.h"
+
+namespace rtc {
+
+// Interface for implementing proxy server sockets.
+class AsyncProxyServerSocket : public BufferedReadAdapter {
+ public:
+  AsyncProxyServerSocket(AsyncSocket* socket, size_t buffer_size);
+  ~AsyncProxyServerSocket() override;
+  sigslot::signal2<AsyncProxyServerSocket*, const SocketAddress&>
+      SignalConnectRequest;
+  virtual void SendConnectResult(int err, const SocketAddress& addr) = 0;
+};
+
+// Implements a socket adapter that performs the server side of a
+// fake SSL handshake. Used when implementing a relay server that does "ssltcp".
+class AsyncSSLServerSocket : public BufferedReadAdapter {
+ public:
+  explicit AsyncSSLServerSocket(AsyncSocket* socket);
+
+ protected:
+  void ProcessInput(char* data, size_t* len) override;
+  RTC_DISALLOW_COPY_AND_ASSIGN(AsyncSSLServerSocket);
+};
+
+// Implements a proxy server socket for the SOCKS protocol.
+class AsyncSocksProxyServerSocket : public AsyncProxyServerSocket {
+ public:
+  explicit AsyncSocksProxyServerSocket(AsyncSocket* socket);
+
+ private:
+  void ProcessInput(char* data, size_t* len) override;
+  void DirectSend(const ByteBufferWriter& buf);
+
+  void HandleHello(ByteBufferReader* request);
+  void SendHelloReply(uint8_t method);
+  void HandleAuth(ByteBufferReader* request);
+  void SendAuthReply(uint8_t result);
+  void HandleConnect(ByteBufferReader* request);
+  void SendConnectResult(int result, const SocketAddress& addr) override;
+
+  void Error(int error);
+
+  static const int kBufferSize = 1024;
+  enum State {
+    SS_HELLO,
+    SS_AUTH,
+    SS_CONNECT,
+    SS_CONNECT_PENDING,
+    SS_TUNNEL,
+    SS_ERROR
+  };
+  State state_;
+  RTC_DISALLOW_COPY_AND_ASSIGN(AsyncSocksProxyServerSocket);
+};
+
+}  // namespace rtc
+
+#endif  // RTC_BASE_SERVER_SOCKET_ADAPTERS_H_
diff --git a/rtc_base/signalthread.cc b/rtc_base/signal_thread.cc
similarity index 97%
rename from rtc_base/signalthread.cc
rename to rtc_base/signal_thread.cc
index 5dd9387..84613db 100644
--- a/rtc_base/signalthread.cc
+++ b/rtc_base/signal_thread.cc
@@ -8,15 +8,15 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#include "rtc_base/signalthread.h"
+#include "rtc_base/signal_thread.h"
 
 #include <memory>
 
 #include "absl/memory/memory.h"
 #include "rtc_base/checks.h"
 #include "rtc_base/location.h"
-#include "rtc_base/nullsocketserver.h"
-#include "rtc_base/socketserver.h"
+#include "rtc_base/null_socket_server.h"
+#include "rtc_base/socket_server.h"
 
 namespace rtc {
 
diff --git a/rtc_base/signalthread.h b/rtc_base/signal_thread.h
similarity index 95%
rename from rtc_base/signalthread.h
rename to rtc_base/signal_thread.h
index 9208e2c..9a20ad2 100644
--- a/rtc_base/signalthread.h
+++ b/rtc_base/signal_thread.h
@@ -8,16 +8,16 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#ifndef RTC_BASE_SIGNALTHREAD_H_
-#define RTC_BASE_SIGNALTHREAD_H_
+#ifndef RTC_BASE_SIGNAL_THREAD_H_
+#define RTC_BASE_SIGNAL_THREAD_H_
 
 #include <string>
 
 #include "rtc_base/checks.h"
-#include "rtc_base/constructormagic.h"
-#include "rtc_base/criticalsection.h"
-#include "rtc_base/messagehandler.h"
-#include "rtc_base/messagequeue.h"
+#include "rtc_base/constructor_magic.h"
+#include "rtc_base/critical_section.h"
+#include "rtc_base/message_handler.h"
+#include "rtc_base/message_queue.h"
 #include "rtc_base/third_party/sigslot/sigslot.h"
 #include "rtc_base/thread.h"
 #include "rtc_base/thread_annotations.h"
@@ -155,4 +155,4 @@
 
 }  // namespace rtc
 
-#endif  // RTC_BASE_SIGNALTHREAD_H_
+#endif  // RTC_BASE_SIGNAL_THREAD_H_
diff --git a/rtc_base/signalthread_unittest.cc b/rtc_base/signal_thread_unittest.cc
similarity index 96%
rename from rtc_base/signalthread_unittest.cc
rename to rtc_base/signal_thread_unittest.cc
index 078710b..2bc0dda 100644
--- a/rtc_base/signalthread_unittest.cc
+++ b/rtc_base/signal_thread_unittest.cc
@@ -10,12 +10,15 @@
 
 #include <memory>
 
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 #include "rtc_base/gunit.h"
-#include "rtc_base/signalthread.h"
+#include "rtc_base/signal_thread.h"
+#include "rtc_base/socket_server.h"
 #include "rtc_base/thread.h"
+#include "test/gtest.h"
 
-using namespace rtc;
+namespace rtc {
+namespace {
 
 // 10 seconds.
 static const int kTimeout = 10000;
@@ -206,3 +209,6 @@
   ExpectState(1, 0, 0, 1, 0);
   ExpectStateWait(1, 1, 0, 1, 1, kTimeout);
 }
+
+}  // namespace
+}  // namespace rtc
diff --git a/rtc_base/sigslotrepeater.h b/rtc_base/sigslot_repeater.h
similarity index 94%
rename from rtc_base/sigslotrepeater.h
rename to rtc_base/sigslot_repeater.h
index 724e624..f562c5a 100644
--- a/rtc_base/sigslotrepeater.h
+++ b/rtc_base/sigslot_repeater.h
@@ -8,8 +8,8 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#ifndef RTC_BASE_SIGSLOTREPEATER_H__
-#define RTC_BASE_SIGSLOTREPEATER_H__
+#ifndef RTC_BASE_SIGSLOT_REPEATER_H__
+#define RTC_BASE_SIGSLOT_REPEATER_H__
 
 // repeaters are both signals and slots, which are designed as intermediate
 // pass-throughs for signals and slots which don't know about each other (for
@@ -53,4 +53,4 @@
 
 }  // namespace sigslot
 
-#endif  // RTC_BASE_SIGSLOTREPEATER_H__
+#endif  // RTC_BASE_SIGSLOT_REPEATER_H__
diff --git a/rtc_base/sigslottester.h b/rtc_base/sigslot_tester.h
similarity index 97%
rename from rtc_base/sigslottester.h
rename to rtc_base/sigslot_tester.h
index 73f4365..58be511 100644
--- a/rtc_base/sigslottester.h
+++ b/rtc_base/sigslot_tester.h
@@ -12,8 +12,8 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#ifndef RTC_BASE_SIGSLOTTESTER_H_
-#define RTC_BASE_SIGSLOTTESTER_H_
+#ifndef RTC_BASE_SIGSLOT_TESTER_H_
+#define RTC_BASE_SIGSLOT_TESTER_H_
 
 // To generate sigslottester.h from sigslottester.h.pump, execute:
 // /home/build/google3/third_party/gtest/scripts/pump.py sigslottester.h.pump
@@ -38,7 +38,7 @@
 //   EXPECT_EQ("hello", capture);
 //   /* See unit-tests for more examples */
 
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 #include "rtc_base/third_party/sigslot/sigslot.h"
 
 namespace rtc {
@@ -237,4 +237,4 @@
 };
 }  // namespace rtc
 
-#endif  // RTC_BASE_SIGSLOTTESTER_H_
+#endif  // RTC_BASE_SIGSLOT_TESTER_H_
diff --git a/rtc_base/sigslottester_unittest.cc b/rtc_base/sigslot_tester_unittest.cc
similarity index 97%
rename from rtc_base/sigslottester_unittest.cc
rename to rtc_base/sigslot_tester_unittest.cc
index 8fde268..6c5b12e 100644
--- a/rtc_base/sigslottester_unittest.cc
+++ b/rtc_base/sigslot_tester_unittest.cc
@@ -8,12 +8,12 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#include "rtc_base/sigslottester.h"
+#include "rtc_base/sigslot_tester.h"
 
 #include <string>
 
-#include "rtc_base/gunit.h"
 #include "rtc_base/third_party/sigslot/sigslot.h"
+#include "test/gtest.h"
 
 namespace rtc {
 
diff --git a/rtc_base/sigslot_unittest.cc b/rtc_base/sigslot_unittest.cc
index 2f3de40..8edab7c 100644
--- a/rtc_base/sigslot_unittest.cc
+++ b/rtc_base/sigslot_unittest.cc
@@ -9,8 +9,9 @@
  */
 
 #include "rtc_base/third_party/sigslot/sigslot.h"
-#include "rtc_base/gunit.h"
-#include "rtc_base/sigslotrepeater.h"
+
+#include "rtc_base/sigslot_repeater.h"
+#include "test/gtest.h"
 
 // This function, when passed a has_slots or signalx, will break the build if
 // its threading requirement is not single threaded
diff --git a/rtc_base/sigslottester.h.pump b/rtc_base/sigslottester.h.pump
index 0c7c693..0a1f411 100755
--- a/rtc_base/sigslottester.h.pump
+++ b/rtc_base/sigslottester.h.pump
@@ -35,7 +35,7 @@
 //   EXPECT_EQ("hello", capture);
 //   /* See unit-tests for more examples */
 
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 #include "rtc_base/third_party/sigslot/sigslot.h"
 
 namespace rtc {
diff --git a/rtc_base/socket.h b/rtc_base/socket.h
index e7e8210..a2b65d1 100644
--- a/rtc_base/socket.h
+++ b/rtc_base/socket.h
@@ -25,9 +25,8 @@
 #include "rtc_base/win32.h"
 #endif
 
-#include "rtc_base/constructormagic.h"
-#include "rtc_base/network/sent_packet.h"
-#include "rtc_base/socketaddress.h"
+#include "rtc_base/constructor_magic.h"
+#include "rtc_base/socket_address.h"
 
 // Rather than converting errors into a private namespace,
 // Reuse the POSIX socket api errors. Note this depends on
diff --git a/rtc_base/socketadapters.cc b/rtc_base/socket_adapters.cc
similarity index 80%
rename from rtc_base/socketadapters.cc
rename to rtc_base/socket_adapters.cc
index 3bac17b..2bcdcd8 100644
--- a/rtc_base/socketadapters.cc
+++ b/rtc_base/socket_adapters.cc
@@ -31,13 +31,12 @@
 
 #include "absl/strings/match.h"
 #include "rtc_base/buffer.h"
-#include "rtc_base/bytebuffer.h"
+#include "rtc_base/byte_buffer.h"
 #include "rtc_base/checks.h"
-#include "rtc_base/httpcommon.h"
+#include "rtc_base/http_common.h"
 #include "rtc_base/logging.h"
-#include "rtc_base/socketadapters.h"
+#include "rtc_base/socket_adapters.h"
 #include "rtc_base/strings/string_builder.h"
-#include "rtc_base/stringutils.h"
 #include "rtc_base/zero_memory.h"
 
 namespace rtc {
@@ -130,12 +129,6 @@
   ProcessInput(buffer_, &data_len_);
 }
 
-AsyncProxyServerSocket::AsyncProxyServerSocket(AsyncSocket* socket,
-                                               size_t buffer_size)
-    : BufferedReadAdapter(socket, buffer_size) {}
-
-AsyncProxyServerSocket::~AsyncProxyServerSocket() = default;
-
 ///////////////////////////////////////////////////////////////////////////////
 
 // This is a SSL v2 CLIENT_HELLO message.
@@ -157,6 +150,13 @@
     0x46, 0x55, 0x2e, 0xb1, 0x83, 0x39, 0xf1, 0xea         //
 };
 
+// static
+ArrayView<const uint8_t> AsyncSSLSocket::SslClientHello() {
+  // Implicit conversion directly from kSslClientHello to ArrayView fails when
+  // built with gcc.
+  return {kSslClientHello, sizeof(kSslClientHello)};
+}
+
 // This is a TLSv1 SERVER_HELLO message.
 static const uint8_t kSslServerHello[] = {
     0x16,                                            // handshake message
@@ -178,6 +178,11 @@
     0x00                                             // null compression
 };
 
+// static
+ArrayView<const uint8_t> AsyncSSLSocket::SslServerHello() {
+  return {kSslServerHello, sizeof(kSslServerHello)};
+}
+
 AsyncSSLSocket::AsyncSSLSocket(AsyncSocket* socket)
     : BufferedReadAdapter(socket, 1024) {}
 
@@ -219,35 +224,6 @@
     SignalReadEvent(this);
 }
 
-AsyncSSLServerSocket::AsyncSSLServerSocket(AsyncSocket* socket)
-    : BufferedReadAdapter(socket, 1024) {
-  BufferInput(true);
-}
-
-void AsyncSSLServerSocket::ProcessInput(char* data, size_t* len) {
-  // We only accept client hello messages.
-  if (*len < sizeof(kSslClientHello)) {
-    return;
-  }
-
-  if (memcmp(kSslClientHello, data, sizeof(kSslClientHello)) != 0) {
-    Close();
-    SignalCloseEvent(this, 0);
-    return;
-  }
-
-  *len -= sizeof(kSslClientHello);
-
-  // Clients should not send more data until the handshake is completed.
-  RTC_DCHECK(*len == 0);
-
-  // Send a server hello back to the client.
-  DirectSend(kSslServerHello, sizeof(kSslServerHello));
-
-  // Handshake completed for us, redirect input to our parent.
-  BufferInput(false);
-}
-
 ///////////////////////////////////////////////////////////////////////////////
 
 AsyncHttpsProxySocket::AsyncHttpsProxySocket(AsyncSocket* socket,
@@ -714,135 +690,4 @@
   SignalCloseEvent(this, error);
 }
 
-AsyncSocksProxyServerSocket::AsyncSocksProxyServerSocket(AsyncSocket* socket)
-    : AsyncProxyServerSocket(socket, kBufferSize), state_(SS_HELLO) {
-  BufferInput(true);
-}
-
-void AsyncSocksProxyServerSocket::ProcessInput(char* data, size_t* len) {
-  // TODO: See if the whole message has arrived
-  RTC_DCHECK(state_ < SS_CONNECT_PENDING);
-
-  ByteBufferReader response(data, *len);
-  if (state_ == SS_HELLO) {
-    HandleHello(&response);
-  } else if (state_ == SS_AUTH) {
-    HandleAuth(&response);
-  } else if (state_ == SS_CONNECT) {
-    HandleConnect(&response);
-  }
-
-  // Consume parsed data
-  *len = response.Length();
-  memmove(data, response.Data(), *len);
-}
-
-void AsyncSocksProxyServerSocket::DirectSend(const ByteBufferWriter& buf) {
-  BufferedReadAdapter::DirectSend(buf.Data(), buf.Length());
-}
-
-void AsyncSocksProxyServerSocket::HandleHello(ByteBufferReader* request) {
-  uint8_t ver, num_methods;
-  if (!request->ReadUInt8(&ver) || !request->ReadUInt8(&num_methods)) {
-    Error(0);
-    return;
-  }
-
-  if (ver != 5) {
-    Error(0);
-    return;
-  }
-
-  // Handle either no-auth (0) or user/pass auth (2)
-  uint8_t method = 0xFF;
-  if (num_methods > 0 && !request->ReadUInt8(&method)) {
-    Error(0);
-    return;
-  }
-
-  // TODO: Ask the server which method to use.
-  SendHelloReply(method);
-  if (method == 0) {
-    state_ = SS_CONNECT;
-  } else if (method == 2) {
-    state_ = SS_AUTH;
-  } else {
-    state_ = SS_ERROR;
-  }
-}
-
-void AsyncSocksProxyServerSocket::SendHelloReply(uint8_t method) {
-  ByteBufferWriter response;
-  response.WriteUInt8(5);       // Socks Version
-  response.WriteUInt8(method);  // Auth method
-  DirectSend(response);
-}
-
-void AsyncSocksProxyServerSocket::HandleAuth(ByteBufferReader* request) {
-  uint8_t ver, user_len, pass_len;
-  std::string user, pass;
-  if (!request->ReadUInt8(&ver) || !request->ReadUInt8(&user_len) ||
-      !request->ReadString(&user, user_len) || !request->ReadUInt8(&pass_len) ||
-      !request->ReadString(&pass, pass_len)) {
-    Error(0);
-    return;
-  }
-
-  // TODO: Allow for checking of credentials.
-  SendAuthReply(0);
-  state_ = SS_CONNECT;
-}
-
-void AsyncSocksProxyServerSocket::SendAuthReply(uint8_t result) {
-  ByteBufferWriter response;
-  response.WriteUInt8(1);  // Negotiation Version
-  response.WriteUInt8(result);
-  DirectSend(response);
-}
-
-void AsyncSocksProxyServerSocket::HandleConnect(ByteBufferReader* request) {
-  uint8_t ver, command, reserved, addr_type;
-  uint32_t ip;
-  uint16_t port;
-  if (!request->ReadUInt8(&ver) || !request->ReadUInt8(&command) ||
-      !request->ReadUInt8(&reserved) || !request->ReadUInt8(&addr_type) ||
-      !request->ReadUInt32(&ip) || !request->ReadUInt16(&port)) {
-    Error(0);
-    return;
-  }
-
-  if (ver != 5 || command != 1 || reserved != 0 || addr_type != 1) {
-    Error(0);
-    return;
-  }
-
-  SignalConnectRequest(this, SocketAddress(ip, port));
-  state_ = SS_CONNECT_PENDING;
-}
-
-void AsyncSocksProxyServerSocket::SendConnectResult(int result,
-                                                    const SocketAddress& addr) {
-  if (state_ != SS_CONNECT_PENDING)
-    return;
-
-  ByteBufferWriter response;
-  response.WriteUInt8(5);              // Socks version
-  response.WriteUInt8((result != 0));  // 0x01 is generic error
-  response.WriteUInt8(0);              // reserved
-  response.WriteUInt8(1);              // IPv4 address
-  response.WriteUInt32(addr.ip());
-  response.WriteUInt16(addr.port());
-  DirectSend(response);
-  BufferInput(false);
-  state_ = SS_TUNNEL;
-}
-
-void AsyncSocksProxyServerSocket::Error(int error) {
-  state_ = SS_ERROR;
-  BufferInput(false);
-  Close();
-  SetError(SOCKET_EACCES);
-  SignalCloseEvent(this, error);
-}
-
 }  // namespace rtc
diff --git a/rtc_base/socketadapters.h b/rtc_base/socket_adapters.h
similarity index 71%
rename from rtc_base/socketadapters.h
rename to rtc_base/socket_adapters.h
index 062f75c..99c9109 100644
--- a/rtc_base/socketadapters.h
+++ b/rtc_base/socket_adapters.h
@@ -8,14 +8,15 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#ifndef RTC_BASE_SOCKETADAPTERS_H_
-#define RTC_BASE_SOCKETADAPTERS_H_
+#ifndef RTC_BASE_SOCKET_ADAPTERS_H_
+#define RTC_BASE_SOCKET_ADAPTERS_H_
 
 #include <string>
 
-#include "rtc_base/asyncsocket.h"
-#include "rtc_base/constructormagic.h"
-#include "rtc_base/cryptstring.h"
+#include "api/array_view.h"
+#include "rtc_base/async_socket.h"
+#include "rtc_base/constructor_magic.h"
+#include "rtc_base/crypt_string.h"
 
 namespace rtc {
 
@@ -55,22 +56,13 @@
 
 ///////////////////////////////////////////////////////////////////////////////
 
-// Interface for implementing proxy server sockets.
-class AsyncProxyServerSocket : public BufferedReadAdapter {
- public:
-  AsyncProxyServerSocket(AsyncSocket* socket, size_t buffer_size);
-  ~AsyncProxyServerSocket() override;
-  sigslot::signal2<AsyncProxyServerSocket*, const SocketAddress&>
-      SignalConnectRequest;
-  virtual void SendConnectResult(int err, const SocketAddress& addr) = 0;
-};
-
-///////////////////////////////////////////////////////////////////////////////
-
 // Implements a socket adapter that performs the client side of a
 // fake SSL handshake. Used for "ssltcp" P2P functionality.
 class AsyncSSLSocket : public BufferedReadAdapter {
  public:
+  static ArrayView<const uint8_t> SslClientHello();
+  static ArrayView<const uint8_t> SslServerHello();
+
   explicit AsyncSSLSocket(AsyncSocket* socket);
 
   int Connect(const SocketAddress& addr) override;
@@ -81,17 +73,6 @@
   RTC_DISALLOW_COPY_AND_ASSIGN(AsyncSSLSocket);
 };
 
-// Implements a socket adapter that performs the server side of a
-// fake SSL handshake. Used when implementing a relay server that does "ssltcp".
-class AsyncSSLServerSocket : public BufferedReadAdapter {
- public:
-  explicit AsyncSSLServerSocket(AsyncSocket* socket);
-
- protected:
-  void ProcessInput(char* data, size_t* len) override;
-  RTC_DISALLOW_COPY_AND_ASSIGN(AsyncSSLServerSocket);
-};
-
 ///////////////////////////////////////////////////////////////////////////////
 
 // Implements a socket adapter that speaks the HTTP/S proxy protocol.
@@ -184,37 +165,6 @@
   RTC_DISALLOW_COPY_AND_ASSIGN(AsyncSocksProxySocket);
 };
 
-// Implements a proxy server socket for the SOCKS protocol.
-class AsyncSocksProxyServerSocket : public AsyncProxyServerSocket {
- public:
-  explicit AsyncSocksProxyServerSocket(AsyncSocket* socket);
-
- private:
-  void ProcessInput(char* data, size_t* len) override;
-  void DirectSend(const ByteBufferWriter& buf);
-
-  void HandleHello(ByteBufferReader* request);
-  void SendHelloReply(uint8_t method);
-  void HandleAuth(ByteBufferReader* request);
-  void SendAuthReply(uint8_t result);
-  void HandleConnect(ByteBufferReader* request);
-  void SendConnectResult(int result, const SocketAddress& addr) override;
-
-  void Error(int error);
-
-  static const int kBufferSize = 1024;
-  enum State {
-    SS_HELLO,
-    SS_AUTH,
-    SS_CONNECT,
-    SS_CONNECT_PENDING,
-    SS_TUNNEL,
-    SS_ERROR
-  };
-  State state_;
-  RTC_DISALLOW_COPY_AND_ASSIGN(AsyncSocksProxyServerSocket);
-};
-
 }  // namespace rtc
 
-#endif  // RTC_BASE_SOCKETADAPTERS_H_
+#endif  // RTC_BASE_SOCKET_ADAPTERS_H_
diff --git a/rtc_base/socketaddress.cc b/rtc_base/socket_address.cc
similarity index 98%
rename from rtc_base/socketaddress.cc
rename to rtc_base/socket_address.cc
index c91846d..3b22a05 100644
--- a/rtc_base/socketaddress.cc
+++ b/rtc_base/socket_address.cc
@@ -8,7 +8,7 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#include "rtc_base/socketaddress.h"
+#include "rtc_base/socket_address.h"
 #include "rtc_base/numerics/safe_conversions.h"
 
 #if defined(WEBRTC_POSIX)
@@ -26,10 +26,10 @@
 #include <unistd.h>
 #endif
 
-#include "rtc_base/byteorder.h"
+#include "rtc_base/byte_order.h"
 #include "rtc_base/checks.h"
 #include "rtc_base/logging.h"
-#include "rtc_base/nethelpers.h"
+#include "rtc_base/net_helpers.h"
 #include "rtc_base/strings/string_builder.h"
 
 #if defined(WEBRTC_WIN)
diff --git a/rtc_base/socketaddress.h b/rtc_base/socket_address.h
similarity index 97%
rename from rtc_base/socketaddress.h
rename to rtc_base/socket_address.h
index b1a52b9..342f5de 100644
--- a/rtc_base/socketaddress.h
+++ b/rtc_base/socket_address.h
@@ -8,14 +8,14 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#ifndef RTC_BASE_SOCKETADDRESS_H_
-#define RTC_BASE_SOCKETADDRESS_H_
+#ifndef RTC_BASE_SOCKET_ADDRESS_H_
+#define RTC_BASE_SOCKET_ADDRESS_H_
 
 #include <string>
 #ifdef UNIT_TEST
 #include <ostream>  // no-presubmit-check TODO(webrtc:8982)
 #endif              // UNIT_TEST
-#include "rtc_base/ipaddress.h"
+#include "rtc_base/ip_address.h"
 
 #undef SetPort
 
@@ -199,4 +199,4 @@
 
 }  // namespace rtc
 
-#endif  // RTC_BASE_SOCKETADDRESS_H_
+#endif  // RTC_BASE_SOCKET_ADDRESS_H_
diff --git a/rtc_base/socketaddresspair.cc b/rtc_base/socket_address_pair.cc
similarity index 95%
rename from rtc_base/socketaddresspair.cc
rename to rtc_base/socket_address_pair.cc
index 914ffd9..54f70ff 100644
--- a/rtc_base/socketaddresspair.cc
+++ b/rtc_base/socket_address_pair.cc
@@ -8,7 +8,7 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#include "rtc_base/socketaddresspair.h"
+#include "rtc_base/socket_address_pair.h"
 
 namespace rtc {
 
diff --git a/rtc_base/socketaddresspair.h b/rtc_base/socket_address_pair.h
similarity index 87%
rename from rtc_base/socketaddresspair.h
rename to rtc_base/socket_address_pair.h
index 6691386..f315e64 100644
--- a/rtc_base/socketaddresspair.h
+++ b/rtc_base/socket_address_pair.h
@@ -8,12 +8,12 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#ifndef RTC_BASE_SOCKETADDRESSPAIR_H_
-#define RTC_BASE_SOCKETADDRESSPAIR_H_
+#ifndef RTC_BASE_SOCKET_ADDRESS_PAIR_H_
+#define RTC_BASE_SOCKET_ADDRESS_PAIR_H_
 
 #include <stddef.h>
 
-#include "rtc_base/socketaddress.h"
+#include "rtc_base/socket_address.h"
 
 namespace rtc {
 
@@ -40,4 +40,4 @@
 
 }  // namespace rtc
 
-#endif  // RTC_BASE_SOCKETADDRESSPAIR_H_
+#endif  // RTC_BASE_SOCKET_ADDRESS_PAIR_H_
diff --git a/rtc_base/socketaddress_unittest.cc b/rtc_base/socket_address_unittest.cc
similarity index 98%
rename from rtc_base/socketaddress_unittest.cc
rename to rtc_base/socket_address_unittest.cc
index b7a2d92..14da8cb 100644
--- a/rtc_base/socketaddress_unittest.cc
+++ b/rtc_base/socket_address_unittest.cc
@@ -12,9 +12,11 @@
 #include <netinet/in.h>  // for sockaddr_in
 #endif
 
-#include "rtc_base/gunit.h"
-#include "rtc_base/ipaddress.h"
-#include "rtc_base/socketaddress.h"
+#include <string.h>
+
+#include "rtc_base/ip_address.h"
+#include "rtc_base/socket_address.h"
+#include "test/gtest.h"
 
 namespace rtc {
 
diff --git a/rtc_base/socketfactory.h b/rtc_base/socket_factory.h
similarity index 85%
rename from rtc_base/socketfactory.h
rename to rtc_base/socket_factory.h
index 5a5cd04..7356745 100644
--- a/rtc_base/socketfactory.h
+++ b/rtc_base/socket_factory.h
@@ -8,10 +8,10 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#ifndef RTC_BASE_SOCKETFACTORY_H_
-#define RTC_BASE_SOCKETFACTORY_H_
+#ifndef RTC_BASE_SOCKET_FACTORY_H_
+#define RTC_BASE_SOCKET_FACTORY_H_
 
-#include "rtc_base/asyncsocket.h"
+#include "rtc_base/async_socket.h"
 #include "rtc_base/socket.h"
 
 namespace rtc {
@@ -30,4 +30,4 @@
 
 }  // namespace rtc
 
-#endif  // RTC_BASE_SOCKETFACTORY_H_
+#endif  // RTC_BASE_SOCKET_FACTORY_H_
diff --git a/rtc_base/socketserver.h b/rtc_base/socket_server.h
similarity index 93%
rename from rtc_base/socketserver.h
rename to rtc_base/socket_server.h
index e29884e..348d099 100644
--- a/rtc_base/socketserver.h
+++ b/rtc_base/socket_server.h
@@ -8,11 +8,11 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#ifndef RTC_BASE_SOCKETSERVER_H_
-#define RTC_BASE_SOCKETSERVER_H_
+#ifndef RTC_BASE_SOCKET_SERVER_H_
+#define RTC_BASE_SOCKET_SERVER_H_
 
 #include <memory>
-#include "rtc_base/socketfactory.h"
+#include "rtc_base/socket_factory.h"
 
 namespace rtc {
 
@@ -59,4 +59,4 @@
 
 }  // namespace rtc
 
-#endif  // RTC_BASE_SOCKETSERVER_H_
+#endif  // RTC_BASE_SOCKET_SERVER_H_
diff --git a/rtc_base/socketstream.cc b/rtc_base/socket_stream.cc
similarity index 98%
rename from rtc_base/socketstream.cc
rename to rtc_base/socket_stream.cc
index 8978404..e93d6aa 100644
--- a/rtc_base/socketstream.cc
+++ b/rtc_base/socket_stream.cc
@@ -8,7 +8,7 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#include "rtc_base/socketstream.h"
+#include "rtc_base/socket_stream.h"
 
 #include "rtc_base/checks.h"
 #include "rtc_base/socket.h"
diff --git a/rtc_base/socketstream.h b/rtc_base/socket_stream.h
similarity index 85%
rename from rtc_base/socketstream.h
rename to rtc_base/socket_stream.h
index f781af1..f9875fe 100644
--- a/rtc_base/socketstream.h
+++ b/rtc_base/socket_stream.h
@@ -8,12 +8,15 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#ifndef RTC_BASE_SOCKETSTREAM_H_
-#define RTC_BASE_SOCKETSTREAM_H_
+#ifndef RTC_BASE_SOCKET_STREAM_H_
+#define RTC_BASE_SOCKET_STREAM_H_
 
-#include "rtc_base/asyncsocket.h"
-#include "rtc_base/constructormagic.h"
+#include <stddef.h>
+
+#include "rtc_base/async_socket.h"
+#include "rtc_base/constructor_magic.h"
 #include "rtc_base/stream.h"
+#include "rtc_base/third_party/sigslot/sigslot.h"
 
 namespace rtc {
 
@@ -58,4 +61,4 @@
 
 }  // namespace rtc
 
-#endif  // RTC_BASE_SOCKETSTREAM_H_
+#endif  // RTC_BASE_SOCKET_STREAM_H_
diff --git a/rtc_base/socket_unittest.cc b/rtc_base/socket_unittest.cc
index cbc5eb5..3166ec7 100644
--- a/rtc_base/socket_unittest.cc
+++ b/rtc_base/socket_unittest.cc
@@ -8,20 +8,32 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
+#include <errno.h>
+#include <stdint.h>
+#include <string.h>
 #include <memory>
 
-#include "rtc_base/socket_unittest.h"
-
 #include "absl/memory/memory.h"
 #include "rtc_base/arraysize.h"
-#include "rtc_base/asyncudpsocket.h"
+#include "rtc_base/async_packet_socket.h"
+#include "rtc_base/async_socket.h"
+#include "rtc_base/async_udp_socket.h"
 #include "rtc_base/buffer.h"
 #include "rtc_base/gunit.h"
-#include "rtc_base/nethelpers.h"
-#include "rtc_base/socketserver.h"
-#include "rtc_base/testclient.h"
-#include "rtc_base/testutils.h"
+#include "rtc_base/location.h"
+#include "rtc_base/logging.h"
+#include "rtc_base/message_handler.h"
+#include "rtc_base/message_queue.h"
+#include "rtc_base/net_helpers.h"
+#include "rtc_base/socket.h"
+#include "rtc_base/socket_address.h"
+#include "rtc_base/socket_server.h"
+#include "rtc_base/socket_unittest.h"
+#include "rtc_base/test_client.h"
+#include "rtc_base/test_utils.h"
+#include "rtc_base/third_party/sigslot/sigslot.h"
 #include "rtc_base/thread.h"
+#include "rtc_base/time_utils.h"
 
 namespace rtc {
 
diff --git a/rtc_base/ssladapter.cc b/rtc_base/ssl_adapter.cc
similarity index 93%
rename from rtc_base/ssladapter.cc
rename to rtc_base/ssl_adapter.cc
index e091f00..9d414ea 100644
--- a/rtc_base/ssladapter.cc
+++ b/rtc_base/ssl_adapter.cc
@@ -8,9 +8,9 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#include "rtc_base/ssladapter.h"
+#include "rtc_base/ssl_adapter.h"
 
-#include "rtc_base/openssladapter.h"
+#include "rtc_base/openssl_adapter.h"
 
 ///////////////////////////////////////////////////////////////////////////////
 
diff --git a/rtc_base/ssladapter.h b/rtc_base/ssl_adapter.h
similarity index 93%
rename from rtc_base/ssladapter.h
rename to rtc_base/ssl_adapter.h
index 7ebedca..240899f 100644
--- a/rtc_base/ssladapter.h
+++ b/rtc_base/ssl_adapter.h
@@ -8,16 +8,16 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#ifndef RTC_BASE_SSLADAPTER_H_
-#define RTC_BASE_SSLADAPTER_H_
+#ifndef RTC_BASE_SSL_ADAPTER_H_
+#define RTC_BASE_SSL_ADAPTER_H_
 
 #include <string>
 #include <vector>
 
-#include "rtc_base/asyncsocket.h"
-#include "rtc_base/sslcertificate.h"
-#include "rtc_base/sslidentity.h"
-#include "rtc_base/sslstreamadapter.h"
+#include "rtc_base/async_socket.h"
+#include "rtc_base/ssl_certificate.h"
+#include "rtc_base/ssl_identity.h"
+#include "rtc_base/ssl_stream_adapter.h"
 
 namespace rtc {
 
@@ -103,4 +103,4 @@
 
 }  // namespace rtc
 
-#endif  // RTC_BASE_SSLADAPTER_H_
+#endif  // RTC_BASE_SSL_ADAPTER_H_
diff --git a/rtc_base/ssladapter_unittest.cc b/rtc_base/ssl_adapter_unittest.cc
similarity index 98%
rename from rtc_base/ssladapter_unittest.cc
rename to rtc_base/ssl_adapter_unittest.cc
index c84c668..b459496 100644
--- a/rtc_base/ssladapter_unittest.cc
+++ b/rtc_base/ssl_adapter_unittest.cc
@@ -14,15 +14,15 @@
 
 #include "absl/memory/memory.h"
 #include "rtc_base/gunit.h"
-#include "rtc_base/ipaddress.h"
-#include "rtc_base/messagedigest.h"
-#include "rtc_base/socketstream.h"
-#include "rtc_base/ssladapter.h"
-#include "rtc_base/sslidentity.h"
-#include "rtc_base/sslstreamadapter.h"
+#include "rtc_base/ip_address.h"
+#include "rtc_base/message_digest.h"
+#include "rtc_base/socket_stream.h"
+#include "rtc_base/ssl_adapter.h"
+#include "rtc_base/ssl_identity.h"
+#include "rtc_base/ssl_stream_adapter.h"
 #include "rtc_base/stream.h"
-#include "rtc_base/stringencode.h"
-#include "rtc_base/virtualsocketserver.h"
+#include "rtc_base/string_encode.h"
+#include "rtc_base/virtual_socket_server.h"
 #include "test/gmock.h"
 
 using ::testing::_;
@@ -53,7 +53,7 @@
   MOCK_METHOD1(Verify, bool(const rtc::SSLCertificate&));
 };
 
-// TODO(benwright) - Move to using INSTANTIATE_TEST_CASE_P instead of using
+// TODO(benwright) - Move to using INSTANTIATE_TEST_SUITE_P instead of using
 // duplicate test cases for simple parameter changes.
 class SSLAdapterTestDummyClient : public sigslot::has_slots<> {
  public:
diff --git a/rtc_base/sslcertificate.cc b/rtc_base/ssl_certificate.cc
similarity index 97%
rename from rtc_base/sslcertificate.cc
rename to rtc_base/ssl_certificate.cc
index 934848f..8f6cfa2 100644
--- a/rtc_base/sslcertificate.cc
+++ b/rtc_base/ssl_certificate.cc
@@ -8,7 +8,7 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#include "rtc_base/sslcertificate.h"
+#include "rtc_base/ssl_certificate.h"
 
 #include <algorithm>
 #include <string>
@@ -16,8 +16,8 @@
 
 #include "absl/memory/memory.h"
 #include "rtc_base/checks.h"
-#include "rtc_base/opensslcertificate.h"
-#include "rtc_base/sslfingerprint.h"
+#include "rtc_base/openssl_certificate.h"
+#include "rtc_base/ssl_fingerprint.h"
 #include "rtc_base/third_party/base64/base64.h"
 
 namespace rtc {
diff --git a/rtc_base/sslcertificate.h b/rtc_base/ssl_certificate.h
similarity index 97%
rename from rtc_base/sslcertificate.h
rename to rtc_base/ssl_certificate.h
index eb81c20..fad1404 100644
--- a/rtc_base/sslcertificate.h
+++ b/rtc_base/ssl_certificate.h
@@ -12,8 +12,8 @@
 // for TLS TURN connections and the SSLStreamAdapter for DTLS Peer to Peer
 // Connections for SRTP Key negotiation and SCTP encryption.
 
-#ifndef RTC_BASE_SSLCERTIFICATE_H_
-#define RTC_BASE_SSLCERTIFICATE_H_
+#ifndef RTC_BASE_SSL_CERTIFICATE_H_
+#define RTC_BASE_SSL_CERTIFICATE_H_
 
 #include <stddef.h>
 #include <stdint.h>
@@ -22,7 +22,7 @@
 #include <vector>
 
 #include "rtc_base/buffer.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace rtc {
 
@@ -134,4 +134,4 @@
 
 }  // namespace rtc
 
-#endif  // RTC_BASE_SSLCERTIFICATE_H_
+#endif  // RTC_BASE_SSL_CERTIFICATE_H_
diff --git a/rtc_base/sslfingerprint.cc b/rtc_base/ssl_fingerprint.cc
similarity index 94%
rename from rtc_base/sslfingerprint.cc
rename to rtc_base/ssl_fingerprint.cc
index b296d33..77b6149 100644
--- a/rtc_base/sslfingerprint.cc
+++ b/rtc_base/ssl_fingerprint.cc
@@ -8,7 +8,7 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#include "rtc_base/sslfingerprint.h"
+#include "rtc_base/ssl_fingerprint.h"
 
 #include <ctype.h>
 #include <algorithm>
@@ -17,11 +17,11 @@
 
 #include "absl/memory/memory.h"
 #include "rtc_base/logging.h"
-#include "rtc_base/messagedigest.h"
-#include "rtc_base/rtccertificate.h"
-#include "rtc_base/sslcertificate.h"
-#include "rtc_base/sslidentity.h"
-#include "rtc_base/stringencode.h"
+#include "rtc_base/message_digest.h"
+#include "rtc_base/rtc_certificate.h"
+#include "rtc_base/ssl_certificate.h"
+#include "rtc_base/ssl_identity.h"
+#include "rtc_base/string_encode.h"
 
 namespace rtc {
 
diff --git a/rtc_base/sslfingerprint.h b/rtc_base/ssl_fingerprint.h
similarity index 93%
rename from rtc_base/sslfingerprint.h
rename to rtc_base/ssl_fingerprint.h
index ea10ede..f4037f7 100644
--- a/rtc_base/sslfingerprint.h
+++ b/rtc_base/ssl_fingerprint.h
@@ -8,14 +8,14 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#ifndef RTC_BASE_SSLFINGERPRINT_H_
-#define RTC_BASE_SSLFINGERPRINT_H_
+#ifndef RTC_BASE_SSL_FINGERPRINT_H_
+#define RTC_BASE_SSL_FINGERPRINT_H_
 
 #include <stddef.h>
 #include <stdint.h>
 #include <string>
 
-#include "rtc_base/copyonwritebuffer.h"
+#include "rtc_base/copy_on_write_buffer.h"
 
 namespace rtc {
 
@@ -70,4 +70,4 @@
 
 }  // namespace rtc
 
-#endif  // RTC_BASE_SSLFINGERPRINT_H_
+#endif  // RTC_BASE_SSL_FINGERPRINT_H_
diff --git a/rtc_base/sslidentity.cc b/rtc_base/ssl_identity.cc
similarity index 97%
rename from rtc_base/sslidentity.cc
rename to rtc_base/ssl_identity.cc
index 41eb35d..64c0f67 100644
--- a/rtc_base/sslidentity.cc
+++ b/rtc_base/ssl_identity.cc
@@ -9,18 +9,18 @@
  */
 
 // Handling of certificates and keypairs for SSLStreamAdapter's peer mode.
-#include "rtc_base/sslidentity.h"
+#include "rtc_base/ssl_identity.h"
 
 #include <string.h>
 #include <time.h>
 #include <string>
 
 #include "rtc_base/checks.h"
-#include "rtc_base/opensslidentity.h"
-#include "rtc_base/sslcertificate.h"
+#include "rtc_base/openssl_identity.h"
+#include "rtc_base/ssl_certificate.h"
 #include "rtc_base/strings/string_builder.h"
 #include "rtc_base/third_party/base64/base64.h"
-#include "rtc_base/timeutils.h"
+#include "rtc_base/time_utils.h"
 
 namespace rtc {
 
@@ -174,7 +174,7 @@
   if (header == std::string::npos) {
     return false;
   }
-  size_t body = pem_string.find("\n", header);
+  size_t body = pem_string.find('\n', header);
   if (body == std::string::npos) {
     return false;
   }
diff --git a/rtc_base/sslidentity.h b/rtc_base/ssl_identity.h
similarity index 98%
rename from rtc_base/sslidentity.h
rename to rtc_base/ssl_identity.h
index 39feeab..c013a89 100644
--- a/rtc_base/sslidentity.h
+++ b/rtc_base/ssl_identity.h
@@ -10,8 +10,8 @@
 
 // Handling of certificates and keypairs for SSLStreamAdapter's peer mode.
 
-#ifndef RTC_BASE_SSLIDENTITY_H_
-#define RTC_BASE_SSLIDENTITY_H_
+#ifndef RTC_BASE_SSL_IDENTITY_H_
+#define RTC_BASE_SSL_IDENTITY_H_
 
 #include <stdint.h>
 #include <ctime>
@@ -164,4 +164,4 @@
 
 }  // namespace rtc
 
-#endif  // RTC_BASE_SSLIDENTITY_H_
+#endif  // RTC_BASE_SSL_IDENTITY_H_
diff --git a/rtc_base/sslidentity_unittest.cc b/rtc_base/ssl_identity_unittest.cc
similarity index 97%
rename from rtc_base/sslidentity_unittest.cc
rename to rtc_base/ssl_identity_unittest.cc
index ba53d17..748041e 100644
--- a/rtc_base/sslidentity_unittest.cc
+++ b/rtc_base/ssl_identity_unittest.cc
@@ -8,17 +8,20 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
+#include <string.h>
 #include <memory>
 #include <string>
+#include <vector>
 
-#include "rtc_base/fakesslidentity.h"
-#include "rtc_base/gunit.h"
+#include "absl/strings/str_replace.h"
+#include "rtc_base/checks.h"
+#include "rtc_base/fake_ssl_identity.h"
 #include "rtc_base/helpers.h"
-#include "rtc_base/messagedigest.h"
-#include "rtc_base/ssladapter.h"
-#include "rtc_base/sslfingerprint.h"
-#include "rtc_base/sslidentity.h"
-#include "rtc_base/stringutils.h"
+#include "rtc_base/logging.h"
+#include "rtc_base/message_digest.h"
+#include "rtc_base/ssl_fingerprint.h"
+#include "rtc_base/ssl_identity.h"
+#include "test/gtest.h"
 
 using rtc::SSLIdentity;
 
@@ -170,10 +173,10 @@
   info.identity.reset(new rtc::FakeSSLIdentity(info.pems));
   // Strip header/footer and newline characters of PEM strings.
   for (size_t i = 0; i < info.pems.size(); ++i) {
-    rtc::replace_substrs("-----BEGIN CERTIFICATE-----", 27, "", 0,
-                         &info.pems[i]);
-    rtc::replace_substrs("-----END CERTIFICATE-----", 25, "", 0, &info.pems[i]);
-    rtc::replace_substrs("\n", 1, "", 0, &info.pems[i]);
+    absl::StrReplaceAll({{"-----BEGIN CERTIFICATE-----", ""},
+                         {"-----END CERTIFICATE-----", ""},
+                         {"\n", ""}},
+                        &info.pems[i]);
   }
   // Fingerprints for the whole certificate chain, starting with leaf
   // certificate.
diff --git a/rtc_base/sslroots.h b/rtc_base/ssl_roots.h
similarity index 99%
rename from rtc_base/sslroots.h
rename to rtc_base/ssl_roots.h
index 0dbd19b..69f6e39 100644
--- a/rtc_base/sslroots.h
+++ b/rtc_base/ssl_roots.h
@@ -8,8 +8,8 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#ifndef RTC_BASE_SSLROOTS_H_
-#define RTC_BASE_SSLROOTS_H_
+#ifndef RTC_BASE_SSL_ROOTS_H_
+#define RTC_BASE_SSL_ROOTS_H_
 
 // This file is the root certificates in C form that are needed to connect to
 // Google.
@@ -4283,4 +4283,4 @@
 
 // clang-format on
 
-#endif  // RTC_BASE_SSLROOTS_H_
+#endif  // RTC_BASE_SSL_ROOTS_H_
diff --git a/rtc_base/sslstreamadapter.cc b/rtc_base/ssl_stream_adapter.cc
similarity index 98%
rename from rtc_base/sslstreamadapter.cc
rename to rtc_base/ssl_stream_adapter.cc
index 9c33a9c..372c37f 100644
--- a/rtc_base/sslstreamadapter.cc
+++ b/rtc_base/ssl_stream_adapter.cc
@@ -8,9 +8,9 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#include "rtc_base/sslstreamadapter.h"
+#include "rtc_base/ssl_stream_adapter.h"
 
-#include "rtc_base/opensslstreamadapter.h"
+#include "rtc_base/openssl_stream_adapter.h"
 
 ///////////////////////////////////////////////////////////////////////////////
 
diff --git a/rtc_base/sslstreamadapter.h b/rtc_base/ssl_stream_adapter.h
similarity index 94%
rename from rtc_base/sslstreamadapter.h
rename to rtc_base/ssl_stream_adapter.h
index 25f4f33..99345ac 100644
--- a/rtc_base/sslstreamadapter.h
+++ b/rtc_base/ssl_stream_adapter.h
@@ -8,15 +8,19 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#ifndef RTC_BASE_SSLSTREAMADAPTER_H_
-#define RTC_BASE_SSLSTREAMADAPTER_H_
+#ifndef RTC_BASE_SSL_STREAM_ADAPTER_H_
+#define RTC_BASE_SSL_STREAM_ADAPTER_H_
 
+#include <stddef.h>
+#include <stdint.h>
 #include <memory>
 #include <string>
 #include <vector>
 
-#include "rtc_base/sslidentity.h"
+#include "rtc_base/ssl_certificate.h"
+#include "rtc_base/ssl_identity.h"
 #include "rtc_base/stream.h"
+#include "rtc_base/third_party/sigslot/sigslot.h"
 
 namespace rtc {
 
@@ -86,6 +90,11 @@
 
 enum SSLRole { SSL_CLIENT, SSL_SERVER };
 enum SSLMode { SSL_MODE_TLS, SSL_MODE_DTLS };
+
+// Note: By default TLS_10, TLS_11, and DTLS_10 will all be upgraded to DTLS1_2
+// unless the trial flag WebRTC-LegacyTlsProtocols/Enabled/ is passed in. These
+// protocol versions will be completely removed in M75
+// TODO(https://bugs.webrtc.org/10261).
 enum SSLProtocolVersion {
   SSL_PROTOCOL_TLS_10,
   SSL_PROTOCOL_TLS_11,
@@ -259,4 +268,4 @@
 
 }  // namespace rtc
 
-#endif  // RTC_BASE_SSLSTREAMADAPTER_H_
+#endif  // RTC_BASE_SSL_STREAM_ADAPTER_H_
diff --git a/rtc_base/sslstreamadapter_unittest.cc b/rtc_base/ssl_stream_adapter_unittest.cc
similarity index 94%
rename from rtc_base/sslstreamadapter_unittest.cc
rename to rtc_base/ssl_stream_adapter_unittest.cc
index 6fbb1d7..abf9880 100644
--- a/rtc_base/sslstreamadapter_unittest.cc
+++ b/rtc_base/ssl_stream_adapter_unittest.cc
@@ -13,21 +13,22 @@
 #include <set>
 #include <string>
 
-#include "rtc_base/bufferqueue.h"
+#include "rtc_base/buffer_queue.h"
 #include "rtc_base/checks.h"
 #include "rtc_base/gunit.h"
 #include "rtc_base/helpers.h"
 #include "rtc_base/memory_stream.h"
-#include "rtc_base/messagedigest.h"
-#include "rtc_base/ssladapter.h"
-#include "rtc_base/sslidentity.h"
-#include "rtc_base/sslstreamadapter.h"
+#include "rtc_base/message_digest.h"
+#include "rtc_base/ssl_adapter.h"
+#include "rtc_base/ssl_identity.h"
+#include "rtc_base/ssl_stream_adapter.h"
 #include "rtc_base/stream.h"
+#include "test/field_trial.h"
 
-using ::testing::WithParamInterface;
-using ::testing::Values;
 using ::testing::Combine;
 using ::testing::tuple;
+using ::testing::Values;
+using ::testing::WithParamInterface;
 
 static const int kBlockSize = 4096;
 static const char kExporterLabel[] = "label";
@@ -283,6 +284,7 @@
       const std::string& client_cert_pem,
       const std::string& client_private_key_pem,
       bool dtls,
+      bool legacy_tls_protocols = false,
       rtc::KeyParams client_key_type = rtc::KeyParams(rtc::KT_DEFAULT),
       rtc::KeyParams server_key_type = rtc::KeyParams(rtc::KT_DEFAULT))
       : client_cert_pem_(client_cert_pem),
@@ -300,7 +302,8 @@
         damage_(false),
         dtls_(dtls),
         handshake_wait_(5000),
-        identities_set_(false) {
+        identities_set_(false),
+        legacy_tls_protocols_(legacy_tls_protocols) {
     // Set use of the test RNG to get predictable loss patterns.
     rtc::SetRandomTestMode(true);
   }
@@ -313,6 +316,10 @@
   void SetUp() override {
     CreateStreams();
 
+    // Enable legacy protocols if required
+    webrtc::test::ScopedFieldTrials trial(
+        legacy_tls_protocols_ ? "WebRTC-LegacyTlsProtocols/Enabled/" : "");
+
     client_ssl_.reset(rtc::SSLStreamAdapter::Create(client_stream_));
     server_ssl_.reset(rtc::SSLStreamAdapter::Create(server_stream_));
 
@@ -645,6 +652,7 @@
   bool dtls_;
   int handshake_wait_;
   bool identities_set_;
+  bool legacy_tls_protocols_;
 };
 
 class SSLStreamAdapterTestTLS
@@ -655,6 +663,7 @@
       : SSLStreamAdapterTestBase("",
                                  "",
                                  false,
+                                 false,
                                  ::testing::get<0>(GetParam()),
                                  ::testing::get<1>(GetParam())),
         client_buffer_(kFifoBufferSize),
@@ -731,7 +740,7 @@
         break;
       }
     }
-  };
+  }
 
   void ReadData(rtc::StreamInterface* stream) override {
     char buffer[1600];
@@ -771,9 +780,13 @@
       public WithParamInterface<tuple<rtc::KeyParams, rtc::KeyParams>> {
  public:
   SSLStreamAdapterTestDTLS()
+      : SSLStreamAdapterTestDTLS(/*legacy_tls_protocols=*/false) {}
+
+  SSLStreamAdapterTestDTLS(bool legacy_tls_protocols)
       : SSLStreamAdapterTestBase("",
                                  "",
                                  true,
+                                 legacy_tls_protocols,
                                  ::testing::get<0>(GetParam()),
                                  ::testing::get<1>(GetParam())),
         client_buffer_(kBufferCapacity, kDefaultBufferSize),
@@ -880,7 +893,7 @@
       RTC_LOG(LS_INFO) << "Sent " << sent_ << " packets; received "
                        << received_.size();
     }
-  };
+  }
 
  private:
   BufferQueueStream client_buffer_;
@@ -907,7 +920,7 @@
   }
 
   return test_base_->DataWritten(this, data, data_len, written, error);
-};
+}
 
 class SSLStreamAdapterTestDTLSFromPEMStrings : public SSLStreamAdapterTestDTLS {
  public:
@@ -919,7 +932,7 @@
 // certificate.
 class SSLStreamAdapterTestDTLSCertChain : public SSLStreamAdapterTestDTLS {
  public:
-  SSLStreamAdapterTestDTLSCertChain() : SSLStreamAdapterTestDTLS("", ""){};
+  SSLStreamAdapterTestDTLSCertChain() : SSLStreamAdapterTestDTLS("", "") {}
   void SetUp() override {
     CreateStreams();
 
@@ -945,12 +958,19 @@
   }
 };
 
+// Enable legacy TLS protocols in DTLS.
+class SSLStreamAdapterTestDTLSLegacyProtocols
+    : public SSLStreamAdapterTestDTLS {
+ public:
+  SSLStreamAdapterTestDTLSLegacyProtocols()
+      : SSLStreamAdapterTestDTLS(/*legacy_tls_protocols=*/true) {}
+};
 // Basic tests: TLS
 
 // Test that we can make a handshake work
 TEST_P(SSLStreamAdapterTestTLS, TestTLSConnect) {
   TestHandshake();
-};
+}
 
 TEST_P(SSLStreamAdapterTestTLS, GetPeerCertChainWithOneCertificate) {
   TestHandshake();
@@ -1009,13 +1029,13 @@
   TestHandshake();
   client_ssl_->Close();
   EXPECT_EQ_WAIT(rtc::SS_CLOSED, server_ssl_->GetState(), handshake_wait_);
-};
+}
 
 // Test transfer -- trivial
 TEST_P(SSLStreamAdapterTestTLS, TestTLSTransfer) {
   TestHandshake();
   TestTransfer(100000);
-};
+}
 
 // Test read-write after close.
 TEST_P(SSLStreamAdapterTestTLS, ReadWriteAfterClose) {
@@ -1034,21 +1054,21 @@
   // But after closed read gives you EOS.
   rv = client_ssl_->Read(block, sizeof(block), &dummy, nullptr);
   ASSERT_EQ(rtc::SR_EOS, rv);
-};
+}
 
 // Test a handshake with a bogus peer digest
 TEST_P(SSLStreamAdapterTestTLS, TestTLSBogusDigest) {
   SetPeerIdentitiesByDigest(false, true);
   TestHandshake(false);
-};
+}
 
 TEST_P(SSLStreamAdapterTestTLS, TestTLSDelayedIdentity) {
   TestHandshakeWithDelayedIdentity(true);
-};
+}
 
 TEST_P(SSLStreamAdapterTestTLS, TestTLSDelayedIdentityWithBogusDigest) {
   TestHandshakeWithDelayedIdentity(false);
-};
+}
 
 // Test that the correct error is returned when SetPeerCertificateDigest is
 // called with an unknown algorithm.
@@ -1093,7 +1113,7 @@
 // Test that we can make a handshake work
 TEST_P(SSLStreamAdapterTestDTLS, TestDTLSConnect) {
   TestHandshake();
-};
+}
 
 // Test that we can make a handshake work if the first packet in
 // each direction is lost. This gives us predictable loss
@@ -1101,7 +1121,7 @@
 TEST_P(SSLStreamAdapterTestDTLS, TestDTLSConnectWithLostFirstPacket) {
   SetLoseFirstPacket(true);
   TestHandshake();
-};
+}
 
 // Test a handshake with loss and delay
 TEST_P(SSLStreamAdapterTestDTLS, TestDTLSConnectWithLostFirstPacketDelay2s) {
@@ -1109,7 +1129,7 @@
   SetDelay(2000);
   SetHandshakeWait(20000);
   TestHandshake();
-};
+}
 
 // Test a handshake with small MTU
 // Disabled due to https://code.google.com/p/webrtc/issues/detail?id=3910
@@ -1117,34 +1137,34 @@
   SetMtu(700);
   SetHandshakeWait(20000);
   TestHandshake();
-};
+}
 
 // Test transfer -- trivial
 TEST_P(SSLStreamAdapterTestDTLS, TestDTLSTransfer) {
   TestHandshake();
   TestTransfer(100);
-};
+}
 
 TEST_P(SSLStreamAdapterTestDTLS, TestDTLSTransferWithLoss) {
   TestHandshake();
   SetLoss(10);
   TestTransfer(100);
-};
+}
 
 TEST_P(SSLStreamAdapterTestDTLS, TestDTLSTransferWithDamage) {
   SetDamage();  // Must be called first because first packet
                 // write happens at end of handshake.
   TestHandshake();
   TestTransfer(100);
-};
+}
 
 TEST_P(SSLStreamAdapterTestDTLS, TestDTLSDelayedIdentity) {
   TestHandshakeWithDelayedIdentity(true);
-};
+}
 
 TEST_P(SSLStreamAdapterTestDTLS, TestDTLSDelayedIdentityWithBogusDigest) {
   TestHandshakeWithDelayedIdentity(false);
-};
+}
 
 // Test DTLS-SRTP with all high ciphers
 TEST_P(SSLStreamAdapterTestDTLS, TestDTLSSrtpHigh) {
@@ -1161,7 +1181,7 @@
 
   ASSERT_EQ(client_cipher, server_cipher);
   ASSERT_EQ(client_cipher, rtc::SRTP_AES128_CM_SHA1_80);
-};
+}
 
 // Test DTLS-SRTP with all low ciphers
 TEST_P(SSLStreamAdapterTestDTLS, TestDTLSSrtpLow) {
@@ -1178,7 +1198,7 @@
 
   ASSERT_EQ(client_cipher, server_cipher);
   ASSERT_EQ(client_cipher, rtc::SRTP_AES128_CM_SHA1_32);
-};
+}
 
 // Test DTLS-SRTP with a mismatch -- should not converge
 TEST_P(SSLStreamAdapterTestDTLS, TestDTLSSrtpHighLow) {
@@ -1194,7 +1214,7 @@
   ASSERT_FALSE(GetDtlsSrtpCryptoSuite(true, &client_cipher));
   int server_cipher;
   ASSERT_FALSE(GetDtlsSrtpCryptoSuite(false, &server_cipher));
-};
+}
 
 // Test DTLS-SRTP with each side being mixed -- should select high
 TEST_P(SSLStreamAdapterTestDTLS, TestDTLSSrtpMixed) {
@@ -1212,7 +1232,7 @@
 
   ASSERT_EQ(client_cipher, server_cipher);
   ASSERT_EQ(client_cipher, rtc::SRTP_AES128_CM_SHA1_80);
-};
+}
 
 // Test DTLS-SRTP with all GCM-128 ciphers.
 TEST_P(SSLStreamAdapterTestDTLS, TestDTLSSrtpGCM128) {
@@ -1229,7 +1249,7 @@
 
   ASSERT_EQ(client_cipher, server_cipher);
   ASSERT_EQ(client_cipher, rtc::SRTP_AEAD_AES_128_GCM);
-};
+}
 
 // Test DTLS-SRTP with all GCM-256 ciphers.
 TEST_P(SSLStreamAdapterTestDTLS, TestDTLSSrtpGCM256) {
@@ -1246,7 +1266,7 @@
 
   ASSERT_EQ(client_cipher, server_cipher);
   ASSERT_EQ(client_cipher, rtc::SRTP_AEAD_AES_256_GCM);
-};
+}
 
 // Test DTLS-SRTP with mixed GCM-128/-256 ciphers -- should not converge.
 TEST_P(SSLStreamAdapterTestDTLS, TestDTLSSrtpGCMMismatch) {
@@ -1262,7 +1282,7 @@
   ASSERT_FALSE(GetDtlsSrtpCryptoSuite(true, &client_cipher));
   int server_cipher;
   ASSERT_FALSE(GetDtlsSrtpCryptoSuite(false, &server_cipher));
-};
+}
 
 // Test DTLS-SRTP with both GCM-128/-256 ciphers -- should select GCM-256.
 TEST_P(SSLStreamAdapterTestDTLS, TestDTLSSrtpGCMMixed) {
@@ -1280,7 +1300,7 @@
 
   ASSERT_EQ(client_cipher, server_cipher);
   ASSERT_EQ(client_cipher, rtc::SRTP_AEAD_AES_256_GCM);
-};
+}
 
 // Test SRTP cipher suite lengths.
 TEST_P(SSLStreamAdapterTestDTLS, TestDTLSSrtpKeyAndSaltLengths) {
@@ -1309,7 +1329,7 @@
                                             &key_len, &salt_len));
   ASSERT_EQ(256 / 8, key_len);
   ASSERT_EQ(96 / 8, salt_len);
-};
+}
 
 // Test an exporter
 TEST_P(SSLStreamAdapterTestDTLS, TestDTLSExporter) {
@@ -1381,7 +1401,7 @@
 
 // Test getting the used DTLS ciphers.
 // DTLS 1.2 enabled for neither client nor server -> DTLS 1.0 will be used.
-TEST_P(SSLStreamAdapterTestDTLS, TestGetSslCipherSuite) {
+TEST_P(SSLStreamAdapterTestDTLSLegacyProtocols, TestGetSslCipherSuite) {
   SetupProtocolVersions(rtc::SSL_PROTOCOL_DTLS_10, rtc::SSL_PROTOCOL_DTLS_10);
   TestHandshake();
 
@@ -1400,6 +1420,64 @@
 
 // Test getting the used DTLS 1.2 ciphers.
 // DTLS 1.2 enabled for client and server -> DTLS 1.2 will be used.
+TEST_P(SSLStreamAdapterTestDTLSLegacyProtocols,
+       TestGetSslCipherSuiteDtls12Both) {
+  SetupProtocolVersions(rtc::SSL_PROTOCOL_DTLS_12, rtc::SSL_PROTOCOL_DTLS_12);
+  TestHandshake();
+
+  int client_cipher;
+  ASSERT_TRUE(GetSslCipherSuite(true, &client_cipher));
+  int server_cipher;
+  ASSERT_TRUE(GetSslCipherSuite(false, &server_cipher));
+
+  ASSERT_EQ(rtc::SSL_PROTOCOL_DTLS_12, GetSslVersion(true));
+  ASSERT_EQ(rtc::SSL_PROTOCOL_DTLS_12, GetSslVersion(false));
+
+  ASSERT_EQ(client_cipher, server_cipher);
+  ASSERT_TRUE(rtc::SSLStreamAdapter::IsAcceptableCipher(
+      server_cipher, ::testing::get<1>(GetParam()).type()));
+}
+
+// DTLS 1.2 enabled for client only -> DTLS 1.0 will be used.
+TEST_P(SSLStreamAdapterTestDTLSLegacyProtocols,
+       TestGetSslCipherSuiteDtls12Client) {
+  SetupProtocolVersions(rtc::SSL_PROTOCOL_DTLS_10, rtc::SSL_PROTOCOL_DTLS_12);
+  TestHandshake();
+
+  int client_cipher;
+  ASSERT_TRUE(GetSslCipherSuite(true, &client_cipher));
+  int server_cipher;
+  ASSERT_TRUE(GetSslCipherSuite(false, &server_cipher));
+
+  ASSERT_EQ(rtc::SSL_PROTOCOL_DTLS_10, GetSslVersion(true));
+  ASSERT_EQ(rtc::SSL_PROTOCOL_DTLS_10, GetSslVersion(false));
+
+  ASSERT_EQ(client_cipher, server_cipher);
+  ASSERT_TRUE(rtc::SSLStreamAdapter::IsAcceptableCipher(
+      server_cipher, ::testing::get<1>(GetParam()).type()));
+}
+
+// DTLS 1.2 enabled for server only -> DTLS 1.0 will be used.
+TEST_P(SSLStreamAdapterTestDTLSLegacyProtocols,
+       TestGetSslCipherSuiteDtls12Server) {
+  SetupProtocolVersions(rtc::SSL_PROTOCOL_DTLS_12, rtc::SSL_PROTOCOL_DTLS_10);
+  TestHandshake();
+
+  int client_cipher;
+  ASSERT_TRUE(GetSslCipherSuite(true, &client_cipher));
+  int server_cipher;
+  ASSERT_TRUE(GetSslCipherSuite(false, &server_cipher));
+
+  ASSERT_EQ(rtc::SSL_PROTOCOL_DTLS_10, GetSslVersion(true));
+  ASSERT_EQ(rtc::SSL_PROTOCOL_DTLS_10, GetSslVersion(false));
+
+  ASSERT_EQ(client_cipher, server_cipher);
+  ASSERT_TRUE(rtc::SSLStreamAdapter::IsAcceptableCipher(
+      server_cipher, ::testing::get<1>(GetParam()).type()));
+}
+
+// Test getting the used DTLS 1.2 ciphers.
+// DTLS 1.2 enabled for client and server -> DTLS 1.2 will be used.
 TEST_P(SSLStreamAdapterTestDTLS, TestGetSslCipherSuiteDtls12Both) {
   SetupProtocolVersions(rtc::SSL_PROTOCOL_DTLS_12, rtc::SSL_PROTOCOL_DTLS_12);
   TestHandshake();
@@ -1417,9 +1495,10 @@
       server_cipher, ::testing::get<1>(GetParam()).type()));
 }
 
-// DTLS 1.2 enabled for client only -> DTLS 1.0 will be used.
-TEST_P(SSLStreamAdapterTestDTLS, TestGetSslCipherSuiteDtls12Client) {
-  SetupProtocolVersions(rtc::SSL_PROTOCOL_DTLS_10, rtc::SSL_PROTOCOL_DTLS_12);
+// Test getting the used DTLS ciphers.
+// DTLS 1.0 enabled for client and server, both will be upgraded to DTLS 1.2
+TEST_P(SSLStreamAdapterTestDTLS, TestGetSslCipherSuite) {
+  SetupProtocolVersions(rtc::SSL_PROTOCOL_DTLS_10, rtc::SSL_PROTOCOL_DTLS_10);
   TestHandshake();
 
   int client_cipher;
@@ -1427,26 +1506,8 @@
   int server_cipher;
   ASSERT_TRUE(GetSslCipherSuite(false, &server_cipher));
 
-  ASSERT_EQ(rtc::SSL_PROTOCOL_DTLS_10, GetSslVersion(true));
-  ASSERT_EQ(rtc::SSL_PROTOCOL_DTLS_10, GetSslVersion(false));
-
-  ASSERT_EQ(client_cipher, server_cipher);
-  ASSERT_TRUE(rtc::SSLStreamAdapter::IsAcceptableCipher(
-      server_cipher, ::testing::get<1>(GetParam()).type()));
-}
-
-// DTLS 1.2 enabled for server only -> DTLS 1.0 will be used.
-TEST_P(SSLStreamAdapterTestDTLS, TestGetSslCipherSuiteDtls12Server) {
-  SetupProtocolVersions(rtc::SSL_PROTOCOL_DTLS_12, rtc::SSL_PROTOCOL_DTLS_10);
-  TestHandshake();
-
-  int client_cipher;
-  ASSERT_TRUE(GetSslCipherSuite(true, &client_cipher));
-  int server_cipher;
-  ASSERT_TRUE(GetSslCipherSuite(false, &server_cipher));
-
-  ASSERT_EQ(rtc::SSL_PROTOCOL_DTLS_10, GetSslVersion(true));
-  ASSERT_EQ(rtc::SSL_PROTOCOL_DTLS_10, GetSslVersion(false));
+  ASSERT_EQ(rtc::SSL_PROTOCOL_DTLS_12, GetSslVersion(true));
+  ASSERT_EQ(rtc::SSL_PROTOCOL_DTLS_12, GetSslVersion(false));
 
   ASSERT_EQ(client_cipher, server_cipher);
   ASSERT_TRUE(rtc::SSLStreamAdapter::IsAcceptableCipher(
@@ -1456,7 +1517,7 @@
 // The RSA keysizes here might look strange, why not include the RFC's size
 // 2048?. The reason is test case slowness; testing two sizes to exercise
 // parametrization is sufficient.
-INSTANTIATE_TEST_CASE_P(
+INSTANTIATE_TEST_SUITE_P(
     SSLStreamAdapterTestsTLS,
     SSLStreamAdapterTestTLS,
     Combine(Values(rtc::KeyParams::RSA(1024, 65537),
@@ -1465,7 +1526,7 @@
             Values(rtc::KeyParams::RSA(1024, 65537),
                    rtc::KeyParams::RSA(1152, 65537),
                    rtc::KeyParams::ECDSA(rtc::EC_NIST_P256))));
-INSTANTIATE_TEST_CASE_P(
+INSTANTIATE_TEST_SUITE_P(
     SSLStreamAdapterTestsDTLS,
     SSLStreamAdapterTestDTLS,
     Combine(Values(rtc::KeyParams::RSA(1024, 65537),
diff --git a/rtc_base/stream.cc b/rtc_base/stream.cc
index 783625c..01f1504 100644
--- a/rtc_base/stream.cc
+++ b/rtc_base/stream.cc
@@ -9,13 +9,12 @@
  */
 #include <errno.h>
 #include <string.h>
-#include <sys/stat.h>
 #include <algorithm>
 #include <string>
 
 #include "rtc_base/checks.h"
 #include "rtc_base/location.h"
-#include "rtc_base/messagequeue.h"
+#include "rtc_base/message_queue.h"
 #include "rtc_base/stream.h"
 #include "rtc_base/thread.h"
 
@@ -23,7 +22,7 @@
 #include <windows.h>
 
 #define fileno _fileno
-#include "rtc_base/stringutils.h"
+#include "rtc_base/string_utils.h"
 #endif
 
 namespace rtc {
@@ -78,26 +77,10 @@
   PostEvent(Thread::Current(), events, err);
 }
 
-bool StreamInterface::SetPosition(size_t position) {
-  return false;
-}
-
-bool StreamInterface::GetPosition(size_t* position) const {
-  return false;
-}
-
-bool StreamInterface::GetSize(size_t* size) const {
-  return false;
-}
-
 bool StreamInterface::Flush() {
   return false;
 }
 
-bool StreamInterface::ReserveSize(size_t size) {
-  return true;
-}
-
 StreamInterface::StreamInterface() {}
 
 void StreamInterface::OnMessage(Message* msg) {
@@ -138,22 +121,6 @@
   stream_->Close();
 }
 
-bool StreamAdapterInterface::SetPosition(size_t position) {
-  return stream_->SetPosition(position);
-}
-
-bool StreamAdapterInterface::GetPosition(size_t* position) const {
-  return stream_->GetPosition(position);
-}
-
-bool StreamAdapterInterface::GetSize(size_t* size) const {
-  return stream_->GetSize(size);
-}
-
-bool StreamAdapterInterface::ReserveSize(size_t size) {
-  return stream_->ReserveSize(size);
-}
-
 bool StreamAdapterInterface::Flush() {
   return stream_->Flush();
 }
@@ -305,35 +272,6 @@
   return (fseek(file_, static_cast<int>(position), SEEK_SET) == 0);
 }
 
-bool FileStream::GetPosition(size_t* position) const {
-  RTC_DCHECK(nullptr != position);
-  if (!file_)
-    return false;
-  long result = ftell(file_);
-  if (result < 0)
-    return false;
-  if (position)
-    *position = result;
-  return true;
-}
-
-bool FileStream::GetSize(size_t* size) const {
-  RTC_DCHECK(nullptr != size);
-  if (!file_)
-    return false;
-  struct stat file_stats;
-  if (fstat(fileno(file_), &file_stats) != 0)
-    return false;
-  if (size)
-    *size = file_stats.st_size;
-  return true;
-}
-
-bool FileStream::ReserveSize(size_t size) {
-  // TODO: extend the file to the proper length
-  return true;
-}
-
 bool FileStream::Flush() {
   if (file_) {
     return (0 == fflush(file_));
diff --git a/rtc_base/stream.h b/rtc_base/stream.h
index 43e7f58..a7c6266 100644
--- a/rtc_base/stream.h
+++ b/rtc_base/stream.h
@@ -16,10 +16,10 @@
 #include <memory>
 
 #include "rtc_base/buffer.h"
-#include "rtc_base/constructormagic.h"
-#include "rtc_base/criticalsection.h"
-#include "rtc_base/messagehandler.h"
-#include "rtc_base/messagequeue.h"
+#include "rtc_base/constructor_magic.h"
+#include "rtc_base/critical_section.h"
+#include "rtc_base/message_handler.h"
+#include "rtc_base/message_queue.h"
 #include "rtc_base/third_party/sigslot/sigslot.h"
 
 namespace rtc {
@@ -107,38 +107,15 @@
   // Like the aforementioned method, but posts to the current thread.
   void PostEvent(int events, int err);
 
-  // Seek to a byte offset from the beginning of the stream.  Returns false if
-  // the stream does not support seeking, or cannot seek to the specified
-  // position.
-  virtual bool SetPosition(size_t position);
-
-  // Get the byte offset of the current position from the start of the stream.
-  // Returns false if the position is not known.
-  virtual bool GetPosition(size_t* position) const;
-
-  // Get the byte length of the entire stream.  Returns false if the length
-  // is not known.
-  virtual bool GetSize(size_t* size) const;
-
   // Return true if flush is successful.
   virtual bool Flush();
 
-  // Communicates the amount of data which will be written to the stream.  The
-  // stream may choose to preallocate memory to accomodate this data.  The
-  // stream may return false to indicate that there is not enough room (ie,
-  // Write will return SR_EOS/SR_ERROR at some point).  Note that calling this
-  // function should not affect the existing state of data in the stream.
-  virtual bool ReserveSize(size_t size);
-
   //
   // CONVENIENCE METHODS
   //
   // These methods are implemented in terms of other methods, for convenience.
   //
 
-  // Seek to the start of the stream.
-  inline bool Rewind() { return SetPosition(0); }
-
   // WriteAll is a helper function which repeatedly calls Write until all the
   // data is written, or something other than SR_SUCCESS is returned.  Note that
   // unlike Write, the argument 'written' is always set, and may be non-zero
@@ -191,10 +168,6 @@
                      int* error) override;
   void Close() override;
 
-  bool SetPosition(size_t position) override;
-  bool GetPosition(size_t* position) const override;
-  bool GetSize(size_t* size) const override;
-  bool ReserveSize(size_t size) override;
   bool Flush() override;
 
   void Attach(StreamInterface* stream, bool owned = true);
@@ -219,6 +192,7 @@
 // support asynchronous notification.
 ///////////////////////////////////////////////////////////////////////////////
 
+// TODO(bugs.webrtc.org/6463): Delete this class.
 class FileStream : public StreamInterface {
  public:
   FileStream();
@@ -245,10 +219,7 @@
                      size_t* written,
                      int* error) override;
   void Close() override;
-  bool SetPosition(size_t position) override;
-  bool GetPosition(size_t* position) const override;
-  bool GetSize(size_t* size) const override;
-  bool ReserveSize(size_t size) override;
+  virtual bool SetPosition(size_t position);
 
   bool Flush() override;
 
@@ -306,6 +277,19 @@
                      size_t* bytes_written,
                      int* error) override;
   void Close() override;
+
+  // Seek to a byte offset from the beginning of the stream.  Returns false if
+  // the stream does not support seeking, or cannot seek to the specified
+  // position.
+  bool SetPosition(size_t position);
+
+  // Get the byte offset of the current position from the start of the stream.
+  // Returns false if the position is not known.
+  bool GetPosition(size_t* position) const;
+
+  // Seek to the start of the stream.
+  bool Rewind() { return SetPosition(0); }
+
   // GetReadData returns a pointer to a buffer which is owned by the stream.
   // The buffer contains data_len bytes.  null is returned if no data is
   // available, or if the method fails.  If the caller processes the data, it
diff --git a/rtc_base/stream_unittest.cc b/rtc_base/stream_unittest.cc
index 2ca2526..bd6e84f 100644
--- a/rtc_base/stream_unittest.cc
+++ b/rtc_base/stream_unittest.cc
@@ -9,7 +9,10 @@
  */
 
 #include "rtc_base/stream.h"
-#include "rtc_base/gunit.h"
+
+#include <string.h>
+
+#include "test/gtest.h"
 
 namespace rtc {
 
@@ -47,19 +50,6 @@
 
   void Close() override {}
 
-  bool SetPosition(size_t position) override {
-    pos_ = position;
-    return true;
-  }
-
-  bool GetPosition(size_t* position) const override {
-    if (position)
-      *position = pos_;
-    return true;
-  }
-
-  bool GetSize(size_t* size) const override { return false; }
-
  private:
   size_t pos_;
 };
@@ -77,26 +67,6 @@
   return passed;
 }
 
-void SeekTest(StreamInterface* stream, const unsigned char value) {
-  size_t bytes;
-  unsigned char buffer[13] = {0};
-  const size_t kBufSize = sizeof(buffer);
-
-  EXPECT_EQ(stream->Read(buffer, kBufSize, &bytes, nullptr), SR_SUCCESS);
-  EXPECT_EQ(bytes, kBufSize);
-  EXPECT_TRUE(VerifyTestBuffer(buffer, kBufSize, value));
-  EXPECT_TRUE(stream->GetPosition(&bytes));
-  EXPECT_EQ(13U, bytes);
-
-  EXPECT_TRUE(stream->SetPosition(7));
-
-  EXPECT_EQ(stream->Read(buffer, kBufSize, &bytes, nullptr), SR_SUCCESS);
-  EXPECT_EQ(bytes, kBufSize);
-  EXPECT_TRUE(VerifyTestBuffer(buffer, kBufSize, value + 7));
-  EXPECT_TRUE(stream->GetPosition(&bytes));
-  EXPECT_EQ(20U, bytes);
-}
-
 TEST(FifoBufferTest, TestAll) {
   const size_t kSize = 16;
   const char in[kSize * 2 + 1] = "0123456789ABCDEFGHIJKLMNOPQRSTUV";
diff --git a/rtc_base/stringencode.cc b/rtc_base/string_encode.cc
similarity index 99%
rename from rtc_base/stringencode.cc
rename to rtc_base/string_encode.cc
index fc4e3bc..45ea586 100644
--- a/rtc_base/stringencode.cc
+++ b/rtc_base/string_encode.cc
@@ -8,13 +8,13 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#include "rtc_base/stringencode.h"
+#include "rtc_base/string_encode.h"
 
 #include <cstdio>
 
 #include "rtc_base/arraysize.h"
 #include "rtc_base/checks.h"
-#include "rtc_base/stringutils.h"
+#include "rtc_base/string_utils.h"
 
 namespace rtc {
 
diff --git a/rtc_base/stringencode.h b/rtc_base/string_encode.h
similarity index 98%
rename from rtc_base/stringencode.h
rename to rtc_base/string_encode.h
index 09bf77f..d3338d9 100644
--- a/rtc_base/stringencode.h
+++ b/rtc_base/string_encode.h
@@ -8,8 +8,8 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#ifndef RTC_BASE_STRINGENCODE_H_
-#define RTC_BASE_STRINGENCODE_H_
+#ifndef RTC_BASE_STRING_ENCODE_H_
+#define RTC_BASE_STRING_ENCODE_H_
 
 #include <stddef.h>
 #include <string>
@@ -197,4 +197,4 @@
 
 }  // namespace rtc
 
-#endif  // RTC_BASE_STRINGENCODE_H__
+#endif  // RTC_BASE_STRING_ENCODE_H__
diff --git a/rtc_base/stringencode_unittest.cc b/rtc_base/string_encode_unittest.cc
similarity index 98%
rename from rtc_base/stringencode_unittest.cc
rename to rtc_base/string_encode_unittest.cc
index f21c4cb..cc72e43 100644
--- a/rtc_base/stringencode_unittest.cc
+++ b/rtc_base/string_encode_unittest.cc
@@ -8,13 +8,13 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#include "rtc_base/stringencode.h"
-#include "rtc_base/arraysize.h"
-#include "rtc_base/gunit.h"
-#include "rtc_base/stringutils.h"
+#include "rtc_base/string_encode.h"
 
+#include <string.h>
 #include <sstream>  // no-presubmit-check TODO(webrtc:8982)
 
+#include "test/gtest.h"
+
 namespace rtc {
 
 class HexEncodeTest : public testing::Test {
diff --git a/rtc_base/string_to_number_unittest.cc b/rtc_base/string_to_number_unittest.cc
index f7bf484..2c2dfcc 100644
--- a/rtc_base/string_to_number_unittest.cc
+++ b/rtc_base/string_to_number_unittest.cc
@@ -10,11 +10,11 @@
 
 #include "rtc_base/string_to_number.h"
 
+#include <stdint.h>
 #include <limits>
 #include <string>
-#include <type_traits>
 
-#include "rtc_base/gunit.h"
+#include "test/gtest.h"
 
 namespace rtc {
 
@@ -36,7 +36,7 @@
 template <typename T>
 class BasicNumberTest : public ::testing::Test {};
 
-TYPED_TEST_CASE_P(BasicNumberTest);
+TYPED_TEST_SUITE_P(BasicNumberTest);
 
 TYPED_TEST_P(BasicNumberTest, TestValidNumbers) {
   using T = TypeParam;
@@ -93,16 +93,16 @@
   EXPECT_EQ(absl::nullopt, StringToNumber<T>("5 "));
 }
 
-REGISTER_TYPED_TEST_CASE_P(BasicNumberTest,
-                           TestValidNumbers,
-                           TestInvalidNumbers,
-                           TestInvalidInputs);
+REGISTER_TYPED_TEST_SUITE_P(BasicNumberTest,
+                            TestValidNumbers,
+                            TestInvalidNumbers,
+                            TestInvalidInputs);
 
 }  // namespace
 
-INSTANTIATE_TYPED_TEST_CASE_P(StringToNumberTest_Integers,
-                              BasicNumberTest,
-                              IntegerTypes);
+INSTANTIATE_TYPED_TEST_SUITE_P(StringToNumberTest_Integers,
+                               BasicNumberTest,
+                               IntegerTypes);
 
 TEST(StringToNumberTest, TestSpecificValues) {
   EXPECT_EQ(absl::nullopt, StringToNumber<uint8_t>("256"));
diff --git a/rtc_base/stringutils.cc b/rtc_base/string_utils.cc
similarity index 65%
rename from rtc_base/stringutils.cc
rename to rtc_base/string_utils.cc
index c808eb2..dfbb548 100644
--- a/rtc_base/stringutils.cc
+++ b/rtc_base/string_utils.cc
@@ -8,7 +8,7 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#include "rtc_base/stringutils.h"
+#include "rtc_base/string_utils.h"
 
 namespace rtc {
 
@@ -30,34 +30,6 @@
   return srclen;
 }
 
-void replace_substrs(const char* search,
-                     size_t search_len,
-                     const char* replace,
-                     size_t replace_len,
-                     std::string* s) {
-  size_t pos = 0;
-  while ((pos = s->find(search, pos, search_len)) != std::string::npos) {
-    s->replace(pos, search_len, replace, replace_len);
-    pos += replace_len;
-  }
-}
-
-bool starts_with(const char* s1, const char* s2) {
-  return strncmp(s1, s2, strlen(s2)) == 0;
-}
-
-bool ends_with(const char* s1, const char* s2) {
-  size_t s1_length = strlen(s1);
-  size_t s2_length = strlen(s2);
-
-  if (s2_length > s1_length) {
-    return false;
-  }
-
-  const char* start = s1 + (s1_length - s2_length);
-  return strncmp(start, s2, s2_length) == 0;
-}
-
 static const char kWhitespace[] = " \n\r\t";
 
 std::string string_trim(const std::string& s) {
diff --git a/rtc_base/stringutils.h b/rtc_base/string_utils.h
similarity index 85%
rename from rtc_base/stringutils.h
rename to rtc_base/string_utils.h
index 702bc67..bc33284 100644
--- a/rtc_base/stringutils.h
+++ b/rtc_base/string_utils.h
@@ -8,8 +8,8 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#ifndef RTC_BASE_STRINGUTILS_H_
-#define RTC_BASE_STRINGUTILS_H_
+#ifndef RTC_BASE_STRING_UTILS_H_
+#define RTC_BASE_STRING_UTILS_H_
 
 #include <ctype.h>
 #include <stdarg.h>
@@ -93,19 +93,6 @@
 
 #endif  // WEBRTC_WIN
 
-// Replaces all occurrences of "search" with "replace".
-void replace_substrs(const char* search,
-                     size_t search_len,
-                     const char* replace,
-                     size_t replace_len,
-                     std::string* s);
-
-// True iff s1 starts with s2.
-bool starts_with(const char* s1, const char* s2);
-
-// True iff s1 ends with s2.
-bool ends_with(const char* s1, const char* s2);
-
 // Remove leading and trailing whitespaces.
 std::string string_trim(const std::string& s);
 
@@ -116,4 +103,4 @@
 
 }  // namespace rtc
 
-#endif  // RTC_BASE_STRINGUTILS_H_
+#endif  // RTC_BASE_STRING_UTILS_H_
diff --git a/rtc_base/string_utils_unittest.cc b/rtc_base/string_utils_unittest.cc
new file mode 100644
index 0000000..b4396f1
--- /dev/null
+++ b/rtc_base/string_utils_unittest.cc
@@ -0,0 +1,31 @@
+/*
+ *  Copyright 2004 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/string_utils.h"
+
+#include "test/gtest.h"
+
+namespace rtc {
+
+TEST(string_trim_Test, Trimming) {
+  EXPECT_EQ("temp", string_trim("\n\r\t temp \n\r\t"));
+  EXPECT_EQ("temp\n\r\t temp", string_trim(" temp\n\r\t temp "));
+  EXPECT_EQ("temp temp", string_trim("temp temp"));
+  EXPECT_EQ("", string_trim(" \r\n\t"));
+  EXPECT_EQ("", string_trim(""));
+}
+
+TEST(string_toHexTest, ToHex) {
+  EXPECT_EQ(ToHex(0), "0");
+  EXPECT_EQ(ToHex(0X1243E), "1243e");
+  EXPECT_EQ(ToHex(-20), "ffffffec");
+}
+
+}  // namespace rtc
diff --git a/rtc_base/strings/json.cc b/rtc_base/strings/json.cc
index efcb97a..8a544a0 100644
--- a/rtc_base/strings/json.cc
+++ b/rtc_base/strings/json.cc
@@ -14,7 +14,7 @@
 #include <limits.h>
 #include <stdlib.h>
 
-#include "rtc_base/stringencode.h"
+#include "rtc_base/string_encode.h"
 
 namespace rtc {
 
diff --git a/rtc_base/strings/json_unittest.cc b/rtc_base/strings/json_unittest.cc
index 2215769..82d26f1 100644
--- a/rtc_base/strings/json_unittest.cc
+++ b/rtc_base/strings/json_unittest.cc
@@ -12,7 +12,7 @@
 
 #include <vector>
 
-#include "rtc_base/gunit.h"
+#include "test/gtest.h"
 
 namespace rtc {
 
diff --git a/rtc_base/strings/string_builder.h b/rtc_base/strings/string_builder.h
index 27001d1..7c45ac4 100644
--- a/rtc_base/strings/string_builder.h
+++ b/rtc_base/strings/string_builder.h
@@ -17,8 +17,8 @@
 
 #include "absl/strings/string_view.h"
 #include "api/array_view.h"
-#include "rtc_base/stringencode.h"
-#include "rtc_base/stringutils.h"
+#include "rtc_base/string_encode.h"
+#include "rtc_base/string_utils.h"
 
 namespace rtc {
 
diff --git a/rtc_base/strings/string_builder_unittest.cc b/rtc_base/strings/string_builder_unittest.cc
index 878e128..6d8b9f2 100644
--- a/rtc_base/strings/string_builder_unittest.cc
+++ b/rtc_base/strings/string_builder_unittest.cc
@@ -10,8 +10,9 @@
 
 #include "rtc_base/strings/string_builder.h"
 
+#include <string.h>
+
 #include "rtc_base/checks.h"
-#include "rtc_base/stringutils.h"
 #include "test/gmock.h"
 #include "test/gtest.h"
 
diff --git a/rtc_base/stringutils_unittest.cc b/rtc_base/stringutils_unittest.cc
deleted file mode 100644
index 663e976..0000000
--- a/rtc_base/stringutils_unittest.cc
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- *  Copyright 2004 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/stringutils.h"
-#include "rtc_base/gunit.h"
-
-namespace rtc {
-
-TEST(string_trim_Test, Trimming) {
-  EXPECT_EQ("temp", string_trim("\n\r\t temp \n\r\t"));
-  EXPECT_EQ("temp\n\r\t temp", string_trim(" temp\n\r\t temp "));
-  EXPECT_EQ("temp temp", string_trim("temp temp"));
-  EXPECT_EQ("", string_trim(" \r\n\t"));
-  EXPECT_EQ("", string_trim(""));
-}
-
-TEST(string_startsTest, StartsWith) {
-  EXPECT_TRUE(starts_with("foobar", "foo"));
-  EXPECT_TRUE(starts_with("foobar", "foobar"));
-  EXPECT_TRUE(starts_with("foobar", ""));
-  EXPECT_TRUE(starts_with("", ""));
-  EXPECT_FALSE(starts_with("foobar", "bar"));
-  EXPECT_FALSE(starts_with("foobar", "foobarbaz"));
-  EXPECT_FALSE(starts_with("", "f"));
-}
-
-TEST(string_endsTest, EndsWith) {
-  EXPECT_TRUE(ends_with("foobar", "bar"));
-  EXPECT_TRUE(ends_with("foobar", "foobar"));
-  EXPECT_TRUE(ends_with("foobar", ""));
-  EXPECT_TRUE(ends_with("", ""));
-  EXPECT_FALSE(ends_with("foobar", "foo"));
-  EXPECT_FALSE(ends_with("foobar", "foobarbaz"));
-  EXPECT_FALSE(ends_with("", "f"));
-}
-
-TEST(string_toHexTest, ToHex) {
-  EXPECT_EQ(ToHex(0), "0");
-  EXPECT_EQ(ToHex(0X1243E), "1243e");
-  EXPECT_EQ(ToHex(-20), "ffffffec");
-}
-
-}  // namespace rtc
diff --git a/rtc_base/swap_queue.h b/rtc_base/swap_queue.h
index 172f2f5..c3246db 100644
--- a/rtc_base/swap_queue.h
+++ b/rtc_base/swap_queue.h
@@ -11,14 +11,15 @@
 #ifndef RTC_BASE_SWAP_QUEUE_H_
 #define RTC_BASE_SWAP_QUEUE_H_
 
-#include <algorithm>
+#include <stddef.h>
 #include <utility>
 #include <vector>
 
 #include "rtc_base/checks.h"
-#include "rtc_base/constructormagic.h"
-#include "rtc_base/criticalsection.h"
+#include "rtc_base/constructor_magic.h"
+#include "rtc_base/critical_section.h"
 #include "rtc_base/system/unused.h"
+#include "rtc_base/thread_annotations.h"
 
 namespace webrtc {
 
diff --git a/rtc_base/swap_queue_unittest.cc b/rtc_base/swap_queue_unittest.cc
index 28f870b..199ac6b 100644
--- a/rtc_base/swap_queue_unittest.cc
+++ b/rtc_base/swap_queue_unittest.cc
@@ -10,6 +10,7 @@
 
 #include "rtc_base/swap_queue.h"
 
+#include <cstdint>
 #include <vector>
 
 #include "test/gtest.h"
diff --git a/rtc_base/system/BUILD.gn b/rtc_base/system/BUILD.gn
index e5aa32b..8b83d04 100644
--- a/rtc_base/system/BUILD.gn
+++ b/rtc_base/system/BUILD.gn
@@ -75,5 +75,6 @@
     deps = [
       "..:checks",
     ]
+    libs = [ "Foundation.framework" ]
   }
 }
diff --git a/rtc_base/system/file_wrapper.cc b/rtc_base/system/file_wrapper.cc
index c033a79..9d99cef 100644
--- a/rtc_base/system/file_wrapper.cc
+++ b/rtc_base/system/file_wrapper.cc
@@ -10,6 +10,8 @@
 
 #include "rtc_base/system/file_wrapper.h"
 
+#include <cerrno>
+
 #ifdef _WIN32
 #include <Windows.h>
 #else
@@ -20,7 +22,7 @@
 
 namespace webrtc {
 namespace {
-FILE* FileOpen(const char* file_name_utf8, bool read_only) {
+FILE* FileOpen(const char* file_name_utf8, bool read_only, int* error) {
 #if defined(_WIN32)
   int len = MultiByteToWideChar(CP_UTF8, 0, file_name_utf8, -1, nullptr, 0);
   std::wstring wstr(len, 0);
@@ -29,27 +31,40 @@
 #else
   FILE* file = fopen(file_name_utf8, read_only ? "rb" : "wb");
 #endif
+  if (!file && error) {
+    *error = errno;
+  }
   return file;
 }
+
+const char* GetCstrCheckNoEmbeddedNul(const std::string& s) {
+  const char* p = s.c_str();
+  RTC_CHECK_EQ(strlen(p), s.size())
+      << "Invalid filename, containing NUL character";
+  return p;
+}
 }  // namespace
 
 // static
-FileWrapper* FileWrapper::Create() {
-  return new FileWrapper();
+FileWrapper FileWrapper::OpenReadOnly(const char* file_name_utf8) {
+  return FileWrapper(FileOpen(file_name_utf8, true, nullptr));
 }
 
 // static
-FileWrapper FileWrapper::Open(const char* file_name_utf8, bool read_only) {
-  return FileWrapper(FileOpen(file_name_utf8, read_only), 0);
+FileWrapper FileWrapper::OpenReadOnly(const std::string& file_name_utf8) {
+  return OpenReadOnly(GetCstrCheckNoEmbeddedNul(file_name_utf8));
 }
 
-FileWrapper::FileWrapper() {}
+// static
+FileWrapper FileWrapper::OpenWriteOnly(const char* file_name_utf8,
+                                       int* error /*=nullptr*/) {
+  return FileWrapper(FileOpen(file_name_utf8, false, error));
+}
 
-FileWrapper::FileWrapper(FILE* file, size_t max_size)
-    : file_(file), max_size_in_bytes_(max_size) {}
-
-FileWrapper::~FileWrapper() {
-  CloseFileImpl();
+// static
+FileWrapper FileWrapper::OpenWriteOnly(const std::string& file_name_utf8,
+                                       int* error /*=nullptr*/) {
+  return OpenWriteOnly(GetCstrCheckNoEmbeddedNul(file_name_utf8), error);
 }
 
 FileWrapper::FileWrapper(FileWrapper&& other) {
@@ -57,95 +72,39 @@
 }
 
 FileWrapper& FileWrapper::operator=(FileWrapper&& other) {
+  Close();
   file_ = other.file_;
-  max_size_in_bytes_ = other.max_size_in_bytes_;
-  position_ = other.position_;
   other.file_ = nullptr;
   return *this;
 }
 
-void FileWrapper::CloseFile() {
-  rtc::CritScope lock(&lock_);
-  CloseFileImpl();
+bool FileWrapper::Rewind() {
+  RTC_DCHECK(file_);
+  return fseek(file_, 0, SEEK_SET) == 0;
 }
 
-int FileWrapper::Rewind() {
-  rtc::CritScope lock(&lock_);
-  if (file_ != nullptr) {
-    position_ = 0;
-    return fseek(file_, 0, SEEK_SET);
-  }
-  return -1;
+bool FileWrapper::Flush() {
+  RTC_DCHECK(file_);
+  return fflush(file_) == 0;
 }
 
-void FileWrapper::SetMaxFileSize(size_t bytes) {
-  rtc::CritScope lock(&lock_);
-  max_size_in_bytes_ = bytes;
-}
-
-int FileWrapper::Flush() {
-  rtc::CritScope lock(&lock_);
-  return FlushImpl();
-}
-
-bool FileWrapper::OpenFile(const char* file_name_utf8, bool read_only) {
-  size_t length = strlen(file_name_utf8);
-  if (length > kMaxFileNameSize - 1)
-    return false;
-
-  rtc::CritScope lock(&lock_);
-  if (file_ != nullptr)
-    return false;
-
-  file_ = FileOpen(file_name_utf8, read_only);
-  return file_ != nullptr;
-}
-
-bool FileWrapper::OpenFromFileHandle(FILE* handle) {
-  if (!handle)
-    return false;
-  rtc::CritScope lock(&lock_);
-  CloseFileImpl();
-  file_ = handle;
-  return true;
-}
-
-int FileWrapper::Read(void* buf, size_t length) {
-  rtc::CritScope lock(&lock_);
-  if (file_ == nullptr)
-    return -1;
-
-  size_t bytes_read = fread(buf, 1, length, file_);
-  return static_cast<int>(bytes_read);
+size_t FileWrapper::Read(void* buf, size_t length) {
+  RTC_DCHECK(file_);
+  return fread(buf, 1, length, file_);
 }
 
 bool FileWrapper::Write(const void* buf, size_t length) {
-  if (buf == nullptr)
-    return false;
+  RTC_DCHECK(file_);
+  return fwrite(buf, 1, length, file_) == length;
+}
 
-  rtc::CritScope lock(&lock_);
-
+bool FileWrapper::Close() {
   if (file_ == nullptr)
-    return false;
+    return true;
 
-  // Check if it's time to stop writing.
-  if (max_size_in_bytes_ > 0 && (position_ + length) > max_size_in_bytes_)
-    return false;
-
-  size_t num_bytes = fwrite(buf, 1, length, file_);
-  position_ += num_bytes;
-
-  return num_bytes == length;
-}
-
-void FileWrapper::CloseFileImpl() {
-  if (file_ != nullptr)
-    fclose(file_);
+  bool success = fclose(file_) == 0;
   file_ = nullptr;
-}
-
-int FileWrapper::FlushImpl() {
-  return (file_ != nullptr) ? fflush(file_) : -1;
+  return success;
 }
 
 }  // namespace webrtc
diff --git a/rtc_base/system/file_wrapper.h b/rtc_base/system/file_wrapper.h
index 0bb86a3..4f5d511 100644
--- a/rtc_base/system/file_wrapper.h
+++ b/rtc_base/system/file_wrapper.h
@@ -14,70 +14,75 @@
 #include <stddef.h>
 #include <stdio.h>
 
-#include "rtc_base/criticalsection.h"
+#include "rtc_base/critical_section.h"
 
 // Implementation that can read (exclusive) or write from/to a file.
 
 namespace webrtc {
 
-// TODO(tommi): Rename to rtc::File and move to base.
+// This class is a thin wrapper around FILE*. It's main features are that it
+// owns the FILE*, calling fclose on destruction, and that on windows, file
+// names passed to the open methods are always treated as utf-8, regardless of
+// system code page.
+
+// Most of the methods return only a success/fail indication. When needed, an
+// optional argument |int* error| should be added to all methods, in the same
+// way as for the OpenWriteOnly methods.
 class FileWrapper final {
  public:
-  static const size_t kMaxFileNameSize = 1024;
+  // Opens a file, in read or write mode. Use the is_open() method on the
+  // returned object to check if the open operation was successful. On failure,
+  // and if |error| is non-null, the system errno value is stored at |*error|.
+  // The file is closed by the destructor.
+  static FileWrapper OpenReadOnly(const char* file_name_utf8);
+  static FileWrapper OpenReadOnly(const std::string& file_name_utf8);
+  static FileWrapper OpenWriteOnly(const char* file_name_utf8,
+                                   int* error = nullptr);
 
-  // Factory methods.
-  // TODO(tommi): Remove Create().
-  static FileWrapper* Create();
-  static FileWrapper Open(const char* file_name_utf8, bool read_only);
+  static FileWrapper OpenWriteOnly(const std::string& file_name_utf8,
+                                   int* error = nullptr);
 
-  FileWrapper(FILE* file, size_t max_size);
-  ~FileWrapper();
+  FileWrapper() = default;
 
-  // Support for move semantics.
-  FileWrapper(FileWrapper&& other);
-  FileWrapper& operator=(FileWrapper&& other);
-
-  // Returns true if a file has been opened.
-  bool is_open() const { return file_ != nullptr; }
-
-  // Opens a file in read or write mode, decided by the read_only parameter.
-  bool OpenFile(const char* file_name_utf8, bool read_only);
-
-  // Initializes the wrapper from an existing handle.  The wrapper
-  // takes ownership of |handle| and closes it in CloseFile().
-  bool OpenFromFileHandle(FILE* handle);
-
-  void CloseFile();
-
-  // Limits the file size to |bytes|. Writing will fail after the cap
-  // is hit. Pass zero to use an unlimited size.
-  // TODO(tommi): Could we move this out into a separate class?
-  void SetMaxFileSize(size_t bytes);
-
-  // Flush any pending writes.  Note: Flushing when closing, is not required.
-  int Flush();
-
-  // Rewinds the file to the start.
-  int Rewind();
-  int Read(void* buf, size_t length);
-  bool Write(const void* buf, size_t length);
-
- private:
-  FileWrapper();
-
-  void CloseFileImpl();
-  int FlushImpl();
-
-  // TODO(tommi): Remove the lock.
-  rtc::CriticalSection lock_;
-
-  FILE* file_ = nullptr;
-  size_t position_ = 0;
-  size_t max_size_in_bytes_ = 0;
+  // Takes over ownership of |file|, closing it on destruction.
+  explicit FileWrapper(FILE* file) : file_(file) {}
+  ~FileWrapper() { Close(); }
 
   // Copying is not supported.
   FileWrapper(const FileWrapper&) = delete;
   FileWrapper& operator=(const FileWrapper&) = delete;
+
+  // Support for move semantics.
+  FileWrapper(FileWrapper&&);
+  FileWrapper& operator=(FileWrapper&&);
+
+  // Returns true if a file has been opened. If the file is not open, no methods
+  // but is_open and Close may be called.
+  bool is_open() const { return file_ != nullptr; }
+
+  // Closes the file, and implies Flush. Returns true on success, false if
+  // writing buffered data fails. On failure, the file is nevertheless closed.
+  // Calling Close on an already closed file does nothing and returns success.
+  bool Close();
+
+  // Write any buffered data to the underlying file. Returns true on success,
+  // false on write error. Note: Flushing when closing, is not required.
+  bool Flush();
+
+  // Seeks to the beginning of file. Returns true on success, false on failure,
+  // e.g., if the underlying file isn't seekable.
+  bool Rewind();
+
+  // Returns number of bytes read. Short count indicates EOF or error.
+  size_t Read(void* buf, size_t length);
+
+  // Returns true if all data was successfully written (or buffered), or false
+  // if there was an error. Writing buffered data can fail later, and is
+  // reported with return value from Flush or Close.
+  bool Write(const void* buf, size_t length);
+
+ private:
+  FILE* file_ = nullptr;
 };
 
 }  // namespace webrtc
diff --git a/rtc_base/task_queue.cc b/rtc_base/task_queue.cc
new file mode 100644
index 0000000..ed489eb
--- /dev/null
+++ b/rtc_base/task_queue.cc
@@ -0,0 +1,57 @@
+/*
+ *  Copyright 2019 The WebRTC Project Authors. All rights reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+#include "rtc_base/task_queue.h"
+
+#include "api/task_queue/global_task_queue_factory.h"
+#include "api/task_queue/task_queue_base.h"
+
+namespace rtc {
+
+TaskQueue::TaskQueue(
+    std::unique_ptr<webrtc::TaskQueueBase, webrtc::TaskQueueDeleter> task_queue)
+    : impl_(task_queue.release()) {
+  impl_->task_queue_ = this;
+}
+
+TaskQueue::TaskQueue(const char* queue_name, Priority priority)
+    : TaskQueue(webrtc::GlobalTaskQueueFactory().CreateTaskQueue(queue_name,
+                                                                 priority)) {}
+
+TaskQueue::~TaskQueue() {
+  // There might running task that tries to rescheduler itself to the TaskQueue
+  // and not yet aware TaskQueue destructor is called.
+  // Calling back to TaskQueue::PostTask need impl_ pointer still be valid, so
+  // do not invalidate impl_ pointer until Delete returns.
+  impl_->Delete();
+}
+
+// static
+TaskQueue* TaskQueue::Current() {
+  webrtc::TaskQueueBase* impl = webrtc::TaskQueueBase::Current();
+  if (impl == nullptr) {
+    return nullptr;
+  }
+  return impl->task_queue_;
+}
+
+bool TaskQueue::IsCurrent() const {
+  return Current() == this;
+}
+
+void TaskQueue::PostTask(std::unique_ptr<QueuedTask> task) {
+  return impl_->PostTask(std::move(task));
+}
+
+void TaskQueue::PostDelayedTask(std::unique_ptr<QueuedTask> task,
+                                uint32_t milliseconds) {
+  return impl_->PostDelayedTask(std::move(task), milliseconds);
+}
+
+}  // namespace rtc
diff --git a/rtc_base/task_queue.h b/rtc_base/task_queue.h
index 888e203..1c0ae29 100644
--- a/rtc_base/task_queue.h
+++ b/rtc_base/task_queue.h
@@ -11,85 +11,24 @@
 #ifndef RTC_BASE_TASK_QUEUE_H_
 #define RTC_BASE_TASK_QUEUE_H_
 
+#include <stdint.h>
 #include <memory>
-#include <type_traits>
 #include <utility>
 
 #include "absl/memory/memory.h"
-#include "rtc_base/constructormagic.h"
-#include "rtc_base/scoped_ref_ptr.h"
+#include "api/task_queue/queued_task.h"
+#include "api/task_queue/task_queue_base.h"
+#include "api/task_queue/task_queue_factory.h"
+#include "rtc_base/constructor_magic.h"
 #include "rtc_base/system/rtc_export.h"
+#include "rtc_base/task_utils/to_queued_task.h"
 #include "rtc_base/thread_annotations.h"
 
 namespace rtc {
 
-// Base interface for asynchronously executed tasks.
-// The interface basically consists of a single function, Run(), that executes
-// on the target queue.  For more details see the Run() method and TaskQueue.
-class QueuedTask {
- public:
-  QueuedTask() {}
-  virtual ~QueuedTask() {}
-
-  // Main routine that will run when the task is executed on the desired queue.
-  // The task should return |true| to indicate that it should be deleted or
-  // |false| to indicate that the queue should consider ownership of the task
-  // having been transferred.  Returning |false| can be useful if a task has
-  // re-posted itself to a different queue or is otherwise being re-used.
-  virtual bool Run() = 0;
-
- private:
-  RTC_DISALLOW_COPY_AND_ASSIGN(QueuedTask);
-};
-
-// Simple implementation of QueuedTask for use with rtc::Bind and lambdas.
-template <class Closure>
-class ClosureTask : public QueuedTask {
- public:
-  explicit ClosureTask(Closure&& closure)
-      : closure_(std::forward<Closure>(closure)) {}
-
- private:
-  bool Run() override {
-    closure_();
-    return true;
-  }
-
-  typename std::remove_const<
-      typename std::remove_reference<Closure>::type>::type closure_;
-};
-
-// Extends ClosureTask to also allow specifying cleanup code.
-// This is useful when using lambdas if guaranteeing cleanup, even if a task
-// was dropped (queue is too full), is required.
-template <class Closure, class Cleanup>
-class ClosureTaskWithCleanup : public ClosureTask<Closure> {
- public:
-  ClosureTaskWithCleanup(Closure&& closure, Cleanup&& cleanup)
-      : ClosureTask<Closure>(std::forward<Closure>(closure)),
-        cleanup_(std::forward<Cleanup>(cleanup)) {}
-  ~ClosureTaskWithCleanup() { cleanup_(); }
-
- private:
-  typename std::remove_const<
-      typename std::remove_reference<Cleanup>::type>::type cleanup_;
-};
-
-// Convenience function to construct closures that can be passed directly
-// to methods that support std::unique_ptr<QueuedTask> but not template
-// based parameters.
-template <class Closure>
-static std::unique_ptr<QueuedTask> NewClosure(Closure&& closure) {
-  return absl::make_unique<ClosureTask<Closure>>(
-      std::forward<Closure>(closure));
-}
-
-template <class Closure, class Cleanup>
-static std::unique_ptr<QueuedTask> NewClosure(Closure&& closure,
-                                              Cleanup&& cleanup) {
-  return absl::make_unique<ClosureTaskWithCleanup<Closure, Cleanup>>(
-      std::forward<Closure>(closure), std::forward<Cleanup>(cleanup));
-}
+// TODO(danilchap): Remove the alias when all of webrtc is updated to use
+// webrtc::QueuedTask directly.
+using ::webrtc::QueuedTask;
 
 // Implements a task queue that asynchronously executes tasks in a way that
 // guarantees that they're executed in FIFO order and that tasks never overlap.
@@ -109,19 +48,7 @@
 //       queue_.PostTask([]() { Work(); });
 //     ...
 //
-//   2) Doing work asynchronously on a worker queue and providing a notification
-//      callback on the current queue, when the work has been done:
-//
-//     void MyClass::StartWorkAndLetMeKnowWhenDone(
-//         std::unique_ptr<QueuedTask> callback) {
-//       DCHECK(TaskQueue::Current()) << "Need to be running on a queue";
-//       queue_.PostTaskAndReply([]() { Work(); }, std::move(callback));
-//     }
-//     ...
-//     my_class->StartWorkAndLetMeKnowWhenDone(
-//         NewClosure([]() { RTC_LOG(INFO) << "The work is done!";}));
-//
-//   3) Posting a custom task on a timer.  The task posts itself again after
+//   2) Posting a custom task on a timer.  The task posts itself again after
 //      every running:
 //
 //     class TimerTask : public QueuedTask {
@@ -155,12 +82,10 @@
  public:
   // TaskQueue priority levels. On some platforms these will map to thread
   // priorities, on others such as Mac and iOS, GCD queue priorities.
-  enum class Priority {
-    NORMAL = 0,
-    HIGH,
-    LOW,
-  };
+  using Priority = ::webrtc::TaskQueueFactory::Priority;
 
+  explicit TaskQueue(std::unique_ptr<webrtc::TaskQueueBase,
+                                     webrtc::TaskQueueDeleter> task_queue);
   explicit TaskQueue(const char* queue_name,
                      Priority priority = Priority::NORMAL);
   ~TaskQueue();
@@ -170,15 +95,13 @@
   // Used for DCHECKing the current queue.
   bool IsCurrent() const;
 
+  // Returns non-owning pointer to the task queue implementation.
+  webrtc::TaskQueueBase* Get() { return impl_; }
+
   // TODO(tommi): For better debuggability, implement RTC_FROM_HERE.
 
   // Ownership of the task is passed to PostTask.
   void PostTask(std::unique_ptr<QueuedTask> task);
-  void PostTaskAndReply(std::unique_ptr<QueuedTask> task,
-                        std::unique_ptr<QueuedTask> reply,
-                        TaskQueue* reply_queue);
-  void PostTaskAndReply(std::unique_ptr<QueuedTask> task,
-                        std::unique_ptr<QueuedTask> reply);
 
   // Schedules a task to execute a specified number of milliseconds from when
   // the call is made. The precision should be considered as "best effort"
@@ -195,7 +118,7 @@
                 Closure,
                 std::unique_ptr<QueuedTask>>::value>::type* = nullptr>
   void PostTask(Closure&& closure) {
-    PostTask(NewClosure(std::forward<Closure>(closure)));
+    PostTask(webrtc::ToQueuedTask(std::forward<Closure>(closure)));
   }
 
   // See documentation above for performance expectations.
@@ -204,36 +127,12 @@
                 Closure,
                 std::unique_ptr<QueuedTask>>::value>::type* = nullptr>
   void PostDelayedTask(Closure&& closure, uint32_t milliseconds) {
-    PostDelayedTask(NewClosure(std::forward<Closure>(closure)), milliseconds);
-  }
-
-  template <class Closure1, class Closure2>
-  void PostTaskAndReply(Closure1&& task,
-                        Closure2&& reply,
-                        TaskQueue* reply_queue) {
-    PostTaskAndReply(NewClosure(std::forward<Closure1>(task)),
-                     NewClosure(std::forward<Closure2>(reply)), reply_queue);
-  }
-
-  template <class Closure>
-  void PostTaskAndReply(std::unique_ptr<QueuedTask> task, Closure&& reply) {
-    PostTaskAndReply(std::move(task), NewClosure(std::forward<Closure>(reply)));
-  }
-
-  template <class Closure>
-  void PostTaskAndReply(Closure&& task, std::unique_ptr<QueuedTask> reply) {
-    PostTaskAndReply(NewClosure(std::forward<Closure>(task)), std::move(reply));
-  }
-
-  template <class Closure1, class Closure2>
-  void PostTaskAndReply(Closure1&& task, Closure2&& reply) {
-    PostTaskAndReply(NewClosure(std::forward(task)),
-                     NewClosure(std::forward(reply)));
+    PostDelayedTask(webrtc::ToQueuedTask(std::forward<Closure>(closure)),
+                    milliseconds);
   }
 
  private:
-  class Impl;
-  const scoped_refptr<Impl> impl_;
+  webrtc::TaskQueueBase* const impl_;
 
   RTC_DISALLOW_COPY_AND_ASSIGN(TaskQueue);
 };
diff --git a/rtc_base/task_queue_for_test.h b/rtc_base/task_queue_for_test.h
index 9162e81..0becc80 100644
--- a/rtc_base/task_queue_for_test.h
+++ b/rtc_base/task_queue_for_test.h
@@ -11,11 +11,12 @@
 #ifndef RTC_BASE_TASK_QUEUE_FOR_TEST_H_
 #define RTC_BASE_TASK_QUEUE_FOR_TEST_H_
 
-#include <utility>
-
 #include "rtc_base/checks.h"
+#include "rtc_base/constructor_magic.h"
 #include "rtc_base/event.h"
 #include "rtc_base/task_queue.h"
+#include "rtc_base/task_utils/to_queued_task.h"
+#include "rtc_base/thread_annotations.h"
 
 namespace rtc {
 namespace test {
@@ -34,7 +35,7 @@
   void SendTask(Closure* task) {
     RTC_DCHECK(!IsCurrent());
     rtc::Event event;
-    PostTask(rtc::NewClosure(
+    PostTask(webrtc::ToQueuedTask(
         [&task]() {
           RTC_CHECK_EQ(false, static_cast<QueuedTask*>(task)->Run());
         },
@@ -48,7 +49,8 @@
   void SendTask(Closure&& task) {
     RTC_DCHECK(!IsCurrent());
     rtc::Event event;
-    PostTask(rtc::NewClosure(std::move(task), [&event]() { event.Set(); }));
+    PostTask(webrtc::ToQueuedTask(std::forward<Closure>(task),
+                                  [&event] { event.Set(); }));
     event.Wait(rtc::Event::kForever);
   }
 
diff --git a/rtc_base/task_queue_gcd.cc b/rtc_base/task_queue_gcd.cc
index c7731dd..c131d82 100644
--- a/rtc_base/task_queue_gcd.cc
+++ b/rtc_base/task_queue_gcd.cc
@@ -12,231 +12,142 @@
 // The implementation uses Grand Central Dispatch queues (GCD) to
 // do the actual task queuing.
 
-#include "rtc_base/task_queue.h"
+#include "rtc_base/task_queue_gcd.h"
 
 #include <string.h>
 
 #include <dispatch/dispatch.h>
 
+#include "absl/memory/memory.h"
+#include "absl/strings/string_view.h"
+#include "api/task_queue/queued_task.h"
+#include "api/task_queue/task_queue_base.h"
 #include "rtc_base/checks.h"
 #include "rtc_base/logging.h"
-#include "rtc_base/refcount.h"
-#include "rtc_base/refcountedobject.h"
-#include "rtc_base/task_queue_posix.h"
 
-namespace rtc {
+namespace webrtc {
 namespace {
 
-using Priority = TaskQueue::Priority;
-
-int TaskQueuePriorityToGCD(Priority priority) {
+int TaskQueuePriorityToGCD(TaskQueueFactory::Priority priority) {
   switch (priority) {
-    case Priority::NORMAL:
+    case TaskQueueFactory::Priority::NORMAL:
       return DISPATCH_QUEUE_PRIORITY_DEFAULT;
-    case Priority::HIGH:
+    case TaskQueueFactory::Priority::HIGH:
       return DISPATCH_QUEUE_PRIORITY_HIGH;
-    case Priority::LOW:
+    case TaskQueueFactory::Priority::LOW:
       return DISPATCH_QUEUE_PRIORITY_LOW;
   }
 }
-}  // namespace
 
-using internal::GetQueuePtrTls;
-using internal::AutoSetCurrentQueuePtr;
-
-class TaskQueue::Impl : public RefCountInterface {
+class TaskQueueGcd : public TaskQueueBase {
  public:
-  Impl(const char* queue_name, TaskQueue* task_queue, Priority priority);
-  ~Impl() override;
+  TaskQueueGcd(absl::string_view queue_name, int gcd_priority);
 
-  static TaskQueue* Current();
-
-  // Used for DCHECKing the current queue.
-  bool IsCurrent() const;
-
-  void PostTask(std::unique_ptr<QueuedTask> task);
-  void PostTaskAndReply(std::unique_ptr<QueuedTask> task,
-                        std::unique_ptr<QueuedTask> reply,
-                        TaskQueue::Impl* reply_queue);
-
-  void PostDelayedTask(std::unique_ptr<QueuedTask> task, uint32_t milliseconds);
+  void Delete() override;
+  void PostTask(std::unique_ptr<QueuedTask> task) override;
+  void PostDelayedTask(std::unique_ptr<QueuedTask> task,
+                       uint32_t milliseconds) override;
 
  private:
-  struct QueueContext {
-    explicit QueueContext(TaskQueue* q) : queue(q), is_active(true) {}
-
-    static void SetNotActive(void* context) {
-      QueueContext* qc = static_cast<QueueContext*>(context);
-      qc->is_active = false;
-    }
-
-    static void DeleteContext(void* context) {
-      QueueContext* qc = static_cast<QueueContext*>(context);
-      delete qc;
-    }
-
-    TaskQueue* const queue;
-    bool is_active;
-  };
-
   struct TaskContext {
-    TaskContext(QueueContext* queue_ctx, std::unique_ptr<QueuedTask> task)
-        : queue_ctx(queue_ctx), task(std::move(task)) {}
-    virtual ~TaskContext() {}
+    TaskContext(TaskQueueGcd* queue, std::unique_ptr<QueuedTask> task)
+        : queue(queue), task(std::move(task)) {}
 
-    static void RunTask(void* context) {
-      std::unique_ptr<TaskContext> tc(static_cast<TaskContext*>(context));
-      if (tc->queue_ctx->is_active) {
-        AutoSetCurrentQueuePtr set_current(tc->queue_ctx->queue);
-        if (!tc->task->Run())
-          tc->task.release();
-      }
-    }
-
-    QueueContext* const queue_ctx;
+    TaskQueueGcd* const queue;
     std::unique_ptr<QueuedTask> task;
   };
 
-  // Special case context for holding two tasks, a |first_task| + the task
-  // that's owned by the parent struct, TaskContext, that then becomes the
-  // second (i.e. 'reply') task.
-  struct PostTaskAndReplyContext : public TaskContext {
-    explicit PostTaskAndReplyContext(QueueContext* first_queue_ctx,
-                                     std::unique_ptr<QueuedTask> first_task,
-                                     QueueContext* second_queue_ctx,
-                                     std::unique_ptr<QueuedTask> second_task)
-        : TaskContext(second_queue_ctx, std::move(second_task)),
-          first_queue_ctx(first_queue_ctx),
-          first_task(std::move(first_task)),
-          reply_queue_(second_queue_ctx->queue->impl_->queue_) {
-      // Retain the reply queue for as long as this object lives.
-      // If we don't, we may have memory leaks and/or failures.
-      dispatch_retain(reply_queue_);
-    }
-    ~PostTaskAndReplyContext() override { dispatch_release(reply_queue_); }
-
-    static void RunTask(void* context) {
-      auto* rc = static_cast<PostTaskAndReplyContext*>(context);
-      if (rc->first_queue_ctx->is_active) {
-        AutoSetCurrentQueuePtr set_current(rc->first_queue_ctx->queue);
-        if (!rc->first_task->Run())
-          rc->first_task.release();
-      }
-      // Post the reply task.  This hands the work over to the parent struct.
-      // This task will eventually delete |this|.
-      dispatch_async_f(rc->reply_queue_, rc, &TaskContext::RunTask);
-    }
-
-    QueueContext* const first_queue_ctx;
-    std::unique_ptr<QueuedTask> first_task;
-    dispatch_queue_t reply_queue_;
-  };
+  ~TaskQueueGcd() override;
+  static void RunTask(void* task_context);
+  static void SetNotActive(void* task_queue);
+  static void DeleteQueue(void* task_queue);
 
   dispatch_queue_t queue_;
-  QueueContext* const context_;
+  bool is_active_;
 };
 
-TaskQueue::Impl::Impl(const char* queue_name,
-                      TaskQueue* task_queue,
-                      Priority priority)
-    : queue_(dispatch_queue_create(queue_name, DISPATCH_QUEUE_SERIAL)),
-      context_(new QueueContext(task_queue)) {
-  RTC_DCHECK(queue_name);
+TaskQueueGcd::TaskQueueGcd(absl::string_view queue_name, int gcd_priority)
+    : queue_(dispatch_queue_create(std::string(queue_name).c_str(),
+                                   DISPATCH_QUEUE_SERIAL)),
+      is_active_(true) {
   RTC_CHECK(queue_);
-  dispatch_set_context(queue_, context_);
-  // Assign a finalizer that will delete the context when the last reference
-  // to the queue is released.  This may run after the TaskQueue object has
-  // been deleted.
-  dispatch_set_finalizer_f(queue_, &QueueContext::DeleteContext);
+  dispatch_set_context(queue_, this);
+  // Assign a finalizer that will delete the queue when the last reference
+  // is released. This may run after the TaskQueue::Delete.
+  dispatch_set_finalizer_f(queue_, &DeleteQueue);
 
-  dispatch_set_target_queue(
-      queue_, dispatch_get_global_queue(TaskQueuePriorityToGCD(priority), 0));
+  dispatch_set_target_queue(queue_, dispatch_get_global_queue(gcd_priority, 0));
 }
 
-TaskQueue::Impl::~Impl() {
+TaskQueueGcd::~TaskQueueGcd() = default;
+
+void TaskQueueGcd::Delete() {
   RTC_DCHECK(!IsCurrent());
   // Implementation/behavioral note:
   // Dispatch queues are reference counted via calls to dispatch_retain and
   // dispatch_release. Pending blocks submitted to a queue also hold a
   // reference to the queue until they have finished. Once all references to a
   // queue have been released, the queue will be deallocated by the system.
-  // This is why we check the context before running tasks.
+  // This is why we check the is_active_ before running tasks.
 
-  // Use dispatch_sync to set the context to null to guarantee that there's not
-  // a race between checking the context and using it from a task.
-  dispatch_sync_f(queue_, context_, &QueueContext::SetNotActive);
+  // Use dispatch_sync to set the is_active_ to guarantee that there's not a
+  // race with checking it from a task.
+  dispatch_sync_f(queue_, this, &SetNotActive);
   dispatch_release(queue_);
 }
 
-// static
-TaskQueue* TaskQueue::Impl::Current() {
-  return static_cast<TaskQueue*>(pthread_getspecific(GetQueuePtrTls()));
+void TaskQueueGcd::PostTask(std::unique_ptr<QueuedTask> task) {
+  auto* context = new TaskContext(this, std::move(task));
+  dispatch_async_f(queue_, context, &RunTask);
 }
 
-bool TaskQueue::Impl::IsCurrent() const {
-  RTC_DCHECK(queue_);
-  const TaskQueue* current = Current();
-  return current && this == current->impl_.get();
-}
-
-void TaskQueue::Impl::PostTask(std::unique_ptr<QueuedTask> task) {
-  auto* context = new TaskContext(context_, std::move(task));
-  dispatch_async_f(queue_, context, &TaskContext::RunTask);
-}
-
-void TaskQueue::Impl::PostDelayedTask(std::unique_ptr<QueuedTask> task,
-                                      uint32_t milliseconds) {
-  auto* context = new TaskContext(context_, std::move(task));
+void TaskQueueGcd::PostDelayedTask(std::unique_ptr<QueuedTask> task,
+                                   uint32_t milliseconds) {
+  auto* context = new TaskContext(this, std::move(task));
   dispatch_after_f(
       dispatch_time(DISPATCH_TIME_NOW, milliseconds * NSEC_PER_MSEC), queue_,
-      context, &TaskContext::RunTask);
+      context, &RunTask);
 }
 
-void TaskQueue::Impl::PostTaskAndReply(std::unique_ptr<QueuedTask> task,
-                                       std::unique_ptr<QueuedTask> reply,
-                                       TaskQueue::Impl* reply_queue) {
-  auto* context = new PostTaskAndReplyContext(
-      context_, std::move(task), reply_queue->context_, std::move(reply));
-  dispatch_async_f(queue_, context, &PostTaskAndReplyContext::RunTask);
-}
-
-// Boilerplate for the PIMPL pattern.
-TaskQueue::TaskQueue(const char* queue_name, Priority priority)
-    : impl_(new RefCountedObject<TaskQueue::Impl>(queue_name, this, priority)) {
-}
-
-TaskQueue::~TaskQueue() {}
-
 // static
-TaskQueue* TaskQueue::Current() {
-  return TaskQueue::Impl::Current();
+void TaskQueueGcd::RunTask(void* task_context) {
+  std::unique_ptr<TaskContext> tc(static_cast<TaskContext*>(task_context));
+  if (!tc->queue->is_active_)
+    return;
+
+  CurrentTaskQueueSetter set_current(tc->queue);
+  auto* task = tc->task.release();
+  if (task->Run()) {
+    // Delete the task before CurrentTaskQueueSetter clears state that this code
+    // is running on the task queue.
+    delete task;
+  }
 }
 
-// Used for DCHECKing the current queue.
-bool TaskQueue::IsCurrent() const {
-  return impl_->IsCurrent();
+// static
+void TaskQueueGcd::SetNotActive(void* task_queue) {
+  static_cast<TaskQueueGcd*>(task_queue)->is_active_ = false;
 }
 
-void TaskQueue::PostTask(std::unique_ptr<QueuedTask> task) {
-  return TaskQueue::impl_->PostTask(std::move(task));
+// static
+void TaskQueueGcd::DeleteQueue(void* task_queue) {
+  delete static_cast<TaskQueueGcd*>(task_queue);
 }
 
-void TaskQueue::PostTaskAndReply(std::unique_ptr<QueuedTask> task,
-                                 std::unique_ptr<QueuedTask> reply,
-                                 TaskQueue* reply_queue) {
-  return TaskQueue::impl_->PostTaskAndReply(std::move(task), std::move(reply),
-                                            reply_queue->impl_.get());
+class TaskQueueGcdFactory final : public TaskQueueFactory {
+ public:
+  std::unique_ptr<TaskQueueBase, TaskQueueDeleter> CreateTaskQueue(
+      absl::string_view name,
+      Priority priority) const override {
+    return std::unique_ptr<TaskQueueBase, TaskQueueDeleter>(
+        new TaskQueueGcd(name, TaskQueuePriorityToGCD(priority)));
+  }
+};
+
+}  // namespace
+
+std::unique_ptr<TaskQueueFactory> CreateTaskQueueGcdFactory() {
+  return absl::make_unique<TaskQueueGcdFactory>();
 }
 
-void TaskQueue::PostTaskAndReply(std::unique_ptr<QueuedTask> task,
-                                 std::unique_ptr<QueuedTask> reply) {
-  return TaskQueue::impl_->PostTaskAndReply(std::move(task), std::move(reply),
-                                            impl_.get());
-}
-
-void TaskQueue::PostDelayedTask(std::unique_ptr<QueuedTask> task,
-                                uint32_t milliseconds) {
-  return TaskQueue::impl_->PostDelayedTask(std::move(task), milliseconds);
-}
-
-}  // namespace rtc
+}  // namespace webrtc
diff --git a/rtc_base/task_queue_gcd.h b/rtc_base/task_queue_gcd.h
new file mode 100644
index 0000000..dc6039e
--- /dev/null
+++ b/rtc_base/task_queue_gcd.h
@@ -0,0 +1,24 @@
+/*
+ *  Copyright 2019 The WebRTC Project Authors. All rights reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef RTC_BASE_TASK_QUEUE_GCD_H_
+#define RTC_BASE_TASK_QUEUE_GCD_H_
+
+#include <memory>
+
+#include "api/task_queue/task_queue_factory.h"
+
+namespace webrtc {
+
+std::unique_ptr<TaskQueueFactory> CreateTaskQueueGcdFactory();
+
+}  // namespace webrtc
+
+#endif  // RTC_BASE_TASK_QUEUE_GCD_H_
diff --git a/rtc_base/task_queue_libevent.cc b/rtc_base/task_queue_libevent.cc
index 7588569..7d93267 100644
--- a/rtc_base/task_queue_libevent.cc
+++ b/rtc_base/task_queue_libevent.cc
@@ -8,7 +8,7 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#include "rtc_base/task_queue.h"
+#include "rtc_base/task_queue_libevent.h"
 
 #include <errno.h>
 #include <fcntl.h>
@@ -22,38 +22,32 @@
 #include <type_traits>
 #include <utility>
 
+#include "absl/memory/memory.h"
+#include "absl/strings/string_view.h"
+#include "api/task_queue/queued_task.h"
+#include "api/task_queue/task_queue_base.h"
 #include <event.h>
 #include "rtc_base/checks.h"
-#include "rtc_base/criticalsection.h"
+#include "rtc_base/critical_section.h"
 #include "rtc_base/logging.h"
 #include "rtc_base/numerics/safe_conversions.h"
 #include "rtc_base/platform_thread.h"
 #include "rtc_base/platform_thread_types.h"
-#include "rtc_base/refcount.h"
-#include "rtc_base/refcountedobject.h"
-#include "rtc_base/scoped_ref_ptr.h"
-#include "rtc_base/system/unused.h"
-#include "rtc_base/task_queue_posix.h"
 #include "rtc_base/thread_annotations.h"
-#include "rtc_base/timeutils.h"
+#include "rtc_base/time_utils.h"
 
-namespace rtc {
-using internal::GetQueuePtrTls;
-using internal::AutoSetCurrentQueuePtr;
-
+namespace webrtc {
 namespace {
-static const char kQuit = 1;
-static const char kRunTask = 2;
-static const char kRunReplyTask = 3;
+constexpr char kQuit = 1;
+constexpr char kRunTask = 2;
 
-using Priority = TaskQueue::Priority;
+using Priority = TaskQueueFactory::Priority;
 
 // This ignores the SIGPIPE signal on the calling thread.
 // This signal can be fired when trying to write() to a pipe that's being
 // closed or while closing a pipe that's being written to.
-// We can run into that situation (e.g. reply tasks that don't get a chance to
-// run because the task queue is being deleted) so we ignore this signal and
-// continue as normal.
+// We can run into that situation so we ignore this signal and continue as
+// normal.
 // As a side note for this implementation, it would be great if we could safely
 // restore the sigmask, but unfortunately the operation of restoring it, can
 // itself actually cause SIGPIPE to be signaled :-| (e.g. on MacOS)
@@ -69,14 +63,6 @@
   pthread_sigmask(SIG_BLOCK, &sigpipe_mask, nullptr);
 }
 
-struct TimerEvent {
-  explicit TimerEvent(std::unique_ptr<QueuedTask> task)
-      : task(std::move(task)) {}
-  ~TimerEvent() { event_del(&ev); }
-  event ev;
-  std::unique_ptr<QueuedTask> task;
-};
-
 bool SetNonBlocking(int fd) {
   const int flags = fcntl(fd, F_GETFL);
   RTC_CHECK(flags != -1);
@@ -103,174 +89,76 @@
 #endif
 }
 
-ThreadPriority TaskQueuePriorityToThreadPriority(Priority priority) {
+rtc::ThreadPriority TaskQueuePriorityToThreadPriority(Priority priority) {
   switch (priority) {
     case Priority::HIGH:
-      return kRealtimePriority;
+      return rtc::kRealtimePriority;
     case Priority::LOW:
-      return kLowPriority;
+      return rtc::kLowPriority;
     case Priority::NORMAL:
-      return kNormalPriority;
+      return rtc::kNormalPriority;
     default:
       RTC_NOTREACHED();
       break;
   }
-  return kNormalPriority;
+  return rtc::kNormalPriority;
 }
-}  // namespace
 
-class TaskQueue::Impl : public RefCountInterface {
+class TaskQueueLibevent final : public TaskQueueBase {
  public:
-  explicit Impl(const char* queue_name,
-                TaskQueue* queue,
-                Priority priority = Priority::NORMAL);
-  ~Impl() override;
+  TaskQueueLibevent(absl::string_view queue_name, rtc::ThreadPriority priority);
 
-  static TaskQueue::Impl* Current();
-  static TaskQueue* CurrentQueue();
-
-  // Used for DCHECKing the current queue.
-  bool IsCurrent() const;
-
-  void PostTask(std::unique_ptr<QueuedTask> task);
-  void PostTaskAndReply(std::unique_ptr<QueuedTask> task,
-                        std::unique_ptr<QueuedTask> reply,
-                        TaskQueue::Impl* reply_queue);
-
-  void PostDelayedTask(std::unique_ptr<QueuedTask> task, uint32_t milliseconds);
+  void Delete() override;
+  void PostTask(std::unique_ptr<QueuedTask> task) override;
+  void PostDelayedTask(std::unique_ptr<QueuedTask> task,
+                       uint32_t milliseconds) override;
 
  private:
+  class SetTimerTask;
+  struct TimerEvent;
+
+  ~TaskQueueLibevent() override = default;
+
   static void ThreadMain(void* context);
   static void OnWakeup(int socket, short flags, void* context);  // NOLINT
   static void RunTask(int fd, short flags, void* context);       // NOLINT
   static void RunTimer(int fd, short flags, void* context);      // NOLINT
 
-  class ReplyTaskOwner;
-  class PostAndReplyTask;
-  class SetTimerTask;
-
-  typedef RefCountedObject<ReplyTaskOwner> ReplyTaskOwnerRef;
-
-  void PrepareReplyTask(scoped_refptr<ReplyTaskOwnerRef> reply_task);
-
-  struct QueueContext;
-  TaskQueue* const queue_;
+  bool is_active_ = true;
   int wakeup_pipe_in_ = -1;
   int wakeup_pipe_out_ = -1;
   event_base* event_base_;
-  std::unique_ptr<event> wakeup_event_;
-  PlatformThread thread_;
+  event wakeup_event_;
+  rtc::PlatformThread thread_;
   rtc::CriticalSection pending_lock_;
   std::list<std::unique_ptr<QueuedTask>> pending_ RTC_GUARDED_BY(pending_lock_);
-  std::list<scoped_refptr<ReplyTaskOwnerRef>> pending_replies_
-      RTC_GUARDED_BY(pending_lock_);
-};
-
-struct TaskQueue::Impl::QueueContext {
-  explicit QueueContext(TaskQueue::Impl* q) : queue(q), is_active(true) {}
-  TaskQueue::Impl* queue;
-  bool is_active;
   // Holds a list of events pending timers for cleanup when the loop exits.
   std::list<TimerEvent*> pending_timers_;
 };
 
-// Posting a reply task is tricky business. This class owns the reply task
-// and a reference to it is held by both the reply queue and the first task.
-// Here's an outline of what happens when dealing with a reply task.
-// * The ReplyTaskOwner owns the |reply_| task.
-// * One ref owned by PostAndReplyTask
-// * One ref owned by the reply TaskQueue
-// * ReplyTaskOwner has a flag |run_task_| initially set to false.
-// * ReplyTaskOwner has a method: HasOneRef() (provided by RefCountedObject).
-// * After successfully running the original |task_|, PostAndReplyTask() calls
-//   set_should_run_task(). This sets |run_task_| to true.
-// * In PostAndReplyTask's dtor:
-//   * It releases its reference to ReplyTaskOwner (important to do this first).
-//   * Sends (write()) a kRunReplyTask message to the reply queue's pipe.
-// * PostAndReplyTask doesn't care if write() fails, but when it does:
-//   * The reply queue is gone.
-//   * ReplyTaskOwner has already been deleted and the reply task too.
-// * If write() succeeds:
-//   * ReplyQueue receives the kRunReplyTask message
-//   * Goes through all pending tasks, finding the first that HasOneRef()
-//   * Calls ReplyTaskOwner::Run()
-//     * if set_should_run_task() was called, the reply task will be run
-//   * Release the reference to ReplyTaskOwner
-//   * ReplyTaskOwner and associated |reply_| are deleted.
-class TaskQueue::Impl::ReplyTaskOwner {
- public:
-  ReplyTaskOwner(std::unique_ptr<QueuedTask> reply)
-      : reply_(std::move(reply)) {}
+struct TaskQueueLibevent::TimerEvent {
+  TimerEvent(TaskQueueLibevent* task_queue, std::unique_ptr<QueuedTask> task)
+      : task_queue(task_queue), task(std::move(task)) {}
+  ~TimerEvent() { event_del(&ev); }
 
-  void Run() {
-    RTC_DCHECK(reply_);
-    if (run_task_) {
-      if (!reply_->Run())
-        reply_.release();
-    }
-    reply_.reset();
-  }
-
-  void set_should_run_task() {
-    RTC_DCHECK(!run_task_);
-    run_task_ = true;
-  }
-
- private:
-  std::unique_ptr<QueuedTask> reply_;
-  bool run_task_ = false;
+  event ev;
+  TaskQueueLibevent* task_queue;
+  std::unique_ptr<QueuedTask> task;
 };
 
-class TaskQueue::Impl::PostAndReplyTask : public QueuedTask {
- public:
-  PostAndReplyTask(std::unique_ptr<QueuedTask> task,
-                   std::unique_ptr<QueuedTask> reply,
-                   TaskQueue::Impl* reply_queue,
-                   int reply_pipe)
-      : task_(std::move(task)),
-        reply_pipe_(reply_pipe),
-        reply_task_owner_(
-            new RefCountedObject<ReplyTaskOwner>(std::move(reply))) {
-    reply_queue->PrepareReplyTask(reply_task_owner_);
-  }
-
-  ~PostAndReplyTask() override {
-    reply_task_owner_ = nullptr;
-    IgnoreSigPipeSignalOnCurrentThread();
-    // Send a signal to the reply queue that the reply task can run now.
-    // Depending on whether |set_should_run_task()| was called by the
-    // PostAndReplyTask(), the reply task may or may not actually run.
-    // In either case, it will be deleted.
-    char message = kRunReplyTask;
-    RTC_UNUSED(write(reply_pipe_, &message, sizeof(message)));
-  }
-
- private:
-  bool Run() override {
-    if (!task_->Run())
-      task_.release();
-    reply_task_owner_->set_should_run_task();
-    return true;
-  }
-
-  std::unique_ptr<QueuedTask> task_;
-  int reply_pipe_;
-  scoped_refptr<RefCountedObject<ReplyTaskOwner>> reply_task_owner_;
-};
-
-class TaskQueue::Impl::SetTimerTask : public QueuedTask {
+class TaskQueueLibevent::SetTimerTask : public QueuedTask {
  public:
   SetTimerTask(std::unique_ptr<QueuedTask> task, uint32_t milliseconds)
       : task_(std::move(task)),
         milliseconds_(milliseconds),
-        posted_(Time32()) {}
+        posted_(rtc::Time32()) {}
 
  private:
   bool Run() override {
     // Compensate for the time that has passed since construction
     // and until we got here.
-    uint32_t post_time = Time32() - posted_;
-    TaskQueue::Impl::Current()->PostDelayedTask(
+    uint32_t post_time = rtc::Time32() - posted_;
+    TaskQueueLibevent::Current()->PostDelayedTask(
         std::move(task_),
         post_time > milliseconds_ ? 0 : milliseconds_ - post_time);
     return true;
@@ -281,17 +169,10 @@
   const uint32_t posted_;
 };
 
-TaskQueue::Impl::Impl(const char* queue_name,
-                      TaskQueue* queue,
-                      Priority priority /*= NORMAL*/)
-    : queue_(queue),
-      event_base_(event_base_new()),
-      wakeup_event_(new event()),
-      thread_(&TaskQueue::Impl::ThreadMain,
-              this,
-              queue_name,
-              TaskQueuePriorityToThreadPriority(priority)) {
-  RTC_DCHECK(queue_name);
+TaskQueueLibevent::TaskQueueLibevent(absl::string_view queue_name,
+                                     rtc::ThreadPriority priority)
+    : event_base_(event_base_new()),
+      thread_(&TaskQueueLibevent::ThreadMain, this, queue_name, priority) {
   int fds[2];
   RTC_CHECK(pipe(fds) == 0);
   SetNonBlocking(fds[0]);
@@ -299,13 +180,13 @@
   wakeup_pipe_out_ = fds[0];
   wakeup_pipe_in_ = fds[1];
 
-  EventAssign(wakeup_event_.get(), event_base_, wakeup_pipe_out_,
+  EventAssign(&wakeup_event_, event_base_, wakeup_pipe_out_,
               EV_READ | EV_PERSIST, OnWakeup, this);
-  event_add(wakeup_event_.get(), 0);
+  event_add(&wakeup_event_, 0);
   thread_.Start();
 }
 
-TaskQueue::Impl::~Impl() {
+void TaskQueueLibevent::Delete() {
   RTC_DCHECK(!IsCurrent());
   struct timespec ts;
   char message = kQuit;
@@ -319,7 +200,7 @@
 
   thread_.Stop();
 
-  event_del(wakeup_event_.get());
+  event_del(&wakeup_event_);
 
   IgnoreSigPipeSignalOnCurrentThread();
 
@@ -329,48 +210,30 @@
   wakeup_pipe_out_ = -1;
 
   event_base_free(event_base_);
+  delete this;
 }
 
-// static
-TaskQueue::Impl* TaskQueue::Impl::Current() {
-  QueueContext* ctx =
-      static_cast<QueueContext*>(pthread_getspecific(GetQueuePtrTls()));
-  return ctx ? ctx->queue : nullptr;
-}
-
-// static
-TaskQueue* TaskQueue::Impl::CurrentQueue() {
-  TaskQueue::Impl* current = Current();
-  if (current) {
-    return current->queue_;
-  }
-  return nullptr;
-}
-
-bool TaskQueue::Impl::IsCurrent() const {
-  return IsThreadRefEqual(thread_.GetThreadRef(), CurrentThreadRef());
-}
-
-void TaskQueue::Impl::PostTask(std::unique_ptr<QueuedTask> task) {
+void TaskQueueLibevent::PostTask(std::unique_ptr<QueuedTask> task) {
   RTC_DCHECK(task.get());
   // libevent isn't thread safe.  This means that we can't use methods such
   // as event_base_once to post tasks to the worker thread from a different
   // thread.  However, we can use it when posting from the worker thread itself.
   if (IsCurrent()) {
-    if (event_base_once(event_base_, -1, EV_TIMEOUT, &TaskQueue::Impl::RunTask,
-                        task.get(), nullptr) == 0) {
+    if (event_base_once(event_base_, -1, EV_TIMEOUT,
+                        &TaskQueueLibevent::RunTask, task.get(),
+                        nullptr) == 0) {
       task.release();
     }
   } else {
     QueuedTask* task_id = task.get();  // Only used for comparison.
     {
-      CritScope lock(&pending_lock_);
+      rtc::CritScope lock(&pending_lock_);
       pending_.push_back(std::move(task));
     }
     char message = kRunTask;
     if (write(wakeup_pipe_in_, &message, sizeof(message)) != sizeof(message)) {
       RTC_LOG(WARNING) << "Failed to queue task.";
-      CritScope lock(&pending_lock_);
+      rtc::CritScope lock(&pending_lock_);
       pending_.remove_if([task_id](std::unique_ptr<QueuedTask>& t) {
         return t.get() == task_id;
       });
@@ -378,92 +241,61 @@
   }
 }
 
-void TaskQueue::Impl::PostDelayedTask(std::unique_ptr<QueuedTask> task,
-                                      uint32_t milliseconds) {
+void TaskQueueLibevent::PostDelayedTask(std::unique_ptr<QueuedTask> task,
+                                        uint32_t milliseconds) {
   if (IsCurrent()) {
-    TimerEvent* timer = new TimerEvent(std::move(task));
-    EventAssign(&timer->ev, event_base_, -1, 0, &TaskQueue::Impl::RunTimer,
+    TimerEvent* timer = new TimerEvent(this, std::move(task));
+    EventAssign(&timer->ev, event_base_, -1, 0, &TaskQueueLibevent::RunTimer,
                 timer);
-    QueueContext* ctx =
-        static_cast<QueueContext*>(pthread_getspecific(GetQueuePtrTls()));
-    ctx->pending_timers_.push_back(timer);
+    pending_timers_.push_back(timer);
     timeval tv = {rtc::dchecked_cast<int>(milliseconds / 1000),
                   rtc::dchecked_cast<int>(milliseconds % 1000) * 1000};
     event_add(&timer->ev, &tv);
   } else {
-    PostTask(std::unique_ptr<QueuedTask>(
-        new SetTimerTask(std::move(task), milliseconds)));
+    PostTask(absl::make_unique<SetTimerTask>(std::move(task), milliseconds));
   }
 }
 
-void TaskQueue::Impl::PostTaskAndReply(std::unique_ptr<QueuedTask> task,
-                                       std::unique_ptr<QueuedTask> reply,
-                                       TaskQueue::Impl* reply_queue) {
-  std::unique_ptr<QueuedTask> wrapper_task(
-      new PostAndReplyTask(std::move(task), std::move(reply), reply_queue,
-                           reply_queue->wakeup_pipe_in_));
-  PostTask(std::move(wrapper_task));
-}
-
 // static
-void TaskQueue::Impl::ThreadMain(void* context) {
-  TaskQueue::Impl* me = static_cast<TaskQueue::Impl*>(context);
+void TaskQueueLibevent::ThreadMain(void* context) {
+  TaskQueueLibevent* me = static_cast<TaskQueueLibevent*>(context);
 
-  QueueContext queue_context(me);
-  pthread_setspecific(GetQueuePtrTls(), &queue_context);
+  {
+    CurrentTaskQueueSetter set_current(me);
+    while (me->is_active_)
+      event_base_loop(me->event_base_, 0);
+  }
 
-  while (queue_context.is_active)
-    event_base_loop(me->event_base_, 0);
-
-  pthread_setspecific(GetQueuePtrTls(), nullptr);
-
-  for (TimerEvent* timer : queue_context.pending_timers_)
+  for (TimerEvent* timer : me->pending_timers_)
     delete timer;
 }
 
 // static
-void TaskQueue::Impl::OnWakeup(int socket,
-                               short flags,
-                               void* context) {  // NOLINT
-  QueueContext* ctx =
-      static_cast<QueueContext*>(pthread_getspecific(GetQueuePtrTls()));
-  RTC_DCHECK(ctx->queue->wakeup_pipe_out_ == socket);
+void TaskQueueLibevent::OnWakeup(int socket,
+                                 short flags,  // NOLINT
+                                 void* context) {
+  TaskQueueLibevent* me = static_cast<TaskQueueLibevent*>(context);
+  RTC_DCHECK(me->wakeup_pipe_out_ == socket);
   char buf;
   RTC_CHECK(sizeof(buf) == read(socket, &buf, sizeof(buf)));
   switch (buf) {
     case kQuit:
-      ctx->is_active = false;
-      event_base_loopbreak(ctx->queue->event_base_);
+      me->is_active_ = false;
+      event_base_loopbreak(me->event_base_);
       break;
     case kRunTask: {
       std::unique_ptr<QueuedTask> task;
       {
-        CritScope lock(&ctx->queue->pending_lock_);
-        RTC_DCHECK(!ctx->queue->pending_.empty());
-        task = std::move(ctx->queue->pending_.front());
-        ctx->queue->pending_.pop_front();
+        rtc::CritScope lock(&me->pending_lock_);
+        RTC_DCHECK(!me->pending_.empty());
+        task = std::move(me->pending_.front());
+        me->pending_.pop_front();
         RTC_DCHECK(task.get());
       }
       if (!task->Run())
         task.release();
       break;
     }
-    case kRunReplyTask: {
-      scoped_refptr<ReplyTaskOwnerRef> reply_task;
-      {
-        CritScope lock(&ctx->queue->pending_lock_);
-        for (auto it = ctx->queue->pending_replies_.begin();
-             it != ctx->queue->pending_replies_.end(); ++it) {
-          if ((*it)->HasOneRef()) {
-            reply_task = std::move(*it);
-            ctx->queue->pending_replies_.erase(it);
-            break;
-          }
-        }
-      }
-      reply_task->Run();
-      break;
-    }
     default:
       RTC_NOTREACHED();
       break;
@@ -471,66 +303,38 @@
 }
 
 // static
-void TaskQueue::Impl::RunTask(int fd, short flags, void* context) {  // NOLINT
+void TaskQueueLibevent::RunTask(int fd, short flags, void* context) {  // NOLINT
   auto* task = static_cast<QueuedTask*>(context);
   if (task->Run())
     delete task;
 }
 
 // static
-void TaskQueue::Impl::RunTimer(int fd, short flags, void* context) {  // NOLINT
+void TaskQueueLibevent::RunTimer(int fd,
+                                 short flags,  // NOLINT
+                                 void* context) {
   TimerEvent* timer = static_cast<TimerEvent*>(context);
   if (!timer->task->Run())
     timer->task.release();
-  QueueContext* ctx =
-      static_cast<QueueContext*>(pthread_getspecific(GetQueuePtrTls()));
-  ctx->pending_timers_.remove(timer);
+  timer->task_queue->pending_timers_.remove(timer);
   delete timer;
 }
 
-void TaskQueue::Impl::PrepareReplyTask(
-    scoped_refptr<ReplyTaskOwnerRef> reply_task) {
-  RTC_DCHECK(reply_task);
-  CritScope lock(&pending_lock_);
-  pending_replies_.push_back(std::move(reply_task));
+class TaskQueueLibeventFactory final : public TaskQueueFactory {
+ public:
+  std::unique_ptr<TaskQueueBase, TaskQueueDeleter> CreateTaskQueue(
+      absl::string_view name,
+      Priority priority) const override {
+    return std::unique_ptr<TaskQueueBase, TaskQueueDeleter>(
+        new TaskQueueLibevent(name,
+                              TaskQueuePriorityToThreadPriority(priority)));
+  }
+};
+
+}  // namespace
+
+std::unique_ptr<TaskQueueFactory> CreateTaskQueueLibeventFactory() {
+  return absl::make_unique<TaskQueueLibeventFactory>();
 }
 
-TaskQueue::TaskQueue(const char* queue_name, Priority priority)
-    : impl_(new RefCountedObject<TaskQueue::Impl>(queue_name, this, priority)) {
-}
-
-TaskQueue::~TaskQueue() {}
-
-// static
-TaskQueue* TaskQueue::Current() {
-  return TaskQueue::Impl::CurrentQueue();
-}
-
-// Used for DCHECKing the current queue.
-bool TaskQueue::IsCurrent() const {
-  return impl_->IsCurrent();
-}
-
-void TaskQueue::PostTask(std::unique_ptr<QueuedTask> task) {
-  return TaskQueue::impl_->PostTask(std::move(task));
-}
-
-void TaskQueue::PostTaskAndReply(std::unique_ptr<QueuedTask> task,
-                                 std::unique_ptr<QueuedTask> reply,
-                                 TaskQueue* reply_queue) {
-  return TaskQueue::impl_->PostTaskAndReply(std::move(task), std::move(reply),
-                                            reply_queue->impl_.get());
-}
-
-void TaskQueue::PostTaskAndReply(std::unique_ptr<QueuedTask> task,
-                                 std::unique_ptr<QueuedTask> reply) {
-  return TaskQueue::impl_->PostTaskAndReply(std::move(task), std::move(reply),
-                                            impl_.get());
-}
-
-void TaskQueue::PostDelayedTask(std::unique_ptr<QueuedTask> task,
-                                uint32_t milliseconds) {
-  return TaskQueue::impl_->PostDelayedTask(std::move(task), milliseconds);
-}
-
-}  // namespace rtc
+}  // namespace webrtc
diff --git a/rtc_base/task_queue_libevent.h b/rtc_base/task_queue_libevent.h
new file mode 100644
index 0000000..aaa72d4
--- /dev/null
+++ b/rtc_base/task_queue_libevent.h
@@ -0,0 +1,24 @@
+/*
+ *  Copyright 2019 The WebRTC Project Authors. All rights reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef RTC_BASE_TASK_QUEUE_LIBEVENT_H_
+#define RTC_BASE_TASK_QUEUE_LIBEVENT_H_
+
+#include <memory>
+
+#include "api/task_queue/task_queue_factory.h"
+
+namespace webrtc {
+
+std::unique_ptr<TaskQueueFactory> CreateTaskQueueLibeventFactory();
+
+}  // namespace webrtc
+
+#endif  // RTC_BASE_TASK_QUEUE_LIBEVENT_H_
diff --git a/rtc_base/task_queue_posix.cc b/rtc_base/task_queue_posix.cc
deleted file mode 100644
index 520b8e9..0000000
--- a/rtc_base/task_queue_posix.cc
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- *  Copyright 2016 The WebRTC Project Authors. All rights reserved.
- *
- *  Use of this source code is governed by a BSD-style license
- *  that can be found in the LICENSE file in the root of the source
- *  tree. An additional intellectual property rights grant can be found
- *  in the file PATENTS.  All contributing project authors may
- *  be found in the AUTHORS file in the root of the source tree.
- */
-
-#include "rtc_base/task_queue_posix.h"
-
-#include "rtc_base/checks.h"
-#include "rtc_base/task_queue.h"
-
-namespace rtc {
-namespace internal {
-pthread_key_t g_queue_ptr_tls = 0;
-
-void InitializeTls() {
-  RTC_CHECK(pthread_key_create(&g_queue_ptr_tls, nullptr) == 0);
-}
-
-pthread_key_t GetQueuePtrTls() {
-  static pthread_once_t init_once = PTHREAD_ONCE_INIT;
-  RTC_CHECK(pthread_once(&init_once, &InitializeTls) == 0);
-  return g_queue_ptr_tls;
-}
-
-AutoSetCurrentQueuePtr::AutoSetCurrentQueuePtr(TaskQueue* q)
-    : prev_(TaskQueue::Current()) {
-  pthread_setspecific(GetQueuePtrTls(), q);
-}
-
-AutoSetCurrentQueuePtr::~AutoSetCurrentQueuePtr() {
-  pthread_setspecific(GetQueuePtrTls(), prev_);
-}
-
-}  // namespace internal
-}  // namespace rtc
diff --git a/rtc_base/task_queue_posix.h b/rtc_base/task_queue_posix.h
deleted file mode 100644
index 3014e20..0000000
--- a/rtc_base/task_queue_posix.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- *  Copyright 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 RTC_BASE_TASK_QUEUE_POSIX_H_
-#define RTC_BASE_TASK_QUEUE_POSIX_H_
-
-#include <pthread.h>
-
-namespace rtc {
-
-class TaskQueue;
-
-namespace internal {
-
-class AutoSetCurrentQueuePtr {
- public:
-  explicit AutoSetCurrentQueuePtr(TaskQueue* q);
-  ~AutoSetCurrentQueuePtr();
-
- private:
-  TaskQueue* const prev_;
-};
-
-pthread_key_t GetQueuePtrTls();
-
-}  // namespace internal
-}  // namespace rtc
-
-#endif  // RTC_BASE_TASK_QUEUE_POSIX_H_
diff --git a/rtc_base/task_queue_stdlib.cc b/rtc_base/task_queue_stdlib.cc
index 0fb0ed2..88128b5 100644
--- a/rtc_base/task_queue_stdlib.cc
+++ b/rtc_base/task_queue_stdlib.cc
@@ -8,83 +8,55 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#include "rtc_base/task_queue.h"
+#include "rtc_base/task_queue_stdlib.h"
 
 #include <string.h>
 #include <algorithm>
-#include <atomic>
-#include <condition_variable>
 #include <map>
 #include <queue>
 #include <utility>
 
+#include "absl/memory/memory.h"
+#include "absl/strings/string_view.h"
+#include "api/task_queue/queued_task.h"
+#include "api/task_queue/task_queue_base.h"
 #include "rtc_base/checks.h"
-#include "rtc_base/criticalsection.h"
+#include "rtc_base/critical_section.h"
 #include "rtc_base/event.h"
 #include "rtc_base/logging.h"
 #include "rtc_base/platform_thread.h"
-#include "rtc_base/refcount.h"
-#include "rtc_base/refcountedobject.h"
 #include "rtc_base/thread_annotations.h"
-#include "rtc_base/timeutils.h"
+#include "rtc_base/time_utils.h"
 
-namespace rtc {
+namespace webrtc {
 namespace {
 
-using Priority = TaskQueue::Priority;
-
-ThreadPriority TaskQueuePriorityToThreadPriority(Priority priority) {
+rtc::ThreadPriority TaskQueuePriorityToThreadPriority(
+    TaskQueueFactory::Priority priority) {
   switch (priority) {
-    case Priority::HIGH:
-      return kRealtimePriority;
-    case Priority::LOW:
-      return kLowPriority;
-    case Priority::NORMAL:
-      return kNormalPriority;
+    case TaskQueueFactory::Priority::HIGH:
+      return rtc::kRealtimePriority;
+    case TaskQueueFactory::Priority::LOW:
+      return rtc::kLowPriority;
+    case TaskQueueFactory::Priority::NORMAL:
+      return rtc::kNormalPriority;
     default:
       RTC_NOTREACHED();
-      return kNormalPriority;
+      return rtc::kNormalPriority;
   }
-  return kNormalPriority;
 }
 
-}  // namespace
-
-class TaskQueue::Impl : public RefCountInterface {
+class TaskQueueStdlib final : public TaskQueueBase {
  public:
-  Impl(const char* queue_name, TaskQueue* queue, Priority priority);
-  ~Impl() override;
+  TaskQueueStdlib(absl::string_view queue_name, rtc::ThreadPriority priority);
+  ~TaskQueueStdlib() override = default;
 
-  static TaskQueue::Impl* Current();
-  static TaskQueue* CurrentQueue();
+  void Delete() override;
+  void PostTask(std::unique_ptr<QueuedTask> task) override;
+  void PostDelayedTask(std::unique_ptr<QueuedTask> task,
+                       uint32_t milliseconds) override;
 
-  // Used for DCHECKing the current queue.
-  bool IsCurrent() const;
-
-  template <class Closure,
-            typename std::enable_if<!std::is_convertible<
-                Closure,
-                std::unique_ptr<QueuedTask>>::value>::type* = nullptr>
-  void PostTask(Closure&& closure) {
-    PostTask(NewClosure(std::forward<Closure>(closure)));
-  }
-
-  void PostTask(std::unique_ptr<QueuedTask> task);
-  void PostTaskAndReply(std::unique_ptr<QueuedTask> task,
-                        std::unique_ptr<QueuedTask> reply,
-                        TaskQueue::Impl* reply_queue);
-
-  void PostDelayedTask(std::unique_ptr<QueuedTask> task, uint32_t milliseconds);
-
-  class WorkerThread : public PlatformThread {
-   public:
-    WorkerThread(ThreadRunFunction func,
-                 void* obj,
-                 const char* thread_name,
-                 ThreadPriority priority)
-        : PlatformThread(func, obj, thread_name, priority) {}
-  };
-
+ private:
   using OrderId = uint64_t;
 
   struct DelayedEntryTimeout {
@@ -103,38 +75,26 @@
     int64_t sleep_time_ms_{};
   };
 
- protected:
   NextTask GetNextTask();
 
- private:
-  // The ThreadQueue::Current() method requires that the current thread
-  // returns the task queue if the current thread is the active task
-  // queue and this variable holds the value needed in thread_local to
-  // on the initialized worker thread holding the queue.
-  static thread_local TaskQueue::Impl* thread_context_;
-
   static void ThreadMain(void* context);
 
   void ProcessTasks();
 
   void NotifyWake();
 
-  // The back pointer from the owner task queue object
-  // from this implementation detail.
-  TaskQueue* const queue_;
-
   // Indicates if the thread has started.
-  Event started_;
+  rtc::Event started_;
 
   // Indicates if the thread has stopped.
-  Event stopped_;
+  rtc::Event stopped_;
 
   // Signaled whenever a new task is pending.
-  Event flag_notify_;
+  rtc::Event flag_notify_;
 
   // Contains the active worker thread assigned to processing
   // tasks (including delayed tasks).
-  WorkerThread thread_;
+  rtc::PlatformThread thread_;
 
   rtc::CriticalSection pending_lock_;
 
@@ -160,57 +120,34 @@
       RTC_GUARDED_BY(pending_lock_);
 };
 
-// static
-thread_local TaskQueue::Impl* TaskQueue::Impl::thread_context_ = nullptr;
-
-TaskQueue::Impl::Impl(const char* queue_name,
-                      TaskQueue* queue,
-                      Priority priority)
-    : queue_(queue),
-      started_(/*manual_reset=*/false, /*initially_signaled=*/false),
+TaskQueueStdlib::TaskQueueStdlib(absl::string_view queue_name,
+                                 rtc::ThreadPriority priority)
+    : started_(/*manual_reset=*/false, /*initially_signaled=*/false),
       stopped_(/*manual_reset=*/false, /*initially_signaled=*/false),
       flag_notify_(/*manual_reset=*/false, /*initially_signaled=*/false),
-      thread_(&TaskQueue::Impl::ThreadMain,
-              this,
-              queue_name,
-              TaskQueuePriorityToThreadPriority(priority)) {
-  RTC_DCHECK(queue_name);
+      thread_(&TaskQueueStdlib::ThreadMain, this, queue_name, priority) {
   thread_.Start();
-  started_.Wait(Event::kForever);
+  started_.Wait(rtc::Event::kForever);
 }
 
-TaskQueue::Impl::~Impl() {
+void TaskQueueStdlib::Delete() {
   RTC_DCHECK(!IsCurrent());
 
   {
-    CritScope lock(&pending_lock_);
+    rtc::CritScope lock(&pending_lock_);
     thread_should_quit_ = true;
   }
 
   NotifyWake();
 
-  stopped_.Wait(Event::kForever);
+  stopped_.Wait(rtc::Event::kForever);
   thread_.Stop();
+  delete this;
 }
 
-// static
-TaskQueue::Impl* TaskQueue::Impl::Current() {
-  return thread_context_;
-}
-
-// static
-TaskQueue* TaskQueue::Impl::CurrentQueue() {
-  TaskQueue::Impl* current = Current();
-  return current ? current->queue_ : nullptr;
-}
-
-bool TaskQueue::Impl::IsCurrent() const {
-  return IsThreadRefEqual(thread_.GetThreadRef(), CurrentThreadRef());
-}
-
-void TaskQueue::Impl::PostTask(std::unique_ptr<QueuedTask> task) {
+void TaskQueueStdlib::PostTask(std::unique_ptr<QueuedTask> task) {
   {
-    CritScope lock(&pending_lock_);
+    rtc::CritScope lock(&pending_lock_);
     OrderId order = thread_posting_order_++;
 
     pending_queue_.push(std::pair<OrderId, std::unique_ptr<QueuedTask>>(
@@ -220,7 +157,7 @@
   NotifyWake();
 }
 
-void TaskQueue::Impl::PostDelayedTask(std::unique_ptr<QueuedTask> task,
+void TaskQueueStdlib::PostDelayedTask(std::unique_ptr<QueuedTask> task,
                                       uint32_t milliseconds) {
   auto fire_at = rtc::TimeMillis() + milliseconds;
 
@@ -228,7 +165,7 @@
   delay.next_fire_at_ms_ = fire_at;
 
   {
-    CritScope lock(&pending_lock_);
+    rtc::CritScope lock(&pending_lock_);
     delay.order_ = ++thread_posting_order_;
     delayed_queue_[delay] = std::move(task);
   }
@@ -236,25 +173,12 @@
   NotifyWake();
 }
 
-void TaskQueue::Impl::PostTaskAndReply(std::unique_ptr<QueuedTask> task,
-                                       std::unique_ptr<QueuedTask> reply,
-                                       TaskQueue::Impl* reply_queue) {
-  QueuedTask* task_ptr = task.release();
-  QueuedTask* reply_task_ptr = reply.release();
-  PostTask([task_ptr, reply_task_ptr, reply_queue]() {
-    if (task_ptr->Run())
-      delete task_ptr;
-
-    reply_queue->PostTask(std::unique_ptr<QueuedTask>(reply_task_ptr));
-  });
-}
-
-TaskQueue::Impl::NextTask TaskQueue::Impl::GetNextTask() {
+TaskQueueStdlib::NextTask TaskQueueStdlib::GetNextTask() {
   NextTask result{};
 
   auto tick = rtc::TimeMillis();
 
-  CritScope lock(&pending_lock_);
+  rtc::CritScope lock(&pending_lock_);
 
   if (thread_should_quit_) {
     result.final_task_ = true;
@@ -295,13 +219,13 @@
 }
 
 // static
-void TaskQueue::Impl::ThreadMain(void* context) {
-  TaskQueue::Impl* me = static_cast<TaskQueue::Impl*>(context);
+void TaskQueueStdlib::ThreadMain(void* context) {
+  TaskQueueStdlib* me = static_cast<TaskQueueStdlib*>(context);
+  CurrentTaskQueueSetter set_current(me);
   me->ProcessTasks();
 }
 
-void TaskQueue::Impl::ProcessTasks() {
-  thread_context_ = this;
+void TaskQueueStdlib::ProcessTasks() {
   started_.Set();
 
   while (true) {
@@ -321,7 +245,7 @@
     }
 
     if (0 == task.sleep_time_ms_)
-      flag_notify_.Wait(Event::kForever);
+      flag_notify_.Wait(rtc::Event::kForever);
     else
       flag_notify_.Wait(task.sleep_time_ms_);
   }
@@ -329,7 +253,7 @@
   stopped_.Set();
 }
 
-void TaskQueue::Impl::NotifyWake() {
+void TaskQueueStdlib::NotifyWake() {
   // The queue holds pending tasks to complete. Either tasks are to be
   // executed immediately or tasks are to be run at some future delayed time.
   // For immediate tasks the task queue's thread is busy running the task and
@@ -357,43 +281,20 @@
   flag_notify_.Set();
 }
 
-// Boilerplate for the PIMPL pattern.
-TaskQueue::TaskQueue(const char* queue_name, Priority priority)
-    : impl_(new RefCountedObject<TaskQueue::Impl>(queue_name, this, priority)) {
+class TaskQueueStdlibFactory final : public TaskQueueFactory {
+ public:
+  std::unique_ptr<TaskQueueBase, TaskQueueDeleter> CreateTaskQueue(
+      absl::string_view name,
+      Priority priority) const override {
+    return std::unique_ptr<TaskQueueBase, TaskQueueDeleter>(
+        new TaskQueueStdlib(name, TaskQueuePriorityToThreadPriority(priority)));
+  }
+};
+
+}  // namespace
+
+std::unique_ptr<TaskQueueFactory> CreateTaskQueueStdlibFactory() {
+  return absl::make_unique<TaskQueueStdlibFactory>();
 }
 
-TaskQueue::~TaskQueue() {}
-
-// static
-TaskQueue* TaskQueue::Current() {
-  return TaskQueue::Impl::CurrentQueue();
-}
-
-// Used for DCHECKing the current queue.
-bool TaskQueue::IsCurrent() const {
-  return impl_->IsCurrent();
-}
-
-void TaskQueue::PostTask(std::unique_ptr<QueuedTask> task) {
-  return TaskQueue::impl_->PostTask(std::move(task));
-}
-
-void TaskQueue::PostTaskAndReply(std::unique_ptr<QueuedTask> task,
-                                 std::unique_ptr<QueuedTask> reply,
-                                 TaskQueue* reply_queue) {
-  return TaskQueue::impl_->PostTaskAndReply(std::move(task), std::move(reply),
-                                            reply_queue->impl_.get());
-}
-
-void TaskQueue::PostTaskAndReply(std::unique_ptr<QueuedTask> task,
-                                 std::unique_ptr<QueuedTask> reply) {
-  return TaskQueue::impl_->PostTaskAndReply(std::move(task), std::move(reply),
-                                            impl_.get());
-}
-
-void TaskQueue::PostDelayedTask(std::unique_ptr<QueuedTask> task,
-                                uint32_t milliseconds) {
-  return TaskQueue::impl_->PostDelayedTask(std::move(task), milliseconds);
-}
-
-}  // namespace rtc
+}  // namespace webrtc
diff --git a/rtc_base/task_queue_stdlib.h b/rtc_base/task_queue_stdlib.h
new file mode 100644
index 0000000..fb03dff
--- /dev/null
+++ b/rtc_base/task_queue_stdlib.h
@@ -0,0 +1,24 @@
+/*
+ *  Copyright 2019 The WebRTC Project Authors. All rights reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef RTC_BASE_TASK_QUEUE_STDLIB_H_
+#define RTC_BASE_TASK_QUEUE_STDLIB_H_
+
+#include <memory>
+
+#include "api/task_queue/task_queue_factory.h"
+
+namespace webrtc {
+
+std::unique_ptr<TaskQueueFactory> CreateTaskQueueStdlibFactory();
+
+}  // namespace webrtc
+
+#endif  // RTC_BASE_TASK_QUEUE_STDLIB_H_
diff --git a/rtc_base/task_queue_unittest.cc b/rtc_base/task_queue_unittest.cc
index 0af39a5..5c80c4f 100644
--- a/rtc_base/task_queue_unittest.cc
+++ b/rtc_base/task_queue_unittest.cc
@@ -15,16 +15,17 @@
 // clang-format on
 #endif
 
+#include <stdint.h>
 #include <memory>
+#include <utility>
 #include <vector>
 
+#include "absl/memory/memory.h"
 #include "rtc_base/bind.h"
 #include "rtc_base/event.h"
-#include "rtc_base/gunit.h"
-#include "rtc_base/task_queue_for_test.h"
-#include "rtc_base/timeutils.h"
-
-using rtc::test::TaskQueueForTest;
+#include "rtc_base/task_queue.h"
+#include "rtc_base/time_utils.h"
+#include "test/gtest.h"
 
 namespace rtc {
 
@@ -56,89 +57,6 @@
 
 }  // namespace
 
-TEST(TaskQueueTest, Construct) {
-  static const char kQueueName[] = "Construct";
-  TaskQueue queue(kQueueName);
-  EXPECT_FALSE(queue.IsCurrent());
-}
-
-TEST(TaskQueueTest, PostAndCheckCurrent) {
-  static const char kQueueName[] = "PostAndCheckCurrent";
-  Event event;
-  TaskQueue queue(kQueueName);
-
-  // We're not running a task, so there shouldn't be a current queue.
-  EXPECT_FALSE(queue.IsCurrent());
-  EXPECT_FALSE(TaskQueue::Current());
-
-  queue.PostTask(Bind(&CheckCurrent, &event, &queue));
-  EXPECT_TRUE(event.Wait(1000));
-}
-
-TEST(TaskQueueTest, PostCustomTask) {
-  static const char kQueueName[] = "PostCustomImplementation";
-  TaskQueueForTest queue(kQueueName);
-
-  class CustomTask : public QueuedTask {
-   public:
-    CustomTask() {}
-    bool ran() const { return ran_; }
-
-   private:
-    bool Run() override {
-      ran_ = true;
-      return false;  // Never allow the task to be deleted by the queue.
-    }
-
-    bool ran_ = false;
-  } my_task;
-
-  queue.SendTask(&my_task);
-  EXPECT_TRUE(my_task.ran());
-}
-
-TEST(TaskQueueTest, PostLambda) {
-  TaskQueueForTest queue("PostLambda");
-  bool ran = false;
-  queue.SendTask([&ran]() { ran = true; });
-  EXPECT_TRUE(ran);
-}
-
-TEST(TaskQueueTest, PostDelayedZero) {
-  static const char kQueueName[] = "PostDelayedZero";
-  Event event;
-  TaskQueue queue(kQueueName);
-
-  queue.PostDelayedTask([&event]() { event.Set(); }, 0);
-  EXPECT_TRUE(event.Wait(1000));
-}
-
-TEST(TaskQueueTest, PostFromQueue) {
-  static const char kQueueName[] = "PostFromQueue";
-  Event event;
-  TaskQueue queue(kQueueName);
-
-  queue.PostTask(
-      [&event, &queue]() { queue.PostTask([&event]() { event.Set(); }); });
-  EXPECT_TRUE(event.Wait(1000));
-}
-
-TEST(TaskQueueTest, PostDelayed) {
-  static const char kQueueName[] = "PostDelayed";
-  Event event;
-  TaskQueue queue(kQueueName, TaskQueue::Priority::HIGH);
-
-  uint32_t start = Time();
-  queue.PostDelayedTask(Bind(&CheckCurrent, &event, &queue), 100);
-  EXPECT_TRUE(event.Wait(1000));
-  uint32_t end = Time();
-  // These tests are a little relaxed due to how "powerful" our test bots can
-  // be.  Most recently we've seen windows bots fire the callback after 94-99ms,
-  // which is why we have a little bit of leeway backwards as well.
-  EXPECT_GE(end - start, 90u);
-  EXPECT_NEAR(end - start, 190u, 100u);  // Accept 90-290.
-}
-
 // This task needs to be run manually due to the slowness of some of our bots.
 // TODO(tommi): Can we run this on the perf bots?
 TEST(TaskQueueTest, DISABLED_PostDelayedHighRes) {
@@ -159,295 +77,4 @@
   EXPECT_NEAR(end - start, 3, 3u);
 }
 
-TEST(TaskQueueTest, PostMultipleDelayed) {
-  static const char kQueueName[] = "PostMultipleDelayed";
-  TaskQueue queue(kQueueName);
-
-  std::vector<std::unique_ptr<Event>> events;
-  for (int i = 0; i < 100; ++i) {
-    events.push_back(absl::make_unique<Event>());
-    queue.PostDelayedTask(Bind(&CheckCurrent, events.back().get(), &queue), i);
-  }
-
-  for (const auto& e : events)
-    EXPECT_TRUE(e->Wait(1000));
-}
-
-TEST(TaskQueueTest, PostDelayedAfterDestruct) {
-  static const char kQueueName[] = "PostDelayedAfterDestruct";
-  Event run;
-  Event deleted;
-  {
-    TaskQueue queue(kQueueName);
-    queue.PostDelayedTask(
-        rtc::NewClosure([&run] { run.Set(); }, [&deleted] { deleted.Set(); }),
-        100);
-  }
-  // Task might outlive the TaskQueue, but still should be deleted.
-  EXPECT_TRUE(deleted.Wait(200));
-  EXPECT_FALSE(run.Wait(0));  // and should not run.
-}
-
-TEST(TaskQueueTest, PostAndReply) {
-  static const char kPostQueue[] = "PostQueue";
-  static const char kReplyQueue[] = "ReplyQueue";
-  Event event;
-  TaskQueue post_queue(kPostQueue);
-  TaskQueue reply_queue(kReplyQueue);
-
-  post_queue.PostTaskAndReply(Bind(&CheckCurrent, nullptr, &post_queue),
-                              Bind(&CheckCurrent, &event, &reply_queue),
-                              &reply_queue);
-  EXPECT_TRUE(event.Wait(1000));
-}
-
-TEST(TaskQueueTest, PostAndReuse) {
-  static const char kPostQueue[] = "PostQueue";
-  static const char kReplyQueue[] = "ReplyQueue";
-  Event event;
-  TaskQueue post_queue(kPostQueue);
-  TaskQueue reply_queue(kReplyQueue);
-
-  int call_count = 0;
-
-  class ReusedTask : public QueuedTask {
-   public:
-    ReusedTask(int* counter, TaskQueue* reply_queue, Event* event)
-        : counter_(counter), reply_queue_(reply_queue), event_(event) {
-      EXPECT_EQ(0, *counter_);
-    }
-
-   private:
-    bool Run() override {
-      if (++(*counter_) == 1) {
-        std::unique_ptr<QueuedTask> myself(this);
-        reply_queue_->PostTask(std::move(myself));
-        // At this point, the object is owned by reply_queue_ and it's
-        // theoratically possible that the object has been deleted (e.g. if
-        // posting wasn't possible).  So, don't touch any member variables here.
-
-        // Indicate to the current queue that ownership has been transferred.
-        return false;
-      } else {
-        EXPECT_EQ(2, *counter_);
-        EXPECT_TRUE(reply_queue_->IsCurrent());
-        event_->Set();
-        return true;  // Indicate that the object should be deleted.
-      }
-    }
-
-    int* const counter_;
-    TaskQueue* const reply_queue_;
-    Event* const event_;
-  };
-
-  std::unique_ptr<ReusedTask> task(
-      new ReusedTask(&call_count, &reply_queue, &event));
-
-  post_queue.PostTask(std::move(task));
-  EXPECT_TRUE(event.Wait(1000));
-}
-
-TEST(TaskQueueTest, PostAndReplyLambda) {
-  static const char kPostQueue[] = "PostQueue";
-  static const char kReplyQueue[] = "ReplyQueue";
-  Event event;
-  TaskQueue post_queue(kPostQueue);
-  TaskQueue reply_queue(kReplyQueue);
-
-  bool my_flag = false;
-  post_queue.PostTaskAndReply([&my_flag]() { my_flag = true; },
-                              [&event]() { event.Set(); }, &reply_queue);
-  EXPECT_TRUE(event.Wait(1000));
-  EXPECT_TRUE(my_flag);
-}
-
-TEST(TaskQueueTest, PostCopyableClosure) {
-  struct CopyableClosure {
-    CopyableClosure(int* num_copies, int* num_moves, Event* event)
-        : num_copies(num_copies), num_moves(num_moves), event(event) {}
-    CopyableClosure(const CopyableClosure& other)
-        : num_copies(other.num_copies),
-          num_moves(other.num_moves),
-          event(other.event) {
-      ++*num_copies;
-    }
-    CopyableClosure(CopyableClosure&& other)
-        : num_copies(other.num_copies),
-          num_moves(other.num_moves),
-          event(other.event) {
-      ++*num_moves;
-    }
-    void operator()() { event->Set(); }
-
-    int* num_copies;
-    int* num_moves;
-    Event* event;
-  };
-
-  int num_copies = 0;
-  int num_moves = 0;
-  Event event;
-
-  static const char kPostQueue[] = "PostCopyableClosure";
-  TaskQueue post_queue(kPostQueue);
-  {
-    CopyableClosure closure(&num_copies, &num_moves, &event);
-    post_queue.PostTask(closure);
-    // Destroy closure to check with msan and tsan posted task has own copy.
-  }
-
-  EXPECT_TRUE(event.Wait(1000));
-  EXPECT_EQ(num_copies, 1);
-  EXPECT_EQ(num_moves, 0);
-}
-
-TEST(TaskQueueTest, PostMoveOnlyClosure) {
-  struct SomeState {
-    explicit SomeState(Event* event) : event(event) {}
-    ~SomeState() { event->Set(); }
-    Event* event;
-  };
-  struct MoveOnlyClosure {
-    MoveOnlyClosure(int* num_moves, std::unique_ptr<SomeState> state)
-        : num_moves(num_moves), state(std::move(state)) {}
-    MoveOnlyClosure(const MoveOnlyClosure&) = delete;
-    MoveOnlyClosure(MoveOnlyClosure&& other)
-        : num_moves(other.num_moves), state(std::move(other.state)) {
-      ++*num_moves;
-    }
-    void operator()() { state.reset(); }
-
-    int* num_moves;
-    std::unique_ptr<SomeState> state;
-  };
-
-  int num_moves = 0;
-  Event event;
-  std::unique_ptr<SomeState> state(new SomeState(&event));
-
-  static const char kPostQueue[] = "PostMoveOnlyClosure";
-  TaskQueue post_queue(kPostQueue);
-  post_queue.PostTask(MoveOnlyClosure(&num_moves, std::move(state)));
-
-  EXPECT_TRUE(event.Wait(1000));
-  EXPECT_EQ(num_moves, 1);
-}
-
-TEST(TaskQueueTest, PostMoveOnlyCleanup) {
-  struct SomeState {
-    explicit SomeState(Event* event) : event(event) {}
-    ~SomeState() { event->Set(); }
-    Event* event;
-  };
-  struct MoveOnlyClosure {
-    void operator()() { state.reset(); }
-
-    std::unique_ptr<SomeState> state;
-  };
-
-  Event event_run;
-  Event event_cleanup;
-  std::unique_ptr<SomeState> state_run(new SomeState(&event_run));
-  std::unique_ptr<SomeState> state_cleanup(new SomeState(&event_cleanup));
-
-  static const char kPostQueue[] = "PostMoveOnlyCleanup";
-  TaskQueue post_queue(kPostQueue);
-  post_queue.PostTask(NewClosure(MoveOnlyClosure{std::move(state_run)},
-                                 MoveOnlyClosure{std::move(state_cleanup)}));
-
-  EXPECT_TRUE(event_cleanup.Wait(1000));
-  // Expect run closure to complete before cleanup closure.
-  EXPECT_TRUE(event_run.Wait(0));
-}
-
-// This test covers a particular bug that we had in the libevent implementation
-// where we could hit a deadlock while trying to post a reply task to a queue
-// that was being deleted.  The test isn't guaranteed to hit that case but it's
-// written in a way that makes it likely and by running with --gtest_repeat=1000
-// the bug would occur. Alas, now it should be fixed.
-TEST(TaskQueueTest, PostAndReplyDeadlock) {
-  Event event;
-  TaskQueue post_queue("PostQueue");
-  TaskQueue reply_queue("ReplyQueue");
-
-  post_queue.PostTaskAndReply([&event]() { event.Set(); }, []() {},
-                              &reply_queue);
-  EXPECT_TRUE(event.Wait(1000));
-}
-
-// http://bugs.webrtc.org/9728
-#if defined(WEBRTC_WIN)
-#define MAYBE_DeleteTaskQueueAfterPostAndReply \
-  DISABLED_DeleteTaskQueueAfterPostAndReply
-#else
-#define MAYBE_DeleteTaskQueueAfterPostAndReply DeleteTaskQueueAfterPostAndReply
-#endif
-TEST(TaskQueueTest, MAYBE_DeleteTaskQueueAfterPostAndReply) {
-  Event task_deleted;
-  Event reply_deleted;
-  auto* task_queue = new TaskQueue("Queue");
-
-  task_queue->PostTaskAndReply(
-      /*task=*/rtc::NewClosure(
-          /*closure=*/[] {},
-          /*cleanup=*/[&task_deleted] { task_deleted.Set(); }),
-      /*reply=*/rtc::NewClosure(
-          /*closure=*/[] {},
-          /*cleanup=*/[&reply_deleted] { reply_deleted.Set(); }));
-
-  delete task_queue;
-
-  EXPECT_TRUE(task_deleted.Wait(1000));
-  EXPECT_TRUE(reply_deleted.Wait(1000));
-}
-
-void TestPostTaskAndReply(TaskQueue* work_queue, Event* event) {
-  ASSERT_FALSE(work_queue->IsCurrent());
-  work_queue->PostTaskAndReply(Bind(&CheckCurrent, nullptr, work_queue),
-                               NewClosure([event]() { event->Set(); }));
-}
-
-// Does a PostTaskAndReply from within a task to post and reply to the current
-// queue.  All in all there will be 3 tasks posted and run.
-TEST(TaskQueueTest, PostAndReply2) {
-  static const char kQueueName[] = "PostAndReply2";
-  static const char kWorkQueueName[] = "PostAndReply2_Worker";
-  Event event;
-  TaskQueue queue(kQueueName);
-  TaskQueue work_queue(kWorkQueueName);
-
-  queue.PostTask(Bind(&TestPostTaskAndReply, &work_queue, &event));
-  EXPECT_TRUE(event.Wait(1000));
-}
-
-// Tests posting more messages than a queue can queue up.
-// In situations like that, tasks will get dropped.
-TEST(TaskQueueTest, PostALot) {
-  // To destruct the event after the queue has gone out of scope.
-  Event event;
-
-  int tasks_executed = 0;
-  int tasks_cleaned_up = 0;
-  static const int kTaskCount = 0xffff;
-
-  {
-    static const char kQueueName[] = "PostALot";
-    TaskQueue queue(kQueueName);
-
-    // On linux, the limit of pending bytes in the pipe buffer is 0xffff.
-    // So here we post a total of 0xffff+1 messages, which triggers a failure
-    // case inside of the libevent queue implementation.
-
-    queue.PostTask([&event]() { event.Wait(Event::kForever); });
-    for (int i = 0; i < kTaskCount; ++i)
-      queue.PostTask(NewClosure([&tasks_executed]() { ++tasks_executed; },
-                                [&tasks_cleaned_up]() { ++tasks_cleaned_up; }));
-    event.Set();  // Unblock the first task.
-  }
-
-  EXPECT_GE(tasks_cleaned_up, tasks_executed);
-  EXPECT_EQ(kTaskCount, tasks_cleaned_up);
-}
-
 }  // namespace rtc
diff --git a/rtc_base/task_queue_win.cc b/rtc_base/task_queue_win.cc
index c1e7c46..696eda3 100644
--- a/rtc_base/task_queue_win.cc
+++ b/rtc_base/task_queue_win.cc
@@ -8,7 +8,7 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#include "rtc_base/task_queue.h"
+#include "rtc_base/task_queue_win.h"
 
 // clang-format off
 // clang formating would change include order.
@@ -27,69 +27,51 @@
 #include <queue>
 #include <utility>
 
+#include "absl/memory/memory.h"
+#include "absl/strings/string_view.h"
+#include "api/task_queue/queued_task.h"
+#include "api/task_queue/task_queue_base.h"
 #include "rtc_base/arraysize.h"
 #include "rtc_base/checks.h"
-#include "rtc_base/criticalsection.h"
+#include "rtc_base/critical_section.h"
 #include "rtc_base/event.h"
 #include "rtc_base/logging.h"
 #include "rtc_base/numerics/safe_conversions.h"
 #include "rtc_base/platform_thread.h"
-#include "rtc_base/refcount.h"
-#include "rtc_base/refcountedobject.h"
-#include "rtc_base/timeutils.h"
+#include "rtc_base/time_utils.h"
 
-namespace rtc {
+namespace webrtc {
 namespace {
 #define WM_RUN_TASK WM_USER + 1
 #define WM_QUEUE_DELAYED_TASK WM_USER + 2
 
-using Priority = TaskQueue::Priority;
-
-DWORD g_queue_ptr_tls = 0;
-
-BOOL CALLBACK InitializeTls(PINIT_ONCE init_once, void* param, void** context) {
-  g_queue_ptr_tls = TlsAlloc();
-  return TRUE;
-}
-
-DWORD GetQueuePtrTls() {
-  static INIT_ONCE init_once = INIT_ONCE_STATIC_INIT;
-  ::InitOnceExecuteOnce(&init_once, InitializeTls, nullptr, nullptr);
-  return g_queue_ptr_tls;
-}
-
-struct ThreadStartupData {
-  Event* started;
-  void* thread_context;
-};
-
 void CALLBACK InitializeQueueThread(ULONG_PTR param) {
   MSG msg;
   ::PeekMessage(&msg, nullptr, WM_USER, WM_USER, PM_NOREMOVE);
-  ThreadStartupData* data = reinterpret_cast<ThreadStartupData*>(param);
-  ::TlsSetValue(GetQueuePtrTls(), data->thread_context);
-  data->started->Set();
+  rtc::Event* data = reinterpret_cast<rtc::Event*>(param);
+  data->Set();
 }
 
-ThreadPriority TaskQueuePriorityToThreadPriority(Priority priority) {
+rtc::ThreadPriority TaskQueuePriorityToThreadPriority(
+    TaskQueueFactory::Priority priority) {
   switch (priority) {
-    case Priority::HIGH:
-      return kRealtimePriority;
-    case Priority::LOW:
-      return kLowPriority;
-    case Priority::NORMAL:
-      return kNormalPriority;
+    case TaskQueueFactory::Priority::HIGH:
+      return rtc::kRealtimePriority;
+    case TaskQueueFactory::Priority::LOW:
+      return rtc::kLowPriority;
+    case TaskQueueFactory::Priority::NORMAL:
+      return rtc::kNormalPriority;
     default:
       RTC_NOTREACHED();
       break;
   }
-  return kNormalPriority;
+  return rtc::kNormalPriority;
 }
 
 int64_t GetTick() {
   static const UINT kPeriod = 1;
   bool high_res = (timeBeginPeriod(kPeriod) == TIMERR_NOERROR);
-  int64_t ret = TimeMillis();
+  int64_t ret = rtc::TimeMillis();
   if (high_res)
     timeEndPeriod(kPeriod);
   return ret;
@@ -168,85 +150,56 @@
   RTC_DISALLOW_COPY_AND_ASSIGN(MultimediaTimer);
 };
 
-}  // namespace
-
-class TaskQueue::Impl : public RefCountInterface {
+class TaskQueueWin : public TaskQueueBase {
  public:
-  Impl(const char* queue_name, TaskQueue* queue, Priority priority);
-  ~Impl() override;
+  TaskQueueWin(absl::string_view queue_name, rtc::ThreadPriority priority);
+  ~TaskQueueWin() override = default;
 
-  static TaskQueue::Impl* Current();
-  static TaskQueue* CurrentQueue();
-
-  // Used for DCHECKing the current queue.
-  bool IsCurrent() const;
-
-  template <class Closure,
-            typename std::enable_if<!std::is_convertible<
-                Closure,
-                std::unique_ptr<QueuedTask>>::value>::type* = nullptr>
-  void PostTask(Closure&& closure) {
-    PostTask(NewClosure(std::forward<Closure>(closure)));
-  }
-
-  void PostTask(std::unique_ptr<QueuedTask> task);
-  void PostTaskAndReply(std::unique_ptr<QueuedTask> task,
-                        std::unique_ptr<QueuedTask> reply,
-                        TaskQueue::Impl* reply_queue);
-
-  void PostDelayedTask(std::unique_ptr<QueuedTask> task, uint32_t milliseconds);
+  void Delete() override;
+  void PostTask(std::unique_ptr<QueuedTask> task) override;
+  void PostDelayedTask(std::unique_ptr<QueuedTask> task,
+                       uint32_t milliseconds) override;
 
   void RunPendingTasks();
 
  private:
   static void ThreadMain(void* context);
 
-  class WorkerThread : public PlatformThread {
+  class WorkerThread : public rtc::PlatformThread {
    public:
-    WorkerThread(ThreadRunFunction func,
+    WorkerThread(rtc::ThreadRunFunction func,
                  void* obj,
-                 const char* thread_name,
-                 ThreadPriority priority)
+                 absl::string_view thread_name,
+                 rtc::ThreadPriority priority)
         : PlatformThread(func, obj, thread_name, priority) {}
 
     bool QueueAPC(PAPCFUNC apc_function, ULONG_PTR data) {
-      return PlatformThread::QueueAPC(apc_function, data);
+      return rtc::PlatformThread::QueueAPC(apc_function, data);
     }
   };
 
-  class ThreadState {
-   public:
-    explicit ThreadState(HANDLE in_queue) : in_queue_(in_queue) {}
-    ~ThreadState() {}
+  void RunThreadMain();
+  bool ProcessQueuedMessages();
+  void RunDueTasks();
+  void ScheduleNextTimer();
+  void CancelTimers();
 
-    void RunThreadMain();
-
-   private:
-    bool ProcessQueuedMessages();
-    void RunDueTasks();
-    void ScheduleNextTimer();
-    void CancelTimers();
-
-    // Since priority_queue<> by defult orders items in terms of
-    // largest->smallest, using std::less<>, and we want smallest->largest,
-    // we would like to use std::greater<> here. Alas it's only available in
-    // C++14 and later, so we roll our own compare template that that relies on
-    // operator<().
-    template <typename T>
-    struct greater {
-      bool operator()(const T& l, const T& r) { return l > r; }
-    };
-
-    MultimediaTimer timer_;
-    std::priority_queue<DelayedTaskInfo,
-                        std::vector<DelayedTaskInfo>,
-                        greater<DelayedTaskInfo>>
-        timer_tasks_;
-    UINT_PTR timer_id_ = 0;
-    HANDLE in_queue_;
+  // Since priority_queue<> by defult orders items in terms of
+  // largest->smallest, using std::less<>, and we want smallest->largest,
+  // we would like to use std::greater<> here. Alas it's only available in
+  // C++14 and later, so we roll our own compare template that that relies on
+  // operator<().
+  template <typename T>
+  struct greater {
+    bool operator()(const T& l, const T& r) { return l > r; }
   };
 
-  TaskQueue* const queue_;
+  MultimediaTimer timer_;
+  std::priority_queue<DelayedTaskInfo,
+                      std::vector<DelayedTaskInfo>,
+                      greater<DelayedTaskInfo>>
+      timer_tasks_;
+  UINT_PTR timer_id_ = 0;
   WorkerThread thread_;
   rtc::CriticalSection pending_lock_;
   std::queue<std::unique_ptr<QueuedTask>> pending_
@@ -254,26 +207,19 @@
   HANDLE in_queue_;
 };
 
-TaskQueue::Impl::Impl(const char* queue_name,
-                      TaskQueue* queue,
-                      Priority priority)
-    : queue_(queue),
-      thread_(&TaskQueue::Impl::ThreadMain,
-              this,
-              queue_name,
-              TaskQueuePriorityToThreadPriority(priority)),
+TaskQueueWin::TaskQueueWin(absl::string_view queue_name,
+                           rtc::ThreadPriority priority)
+    : thread_(&TaskQueueWin::ThreadMain, this, queue_name, priority),
       in_queue_(::CreateEvent(nullptr, true, false, nullptr)) {
-  RTC_DCHECK(queue_name);
   RTC_DCHECK(in_queue_);
   thread_.Start();
-  Event event(false, false);
-  ThreadStartupData startup = {&event, this};
+  rtc::Event event(false, false);
   RTC_CHECK(thread_.QueueAPC(&InitializeQueueThread,
-                             reinterpret_cast<ULONG_PTR>(&startup)));
-  event.Wait(Event::kForever);
+                             reinterpret_cast<ULONG_PTR>(&event)));
+  event.Wait(rtc::Event::kForever);
 }
 
-TaskQueue::Impl::~Impl() {
+void TaskQueueWin::Delete() {
   RTC_DCHECK(!IsCurrent());
   while (!::PostThreadMessage(thread_.GetThreadRef(), WM_QUIT, 0, 0)) {
     RTC_CHECK_EQ(ERROR_NOT_ENOUGH_QUOTA, ::GetLastError());
@@ -281,31 +227,17 @@
   }
   thread_.Stop();
   ::CloseHandle(in_queue_);
+  delete this;
 }
 
-// static
-TaskQueue::Impl* TaskQueue::Impl::Current() {
-  return static_cast<TaskQueue::Impl*>(::TlsGetValue(GetQueuePtrTls()));
-}
-
-// static
-TaskQueue* TaskQueue::Impl::CurrentQueue() {
-  TaskQueue::Impl* current = Current();
-  return current ? current->queue_ : nullptr;
-}
-
-bool TaskQueue::Impl::IsCurrent() const {
-  return IsThreadRefEqual(thread_.GetThreadRef(), CurrentThreadRef());
-}
-
-void TaskQueue::Impl::PostTask(std::unique_ptr<QueuedTask> task) {
+void TaskQueueWin::PostTask(std::unique_ptr<QueuedTask> task) {
   rtc::CritScope lock(&pending_lock_);
   pending_.push(std::move(task));
   ::SetEvent(in_queue_);
 }
 
-void TaskQueue::Impl::PostDelayedTask(std::unique_ptr<QueuedTask> task,
-                                      uint32_t milliseconds) {
+void TaskQueueWin::PostDelayedTask(std::unique_ptr<QueuedTask> task,
+                                   uint32_t milliseconds) {
   if (!milliseconds) {
     PostTask(std::move(task));
     return;
@@ -322,25 +254,7 @@
   }
 }
 
-void TaskQueue::Impl::PostTaskAndReply(std::unique_ptr<QueuedTask> task,
-                                       std::unique_ptr<QueuedTask> reply,
-                                       TaskQueue::Impl* reply_queue) {
-  QueuedTask* task_ptr = task.release();
-  QueuedTask* reply_task_ptr = reply.release();
-  DWORD reply_thread_id = reply_queue->thread_.GetThreadRef();
-  PostTask([task_ptr, reply_task_ptr, reply_thread_id]() {
-    if (task_ptr->Run())
-      delete task_ptr;
-    // If the thread's message queue is full, we can't queue the task and will
-    // have to drop it (i.e. delete).
-    if (!::PostThreadMessage(reply_thread_id, WM_RUN_TASK, 0,
-                             reinterpret_cast<LPARAM>(reply_task_ptr))) {
-      delete reply_task_ptr;
-    }
-  });
-}
-
-void TaskQueue::Impl::RunPendingTasks() {
+void TaskQueueWin::RunPendingTasks() {
   while (true) {
     std::unique_ptr<QueuedTask> task;
     {
@@ -357,12 +271,12 @@
 }
 
 // static
-void TaskQueue::Impl::ThreadMain(void* context) {
-  ThreadState state(static_cast<TaskQueue::Impl*>(context)->in_queue_);
-  state.RunThreadMain();
+void TaskQueueWin::ThreadMain(void* context) {
+  static_cast<TaskQueueWin*>(context)->RunThreadMain();
 }
 
-void TaskQueue::Impl::ThreadState::RunThreadMain() {
+void TaskQueueWin::RunThreadMain() {
+  CurrentTaskQueueSetter set_current(this);
   HANDLE handles[2] = {*timer_.event_for_wait(), in_queue_};
   while (true) {
     // Make sure we do an alertable wait as that's required to allow APCs to run
@@ -388,12 +302,12 @@
 
     if (result == (WAIT_OBJECT_0 + 1)) {
       ::ResetEvent(in_queue_);
-      TaskQueue::Impl::Current()->RunPendingTasks();
+      RunPendingTasks();
     }
   }
 }
 
-bool TaskQueue::Impl::ThreadState::ProcessQueuedMessages() {
+bool TaskQueueWin::ProcessQueuedMessages() {
   MSG msg = {};
   // To protect against overly busy message queues, we limit the time
   // we process tasks to a few milliseconds. If we don't do that, there's
@@ -447,7 +361,7 @@
   return msg.message != WM_QUIT;
 }
 
-void TaskQueue::Impl::ThreadState::RunDueTasks() {
+void TaskQueueWin::RunDueTasks() {
   RTC_DCHECK(!timer_tasks_.empty());
   auto now = GetTick();
   do {
@@ -459,7 +373,7 @@
   } while (!timer_tasks_.empty());
 }
 
-void TaskQueue::Impl::ThreadState::ScheduleNextTimer() {
+void TaskQueueWin::ScheduleNextTimer() {
   RTC_DCHECK_EQ(timer_id_, 0);
   if (timer_tasks_.empty())
     return;
@@ -471,7 +385,7 @@
     timer_id_ = ::SetTimer(nullptr, 0, milliseconds, nullptr);
 }
 
-void TaskQueue::Impl::ThreadState::CancelTimers() {
+void TaskQueueWin::CancelTimers() {
   timer_.Cancel();
   if (timer_id_) {
     ::KillTimer(nullptr, timer_id_);
@@ -479,43 +393,20 @@
   }
 }
 
-// Boilerplate for the PIMPL pattern.
-TaskQueue::TaskQueue(const char* queue_name, Priority priority)
-    : impl_(new RefCountedObject<TaskQueue::Impl>(queue_name, this, priority)) {
+class TaskQueueWinFactory : public TaskQueueFactory {
+ public:
+  std::unique_ptr<TaskQueueBase, TaskQueueDeleter> CreateTaskQueue(
+      absl::string_view name,
+      Priority priority) const override {
+    return std::unique_ptr<TaskQueueBase, TaskQueueDeleter>(
+        new TaskQueueWin(name, TaskQueuePriorityToThreadPriority(priority)));
+  }
+};
+
+}  // namespace
+
+std::unique_ptr<TaskQueueFactory> CreateTaskQueueWinFactory() {
+  return absl::make_unique<TaskQueueWinFactory>();
 }
 
-TaskQueue::~TaskQueue() {}
-
-// static
-TaskQueue* TaskQueue::Current() {
-  return TaskQueue::Impl::CurrentQueue();
-}
-
-// Used for DCHECKing the current queue.
-bool TaskQueue::IsCurrent() const {
-  return impl_->IsCurrent();
-}
-
-void TaskQueue::PostTask(std::unique_ptr<QueuedTask> task) {
-  return TaskQueue::impl_->PostTask(std::move(task));
-}
-
-void TaskQueue::PostTaskAndReply(std::unique_ptr<QueuedTask> task,
-                                 std::unique_ptr<QueuedTask> reply,
-                                 TaskQueue* reply_queue) {
-  return TaskQueue::impl_->PostTaskAndReply(std::move(task), std::move(reply),
-                                            reply_queue->impl_.get());
-}
-
-void TaskQueue::PostTaskAndReply(std::unique_ptr<QueuedTask> task,
-                                 std::unique_ptr<QueuedTask> reply) {
-  return TaskQueue::impl_->PostTaskAndReply(std::move(task), std::move(reply),
-                                            impl_.get());
-}
-
-void TaskQueue::PostDelayedTask(std::unique_ptr<QueuedTask> task,
-                                uint32_t milliseconds) {
-  return TaskQueue::impl_->PostDelayedTask(std::move(task), milliseconds);
-}
-
-}  // namespace rtc
+}  // namespace webrtc
diff --git a/rtc_base/task_queue_win.h b/rtc_base/task_queue_win.h
new file mode 100644
index 0000000..972611a
--- /dev/null
+++ b/rtc_base/task_queue_win.h
@@ -0,0 +1,24 @@
+/*
+ *  Copyright 2019 The WebRTC Project Authors. All rights reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef RTC_BASE_TASK_QUEUE_WIN_H_
+#define RTC_BASE_TASK_QUEUE_WIN_H_
+
+#include <memory>
+
+#include "api/task_queue/task_queue_factory.h"
+
+namespace webrtc {
+
+std::unique_ptr<TaskQueueFactory> CreateTaskQueueWinFactory();
+
+}
+
+#endif  // RTC_BASE_TASK_QUEUE_WIN_H_
diff --git a/rtc_base/task_utils/BUILD.gn b/rtc_base/task_utils/BUILD.gn
new file mode 100644
index 0000000..0ec6739
--- /dev/null
+++ b/rtc_base/task_utils/BUILD.gn
@@ -0,0 +1,64 @@
+# Copyright (c) 2019 The WebRTC project authors. All Rights Reserved.
+#
+# Use of this source code is governed by a BSD-style license
+# that can be found in the LICENSE file in the root of the source
+# tree. An additional intellectual property rights grant can be found
+# in the file PATENTS.  All contributing project authors may
+# be found in the AUTHORS file in the root of the source tree.
+
+import("../../webrtc.gni")
+
+rtc_source_set("repeating_task") {
+  sources = [
+    "repeating_task.cc",
+    "repeating_task.h",
+  ]
+  deps = [
+    "..:logging",
+    "..:rtc_task_queue",
+    "..:sequenced_task_checker",
+    "..:thread_checker",
+    "..:timeutils",
+    "../../api/units:time_delta",
+    "../../api/units:timestamp",
+    "//third_party/abseil-cpp/absl/memory",
+  ]
+}
+
+rtc_source_set("to_queued_task") {
+  sources = [
+    "to_queued_task.h",
+  ]
+  deps = [
+    "../../api/task_queue",
+    "//third_party/abseil-cpp/absl/memory",
+  ]
+}
+
+if (rtc_include_tests) {
+  rtc_source_set("repeating_task_unittests") {
+    testonly = true
+    sources = [
+      "repeating_task_unittest.cc",
+    ]
+    deps = [
+      ":repeating_task",
+      "..:rtc_base_approved",
+      "../../test:test_support",
+      "//third_party/abseil-cpp/absl/memory",
+    ]
+  }
+
+  rtc_source_set("to_queued_task_unittests") {
+    testonly = true
+    sources = [
+      "to_queued_task_unittest.cc",
+    ]
+    deps = [
+      ":to_queued_task",
+      "../../api/task_queue",
+      "../../test:test_support",
+      "//third_party/abseil-cpp/absl/memory",
+    ]
+  }
+}
diff --git a/rtc_base/task_utils/repeating_task.cc b/rtc_base/task_utils/repeating_task.cc
new file mode 100644
index 0000000..5f366cb
--- /dev/null
+++ b/rtc_base/task_utils/repeating_task.cc
@@ -0,0 +1,117 @@
+/*
+ *  Copyright 2019 The WebRTC Project Authors. All rights reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "rtc_base/task_utils/repeating_task.h"
+#include "rtc_base/logging.h"
+#include "rtc_base/time_utils.h"
+
+namespace webrtc {
+namespace webrtc_repeating_task_impl {
+RepeatingTaskBase::RepeatingTaskBase(rtc::TaskQueue* task_queue,
+                                     TimeDelta first_delay)
+    : task_queue_(task_queue),
+      next_run_time_(Timestamp::us(rtc::TimeMicros()) + first_delay) {}
+
+RepeatingTaskBase::~RepeatingTaskBase() = default;
+
+bool RepeatingTaskBase::Run() {
+  RTC_DCHECK_RUN_ON(task_queue_);
+  // Return true to tell the TaskQueue to destruct this object.
+  if (next_run_time_.IsPlusInfinity())
+    return true;
+
+  TimeDelta delay = RunClosure();
+  RTC_DCHECK(delay.IsFinite());
+
+  // The closure might have stopped this task, in which case we return true to
+  // destruct this object.
+  if (next_run_time_.IsPlusInfinity())
+    return true;
+
+  TimeDelta lost_time = Timestamp::us(rtc::TimeMicros()) - next_run_time_;
+  next_run_time_ += delay;
+  delay -= lost_time;
+  delay = std::max(delay, TimeDelta::Zero());
+
+  task_queue_->PostDelayedTask(absl::WrapUnique(this), delay.ms());
+
+  // Return false to tell the TaskQueue to not destruct this object since we
+  // have taken ownership with absl::WrapUnique.
+  return false;
+}
+
+void RepeatingTaskBase::Stop() {
+  RTC_DCHECK(next_run_time_.IsFinite());
+  next_run_time_ = Timestamp::PlusInfinity();
+}
+
+void RepeatingTaskBase::PostStop() {
+  if (task_queue_->IsCurrent()) {
+    RTC_DLOG(LS_INFO) << "Using PostStop() from the task queue running the "
+                         "repeated task. Consider calling Stop() instead.";
+  }
+  task_queue_->PostTask([this] {
+    RTC_DCHECK_RUN_ON(task_queue_);
+    Stop();
+  });
+}
+
+}  // namespace webrtc_repeating_task_impl
+RepeatingTaskHandle::RepeatingTaskHandle() {
+  sequence_checker_.Detach();
+}
+RepeatingTaskHandle::~RepeatingTaskHandle() {
+  sequence_checker_.Detach();
+}
+
+RepeatingTaskHandle::RepeatingTaskHandle(RepeatingTaskHandle&& other)
+    : repeating_task_(other.repeating_task_) {
+  RTC_DCHECK_RUN_ON(&sequence_checker_);
+  other.repeating_task_ = nullptr;
+}
+
+RepeatingTaskHandle& RepeatingTaskHandle::operator=(
+    RepeatingTaskHandle&& other) {
+  RTC_DCHECK_RUN_ON(&other.sequence_checker_);
+  {
+    RTC_DCHECK_RUN_ON(&sequence_checker_);
+    repeating_task_ = other.repeating_task_;
+  }
+  other.repeating_task_ = nullptr;
+  return *this;
+}
+
+RepeatingTaskHandle::RepeatingTaskHandle(
+    webrtc_repeating_task_impl::RepeatingTaskBase* repeating_task)
+    : repeating_task_(repeating_task) {}
+
+void RepeatingTaskHandle::Stop() {
+  RTC_DCHECK_RUN_ON(&sequence_checker_);
+  if (repeating_task_) {
+    RTC_DCHECK_RUN_ON(repeating_task_->task_queue_);
+    repeating_task_->Stop();
+    repeating_task_ = nullptr;
+  }
+}
+
+void RepeatingTaskHandle::PostStop() {
+  RTC_DCHECK_RUN_ON(&sequence_checker_);
+  if (repeating_task_) {
+    repeating_task_->PostStop();
+    repeating_task_ = nullptr;
+  }
+}
+
+bool RepeatingTaskHandle::Running() const {
+  RTC_DCHECK_RUN_ON(&sequence_checker_);
+  return repeating_task_ != nullptr;
+}
+
+}  // namespace webrtc
diff --git a/rtc_base/task_utils/repeating_task.h b/rtc_base/task_utils/repeating_task.h
new file mode 100644
index 0000000..c4e760a
--- /dev/null
+++ b/rtc_base/task_utils/repeating_task.h
@@ -0,0 +1,153 @@
+/*
+ *  Copyright 2019 The WebRTC Project Authors. All rights reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef RTC_BASE_TASK_UTILS_REPEATING_TASK_H_
+#define RTC_BASE_TASK_UTILS_REPEATING_TASK_H_
+
+#include <type_traits>
+#include <utility>
+
+#include "absl/memory/memory.h"
+#include "api/units/time_delta.h"
+#include "api/units/timestamp.h"
+#include "rtc_base/sequenced_task_checker.h"
+#include "rtc_base/task_queue.h"
+#include "rtc_base/thread_checker.h"
+
+namespace webrtc {
+
+class RepeatingTaskHandle;
+
+namespace webrtc_repeating_task_impl {
+class RepeatingTaskBase : public rtc::QueuedTask {
+ public:
+  RepeatingTaskBase(rtc::TaskQueue* task_queue, TimeDelta first_delay);
+  ~RepeatingTaskBase() override;
+  virtual TimeDelta RunClosure() = 0;
+
+ private:
+  friend class ::webrtc::RepeatingTaskHandle;
+
+  bool Run() final;
+  void Stop() RTC_RUN_ON(task_queue_);
+  void PostStop();
+
+  rtc::TaskQueue* const task_queue_;
+  // This is always finite, except for the special case where it's PlusInfinity
+  // to signal that the task should stop.
+  Timestamp next_run_time_ RTC_GUARDED_BY(task_queue_);
+};
+
+// The template closure pattern is based on rtc::ClosureTask.
+template <class Closure>
+class RepeatingTaskImpl final : public RepeatingTaskBase {
+ public:
+  RepeatingTaskImpl(rtc::TaskQueue* task_queue,
+                    TimeDelta first_delay,
+                    Closure&& closure)
+      : RepeatingTaskBase(task_queue, first_delay),
+        closure_(std::forward<Closure>(closure)) {
+    static_assert(
+        std::is_same<TimeDelta,
+                     typename std::result_of<decltype (&Closure::operator())(
+                         Closure)>::type>::value,
+        "");
+  }
+
+  TimeDelta RunClosure() override { return closure_(); }
+
+ private:
+  typename std::remove_const<
+      typename std::remove_reference<Closure>::type>::type closure_;
+};
+}  // namespace webrtc_repeating_task_impl
+
+// Allows starting tasks that repeat themselves on a TaskQueue indefinately
+// until they are stopped or the TaskQueue is destroyed. It allows starting and
+// stopping multiple times, but you must stop one task before starting another
+// and it can only be stopped when in the running state. The public interface is
+// not thread safe.
+class RepeatingTaskHandle {
+ public:
+  RepeatingTaskHandle();
+  ~RepeatingTaskHandle();
+  RepeatingTaskHandle(RepeatingTaskHandle&& other);
+  RepeatingTaskHandle& operator=(RepeatingTaskHandle&& other);
+  RepeatingTaskHandle(const RepeatingTaskHandle&) = delete;
+  RepeatingTaskHandle& operator=(const RepeatingTaskHandle&) = delete;
+
+  // Start can be used to start a task that will be reposted with a delay
+  // determined by the return value of the provided closure. The actual task is
+  // owned by the TaskQueue and will live until it has been stopped or the
+  // TaskQueue is destroyed. Note that this means that trying to stop the
+  // repeating task after the TaskQueue is destroyed is an error. However, it's
+  // perfectly fine to destroy the handle while the task is running, since the
+  // repeated task is owned by the TaskQueue.
+  template <class Closure>
+  static RepeatingTaskHandle Start(rtc::TaskQueue* task_queue,
+                                   Closure&& closure) {
+    auto repeating_task = absl::make_unique<
+        webrtc_repeating_task_impl::RepeatingTaskImpl<Closure>>(
+        task_queue, TimeDelta::Zero(), std::forward<Closure>(closure));
+    auto* repeating_task_ptr = repeating_task.get();
+    task_queue->PostTask(std::move(repeating_task));
+    return RepeatingTaskHandle(repeating_task_ptr);
+  }
+  template <class Closure>
+  static RepeatingTaskHandle Start(Closure&& closure) {
+    return Start(rtc::TaskQueue::Current(), std::forward<Closure>(closure));
+  }
+
+  // DelayedStart is equivalent to Start except that the first invocation of the
+  // closure will be delayed by the given amount.
+  template <class Closure>
+  static RepeatingTaskHandle DelayedStart(rtc::TaskQueue* task_queue,
+                                          TimeDelta first_delay,
+                                          Closure&& closure) {
+    auto repeating_task = absl::make_unique<
+        webrtc_repeating_task_impl::RepeatingTaskImpl<Closure>>(
+        task_queue, first_delay, std::forward<Closure>(closure));
+    auto* repeating_task_ptr = repeating_task.get();
+    task_queue->PostDelayedTask(std::move(repeating_task), first_delay.ms());
+    return RepeatingTaskHandle(repeating_task_ptr);
+  }
+  template <class Closure>
+  static RepeatingTaskHandle DelayedStart(TimeDelta first_delay,
+                                          Closure&& closure) {
+    return DelayedStart(rtc::TaskQueue::Current(), first_delay,
+                        std::forward<Closure>(closure));
+  }
+
+  // Stops future invocations of the repeating task closure. Can only be called
+  // from the TaskQueue where the task is running. The closure is guaranteed to
+  // not be running after Stop() returns unless Stop() is called from the
+  // closure itself.
+  void Stop();
+
+  // Stops future invocations of the repeating task closure. The closure might
+  // still be running when PostStop() returns, but there will be no future
+  // invocation.
+  void PostStop();
+
+  // Returns true if Start() or DelayedStart() was called most recently. Returns
+  // false initially and if Stop() or PostStop() was called most recently.
+  bool Running() const;
+
+ private:
+  explicit RepeatingTaskHandle(
+      webrtc_repeating_task_impl::RepeatingTaskBase* repeating_task);
+  rtc::SequencedTaskChecker sequence_checker_;
+  // Owned by the task queue.
+  webrtc_repeating_task_impl::RepeatingTaskBase* repeating_task_
+      RTC_GUARDED_BY(sequence_checker_) = nullptr;
+};
+
+}  // namespace webrtc
+#endif  // RTC_BASE_TASK_UTILS_REPEATING_TASK_H_
diff --git a/rtc_base/task_utils/repeating_task_unittest.cc b/rtc_base/task_utils/repeating_task_unittest.cc
new file mode 100644
index 0000000..52683e3
--- /dev/null
+++ b/rtc_base/task_utils/repeating_task_unittest.cc
@@ -0,0 +1,224 @@
+/*
+ *  Copyright 2019 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include <atomic>
+#include <chrono>  // Not allowed in production per Chromium style guide.
+#include <memory>
+#include <thread>  // Not allowed in production per Chromium style guide.
+
+#include "absl/memory/memory.h"
+#include "rtc_base/event.h"
+#include "rtc_base/task_utils/repeating_task.h"
+#include "test/gmock.h"
+#include "test/gtest.h"
+
+// NOTE: Since these tests rely on real time behavior, they will be flaky
+// if run on heavily loaded systems.
+namespace webrtc {
+namespace {
+using ::testing::AtLeast;
+using ::testing::Invoke;
+using ::testing::MockFunction;
+using ::testing::NiceMock;
+using ::testing::Return;
+
+constexpr TimeDelta kTimeout = TimeDelta::Millis<1000>();
+
+void Sleep(TimeDelta time_delta) {
+  // Note that Chromium style guide prohibits use of <thread> and <chrono> in
+  // production code, used here since webrtc::SleepMs may return early.
+  std::this_thread::sleep_for(std::chrono::microseconds(time_delta.us()));
+}
+
+class MockClosure {
+ public:
+  MOCK_METHOD0(Call, TimeDelta());
+  MOCK_METHOD0(Delete, void());
+};
+
+class MoveOnlyClosure {
+ public:
+  explicit MoveOnlyClosure(MockClosure* mock) : mock_(mock) {}
+  MoveOnlyClosure(const MoveOnlyClosure&) = delete;
+  MoveOnlyClosure(MoveOnlyClosure&& other) : mock_(other.mock_) {
+    other.mock_ = nullptr;
+  }
+  ~MoveOnlyClosure() {
+    if (mock_)
+      mock_->Delete();
+  }
+  TimeDelta operator()() { return mock_->Call(); }
+
+ private:
+  MockClosure* mock_;
+};
+}  // namespace
+
+TEST(RepeatingTaskTest, TaskIsStoppedOnStop) {
+  const TimeDelta kShortInterval = TimeDelta::ms(5);
+  const TimeDelta kLongInterval = TimeDelta::ms(20);
+  const int kShortIntervalCount = 4;
+  const int kMargin = 1;
+
+  rtc::TaskQueue task_queue("TestQueue");
+  std::atomic_int counter(0);
+  auto handle = RepeatingTaskHandle::Start(&task_queue, [&] {
+    if (++counter >= kShortIntervalCount)
+      return kLongInterval;
+    return kShortInterval;
+  });
+  // Sleep long enough to go through the initial phase.
+  Sleep(kShortInterval * (kShortIntervalCount + kMargin));
+  EXPECT_EQ(counter.load(), kShortIntervalCount);
+
+  handle.PostStop();
+  // Sleep long enough that the task would run at least once more if not
+  // stopped.
+  Sleep(kLongInterval * 2);
+  EXPECT_EQ(counter.load(), kShortIntervalCount);
+}
+
+TEST(RepeatingTaskTest, CompensatesForLongRunTime) {
+  const int kTargetCount = 20;
+  const int kTargetCountMargin = 2;
+  const TimeDelta kRepeatInterval = TimeDelta::ms(2);
+  // Sleeping inside the task for longer than the repeat interval once, should
+  // be compensated for by repeating the task faster to catch up.
+  const TimeDelta kSleepDuration = TimeDelta::ms(20);
+  const int kSleepAtCount = 3;
+
+  std::atomic_int counter(0);
+  rtc::TaskQueue task_queue("TestQueue");
+  RepeatingTaskHandle::Start(&task_queue, [&] {
+    if (++counter == kSleepAtCount)
+      Sleep(kSleepDuration);
+    return kRepeatInterval;
+  });
+  Sleep(kRepeatInterval * kTargetCount);
+  // Execution time should not have affected the run count,
+  // but we allow some margin to reduce flakiness.
+  EXPECT_GE(counter.load(), kTargetCount - kTargetCountMargin);
+}
+
+TEST(RepeatingTaskTest, CompensatesForShortRunTime) {
+  std::atomic_int counter(0);
+  rtc::TaskQueue task_queue("TestQueue");
+  RepeatingTaskHandle::Start(&task_queue, [&] {
+    ++counter;
+    // Sleeping for the 10 ms should be compensated.
+    Sleep(TimeDelta::ms(10));
+    return TimeDelta::ms(30);
+  });
+  Sleep(TimeDelta::ms(40));
+
+  // We expect that the task have been called twice, once directly at Start and
+  // once after 30 ms has passed.
+  EXPECT_EQ(counter.load(), 2);
+}
+
+TEST(RepeatingTaskTest, CancelDelayedTaskBeforeItRuns) {
+  rtc::Event done;
+  MockClosure mock;
+  EXPECT_CALL(mock, Call).Times(0);
+  EXPECT_CALL(mock, Delete).WillOnce(Invoke([&done] { done.Set(); }));
+  rtc::TaskQueue task_queue("queue");
+  auto handle = RepeatingTaskHandle::DelayedStart(
+      &task_queue, TimeDelta::ms(100), MoveOnlyClosure(&mock));
+  handle.PostStop();
+  EXPECT_TRUE(done.Wait(kTimeout.ms()));
+}
+
+TEST(RepeatingTaskTest, CancelTaskAfterItRuns) {
+  rtc::Event done;
+  MockClosure mock;
+  EXPECT_CALL(mock, Call).WillOnce(Return(TimeDelta::ms(100)));
+  EXPECT_CALL(mock, Delete).WillOnce(Invoke([&done] { done.Set(); }));
+  rtc::TaskQueue task_queue("queue");
+  auto handle = RepeatingTaskHandle::Start(&task_queue, MoveOnlyClosure(&mock));
+  handle.PostStop();
+  EXPECT_TRUE(done.Wait(kTimeout.ms()));
+}
+
+TEST(RepeatingTaskTest, TaskCanStopItself) {
+  std::atomic_int counter(0);
+  rtc::TaskQueue task_queue("TestQueue");
+  RepeatingTaskHandle handle;
+  task_queue.PostTask([&] {
+    handle = RepeatingTaskHandle::Start(&task_queue, [&] {
+      ++counter;
+      handle.Stop();
+      return TimeDelta::ms(2);
+    });
+  });
+  Sleep(TimeDelta::ms(10));
+  EXPECT_EQ(counter.load(), 1);
+}
+
+TEST(RepeatingTaskTest, ZeroReturnValueRepostsTheTask) {
+  NiceMock<MockClosure> closure;
+  rtc::Event done;
+  EXPECT_CALL(closure, Call())
+      .WillOnce(Return(TimeDelta::Zero()))
+      .WillOnce(Invoke([&done] {
+        done.Set();
+        return kTimeout;
+      }));
+  rtc::TaskQueue task_queue("queue");
+  RepeatingTaskHandle::Start(&task_queue, MoveOnlyClosure(&closure));
+  EXPECT_TRUE(done.Wait(kTimeout.ms()));
+}
+
+TEST(RepeatingTaskTest, StartPeriodicTask) {
+  MockFunction<TimeDelta()> closure;
+  rtc::Event done;
+  EXPECT_CALL(closure, Call())
+      .WillOnce(Return(TimeDelta::ms(20)))
+      .WillOnce(Return(TimeDelta::ms(20)))
+      .WillOnce(Invoke([&done] {
+        done.Set();
+        return kTimeout;
+      }));
+  rtc::TaskQueue task_queue("queue");
+  RepeatingTaskHandle::Start(&task_queue, closure.AsStdFunction());
+  EXPECT_TRUE(done.Wait(kTimeout.ms()));
+}
+
+TEST(RepeatingTaskTest, Example) {
+  class ObjectOnTaskQueue {
+   public:
+    void DoPeriodicTask() {}
+    TimeDelta TimeUntilNextRun() { return TimeDelta::ms(100); }
+    void StartPeriodicTask(RepeatingTaskHandle* handle,
+                           rtc::TaskQueue* task_queue) {
+      *handle = RepeatingTaskHandle::Start(task_queue, [this] {
+        DoPeriodicTask();
+        return TimeUntilNextRun();
+      });
+    }
+  };
+  rtc::TaskQueue task_queue("queue");
+  auto object = absl::make_unique<ObjectOnTaskQueue>();
+  // Create and start the periodic task.
+  RepeatingTaskHandle handle;
+  object->StartPeriodicTask(&handle, &task_queue);
+  // Restart the task
+  handle.PostStop();
+  object->StartPeriodicTask(&handle, &task_queue);
+  handle.PostStop();
+  struct Destructor {
+    void operator()() { object.reset(); }
+    std::unique_ptr<ObjectOnTaskQueue> object;
+  };
+  task_queue.PostTask(Destructor{std::move(object)});
+  // Do not wait for the destructor closure in order to create a race between
+  // task queue destruction and running the desctructor closure.
+}
+
+}  // namespace webrtc
diff --git a/rtc_base/task_utils/to_queued_task.h b/rtc_base/task_utils/to_queued_task.h
new file mode 100644
index 0000000..5088af9
--- /dev/null
+++ b/rtc_base/task_utils/to_queued_task.h
@@ -0,0 +1,73 @@
+/*
+ *  Copyright 2019 The WebRTC Project Authors. All rights reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef RTC_BASE_TASK_UTILS_TO_QUEUED_TASK_H_
+#define RTC_BASE_TASK_UTILS_TO_QUEUED_TASK_H_
+
+#include <memory>
+#include <type_traits>
+#include <utility>
+
+#include "absl/memory/memory.h"
+#include "api/task_queue/queued_task.h"
+
+namespace webrtc {
+namespace webrtc_new_closure_impl {
+// Simple implementation of QueuedTask for use with rtc::Bind and lambdas.
+template <typename Closure>
+class ClosureTask : public QueuedTask {
+ public:
+  explicit ClosureTask(Closure&& closure)
+      : closure_(std::forward<Closure>(closure)) {}
+
+ private:
+  bool Run() override {
+    closure_();
+    return true;
+  }
+
+  typename std::decay<Closure>::type closure_;
+};
+
+// Extends ClosureTask to also allow specifying cleanup code.
+// This is useful when using lambdas if guaranteeing cleanup, even if a task
+// was dropped (queue is too full), is required.
+template <typename Closure, typename Cleanup>
+class ClosureTaskWithCleanup : public ClosureTask<Closure> {
+ public:
+  ClosureTaskWithCleanup(Closure&& closure, Cleanup&& cleanup)
+      : ClosureTask<Closure>(std::forward<Closure>(closure)),
+        cleanup_(std::forward<Cleanup>(cleanup)) {}
+  ~ClosureTaskWithCleanup() override { cleanup_(); }
+
+ private:
+  typename std::decay<Cleanup>::type cleanup_;
+};
+}  // namespace webrtc_new_closure_impl
+
+// Convenience function to construct closures that can be passed directly
+// to methods that support std::unique_ptr<QueuedTask> but not template
+// based parameters.
+template <typename Closure>
+std::unique_ptr<QueuedTask> ToQueuedTask(Closure&& closure) {
+  return absl::make_unique<webrtc_new_closure_impl::ClosureTask<Closure>>(
+      std::forward<Closure>(closure));
+}
+
+template <typename Closure, typename Cleanup>
+std::unique_ptr<QueuedTask> ToQueuedTask(Closure&& closure, Cleanup&& cleanup) {
+  return absl::make_unique<
+      webrtc_new_closure_impl::ClosureTaskWithCleanup<Closure, Cleanup>>(
+      std::forward<Closure>(closure), std::forward<Cleanup>(cleanup));
+}
+
+}  // namespace webrtc
+
+#endif  // RTC_BASE_TASK_UTILS_TO_QUEUED_TASK_H_
diff --git a/rtc_base/task_utils/to_queued_task_unittest.cc b/rtc_base/task_utils/to_queued_task_unittest.cc
new file mode 100644
index 0000000..45dec77
--- /dev/null
+++ b/rtc_base/task_utils/to_queued_task_unittest.cc
@@ -0,0 +1,130 @@
+/*
+ *  Copyright 2019 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "rtc_base/task_utils/to_queued_task.h"
+
+#include <memory>
+
+#include "absl/memory/memory.h"
+#include "api/task_queue/queued_task.h"
+#include "test/gmock.h"
+#include "test/gtest.h"
+
+namespace webrtc {
+namespace {
+
+using ::testing::InSequence;
+using ::testing::MockFunction;
+
+void RunTask(std::unique_ptr<QueuedTask> task) {
+  // Simulate how task queue suppose to run tasks.
+  QueuedTask* raw = task.release();
+  if (raw->Run())
+    delete raw;
+}
+
+TEST(ToQueuedTaskTest, AcceptsLambda) {
+  bool run = false;
+  std::unique_ptr<QueuedTask> task = ToQueuedTask([&run] { run = true; });
+  EXPECT_FALSE(run);
+  RunTask(std::move(task));
+  EXPECT_TRUE(run);
+}
+
+TEST(ToQueuedTaskTest, AcceptsCopyableClosure) {
+  struct CopyableClosure {
+    CopyableClosure(int* num_copies, int* num_moves, int* num_runs)
+        : num_copies(num_copies), num_moves(num_moves), num_runs(num_runs) {}
+    CopyableClosure(const CopyableClosure& other)
+        : num_copies(other.num_copies),
+          num_moves(other.num_moves),
+          num_runs(other.num_runs) {
+      ++*num_copies;
+    }
+    CopyableClosure(CopyableClosure&& other)
+        : num_copies(other.num_copies),
+          num_moves(other.num_moves),
+          num_runs(other.num_runs) {
+      ++*num_moves;
+    }
+    void operator()() { ++*num_runs; }
+
+    int* num_copies;
+    int* num_moves;
+    int* num_runs;
+  };
+
+  int num_copies = 0;
+  int num_moves = 0;
+  int num_runs = 0;
+
+  std::unique_ptr<QueuedTask> task;
+  {
+    CopyableClosure closure(&num_copies, &num_moves, &num_runs);
+    task = ToQueuedTask(closure);
+    // Destroy closure to check with msan task has own copy.
+  }
+  EXPECT_EQ(num_copies, 1);
+  EXPECT_EQ(num_runs, 0);
+  RunTask(std::move(task));
+  EXPECT_EQ(num_copies, 1);
+  EXPECT_EQ(num_moves, 0);
+  EXPECT_EQ(num_runs, 1);
+}
+
+TEST(ToQueuedTaskTest, AcceptsMoveOnlyClosure) {
+  struct MoveOnlyClosure {
+    MoveOnlyClosure(int* num_moves, std::function<void()> trigger)
+        : num_moves(num_moves), trigger(std::move(trigger)) {}
+    MoveOnlyClosure(const MoveOnlyClosure&) = delete;
+    MoveOnlyClosure(MoveOnlyClosure&& other)
+        : num_moves(other.num_moves), trigger(std::move(other.trigger)) {
+      ++*num_moves;
+    }
+    void operator()() { trigger(); }
+
+    int* num_moves;
+    std::function<void()> trigger;
+  };
+
+  int num_moves = 0;
+  MockFunction<void()> run;
+
+  auto task = ToQueuedTask(MoveOnlyClosure(&num_moves, run.AsStdFunction()));
+  EXPECT_EQ(num_moves, 1);
+  EXPECT_CALL(run, Call);
+  RunTask(std::move(task));
+  EXPECT_EQ(num_moves, 1);
+}
+
+TEST(ToQueuedTaskTest, AcceptsMoveOnlyCleanup) {
+  struct MoveOnlyClosure {
+    MoveOnlyClosure(const MoveOnlyClosure&) = delete;
+    MoveOnlyClosure(MoveOnlyClosure&&) = default;
+    void operator()() { trigger(); }
+
+    std::function<void()> trigger;
+  };
+
+  MockFunction<void()> run;
+  MockFunction<void()> cleanup;
+
+  auto task = ToQueuedTask(MoveOnlyClosure{run.AsStdFunction()},
+                           MoveOnlyClosure{cleanup.AsStdFunction()});
+
+  // Expect run closure to complete before cleanup closure.
+  InSequence in_sequence;
+  EXPECT_CALL(run, Call);
+  EXPECT_CALL(cleanup, Call);
+  RunTask(std::move(task));
+}
+
+}  // namespace
+}  // namespace webrtc
diff --git a/rtc_base/testbase64.h b/rtc_base/test_base64.h
similarity index 99%
rename from rtc_base/testbase64.h
rename to rtc_base/test_base64.h
index 5dc94b6..51d8c58 100644
--- a/rtc_base/testbase64.h
+++ b/rtc_base/test_base64.h
@@ -8,8 +8,8 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#ifndef RTC_BASE_TESTBASE64_H_
-#define RTC_BASE_TESTBASE64_H_
+#ifndef RTC_BASE_TEST_BASE64_H_
+#define RTC_BASE_TEST_BASE64_H_
 
 /* This file was generated by googleclient/talk/binary2header.sh */
 
@@ -2108,4 +2108,4 @@
     0xba, 0x5b, 0xfe, 0x97, 0xfa, 0x4b, 0xfc, 0xba, 0x7f, 0xb1, 0xc7, 0xab,
     0x1e, 0x8f, 0xff, 0xd9};
 
-#endif  // RTC_BASE_TESTBASE64_H_
+#endif  // RTC_BASE_TEST_BASE64_H_
diff --git a/rtc_base/testcertificateverifier.h b/rtc_base/test_certificate_verifier.h
similarity index 81%
rename from rtc_base/testcertificateverifier.h
rename to rtc_base/test_certificate_verifier.h
index 8ad6e4d..9775615 100644
--- a/rtc_base/testcertificateverifier.h
+++ b/rtc_base/test_certificate_verifier.h
@@ -8,10 +8,10 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#ifndef RTC_BASE_TESTCERTIFICATEVERIFIER_H_
-#define RTC_BASE_TESTCERTIFICATEVERIFIER_H_
+#ifndef RTC_BASE_TEST_CERTIFICATE_VERIFIER_H_
+#define RTC_BASE_TEST_CERTIFICATE_VERIFIER_H_
 
-#include "rtc_base/sslcertificate.h"
+#include "rtc_base/ssl_certificate.h"
 
 namespace rtc {
 
@@ -31,4 +31,4 @@
 
 }  // namespace rtc
 
-#endif  // RTC_BASE_TESTCERTIFICATEVERIFIER_H_
+#endif  // RTC_BASE_TEST_CERTIFICATE_VERIFIER_H_
diff --git a/rtc_base/testclient.cc b/rtc_base/test_client.cc
similarity index 97%
rename from rtc_base/testclient.cc
rename to rtc_base/test_client.cc
index a5b90dd..274b6ca 100644
--- a/rtc_base/testclient.cc
+++ b/rtc_base/test_client.cc
@@ -8,12 +8,15 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#include "rtc_base/testclient.h"
+#include "rtc_base/test_client.h"
+
+#include <string.h>
+#include <utility>
 
 #include "absl/memory/memory.h"
 #include "rtc_base/gunit.h"
 #include "rtc_base/thread.h"
-#include "rtc_base/timeutils.h"
+#include "rtc_base/time_utils.h"
 
 namespace rtc {
 
diff --git a/rtc_base/testclient.h b/rtc_base/test_client.h
similarity index 93%
rename from rtc_base/testclient.h
rename to rtc_base/test_client.h
index 16fb6ba..fb8a2f9 100644
--- a/rtc_base/testclient.h
+++ b/rtc_base/test_client.h
@@ -8,15 +8,15 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#ifndef RTC_BASE_TESTCLIENT_H_
-#define RTC_BASE_TESTCLIENT_H_
+#ifndef RTC_BASE_TEST_CLIENT_H_
+#define RTC_BASE_TEST_CLIENT_H_
 
 #include <memory>
 #include <vector>
-#include "rtc_base/asyncudpsocket.h"
-#include "rtc_base/constructormagic.h"
-#include "rtc_base/criticalsection.h"
-#include "rtc_base/fakeclock.h"
+#include "rtc_base/async_udp_socket.h"
+#include "rtc_base/constructor_magic.h"
+#include "rtc_base/critical_section.h"
+#include "rtc_base/fake_clock.h"
 
 namespace rtc {
 
@@ -113,4 +113,4 @@
 
 }  // namespace rtc
 
-#endif  // RTC_BASE_TESTCLIENT_H_
+#endif  // RTC_BASE_TEST_CLIENT_H_
diff --git a/rtc_base/testclient_unittest.cc b/rtc_base/test_client_unittest.cc
similarity index 87%
rename from rtc_base/testclient_unittest.cc
rename to rtc_base/test_client_unittest.cc
index b3a6c80..382aaaf 100644
--- a/rtc_base/testclient_unittest.cc
+++ b/rtc_base/test_client_unittest.cc
@@ -8,15 +8,23 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#include "rtc_base/testclient.h"
-#include "absl/memory/memory.h"
-#include "rtc_base/gunit.h"
-#include "rtc_base/nethelpers.h"
-#include "rtc_base/physicalsocketserver.h"
-#include "rtc_base/testechoserver.h"
-#include "rtc_base/thread.h"
+#include "rtc_base/test_client.h"
 
-using namespace rtc;
+#include <utility>
+
+#include "absl/memory/memory.h"
+#include "rtc_base/async_socket.h"
+#include "rtc_base/async_tcp_socket.h"
+#include "rtc_base/async_udp_socket.h"
+#include "rtc_base/logging.h"
+#include "rtc_base/net_helpers.h"
+#include "rtc_base/socket_server.h"
+#include "rtc_base/test_echo_server.h"
+#include "rtc_base/thread.h"
+#include "test/gtest.h"
+
+namespace rtc {
+namespace {
 
 #define MAYBE_SKIP_IPV4                        \
   if (!HasIPv4Enabled()) {                     \
@@ -94,3 +102,6 @@
   MAYBE_SKIP_IPV6;
   TestTcpInternal(SocketAddress("::1", 0));
 }
+
+}  // namespace
+}  // namespace rtc
diff --git a/rtc_base/testechoserver.cc b/rtc_base/test_echo_server.cc
similarity index 92%
rename from rtc_base/testechoserver.cc
rename to rtc_base/test_echo_server.cc
index a5eb7de..d2e11d6 100644
--- a/rtc_base/testechoserver.cc
+++ b/rtc_base/test_echo_server.cc
@@ -8,7 +8,9 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#include "rtc_base/testechoserver.h"
+#include "rtc_base/test_echo_server.h"
+
+#include "rtc_base/socket_server.h"
 
 namespace rtc {
 
diff --git a/rtc_base/testechoserver.h b/rtc_base/test_echo_server.h
similarity index 82%
rename from rtc_base/testechoserver.h
rename to rtc_base/test_echo_server.h
index 9ffd786..4710560 100644
--- a/rtc_base/testechoserver.h
+++ b/rtc_base/test_echo_server.h
@@ -8,15 +8,21 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#ifndef RTC_BASE_TESTECHOSERVER_H_
-#define RTC_BASE_TESTECHOSERVER_H_
+#ifndef RTC_BASE_TEST_ECHO_SERVER_H_
+#define RTC_BASE_TEST_ECHO_SERVER_H_
 
+#include <stddef.h>
+#include <stdint.h>
+#include <algorithm>
 #include <list>
 #include <memory>
 
-#include "rtc_base/asynctcpsocket.h"
-#include "rtc_base/constructormagic.h"
-#include "rtc_base/socketaddress.h"
+#include "rtc_base/async_packet_socket.h"
+#include "rtc_base/async_socket.h"
+#include "rtc_base/async_tcp_socket.h"
+#include "rtc_base/constructor_magic.h"
+#include "rtc_base/socket_address.h"
+#include "rtc_base/third_party/sigslot/sigslot.h"
 #include "rtc_base/thread.h"
 
 namespace rtc {
@@ -63,4 +69,4 @@
 
 }  // namespace rtc
 
-#endif  // RTC_BASE_TESTECHOSERVER_H_
+#endif  // RTC_BASE_TEST_ECHO_SERVER_H_
diff --git a/rtc_base/testutils.cc b/rtc_base/test_utils.cc
similarity index 94%
rename from rtc_base/testutils.cc
rename to rtc_base/test_utils.cc
index f3292fd..ecf2cfa 100644
--- a/rtc_base/testutils.cc
+++ b/rtc_base/test_utils.cc
@@ -8,7 +8,7 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#include "rtc_base/testutils.h"
+#include "rtc_base/test_utils.h"
 
 namespace webrtc {
 namespace testing {
diff --git a/rtc_base/testutils.h b/rtc_base/test_utils.h
similarity index 73%
rename from rtc_base/testutils.h
rename to rtc_base/test_utils.h
index ac74203..4746e96 100644
--- a/rtc_base/testutils.h
+++ b/rtc_base/test_utils.h
@@ -8,24 +8,21 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#ifndef RTC_BASE_TESTUTILS_H_
-#define RTC_BASE_TESTUTILS_H_
+#ifndef RTC_BASE_TEST_UTILS_H_
+#define RTC_BASE_TEST_UTILS_H_
 
 // Utilities for testing rtc infrastructure in unittests
 
-#include <algorithm>
 #include <map>
-#include <memory>
-#include <vector>
-#include "rtc_base/asyncsocket.h"
-#include "rtc_base/checks.h"
+#include <utility>
+
+#include "rtc_base/async_socket.h"
 #include "rtc_base/stream.h"
+#include "rtc_base/third_party/sigslot/sigslot.h"
 
 namespace webrtc {
 namespace testing {
 
-using namespace rtc;
-
 ///////////////////////////////////////////////////////////////////////////////
 // StreamSink - Monitor asynchronously signalled events from StreamInterface
 // or AsyncSocket (which should probably be a StreamInterface.
@@ -35,10 +32,10 @@
 // event.
 
 enum StreamSinkEvent {
-  SSE_OPEN = SE_OPEN,
-  SSE_READ = SE_READ,
-  SSE_WRITE = SE_WRITE,
-  SSE_CLOSE = SE_CLOSE,
+  SSE_OPEN = rtc::SE_OPEN,
+  SSE_READ = rtc::SE_READ,
+  SSE_WRITE = rtc::SE_WRITE,
+  SSE_CLOSE = rtc::SE_CLOSE,
   SSE_ERROR = 16
 };
 
@@ -47,25 +44,25 @@
   StreamSink();
   ~StreamSink() override;
 
-  void Monitor(StreamInterface* stream) {
+  void Monitor(rtc::StreamInterface* stream) {
     stream->SignalEvent.connect(this, &StreamSink::OnEvent);
     events_.erase(stream);
   }
-  void Unmonitor(StreamInterface* stream) {
+  void Unmonitor(rtc::StreamInterface* stream) {
     stream->SignalEvent.disconnect(this);
     // In case you forgot to unmonitor a previous object with this address
     events_.erase(stream);
   }
-  bool Check(StreamInterface* stream,
+  bool Check(rtc::StreamInterface* stream,
              StreamSinkEvent event,
              bool reset = true) {
     return DoCheck(stream, event, reset);
   }
-  int Events(StreamInterface* stream, bool reset = true) {
+  int Events(rtc::StreamInterface* stream, bool reset = true) {
     return DoEvents(stream, reset);
   }
 
-  void Monitor(AsyncSocket* socket) {
+  void Monitor(rtc::AsyncSocket* socket) {
     socket->SignalConnectEvent.connect(this, &StreamSink::OnConnectEvent);
     socket->SignalReadEvent.connect(this, &StreamSink::OnReadEvent);
     socket->SignalWriteEvent.connect(this, &StreamSink::OnWriteEvent);
@@ -73,33 +70,35 @@
     // In case you forgot to unmonitor a previous object with this address
     events_.erase(socket);
   }
-  void Unmonitor(AsyncSocket* socket) {
+  void Unmonitor(rtc::AsyncSocket* socket) {
     socket->SignalConnectEvent.disconnect(this);
     socket->SignalReadEvent.disconnect(this);
     socket->SignalWriteEvent.disconnect(this);
     socket->SignalCloseEvent.disconnect(this);
     events_.erase(socket);
   }
-  bool Check(AsyncSocket* socket, StreamSinkEvent event, bool reset = true) {
+  bool Check(rtc::AsyncSocket* socket,
+             StreamSinkEvent event,
+             bool reset = true) {
     return DoCheck(socket, event, reset);
   }
-  int Events(AsyncSocket* socket, bool reset = true) {
+  int Events(rtc::AsyncSocket* socket, bool reset = true) {
     return DoEvents(socket, reset);
   }
 
  private:
   typedef std::map<void*, int> EventMap;
 
-  void OnEvent(StreamInterface* stream, int events, int error) {
+  void OnEvent(rtc::StreamInterface* stream, int events, int error) {
     if (error) {
       events = SSE_ERROR;
     }
     AddEvents(stream, events);
   }
-  void OnConnectEvent(AsyncSocket* socket) { AddEvents(socket, SSE_OPEN); }
-  void OnReadEvent(AsyncSocket* socket) { AddEvents(socket, SSE_READ); }
-  void OnWriteEvent(AsyncSocket* socket) { AddEvents(socket, SSE_WRITE); }
-  void OnCloseEvent(AsyncSocket* socket, int error) {
+  void OnConnectEvent(rtc::AsyncSocket* socket) { AddEvents(socket, SSE_OPEN); }
+  void OnReadEvent(rtc::AsyncSocket* socket) { AddEvents(socket, SSE_READ); }
+  void OnWriteEvent(rtc::AsyncSocket* socket) { AddEvents(socket, SSE_WRITE); }
+  void OnCloseEvent(rtc::AsyncSocket* socket, int error) {
     AddEvents(socket, (0 == error) ? SSE_CLOSE : SSE_ERROR);
   }
 
@@ -138,4 +137,4 @@
 }  // namespace testing
 }  // namespace webrtc
 
-#endif  // RTC_BASE_TESTUTILS_H_
+#endif  // RTC_BASE_TEST_UTILS_H_
diff --git a/rtc_base/thread.cc b/rtc_base/thread.cc
index 4dd5fd2..936871c 100644
--- a/rtc_base/thread.cc
+++ b/rtc_base/thread.cc
@@ -28,10 +28,10 @@
 #include <utility>
 
 #include "rtc_base/checks.h"
-#include "rtc_base/criticalsection.h"
+#include "rtc_base/critical_section.h"
 #include "rtc_base/logging.h"
-#include "rtc_base/nullsocketserver.h"
-#include "rtc_base/timeutils.h"
+#include "rtc_base/null_socket_server.h"
+#include "rtc_base/time_utils.h"
 #include "rtc_base/trace_event.h"
 
 #if defined(WEBRTC_MAC)
diff --git a/rtc_base/thread.h b/rtc_base/thread.h
index 039192c..7bb7a3c 100644
--- a/rtc_base/thread.h
+++ b/rtc_base/thread.h
@@ -20,12 +20,12 @@
 #if defined(WEBRTC_POSIX)
 #include <pthread.h>
 #endif
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 #include "rtc_base/location.h"
-#include "rtc_base/messagehandler.h"
-#include "rtc_base/messagequeue.h"
+#include "rtc_base/message_handler.h"
+#include "rtc_base/message_queue.h"
 #include "rtc_base/platform_thread_types.h"
-#include "rtc_base/socketserver.h"
+#include "rtc_base/socket_server.h"
 #include "rtc_base/thread_annotations.h"
 
 #if defined(WEBRTC_WIN)
@@ -36,6 +36,29 @@
 
 class Thread;
 
+namespace rtc_thread_internal {
+
+template <class FunctorT>
+class SingleMessageHandlerWithFunctor final : public MessageHandler {
+ public:
+  explicit SingleMessageHandlerWithFunctor(FunctorT&& functor)
+      : functor_(std::forward<FunctorT>(functor)) {}
+
+  void OnMessage(Message* msg) override {
+    functor_();
+    delete this;
+  }
+
+ private:
+  ~SingleMessageHandlerWithFunctor() override {}
+
+  typename std::remove_reference<FunctorT>::type functor_;
+
+  RTC_DISALLOW_COPY_AND_ASSIGN(SingleMessageHandlerWithFunctor);
+};
+
+}  // namespace rtc_thread_internal
+
 class ThreadManager {
  public:
   static const int kForever = -1;
@@ -183,6 +206,8 @@
   // &MyFunctionReturningBool);
   // NOTE: This function can only be called when synchronous calls are allowed.
   // See ScopedDisallowBlockingCalls for details.
+  // NOTE: Blocking invokes are DISCOURAGED, consider if what you're doing can
+  // be achieved with PostTask() and callbacks instead.
   template <class ReturnT, class FunctorT>
   ReturnT Invoke(const Location& posted_from, FunctorT&& functor) {
     FunctorMessageHandler<ReturnT, FunctorT> handler(
@@ -191,6 +216,44 @@
     return handler.MoveResult();
   }
 
+  // Posts a task to invoke the functor on |this| thread asynchronously, i.e.
+  // without blocking the thread that invoked PostTask(). Ownership of |functor|
+  // is passed and destroyed on |this| thread after it is invoked.
+  // Requirements of FunctorT:
+  // - FunctorT is movable.
+  // - FunctorT implements "T operator()()" or "T operator()() const" for some T
+  //   (if T is not void, the return value is discarded on |this| thread).
+  // - FunctorT has a public destructor that can be invoked from |this| thread
+  //   after operation() has been invoked.
+  // - The functor must not cause the thread to quit before PostTask() is done.
+  //
+  // Example - Calling a class method:
+  // class Foo {
+  //  public:
+  //   void DoTheThing();
+  // };
+  // Foo foo;
+  // thread->PostTask(RTC_FROM_HERE, Bind(&Foo::DoTheThing, &foo));
+  //
+  // Example - Calling a lambda function:
+  // thread->PostTask(RTC_FROM_HERE,
+  //                  [&x, &y] { x.TrackComputations(y.Compute()); });
+  template <class FunctorT>
+  void PostTask(const Location& posted_from, FunctorT&& functor) {
+    Post(posted_from,
+         new rtc_thread_internal::SingleMessageHandlerWithFunctor<FunctorT>(
+             std::forward<FunctorT>(functor)));
+    // This DCHECK guarantees that the post was successful.
+    // Post() doesn't say whether it succeeded, but it will only fail if the
+    // thread is quitting. DCHECKing that the thread is not quitting *after*
+    // posting might yield some false positives (where the thread did in fact
+    // quit, but only after posting), but if we have false positives here then
+    // we have a race condition anyway.
+    // TODO(https://crbug.com/webrtc/10364): When Post() returns a bool we can
+    // DCHECK the result instead of inferring success from IsQuitting().
+    RTC_DCHECK(!IsQuitting());
+  }
+
   // From MessageQueue
   bool IsProcessingMessagesForTesting() override;
   void Clear(MessageHandler* phandler,
@@ -219,10 +282,6 @@
   // of whatever code is conditionally executing because of the return value!
   bool RunningForTest() { return IsRunning(); }
 
-  // Sets the per-thread allow-blocking-calls flag and returns the previous
-  // value. Must be called on this thread.
-  bool SetAllowBlockingCalls(bool allow);
-
   // These functions are public to avoid injecting test hooks. Don't call them
   // outside of tests.
   // This method should be called when thread is created using non standard
@@ -232,6 +291,17 @@
   bool WrapCurrent();
   void UnwrapCurrent();
 
+  // Sets the per-thread allow-blocking-calls flag to false; this is
+  // irrevocable. Must be called on this thread.
+  void DisallowBlockingCalls() { SetAllowBlockingCalls(false); }
+
+#ifdef WEBRTC_ANDROID
+  // Sets the per-thread allow-blocking-calls flag to true, sidestepping the
+  // invariants upheld by DisallowBlockingCalls() and
+  // ScopedDisallowBlockingCalls. Must be called on this thread.
+  void DEPRECATED_AllowBlockingCalls() { SetAllowBlockingCalls(true); }
+#endif
+
  protected:
   // Same as WrapCurrent except that it never fails as it does not try to
   // acquire the synchronization access of the thread. The caller should never
@@ -251,6 +321,10 @@
     Runnable* runnable;
   };
 
+  // Sets the per-thread allow-blocking-calls flag and returns the previous
+  // value. Must be called on this thread.
+  bool SetAllowBlockingCalls(bool allow);
+
 #if defined(WEBRTC_WIN)
   static DWORD WINAPI PreRun(LPVOID context);
 #else
diff --git a/rtc_base/thread_checker.h b/rtc_base/thread_checker.h
index ad04508..43f7320 100644
--- a/rtc_base/thread_checker.h
+++ b/rtc_base/thread_checker.h
@@ -20,7 +20,7 @@
 #define RTC_ENABLE_THREAD_CHECKER RTC_DCHECK_IS_ON
 
 #include "rtc_base/checks.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 #include "rtc_base/thread_annotations.h"
 #include "rtc_base/thread_checker_impl.h"
 
@@ -152,12 +152,12 @@
 //     // Will fail at runtime when DCHECK is enabled:
 //     // encoder_->Encode();
 //     // Will work:
-//     rtc::scoped_ref_ptr<Encoder> encoder = encoder_;
+//     rtc::scoped_refptr<Encoder> encoder = encoder_;
 //     encoder_->Queue()->PostTask([encoder] { encoder->Encode(); });
 //   }
 //
 //  private:
-//   rtc::scoped_ref_ptr<Encoder> encoder_;
+//   rtc::scoped_refptr<Encoder> encoder_;
 // }
 
 // Document if a function expected to be called from same thread/task queue.
diff --git a/rtc_base/thread_checker_impl.h b/rtc_base/thread_checker_impl.h
index c82fe1d..c39e10f 100644
--- a/rtc_base/thread_checker_impl.h
+++ b/rtc_base/thread_checker_impl.h
@@ -13,7 +13,7 @@
 #ifndef RTC_BASE_THREAD_CHECKER_IMPL_H_
 #define RTC_BASE_THREAD_CHECKER_IMPL_H_
 
-#include "rtc_base/criticalsection.h"
+#include "rtc_base/critical_section.h"
 #include "rtc_base/platform_thread_types.h"
 
 namespace rtc {
diff --git a/rtc_base/thread_checker_unittest.cc b/rtc_base/thread_checker_unittest.cc
index 9c0942f..a40196f 100644
--- a/rtc_base/thread_checker_unittest.cc
+++ b/rtc_base/thread_checker_unittest.cc
@@ -11,10 +11,12 @@
 // Borrowed from Chromium's src/base/threading/thread_checker_unittest.cc.
 
 #include <memory>
+#include <utility>
 
 #include "rtc_base/checks.h"
-#include "rtc_base/constructormagic.h"
-#include "rtc_base/nullsocketserver.h"
+#include "rtc_base/constructor_magic.h"
+#include "rtc_base/null_socket_server.h"
+#include "rtc_base/socket_server.h"
 #include "rtc_base/task_queue.h"
 #include "rtc_base/thread.h"
 #include "rtc_base/thread_checker.h"
diff --git a/rtc_base/thread_unittest.cc b/rtc_base/thread_unittest.cc
index 7e392af..63edcf8 100644
--- a/rtc_base/thread_unittest.cc
+++ b/rtc_base/thread_unittest.cc
@@ -10,13 +10,13 @@
 
 #include <memory>
 
-#include "rtc_base/asyncinvoker.h"
-#include "rtc_base/asyncudpsocket.h"
+#include "rtc_base/async_invoker.h"
+#include "rtc_base/async_udp_socket.h"
 #include "rtc_base/event.h"
 #include "rtc_base/gunit.h"
-#include "rtc_base/nullsocketserver.h"
-#include "rtc_base/physicalsocketserver.h"
-#include "rtc_base/socketaddress.h"
+#include "rtc_base/null_socket_server.h"
+#include "rtc_base/physical_socket_server.h"
+#include "rtc_base/socket_address.h"
 #include "rtc_base/third_party/sigslot/sigslot.h"
 #include "rtc_base/thread.h"
 
@@ -24,7 +24,8 @@
 #include <comdef.h>  // NOLINT
 #endif
 
-using namespace rtc;
+namespace rtc {
+namespace {
 
 // Generates a sequence of numbers (collaboratively).
 class TestGenerator {
@@ -669,3 +670,231 @@
   EXPECT_FALSE(flag1.get());
   EXPECT_TRUE(flag2.get());
 }
+
+void ThreadIsCurrent(Thread* thread, bool* result, Event* event) {
+  *result = thread->IsCurrent();
+  event->Set();
+}
+
+void WaitAndSetEvent(Event* wait_event, Event* set_event) {
+  wait_event->Wait(Event::kForever);
+  set_event->Set();
+}
+
+// A functor that keeps track of the number of copies and moves.
+class LifeCycleFunctor {
+ public:
+  struct Stats {
+    size_t copy_count = 0;
+    size_t move_count = 0;
+  };
+
+  LifeCycleFunctor(Stats* stats, Event* event) : stats_(stats), event_(event) {}
+  LifeCycleFunctor(const LifeCycleFunctor& other) { *this = other; }
+  LifeCycleFunctor(LifeCycleFunctor&& other) { *this = std::move(other); }
+
+  LifeCycleFunctor& operator=(const LifeCycleFunctor& other) {
+    stats_ = other.stats_;
+    event_ = other.event_;
+    ++stats_->copy_count;
+    return *this;
+  }
+
+  LifeCycleFunctor& operator=(LifeCycleFunctor&& other) {
+    stats_ = other.stats_;
+    event_ = other.event_;
+    ++stats_->move_count;
+    return *this;
+  }
+
+  void operator()() { event_->Set(); }
+
+ private:
+  Stats* stats_;
+  Event* event_;
+};
+
+// A functor that verifies the thread it was destroyed on.
+class DestructionFunctor {
+ public:
+  DestructionFunctor(Thread* thread, bool* thread_was_current, Event* event)
+      : thread_(thread),
+        thread_was_current_(thread_was_current),
+        event_(event) {}
+  ~DestructionFunctor() {
+    // Only signal the event if this was the functor that was invoked to avoid
+    // the event being signaled due to the destruction of temporary/moved
+    // versions of this object.
+    if (was_invoked_) {
+      *thread_was_current_ = thread_->IsCurrent();
+      event_->Set();
+    }
+  }
+
+  void operator()() { was_invoked_ = true; }
+
+ private:
+  Thread* thread_;
+  bool* thread_was_current_;
+  Event* event_;
+  bool was_invoked_ = false;
+};
+
+TEST(ThreadPostTaskTest, InvokesWithBind) {
+  std::unique_ptr<rtc::Thread> background_thread(rtc::Thread::Create());
+  background_thread->Start();
+
+  Event event;
+  background_thread->PostTask(RTC_FROM_HERE, Bind(&Event::Set, &event));
+  event.Wait(Event::kForever);
+}
+
+TEST(ThreadPostTaskTest, InvokesWithLambda) {
+  std::unique_ptr<rtc::Thread> background_thread(rtc::Thread::Create());
+  background_thread->Start();
+
+  Event event;
+  background_thread->PostTask(RTC_FROM_HERE, [&event] { event.Set(); });
+  event.Wait(Event::kForever);
+}
+
+TEST(ThreadPostTaskTest, InvokesWithCopiedFunctor) {
+  std::unique_ptr<rtc::Thread> background_thread(rtc::Thread::Create());
+  background_thread->Start();
+
+  LifeCycleFunctor::Stats stats;
+  Event event;
+  LifeCycleFunctor functor(&stats, &event);
+  background_thread->PostTask(RTC_FROM_HERE, functor);
+  event.Wait(Event::kForever);
+
+  EXPECT_EQ(1u, stats.copy_count);
+  EXPECT_EQ(0u, stats.move_count);
+}
+
+TEST(ThreadPostTaskTest, InvokesWithMovedFunctor) {
+  std::unique_ptr<rtc::Thread> background_thread(rtc::Thread::Create());
+  background_thread->Start();
+
+  LifeCycleFunctor::Stats stats;
+  Event event;
+  LifeCycleFunctor functor(&stats, &event);
+  background_thread->PostTask(RTC_FROM_HERE, std::move(functor));
+  event.Wait(Event::kForever);
+
+  EXPECT_EQ(0u, stats.copy_count);
+  EXPECT_EQ(1u, stats.move_count);
+}
+
+TEST(ThreadPostTaskTest, InvokesWithReferencedFunctorShouldCopy) {
+  std::unique_ptr<rtc::Thread> background_thread(rtc::Thread::Create());
+  background_thread->Start();
+
+  LifeCycleFunctor::Stats stats;
+  Event event;
+  LifeCycleFunctor functor(&stats, &event);
+  LifeCycleFunctor& functor_ref = functor;
+  background_thread->PostTask(RTC_FROM_HERE, functor_ref);
+  event.Wait(Event::kForever);
+
+  EXPECT_EQ(1u, stats.copy_count);
+  EXPECT_EQ(0u, stats.move_count);
+}
+
+TEST(ThreadPostTaskTest, InvokesWithCopiedFunctorDestroyedOnTargetThread) {
+  std::unique_ptr<rtc::Thread> background_thread(rtc::Thread::Create());
+  background_thread->Start();
+
+  Event event;
+  bool was_invoked_on_background_thread = false;
+  DestructionFunctor functor(background_thread.get(),
+                             &was_invoked_on_background_thread, &event);
+  background_thread->PostTask(RTC_FROM_HERE, functor);
+  event.Wait(Event::kForever);
+
+  EXPECT_TRUE(was_invoked_on_background_thread);
+}
+
+TEST(ThreadPostTaskTest, InvokesWithMovedFunctorDestroyedOnTargetThread) {
+  std::unique_ptr<rtc::Thread> background_thread(rtc::Thread::Create());
+  background_thread->Start();
+
+  Event event;
+  bool was_invoked_on_background_thread = false;
+  DestructionFunctor functor(background_thread.get(),
+                             &was_invoked_on_background_thread, &event);
+  background_thread->PostTask(RTC_FROM_HERE, std::move(functor));
+  event.Wait(Event::kForever);
+
+  EXPECT_TRUE(was_invoked_on_background_thread);
+}
+
+TEST(ThreadPostTaskTest,
+     InvokesWithReferencedFunctorShouldCopyAndDestroyedOnTargetThread) {
+  std::unique_ptr<rtc::Thread> background_thread(rtc::Thread::Create());
+  background_thread->Start();
+
+  Event event;
+  bool was_invoked_on_background_thread = false;
+  DestructionFunctor functor(background_thread.get(),
+                             &was_invoked_on_background_thread, &event);
+  DestructionFunctor& functor_ref = functor;
+  background_thread->PostTask(RTC_FROM_HERE, functor_ref);
+  event.Wait(Event::kForever);
+
+  EXPECT_TRUE(was_invoked_on_background_thread);
+}
+
+TEST(ThreadPostTaskTest, InvokesOnBackgroundThread) {
+  std::unique_ptr<rtc::Thread> background_thread(rtc::Thread::Create());
+  background_thread->Start();
+
+  Event event;
+  bool was_invoked_on_background_thread = false;
+  background_thread->PostTask(RTC_FROM_HERE,
+                              Bind(&ThreadIsCurrent, background_thread.get(),
+                                   &was_invoked_on_background_thread, &event));
+  event.Wait(Event::kForever);
+
+  EXPECT_TRUE(was_invoked_on_background_thread);
+}
+
+TEST(ThreadPostTaskTest, InvokesAsynchronously) {
+  std::unique_ptr<rtc::Thread> background_thread(rtc::Thread::Create());
+  background_thread->Start();
+
+  // The first event ensures that SendSingleMessage() is not blocking this
+  // thread. The second event ensures that the message is processed.
+  Event event_set_by_test_thread;
+  Event event_set_by_background_thread;
+  background_thread->PostTask(RTC_FROM_HERE,
+                              Bind(&WaitAndSetEvent, &event_set_by_test_thread,
+                                   &event_set_by_background_thread));
+  event_set_by_test_thread.Set();
+  event_set_by_background_thread.Wait(Event::kForever);
+}
+
+TEST(ThreadPostTaskTest, InvokesInPostedOrder) {
+  std::unique_ptr<rtc::Thread> background_thread(rtc::Thread::Create());
+  background_thread->Start();
+
+  Event first;
+  Event second;
+  Event third;
+  Event fourth;
+
+  background_thread->PostTask(RTC_FROM_HERE,
+                              Bind(&WaitAndSetEvent, &first, &second));
+  background_thread->PostTask(RTC_FROM_HERE,
+                              Bind(&WaitAndSetEvent, &second, &third));
+  background_thread->PostTask(RTC_FROM_HERE,
+                              Bind(&WaitAndSetEvent, &third, &fourth));
+
+  // All tasks have been posted before the first one is unblocked.
+  first.Set();
+  // Only if the chain is invoked in posted order will the last event be set.
+  fourth.Wait(Event::kForever);
+}
+
+}  // namespace
+}  // namespace rtc
diff --git a/rtc_base/timeutils.cc b/rtc_base/time_utils.cc
similarity index 99%
rename from rtc_base/timeutils.cc
rename to rtc_base/time_utils.cc
index 0f79a87..53f8b36 100644
--- a/rtc_base/timeutils.cc
+++ b/rtc_base/time_utils.cc
@@ -29,7 +29,7 @@
 #endif
 
 #include "rtc_base/checks.h"
-#include "rtc_base/timeutils.h"
+#include "rtc_base/time_utils.h"
 
 namespace rtc {
 
diff --git a/rtc_base/timeutils.h b/rtc_base/time_utils.h
similarity index 97%
rename from rtc_base/timeutils.h
rename to rtc_base/time_utils.h
index c6ddd73..d1d8b05 100644
--- a/rtc_base/timeutils.h
+++ b/rtc_base/time_utils.h
@@ -8,8 +8,8 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#ifndef RTC_BASE_TIMEUTILS_H_
-#define RTC_BASE_TIMEUTILS_H_
+#ifndef RTC_BASE_TIME_UTILS_H_
+#define RTC_BASE_TIME_UTILS_H_
 
 #include <stdint.h>
 #include <time.h>
@@ -165,4 +165,4 @@
 
 }  // namespace rtc
 
-#endif  // RTC_BASE_TIMEUTILS_H_
+#endif  // RTC_BASE_TIME_UTILS_H_
diff --git a/rtc_base/timeutils_unittest.cc b/rtc_base/time_utils_unittest.cc
similarity index 96%
rename from rtc_base/timeutils_unittest.cc
rename to rtc_base/time_utils_unittest.cc
index 577efda..b4cefb7 100644
--- a/rtc_base/timeutils_unittest.cc
+++ b/rtc_base/time_utils_unittest.cc
@@ -8,12 +8,18 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#include "rtc_base/timeutils.h"
+#include "rtc_base/time_utils.h"
+
+#include <memory>
+
+#include "api/units/time_delta.h"
 #include "rtc_base/event.h"
-#include "rtc_base/fakeclock.h"
-#include "rtc_base/gunit.h"
+#include "rtc_base/fake_clock.h"
 #include "rtc_base/helpers.h"
+#include "rtc_base/location.h"
+#include "rtc_base/message_handler.h"
 #include "rtc_base/thread.h"
+#include "test/gtest.h"
 
 namespace rtc {
 
@@ -266,7 +272,7 @@
   auto functor = [&message_handler_dispatched] {
     message_handler_dispatched.Set();
   };
-  FunctorMessageHandler<void, decltype(functor)> handler(functor);
+  FunctorMessageHandler<void, decltype(functor)> handler(std::move(functor));
   worker->PostDelayed(RTC_FROM_HERE, 60000, &handler);
 
   // Wait for a bit for the worker thread to be started and enter its socket
diff --git a/rtc_base/timestampaligner.cc b/rtc_base/timestamp_aligner.cc
similarity index 98%
rename from rtc_base/timestampaligner.cc
rename to rtc_base/timestamp_aligner.cc
index f2da101..3d92dd8 100644
--- a/rtc_base/timestampaligner.cc
+++ b/rtc_base/timestamp_aligner.cc
@@ -13,8 +13,8 @@
 
 #include "rtc_base/checks.h"
 #include "rtc_base/logging.h"
-#include "rtc_base/timestampaligner.h"
-#include "rtc_base/timeutils.h"
+#include "rtc_base/time_utils.h"
+#include "rtc_base/timestamp_aligner.h"
 
 namespace rtc {
 
diff --git a/rtc_base/timestampaligner.h b/rtc_base/timestamp_aligner.h
similarity index 94%
rename from rtc_base/timestampaligner.h
rename to rtc_base/timestamp_aligner.h
index 6fa8d69..2146880 100644
--- a/rtc_base/timestampaligner.h
+++ b/rtc_base/timestamp_aligner.h
@@ -8,12 +8,12 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#ifndef RTC_BASE_TIMESTAMPALIGNER_H_
-#define RTC_BASE_TIMESTAMPALIGNER_H_
+#ifndef RTC_BASE_TIMESTAMP_ALIGNER_H_
+#define RTC_BASE_TIMESTAMP_ALIGNER_H_
 
 #include <stdint.h>
 
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace rtc {
 
@@ -71,4 +71,4 @@
 
 }  // namespace rtc
 
-#endif  // RTC_BASE_TIMESTAMPALIGNER_H_
+#endif  // RTC_BASE_TIMESTAMP_ALIGNER_H_
diff --git a/rtc_base/timestampaligner_unittest.cc b/rtc_base/timestamp_aligner_unittest.cc
similarity index 98%
rename from rtc_base/timestampaligner_unittest.cc
rename to rtc_base/timestamp_aligner_unittest.cc
index 8ba5be9..f92cd96 100644
--- a/rtc_base/timestampaligner_unittest.cc
+++ b/rtc_base/timestamp_aligner_unittest.cc
@@ -9,13 +9,13 @@
  */
 
 #include <math.h>
-
 #include <algorithm>
 #include <limits>
 
-#include "rtc_base/gunit.h"
 #include "rtc_base/random.h"
-#include "rtc_base/timestampaligner.h"
+#include "rtc_base/time_utils.h"
+#include "rtc_base/timestamp_aligner.h"
+#include "test/gtest.h"
 
 namespace rtc {
 
diff --git a/rtc_base/unique_id_generator.cc b/rtc_base/unique_id_generator.cc
new file mode 100644
index 0000000..d41fa8d
--- /dev/null
+++ b/rtc_base/unique_id_generator.cc
@@ -0,0 +1,65 @@
+/*
+ *  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/unique_id_generator.h"
+
+#include <limits>
+#include <vector>
+
+#include "rtc_base/helpers.h"
+#include "rtc_base/string_encode.h"
+#include "rtc_base/string_to_number.h"
+
+namespace rtc {
+
+UniqueRandomIdGenerator::UniqueRandomIdGenerator() : known_ids_() {}
+UniqueRandomIdGenerator::UniqueRandomIdGenerator(ArrayView<uint32_t> known_ids)
+    : known_ids_(known_ids.begin(), known_ids.end()) {}
+
+UniqueRandomIdGenerator::~UniqueRandomIdGenerator() = default;
+
+uint32_t UniqueRandomIdGenerator::GenerateId() {
+  RTC_CHECK_LT(known_ids_.size(), std::numeric_limits<uint32_t>::max() - 1);
+  while (true) {
+    auto pair = known_ids_.insert(CreateRandomNonZeroId());
+    if (pair.second) {
+      return *pair.first;
+    }
+  }
+}
+
+bool UniqueRandomIdGenerator::AddKnownId(uint32_t value) {
+  return known_ids_.insert(value).second;
+}
+
+UniqueStringGenerator::UniqueStringGenerator() : unique_number_generator_() {}
+UniqueStringGenerator::UniqueStringGenerator(ArrayView<std::string> known_ids) {
+  for (const std::string& str : known_ids) {
+    AddKnownId(str);
+  }
+}
+
+UniqueStringGenerator::~UniqueStringGenerator() = default;
+
+std::string UniqueStringGenerator::GenerateString() {
+  return ToString(unique_number_generator_.GenerateNumber());
+}
+
+bool UniqueStringGenerator::AddKnownId(const std::string& value) {
+  absl::optional<uint32_t> int_value = StringToNumber<uint32_t>(value);
+  // The underlying generator works for uint32_t values, so if the provided
+  // value is not a uint32_t it will never be generated anyway.
+  if (int_value.has_value()) {
+    return unique_number_generator_.AddKnownId(int_value.value());
+  }
+  return false;
+}
+
+}  // namespace rtc
diff --git a/rtc_base/unique_id_generator.h b/rtc_base/unique_id_generator.h
new file mode 100644
index 0000000..836dc70
--- /dev/null
+++ b/rtc_base/unique_id_generator.h
@@ -0,0 +1,134 @@
+/*
+ *  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_UNIQUE_ID_GENERATOR_H_
+#define RTC_BASE_UNIQUE_ID_GENERATOR_H_
+
+#include <limits>
+#include <set>
+#include <string>
+
+#include "api/array_view.h"
+
+namespace rtc {
+
+// This class will generate numbers. A common use case is for identifiers.
+// The generated numbers will be unique, in the local scope of the generator.
+// This means that a generator will never generate the same number twice.
+// The generator can also be initialized with a sequence of known ids.
+// In such a case, it will never generate an id from that list.
+// Recommendedations:
+//  * Prefer unsigned types.
+//  * Prefer larger types (uint8_t will run out quickly).
+template <typename TIntegral>
+class UniqueNumberGenerator {
+ public:
+  typedef TIntegral value_type;
+  UniqueNumberGenerator();
+  // Creates a generator that will never return any value from the given list.
+  explicit UniqueNumberGenerator(ArrayView<TIntegral> known_ids);
+  ~UniqueNumberGenerator();
+
+  // Generates a number that this generator has never produced before.
+  // If there are no available numbers to generate, this method will fail
+  // with an |RTC_CHECK|.
+  TIntegral GenerateNumber();
+  TIntegral operator()() { return GenerateNumber(); }
+
+  // Adds an id that this generator should no longer generate.
+  // Return value indicates whether the ID was hitherto unknown.
+  bool AddKnownId(TIntegral value);
+
+ private:
+  static_assert(std::is_integral<TIntegral>::value, "Must be integral type.");
+  TIntegral counter_;
+  std::set<TIntegral> known_ids_;
+};
+
+// This class will generate unique ids. Ids are 32 bit unsigned integers.
+// The generated ids will be unique, in the local scope of the generator.
+// This means that a generator will never generate the same id twice.
+// The generator can also be initialized with a sequence of known ids.
+// In such a case, it will never generate an id from that list.
+class UniqueRandomIdGenerator {
+ public:
+  typedef uint32_t value_type;
+  UniqueRandomIdGenerator();
+  // Create a generator that will never return any value from the given list.
+  explicit UniqueRandomIdGenerator(ArrayView<uint32_t> known_ids);
+  ~UniqueRandomIdGenerator();
+
+  // Generates a random id that this generator has never produced before.
+  // This method becomes more expensive with each use, as the probability of
+  // collision for the randomly generated numbers increases.
+  uint32_t GenerateId();
+  uint32_t operator()() { return GenerateId(); }
+
+  // Adds an id that this generator should no longer generate.
+  // Return value indicates whether the ID was hitherto unknown.
+  bool AddKnownId(uint32_t value);
+
+ private:
+  std::set<uint32_t> known_ids_;
+};
+
+// This class will generate strings. A common use case is for identifiers.
+// The generated strings will be unique, in the local scope of the generator.
+// This means that a generator will never generate the same string twice.
+// The generator can also be initialized with a sequence of known ids.
+// In such a case, it will never generate an id from that list.
+class UniqueStringGenerator {
+ public:
+  typedef std::string value_type;
+  UniqueStringGenerator();
+  explicit UniqueStringGenerator(ArrayView<std::string> known_ids);
+  ~UniqueStringGenerator();
+
+  std::string GenerateString();
+  std::string operator()() { return GenerateString(); }
+
+  // Adds an id that this generator should no longer generate.
+  // Return value indicates whether the ID was hitherto unknown.
+  bool AddKnownId(const std::string& value);
+
+ private:
+  // This implementation will be simple and will generate "0", "1", ...
+  UniqueNumberGenerator<uint32_t> unique_number_generator_;
+};
+
+template <typename TIntegral>
+UniqueNumberGenerator<TIntegral>::UniqueNumberGenerator() : counter_(0) {}
+
+template <typename TIntegral>
+UniqueNumberGenerator<TIntegral>::UniqueNumberGenerator(
+    ArrayView<TIntegral> known_ids)
+    : counter_(0), known_ids_(known_ids.begin(), known_ids.end()) {}
+
+template <typename TIntegral>
+UniqueNumberGenerator<TIntegral>::~UniqueNumberGenerator() {}
+
+template <typename TIntegral>
+TIntegral UniqueNumberGenerator<TIntegral>::GenerateNumber() {
+  while (true) {
+    RTC_CHECK_LT(counter_, std::numeric_limits<TIntegral>::max());
+    auto pair = known_ids_.insert(counter_++);
+    if (pair.second) {
+      return *pair.first;
+    }
+  }
+}
+
+template <typename TIntegral>
+bool UniqueNumberGenerator<TIntegral>::AddKnownId(TIntegral value) {
+  return known_ids_.insert(value).second;
+}
+}  // namespace rtc
+
+#endif  // RTC_BASE_UNIQUE_ID_GENERATOR_H_
diff --git a/rtc_base/unique_id_generator_unittest.cc b/rtc_base/unique_id_generator_unittest.cc
new file mode 100644
index 0000000..7ce192c
--- /dev/null
+++ b/rtc_base/unique_id_generator_unittest.cc
@@ -0,0 +1,150 @@
+/*
+ *  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 "algorithm"
+#include "string"
+#include "vector"
+
+#include "api/array_view.h"
+#include "rtc_base/gunit.h"
+#include "rtc_base/helpers.h"
+#include "rtc_base/unique_id_generator.h"
+#include "test/gmock.h"
+
+using ::testing::IsEmpty;
+using ::testing::Test;
+
+namespace rtc {
+
+template <typename Generator>
+class UniqueIdGeneratorTest : public Test {};
+
+using test_types = ::testing::Types<UniqueNumberGenerator<uint8_t>,
+                                    UniqueNumberGenerator<uint16_t>,
+                                    UniqueNumberGenerator<uint32_t>,
+                                    UniqueNumberGenerator<int>,
+                                    UniqueRandomIdGenerator,
+                                    UniqueStringGenerator>;
+
+TYPED_TEST_SUITE(UniqueIdGeneratorTest, test_types);
+
+TYPED_TEST(UniqueIdGeneratorTest, ElementsDoNotRepeat) {
+  typedef TypeParam Generator;
+  const size_t num_elements = 255;
+  Generator generator;
+  std::vector<typename Generator::value_type> values;
+  for (size_t i = 0; i < num_elements; i++) {
+    values.push_back(generator());
+  }
+
+  EXPECT_EQ(num_elements, values.size());
+  // Use a set to check uniqueness.
+  std::set<typename Generator::value_type> set(values.begin(), values.end());
+  EXPECT_EQ(values.size(), set.size()) << "Returned values were not unique.";
+}
+
+TYPED_TEST(UniqueIdGeneratorTest, KnownElementsAreNotGenerated) {
+  typedef TypeParam Generator;
+  const size_t num_elements = 100;
+  rtc::InitRandom(0);
+  Generator generator1;
+  std::vector<typename Generator::value_type> known_values;
+  for (size_t i = 0; i < num_elements; i++) {
+    known_values.push_back(generator1());
+  }
+  EXPECT_EQ(num_elements, known_values.size());
+
+  rtc::InitRandom(0);
+  Generator generator2(known_values);
+
+  std::vector<typename Generator::value_type> values;
+  for (size_t i = 0; i < num_elements; i++) {
+    values.push_back(generator2());
+  }
+  EXPECT_THAT(values, ::testing::SizeIs(num_elements));
+  std::sort(values.begin(), values.end());
+  std::sort(known_values.begin(), known_values.end());
+  std::vector<typename Generator::value_type> intersection;
+  std::set_intersection(values.begin(), values.end(), known_values.begin(),
+                        known_values.end(), std::back_inserter(intersection));
+  EXPECT_THAT(intersection, IsEmpty());
+}
+
+TYPED_TEST(UniqueIdGeneratorTest, AddedElementsAreNotGenerated) {
+  typedef TypeParam Generator;
+  const size_t num_elements = 100;
+  rtc::InitRandom(0);
+  Generator generator1;
+  std::vector<typename Generator::value_type> known_values;
+  for (size_t i = 0; i < num_elements; i++) {
+    known_values.push_back(generator1());
+  }
+  EXPECT_EQ(num_elements, known_values.size());
+
+  rtc::InitRandom(0);
+  Generator generator2;
+
+  for (const typename Generator::value_type& value : known_values) {
+    generator2.AddKnownId(value);
+  }
+
+  std::vector<typename Generator::value_type> values;
+  for (size_t i = 0; i < num_elements; i++) {
+    values.push_back(generator2());
+  }
+  EXPECT_THAT(values, ::testing::SizeIs(num_elements));
+  std::sort(values.begin(), values.end());
+  std::sort(known_values.begin(), known_values.end());
+  std::vector<typename Generator::value_type> intersection;
+  std::set_intersection(values.begin(), values.end(), known_values.begin(),
+                        known_values.end(), std::back_inserter(intersection));
+  EXPECT_THAT(intersection, IsEmpty());
+}
+
+TYPED_TEST(UniqueIdGeneratorTest, AddKnownIdOnNewIdReturnsTrue) {
+  typedef TypeParam Generator;
+
+  rtc::InitRandom(0);
+  Generator generator1;
+  const typename Generator::value_type id = generator1();
+
+  rtc::InitRandom(0);
+  Generator generator2;
+  EXPECT_TRUE(generator2.AddKnownId(id));
+}
+
+TYPED_TEST(UniqueIdGeneratorTest, AddKnownIdCalledAgainForSameIdReturnsFalse) {
+  typedef TypeParam Generator;
+
+  rtc::InitRandom(0);
+  Generator generator1;
+  const typename Generator::value_type id = generator1();
+
+  rtc::InitRandom(0);
+  Generator generator2;
+  ASSERT_TRUE(generator2.AddKnownId(id));
+  EXPECT_FALSE(generator2.AddKnownId(id));
+}
+
+TYPED_TEST(UniqueIdGeneratorTest,
+           AddKnownIdOnIdProvidedAsKnownToCtorReturnsFalse) {
+  typedef TypeParam Generator;
+
+  rtc::InitRandom(0);
+  Generator generator1;
+  const typename Generator::value_type id = generator1();
+  std::vector<typename Generator::value_type> known_values = {id};
+
+  rtc::InitRandom(0);
+  Generator generator2(known_values);
+  EXPECT_FALSE(generator2.AddKnownId(id));
+}
+
+}  // namespace rtc
diff --git a/rtc_base/units/unit_base.h b/rtc_base/units/unit_base.h
index 5503a32..37b60a0 100644
--- a/rtc_base/units/unit_base.h
+++ b/rtc_base/units/unit_base.h
@@ -23,7 +23,7 @@
 namespace rtc_units_impl {
 
 // UnitBase is a base class for implementing custom value types with a specific
-// unit. It provides type safety and sommonly useful operations. The undelying
+// unit. It provides type safety and commonly useful operations. The underlying
 // storage is always an int64_t, it's up to the unit implementation to choose
 // what scale it represents.
 //
diff --git a/rtc_base/unittest_main.cc b/rtc_base/unittest_main.cc
index 5fd3a99..def0104 100644
--- a/rtc_base/unittest_main.cc
+++ b/rtc_base/unittest_main.cc
@@ -15,16 +15,16 @@
 #endif
 
 #include "rtc_base/flags.h"
-#include "rtc_base/gunit.h"
 #include "rtc_base/logging.h"
-#include "rtc_base/ssladapter.h"
-#include "rtc_base/sslstreamadapter.h"
+#include "rtc_base/ssl_adapter.h"
+#include "rtc_base/ssl_stream_adapter.h"
 #include "system_wrappers/include/field_trial.h"
 #include "system_wrappers/include/metrics.h"
 #include "test/field_trial.h"
+#include "test/gtest.h"
 
 #if defined(WEBRTC_WIN)
-#include "rtc_base/win32socketinit.h"
+#include "rtc_base/win32_socket_init.h"
 #endif
 
 #if defined(WEBRTC_IOS)
diff --git a/rtc_base/virtualsocketserver.cc b/rtc_base/virtual_socket_server.cc
similarity index 99%
rename from rtc_base/virtualsocketserver.cc
rename to rtc_base/virtual_socket_server.cc
index 7969411..3255124 100644
--- a/rtc_base/virtualsocketserver.cc
+++ b/rtc_base/virtual_socket_server.cc
@@ -8,7 +8,7 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#include "rtc_base/virtualsocketserver.h"
+#include "rtc_base/virtual_socket_server.h"
 
 #include <errno.h>
 #include <math.h>
@@ -19,12 +19,12 @@
 #include <vector>
 
 #include "rtc_base/checks.h"
-#include "rtc_base/fakeclock.h"
+#include "rtc_base/fake_clock.h"
 #include "rtc_base/logging.h"
-#include "rtc_base/physicalsocketserver.h"
-#include "rtc_base/socketaddresspair.h"
+#include "rtc_base/physical_socket_server.h"
+#include "rtc_base/socket_address_pair.h"
 #include "rtc_base/thread.h"
-#include "rtc_base/timeutils.h"
+#include "rtc_base/time_utils.h"
 
 namespace rtc {
 #if defined(WEBRTC_WIN)
diff --git a/rtc_base/virtualsocketserver.h b/rtc_base/virtual_socket_server.h
similarity index 97%
rename from rtc_base/virtualsocketserver.h
rename to rtc_base/virtual_socket_server.h
index 4fa7d77..610c0fb 100644
--- a/rtc_base/virtualsocketserver.h
+++ b/rtc_base/virtual_socket_server.h
@@ -8,18 +8,18 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#ifndef RTC_BASE_VIRTUALSOCKETSERVER_H_
-#define RTC_BASE_VIRTUALSOCKETSERVER_H_
+#ifndef RTC_BASE_VIRTUAL_SOCKET_SERVER_H_
+#define RTC_BASE_VIRTUAL_SOCKET_SERVER_H_
 
 #include <deque>
 #include <map>
 
 #include "rtc_base/checks.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 #include "rtc_base/event.h"
-#include "rtc_base/fakeclock.h"
-#include "rtc_base/messagequeue.h"
-#include "rtc_base/socketserver.h"
+#include "rtc_base/fake_clock.h"
+#include "rtc_base/message_queue.h"
+#include "rtc_base/socket_server.h"
 
 namespace rtc {
 
@@ -409,4 +409,4 @@
 
 }  // namespace rtc
 
-#endif  // RTC_BASE_VIRTUALSOCKETSERVER_H_
+#endif  // RTC_BASE_VIRTUAL_SOCKET_SERVER_H_
diff --git a/rtc_base/virtualsocket_unittest.cc b/rtc_base/virtual_socket_unittest.cc
similarity index 98%
rename from rtc_base/virtualsocket_unittest.cc
rename to rtc_base/virtual_socket_unittest.cc
index d44f46a..ac0af08 100644
--- a/rtc_base/virtualsocket_unittest.cc
+++ b/rtc_base/virtual_socket_unittest.cc
@@ -9,25 +9,42 @@
  */
 
 #include <math.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
 #include <time.h>
 #if defined(WEBRTC_POSIX)
 #include <netinet/in.h>
 #endif
 
+#include <algorithm>
 #include <memory>
+#include <utility>
 
 #include "absl/memory/memory.h"
 #include "rtc_base/arraysize.h"
-#include "rtc_base/fakeclock.h"
+#include "rtc_base/async_packet_socket.h"
+#include "rtc_base/async_socket.h"
+#include "rtc_base/async_udp_socket.h"
+#include "rtc_base/fake_clock.h"
 #include "rtc_base/gunit.h"
+#include "rtc_base/ip_address.h"
+#include "rtc_base/location.h"
 #include "rtc_base/logging.h"
-#include "rtc_base/testclient.h"
-#include "rtc_base/testutils.h"
+#include "rtc_base/message_handler.h"
+#include "rtc_base/message_queue.h"
+#include "rtc_base/socket.h"
+#include "rtc_base/socket_address.h"
+#include "rtc_base/test_client.h"
+#include "rtc_base/test_utils.h"
+#include "rtc_base/third_party/sigslot/sigslot.h"
 #include "rtc_base/thread.h"
-#include "rtc_base/timeutils.h"
-#include "rtc_base/virtualsocketserver.h"
+#include "rtc_base/time_utils.h"
+#include "rtc_base/virtual_socket_server.h"
+#include "test/gtest.h"
 
-using namespace rtc;
+namespace rtc {
+namespace {
 
 using webrtc::testing::SSE_CLOSE;
 using webrtc::testing::SSE_ERROR;
@@ -1127,3 +1144,6 @@
     }
   }
 }
+
+}  // namespace
+}  // namespace rtc
diff --git a/rtc_base/weak_ptr.h b/rtc_base/weak_ptr.h
index 8acfab0..89969d6 100644
--- a/rtc_base/weak_ptr.h
+++ b/rtc_base/weak_ptr.h
@@ -15,9 +15,9 @@
 
 #include <utility>
 
-#include "rtc_base/refcount.h"
-#include "rtc_base/refcountedobject.h"
-#include "rtc_base/scoped_ref_ptr.h"
+#include "api/scoped_refptr.h"
+#include "rtc_base/ref_count.h"
+#include "rtc_base/ref_counted_object.h"
 #include "rtc_base/sequenced_task_checker.h"
 
 // The implementation is borrowed from chromium except that it does not
diff --git a/rtc_base/weak_ptr_unittest.cc b/rtc_base/weak_ptr_unittest.cc
index 66f2b4d..8f09a33 100644
--- a/rtc_base/weak_ptr_unittest.cc
+++ b/rtc_base/weak_ptr_unittest.cc
@@ -8,12 +8,14 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
+#include <memory>
 #include <string>
 
+#include "absl/memory/memory.h"
 #include "rtc_base/event.h"
-#include "rtc_base/gunit.h"
 #include "rtc_base/task_queue.h"
 #include "rtc_base/weak_ptr.h"
+#include "test/gtest.h"
 
 namespace rtc {
 
diff --git a/rtc_base/win/windows_version.cc b/rtc_base/win/windows_version.cc
index 65ef4fd..72aa5c6 100644
--- a/rtc_base/win/windows_version.cc
+++ b/rtc_base/win/windows_version.cc
@@ -14,7 +14,7 @@
 #include <memory>
 
 #include "rtc_base/checks.h"
-#include "rtc_base/stringutils.h"
+#include "rtc_base/string_utils.h"
 
 #if !defined(__clang__) && _MSC_FULL_VER < 191125507
 #error VS 2017 Update 3.2 or higher is required
diff --git a/rtc_base/win/windows_version.h b/rtc_base/win/windows_version.h
index 39d333e..fa0a767 100644
--- a/rtc_base/win/windows_version.h
+++ b/rtc_base/win/windows_version.h
@@ -14,7 +14,7 @@
 #include <stddef.h>
 #include <string>
 
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 typedef void* HANDLE;
 
diff --git a/rtc_base/win32.cc b/rtc_base/win32.cc
index 480d97b..b5a2611 100644
--- a/rtc_base/win32.cc
+++ b/rtc_base/win32.cc
@@ -15,10 +15,10 @@
 #include <algorithm>
 
 #include "rtc_base/arraysize.h"
-#include "rtc_base/byteorder.h"
+#include "rtc_base/byte_order.h"
 #include "rtc_base/checks.h"
 #include "rtc_base/logging.h"
-#include "rtc_base/stringutils.h"
+#include "rtc_base/string_utils.h"
 
 namespace rtc {
 
diff --git a/rtc_base/win32socketinit.h b/rtc_base/win32_socket_init.h
similarity index 87%
rename from rtc_base/win32socketinit.h
rename to rtc_base/win32_socket_init.h
index 7f9bdcc..4a90e14 100644
--- a/rtc_base/win32socketinit.h
+++ b/rtc_base/win32_socket_init.h
@@ -8,8 +8,8 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#ifndef RTC_BASE_WIN32SOCKETINIT_H_
-#define RTC_BASE_WIN32SOCKETINIT_H_
+#ifndef RTC_BASE_WIN32_SOCKET_INIT_H_
+#define RTC_BASE_WIN32_SOCKET_INIT_H_
 
 #ifndef WEBRTC_WIN
 #error "Only #include this header in Windows builds"
@@ -38,4 +38,4 @@
 
 }  // namespace rtc
 
-#endif  // RTC_BASE_WIN32SOCKETINIT_H_
+#endif  // RTC_BASE_WIN32_SOCKET_INIT_H_
diff --git a/rtc_base/win32socketserver.cc b/rtc_base/win32_socket_server.cc
similarity index 98%
rename from rtc_base/win32socketserver.cc
rename to rtc_base/win32_socket_server.cc
index 230f3ed..389b76b 100644
--- a/rtc_base/win32socketserver.cc
+++ b/rtc_base/win32_socket_server.cc
@@ -8,16 +8,16 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#include "rtc_base/win32socketserver.h"
+#include "rtc_base/win32_socket_server.h"
 
 #include <ws2tcpip.h>  // NOLINT
 #include <algorithm>
 
-#include "rtc_base/byteorder.h"
+#include "rtc_base/byte_order.h"
 #include "rtc_base/checks.h"
 #include "rtc_base/logging.h"
-#include "rtc_base/timeutils.h"  // For Time, TimeSince
-#include "rtc_base/win32window.h"
+#include "rtc_base/time_utils.h"  // For Time, TimeSince
+#include "rtc_base/win32_window.h"
 
 namespace rtc {
 
diff --git a/rtc_base/win32socketserver.h b/rtc_base/win32_socket_server.h
similarity index 92%
rename from rtc_base/win32socketserver.h
rename to rtc_base/win32_socket_server.h
index 0b11d64..37515d9 100644
--- a/rtc_base/win32socketserver.h
+++ b/rtc_base/win32_socket_server.h
@@ -8,18 +8,18 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#ifndef RTC_BASE_WIN32SOCKETSERVER_H_
-#define RTC_BASE_WIN32SOCKETSERVER_H_
+#ifndef RTC_BASE_WIN32_SOCKET_SERVER_H_
+#define RTC_BASE_WIN32_SOCKET_SERVER_H_
 
 #if defined(WEBRTC_WIN)
-#include "rtc_base/asyncsocket.h"
-#include "rtc_base/criticalsection.h"
-#include "rtc_base/messagequeue.h"
+#include "rtc_base/async_socket.h"
+#include "rtc_base/critical_section.h"
+#include "rtc_base/message_queue.h"
 #include "rtc_base/socket.h"
-#include "rtc_base/socketfactory.h"
-#include "rtc_base/socketserver.h"
+#include "rtc_base/socket_factory.h"
+#include "rtc_base/socket_server.h"
 #include "rtc_base/thread.h"
-#include "rtc_base/win32window.h"
+#include "rtc_base/win32_window.h"
 
 namespace rtc {
 
@@ -151,4 +151,4 @@
 
 #endif  // WEBRTC_WIN
 
-#endif  // RTC_BASE_WIN32SOCKETSERVER_H_
+#endif  // RTC_BASE_WIN32_SOCKET_SERVER_H_
diff --git a/rtc_base/win32socketserver_unittest.cc b/rtc_base/win32_socket_server_unittest.cc
similarity index 98%
rename from rtc_base/win32socketserver_unittest.cc
rename to rtc_base/win32_socket_server_unittest.cc
index 60295f1..d8484d1 100644
--- a/rtc_base/win32socketserver_unittest.cc
+++ b/rtc_base/win32_socket_server_unittest.cc
@@ -7,7 +7,7 @@
  *  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/win32socketserver.h"
+#include "rtc_base/win32_socket_server.h"
 #include "rtc_base/gunit.h"
 #include "rtc_base/socket_unittest.h"
 #include "rtc_base/thread.h"
diff --git a/rtc_base/win32_unittest.cc b/rtc_base/win32_unittest.cc
index 5691be4..913aa01 100644
--- a/rtc_base/win32_unittest.cc
+++ b/rtc_base/win32_unittest.cc
@@ -11,7 +11,7 @@
 #include <string>
 
 #include "rtc_base/gunit.h"
-#include "rtc_base/nethelpers.h"
+#include "rtc_base/net_helpers.h"
 #include "rtc_base/win32.h"
 
 #if !defined(WEBRTC_WIN)
diff --git a/rtc_base/win32window.cc b/rtc_base/win32_window.cc
similarity index 98%
rename from rtc_base/win32window.cc
rename to rtc_base/win32_window.cc
index 4290894..fc7b4c3 100644
--- a/rtc_base/win32window.cc
+++ b/rtc_base/win32_window.cc
@@ -8,7 +8,7 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#include "rtc_base/win32window.h"
+#include "rtc_base/win32_window.h"
 #include "rtc_base/checks.h"
 #include "rtc_base/logging.h"
 
diff --git a/rtc_base/win32window.h b/rtc_base/win32_window.h
similarity index 94%
rename from rtc_base/win32window.h
rename to rtc_base/win32_window.h
index e96aa35..5256a85 100644
--- a/rtc_base/win32window.h
+++ b/rtc_base/win32_window.h
@@ -8,8 +8,8 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#ifndef RTC_BASE_WIN32WINDOW_H_
-#define RTC_BASE_WIN32WINDOW_H_
+#ifndef RTC_BASE_WIN32_WINDOW_H_
+#define RTC_BASE_WIN32_WINDOW_H_
 
 #if defined(WEBRTC_WIN)
 
@@ -67,4 +67,4 @@
 
 #endif  // WEBRTC_WIN
 
-#endif  // RTC_BASE_WIN32WINDOW_H_
+#endif  // RTC_BASE_WIN32_WINDOW_H_
diff --git a/rtc_base/win32window_unittest.cc b/rtc_base/win32_window_unittest.cc
similarity index 98%
rename from rtc_base/win32window_unittest.cc
rename to rtc_base/win32_window_unittest.cc
index c659349..62430bb 100644
--- a/rtc_base/win32window_unittest.cc
+++ b/rtc_base/win32_window_unittest.cc
@@ -8,7 +8,7 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#include "rtc_base/win32window.h"
+#include "rtc_base/win32_window.h"
 #include "rtc_base/gunit.h"
 #include "rtc_base/logging.h"
 
diff --git a/rtc_base/zero_memory_unittest.cc b/rtc_base/zero_memory_unittest.cc
index 0f49670..74d95f4 100644
--- a/rtc_base/zero_memory_unittest.cc
+++ b/rtc_base/zero_memory_unittest.cc
@@ -10,9 +10,10 @@
 
 #include "rtc_base/zero_memory.h"
 
+#include <stdint.h>
+
 #include "api/array_view.h"
-#include "rtc_base/buffer.h"
-#include "rtc_base/gunit.h"
+#include "test/gtest.h"
 
 namespace rtc {
 
diff --git a/script/sync-apm.sh b/script/sync-apm.sh
index 47eccdd..c88a656 100755
--- a/script/sync-apm.sh
+++ b/script/sync-apm.sh
@@ -48,7 +48,7 @@
 
 rsync "${OPTIONS[@]}" --include="*.cc" --include="*.h" --include="audio" \
 	--include="video" --include="transport" --include="units" \
-	--exclude="*" ${FROM}/api/* ${TO}/api
+	--include="task_queue" --exclude="*" ${FROM}/api/* ${TO}/api
 
 # Adjust include path to use libevent header on chroot
 sed -i 's/include "base\/third_party\/libevent\/event\.h"/include <event.h>/' \
diff --git a/system_wrappers/BUILD.gn b/system_wrappers/BUILD.gn
index da83d12..ee24c8b 100644
--- a/system_wrappers/BUILD.gn
+++ b/system_wrappers/BUILD.gn
@@ -42,8 +42,6 @@
   ]
 
   if (is_android) {
-    defines += [ "WEBRTC_THREAD_RR" ]
-
     if (build_with_mozilla) {
       include_dirs = [
         "/config/external/nspr",
@@ -58,8 +56,6 @@
   }
 
   if (is_linux) {
-    defines += [ "WEBRTC_THREAD_RR" ]
-
     if (!build_with_chromium) {
       deps += [ ":cpu_features_linux" ]
     }
@@ -67,10 +63,6 @@
     libs += [ "rt" ]
   }
 
-  if (is_ios || is_mac) {
-    defines += [ "WEBRTC_THREAD_RR" ]
-  }
-
   if (is_win) {
     libs += [ "winmm.lib" ]
 
@@ -174,6 +166,7 @@
       ":metrics",
       ":system_wrappers",
       "..:webrtc_common",
+      "../rtc_base:checks",
       "../rtc_base:rtc_base_approved",
       "../test:test_main",
       "../test:test_support",
diff --git a/system_wrappers/include/clock.h b/system_wrappers/include/clock.h
index f1fc11f..b2c6c5f 100644
--- a/system_wrappers/include/clock.h
+++ b/system_wrappers/include/clock.h
@@ -32,17 +32,17 @@
 
   // Return a timestamp in milliseconds relative to some arbitrary source; the
   // source is fixed for this clock.
-  virtual int64_t TimeInMilliseconds() const = 0;
+  virtual int64_t TimeInMilliseconds() = 0;
 
   // Return a timestamp in microseconds relative to some arbitrary source; the
   // source is fixed for this clock.
-  virtual int64_t TimeInMicroseconds() const = 0;
+  virtual int64_t TimeInMicroseconds() = 0;
 
   // Retrieve an NTP absolute timestamp.
-  virtual NtpTime CurrentNtpTime() const = 0;
+  virtual NtpTime CurrentNtpTime() = 0;
 
   // Retrieve an NTP absolute timestamp in milliseconds.
-  virtual int64_t CurrentNtpInMilliseconds() const = 0;
+  virtual int64_t CurrentNtpInMilliseconds() = 0;
 
   // Converts an NTP timestamp to a millisecond timestamp.
   static int64_t NtpToMs(uint32_t seconds, uint32_t fractions) {
@@ -61,17 +61,17 @@
 
   // Return a timestamp in milliseconds relative to some arbitrary source; the
   // source is fixed for this clock.
-  int64_t TimeInMilliseconds() const override;
+  int64_t TimeInMilliseconds() override;
 
   // Return a timestamp in microseconds relative to some arbitrary source; the
   // source is fixed for this clock.
-  int64_t TimeInMicroseconds() const override;
+  int64_t TimeInMicroseconds() override;
 
   // Retrieve an NTP absolute timestamp.
-  NtpTime CurrentNtpTime() const override;
+  NtpTime CurrentNtpTime() override;
 
   // Converts an NTP timestamp to a millisecond timestamp.
-  int64_t CurrentNtpInMilliseconds() const override;
+  int64_t CurrentNtpInMilliseconds() override;
 
   // Advance the simulated clock with a given number of milliseconds or
   // microseconds.
@@ -83,6 +83,6 @@
   std::unique_ptr<RWLockWrapper> lock_;
 };
 
-};  // namespace webrtc
+}  // namespace webrtc
 
 #endif  // SYSTEM_WRAPPERS_INCLUDE_CLOCK_H_
diff --git a/system_wrappers/include/metrics.h b/system_wrappers/include/metrics.h
index f00ecf2..62dc6c6 100644
--- a/system_wrappers/include/metrics.h
+++ b/system_wrappers/include/metrics.h
@@ -11,11 +11,12 @@
 #ifndef SYSTEM_WRAPPERS_INCLUDE_METRICS_H_
 #define SYSTEM_WRAPPERS_INCLUDE_METRICS_H_
 
+#include <stddef.h>
 #include <map>
 #include <memory>
 #include <string>
 
-#include "rtc_base/atomicops.h"
+#include "rtc_base/atomic_ops.h"
 #include "rtc_base/checks.h"
 
 // Macros for allowing WebRTC clients (e.g. Chrome) to gather and aggregate
@@ -133,7 +134,7 @@
 // TODO(qingsi): Refactor the default implementation given by RtcHistogram,
 // which is already sparse, and remove the boundary argument from the macro.
 #define RTC_HISTOGRAM_ENUMERATION_SPARSE(name, sample, boundary) \
-  RTC_HISTOGRAM_COMMON_BLOCK(                                    \
+  RTC_HISTOGRAM_COMMON_BLOCK_SLOW(                               \
       name, sample,                                              \
       webrtc::metrics::SparseHistogramFactoryGetEnumeration(name, boundary))
 
@@ -148,7 +149,7 @@
 // Histogram for enumerators (evenly spaced buckets).
 // |boundary| should be above the max enumerator sample.
 #define RTC_HISTOGRAM_ENUMERATION(name, sample, boundary) \
-  RTC_HISTOGRAM_COMMON_BLOCK(                             \
+  RTC_HISTOGRAM_COMMON_BLOCK_SLOW(                        \
       name, sample,                                       \
       webrtc::metrics::HistogramFactoryGetEnumeration(name, boundary))
 
@@ -175,7 +176,6 @@
     }                                                                      \
   } while (0)
 
-// Deprecated.
 // The histogram is constructed/found for each call.
 // May be used for histograms with infrequent updates.`
 #define RTC_HISTOGRAM_COMMON_BLOCK_SLOW(name, sample, factory_get_invocation) \
@@ -309,6 +309,10 @@
 // Returns the minimum sample value (or -1 if the histogram has no samples).
 int MinSample(const std::string& name);
 
+// Returns a map with keys the samples with at least one event and values the
+// number of events for that sample.
+std::map<int, int> Samples(const std::string& name);
+
 }  // namespace metrics
 }  // namespace webrtc
 
diff --git a/system_wrappers/source/clock.cc b/system_wrappers/source/clock.cc
index 32cf1de..f69d13c 100644
--- a/system_wrappers/source/clock.cc
+++ b/system_wrappers/source/clock.cc
@@ -17,7 +17,7 @@
 
 #include <mmsystem.h>
 
-#include "rtc_base/criticalsection.h"
+#include "rtc_base/critical_section.h"
 
 #elif defined(WEBRTC_POSIX)
 
@@ -27,21 +27,21 @@
 #endif  // defined(WEBRTC_POSIX)
 
 #include "rtc_base/synchronization/rw_lock_wrapper.h"
-#include "rtc_base/timeutils.h"
+#include "rtc_base/time_utils.h"
 
 namespace webrtc {
 
 class RealTimeClock : public Clock {
   // Return a timestamp in milliseconds relative to some arbitrary source; the
   // source is fixed for this clock.
-  int64_t TimeInMilliseconds() const override { return rtc::TimeMillis(); }
+  int64_t TimeInMilliseconds() override { return rtc::TimeMillis(); }
 
   // Return a timestamp in microseconds relative to some arbitrary source; the
   // source is fixed for this clock.
-  int64_t TimeInMicroseconds() const override { return rtc::TimeMicros(); }
+  int64_t TimeInMicroseconds() override { return rtc::TimeMicros(); }
 
   // Retrieve an NTP absolute timestamp.
-  NtpTime CurrentNtpTime() const override {
+  NtpTime CurrentNtpTime() override {
     timeval tv = CurrentTimeVal();
     double microseconds_in_seconds;
     uint32_t seconds;
@@ -52,7 +52,7 @@
   }
 
   // Retrieve an NTP absolute timestamp in milliseconds.
-  int64_t CurrentNtpInMilliseconds() const override {
+  int64_t CurrentNtpInMilliseconds() override {
     timeval tv = CurrentTimeVal();
     uint32_t seconds;
     double microseconds_in_seconds;
@@ -62,7 +62,7 @@
   }
 
  protected:
-  virtual timeval CurrentTimeVal() const = 0;
+  virtual timeval CurrentTimeVal() = 0;
 
   static void Adjust(const timeval& tv,
                      uint32_t* adjusted_s,
@@ -87,7 +87,7 @@
   ~WinUwpRealTimeClock() override {}
 
  protected:
-  timeval CurrentTimeVal() const override {
+  timeval CurrentTimeVal() override {
     // The rtc::SystemTimeNanos() method is already time offset from a base
     // epoch value and might as be synchronized against an NTP time server as
     // an added bonus.
@@ -104,7 +104,7 @@
 
 #elif defined(WEBRTC_WIN)
 // TODO(pbos): Consider modifying the implementation to synchronize itself
-// against system time (update ref_point_, make it non-const) periodically to
+// against system time (update ref_point_) periodically to
 // prevent clock drift.
 class WindowsRealTimeClock : public RealTimeClock {
  public:
@@ -121,7 +121,7 @@
     LARGE_INTEGER counter_ms;
   };
 
-  timeval CurrentTimeVal() const override {
+  timeval CurrentTimeVal() override {
     const uint64_t FILETIME_1970 = 0x019db1ded53e8000;
 
     FILETIME StartTime;
@@ -143,7 +143,7 @@
     return tv;
   }
 
-  void GetTime(FILETIME* current_time) const {
+  void GetTime(FILETIME* current_time) {
     DWORD t;
     LARGE_INTEGER elapsed_ms;
     {
@@ -197,10 +197,9 @@
     return ref;
   }
 
-  // mutable as time-accessing functions are const.
   rtc::CriticalSection crit_;
-  mutable DWORD last_time_ms_;
-  mutable LONG num_timer_wraps_;
+  DWORD last_time_ms_;
+  LONG num_timer_wraps_;
   const ReferencePoint ref_point_;
 };
 
@@ -212,7 +211,7 @@
   ~UnixRealTimeClock() override {}
 
  protected:
-  timeval CurrentTimeVal() const override {
+  timeval CurrentTimeVal() override {
     struct timeval tv;
     struct timezone tz;
     tz.tz_minuteswest = 0;
@@ -241,17 +240,17 @@
 
 SimulatedClock::~SimulatedClock() {}
 
-int64_t SimulatedClock::TimeInMilliseconds() const {
+int64_t SimulatedClock::TimeInMilliseconds() {
   ReadLockScoped synchronize(*lock_);
   return (time_us_ + 500) / 1000;
 }
 
-int64_t SimulatedClock::TimeInMicroseconds() const {
+int64_t SimulatedClock::TimeInMicroseconds() {
   ReadLockScoped synchronize(*lock_);
   return time_us_;
 }
 
-NtpTime SimulatedClock::CurrentNtpTime() const {
+NtpTime SimulatedClock::CurrentNtpTime() {
   int64_t now_ms = TimeInMilliseconds();
   uint32_t seconds = (now_ms / 1000) + kNtpJan1970;
   uint32_t fractions =
@@ -259,7 +258,7 @@
   return NtpTime(seconds, fractions);
 }
 
-int64_t SimulatedClock::CurrentNtpInMilliseconds() const {
+int64_t SimulatedClock::CurrentNtpInMilliseconds() {
   return TimeInMilliseconds() + 1000 * static_cast<int64_t>(kNtpJan1970);
 }
 
@@ -272,4 +271,4 @@
   time_us_ += microseconds;
 }
 
-};  // namespace webrtc
+}  // namespace webrtc
diff --git a/system_wrappers/source/cpu_info.cc b/system_wrappers/source/cpu_info.cc
index c17d59d..6bcdd5f 100644
--- a/system_wrappers/source/cpu_info.cc
+++ b/system_wrappers/source/cpu_info.cc
@@ -14,9 +14,10 @@
 #include <windows.h>
 #elif defined(WEBRTC_LINUX)
 #include <unistd.h>
-#endif
-#if defined(WEBRTC_MAC)
+#elif defined(WEBRTC_MAC)
 #include <sys/sysctl.h>
+#elif defined(WEBRTC_FUCHSIA)
+#include <zircon/syscalls.h>
 #endif
 
 #include "rtc_base/logging.h"
@@ -32,13 +33,15 @@
   number_of_cores = static_cast<int>(si.dwNumberOfProcessors);
 #elif defined(WEBRTC_LINUX) || defined(WEBRTC_ANDROID)
   number_of_cores = static_cast<int>(sysconf(_SC_NPROCESSORS_ONLN));
-#elif defined(WEBRTC_MAC)
+#elif defined(WEBRTC_MAC) || defined(WEBRTC_IOS)
   int name[] = {CTL_HW, HW_AVAILCPU};
   size_t size = sizeof(number_of_cores);
   if (0 != sysctl(name, 2, &number_of_cores, &size, NULL, 0)) {
     RTC_LOG(LS_ERROR) << "Failed to get number of cores";
     number_of_cores = 1;
   }
+#elif defined(WEBRTC_FUCHSIA)
+  number_of_cores = zx_system_get_num_cpus();
 #else
   RTC_LOG(LS_ERROR) << "No function to get number of cores";
 #endif
diff --git a/system_wrappers/source/metrics.cc b/system_wrappers/source/metrics.cc
index 4aa8770..2383272 100644
--- a/system_wrappers/source/metrics.cc
+++ b/system_wrappers/source/metrics.cc
@@ -11,7 +11,7 @@
 
 #include <algorithm>
 
-#include "rtc_base/criticalsection.h"
+#include "rtc_base/critical_section.h"
 #include "rtc_base/thread_annotations.h"
 
 // Default implementation of histogram methods for WebRTC clients that do not
@@ -88,6 +88,11 @@
     return (info_.samples.empty()) ? -1 : info_.samples.begin()->first;
   }
 
+  std::map<int, int> Samples() const {
+    rtc::CritScope cs(&crit_);
+    return info_.samples;
+  }
+
  private:
   rtc::CriticalSection crit_;
   const int min_;
@@ -162,6 +167,12 @@
     return (it == map_.end()) ? -1 : it->second->MinSample();
   }
 
+  std::map<int, int> Samples(const std::string& name) const {
+    rtc::CritScope cs(&crit_);
+    const auto& it = map_.find(name);
+    return (it == map_.end()) ? std::map<int, int>() : it->second->Samples();
+  }
+
  private:
   rtc::CriticalSection crit_;
   std::map<std::string, std::unique_ptr<RtcHistogram>> map_
@@ -307,5 +318,10 @@
   return map ? map->MinSample(name) : -1;
 }
 
+std::map<int, int> Samples(const std::string& name) {
+  RtcHistogramMap* map = GetMap();
+  return map ? map->Samples(name) : std::map<int, int>();
+}
+
 }  // namespace metrics
 }  // namespace webrtc
diff --git a/system_wrappers/source/metrics_default_unittest.cc b/system_wrappers/source/metrics_default_unittest.cc
index b2d2023..cb427c2 100644
--- a/system_wrappers/source/metrics_default_unittest.cc
+++ b/system_wrappers/source/metrics_default_unittest.cc
@@ -8,6 +8,12 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
+#include <map>
+#include <memory>
+#include <string>
+#include <utility>
+
+#include "rtc_base/checks.h"
 #include "system_wrappers/include/metrics.h"
 #include "test/gtest.h"
 
diff --git a/system_wrappers/source/metrics_unittest.cc b/system_wrappers/source/metrics_unittest.cc
index dac8177..9c96ba0 100644
--- a/system_wrappers/source/metrics_unittest.cc
+++ b/system_wrappers/source/metrics_unittest.cc
@@ -9,8 +9,13 @@
  */
 
 #include "system_wrappers/include/metrics.h"
+#include "test/gmock.h"
 #include "test/gtest.h"
 
+using ::testing::ElementsAre;
+using ::testing::IsEmpty;
+using ::testing::Pair;
+
 namespace webrtc {
 namespace {
 const int kSample = 22;
@@ -34,6 +39,7 @@
 TEST_F(MetricsTest, InitiallyNoSamples) {
   EXPECT_EQ(0, metrics::NumSamples("NonExisting"));
   EXPECT_EQ(0, metrics::NumEvents("NonExisting", kSample));
+  EXPECT_THAT(metrics::Samples("NonExisting"), IsEmpty());
 }
 
 TEST_F(MetricsTest, RtcHistogramPercent_AddSample) {
@@ -41,6 +47,7 @@
   RTC_HISTOGRAM_PERCENTAGE(kName, kSample);
   EXPECT_EQ(1, metrics::NumSamples(kName));
   EXPECT_EQ(1, metrics::NumEvents(kName, kSample));
+  EXPECT_THAT(metrics::Samples(kName), ElementsAre(Pair(kSample, 1)));
 }
 
 TEST_F(MetricsTest, RtcHistogramEnumeration_AddSample) {
@@ -48,6 +55,7 @@
   RTC_HISTOGRAM_ENUMERATION(kName, kSample, kSample + 1);
   EXPECT_EQ(1, metrics::NumSamples(kName));
   EXPECT_EQ(1, metrics::NumEvents(kName, kSample));
+  EXPECT_THAT(metrics::Samples(kName), ElementsAre(Pair(kSample, 1)));
 }
 
 TEST_F(MetricsTest, RtcHistogramBoolean_AddSample) {
@@ -56,6 +64,7 @@
   RTC_HISTOGRAM_BOOLEAN(kName, kSample);
   EXPECT_EQ(1, metrics::NumSamples(kName));
   EXPECT_EQ(1, metrics::NumEvents(kName, kSample));
+  EXPECT_THAT(metrics::Samples(kName), ElementsAre(Pair(kSample, 1)));
 }
 
 TEST_F(MetricsTest, RtcHistogramCountsSparse_AddSample) {
@@ -63,6 +72,7 @@
   RTC_HISTOGRAM_COUNTS_SPARSE_100(kName, kSample);
   EXPECT_EQ(1, metrics::NumSamples(kName));
   EXPECT_EQ(1, metrics::NumEvents(kName, kSample));
+  EXPECT_THAT(metrics::Samples(kName), ElementsAre(Pair(kSample, 1)));
 }
 
 TEST_F(MetricsTest, RtcHistogramCounts_AddSample) {
@@ -70,16 +80,20 @@
   RTC_HISTOGRAM_COUNTS_100(kName, kSample);
   EXPECT_EQ(1, metrics::NumSamples(kName));
   EXPECT_EQ(1, metrics::NumEvents(kName, kSample));
+  EXPECT_THAT(metrics::Samples(kName), ElementsAre(Pair(kSample, 1)));
 }
 
 TEST_F(MetricsTest, RtcHistogramCounts_AddMultipleSamples) {
   const std::string kName = "Counts200";
   const int kNumSamples = 10;
+  std::map<int, int> samples;
   for (int i = 1; i <= kNumSamples; ++i) {
     RTC_HISTOGRAM_COUNTS_200(kName, i);
     EXPECT_EQ(1, metrics::NumEvents(kName, i));
     EXPECT_EQ(i, metrics::NumSamples(kName));
+    samples[i] = 1;
   }
+  EXPECT_EQ(samples, metrics::Samples(kName));
 }
 
 TEST_F(MetricsTest, RtcHistogramsCounts_AddSample) {
@@ -92,6 +106,9 @@
   EXPECT_EQ(1, metrics::NumEvents("Name1", kSample + 0));
   EXPECT_EQ(1, metrics::NumEvents("Name2", kSample + 1));
   EXPECT_EQ(1, metrics::NumEvents("Name3", kSample + 2));
+  EXPECT_THAT(metrics::Samples("Name1"), ElementsAre(Pair(kSample + 0, 1)));
+  EXPECT_THAT(metrics::Samples("Name2"), ElementsAre(Pair(kSample + 1, 1)));
+  EXPECT_THAT(metrics::Samples("Name3"), ElementsAre(Pair(kSample + 2, 1)));
 }
 
 #if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
@@ -107,6 +124,8 @@
   AddSparseSample("Sparse2", kSample);
   EXPECT_EQ(1, metrics::NumSamples("Sparse1"));
   EXPECT_EQ(1, metrics::NumSamples("Sparse2"));
+  EXPECT_THAT(metrics::Samples("Sparse1"), ElementsAre(Pair(kSample, 1)));
+  EXPECT_THAT(metrics::Samples("Sparse2"), ElementsAre(Pair(kSample, 1)));
 }
 
 }  // namespace webrtc
diff --git a/system_wrappers/source/rtp_to_ntp_estimator_unittest.cc b/system_wrappers/source/rtp_to_ntp_estimator_unittest.cc
index b0b83bb..14bc6e0 100644
--- a/system_wrappers/source/rtp_to_ntp_estimator_unittest.cc
+++ b/system_wrappers/source/rtp_to_ntp_estimator_unittest.cc
@@ -9,6 +9,9 @@
  */
 
 #include "system_wrappers/include/rtp_to_ntp_estimator.h"
+
+#include <stddef.h>
+
 #include "rtc_base/random.h"
 #include "test/gtest.h"
 
@@ -343,4 +346,4 @@
   }
 }
 
-};  // namespace webrtc
+}  // namespace webrtc
diff --git a/third_party/rnnoise/src/kiss_fft_unittest.cc b/third_party/rnnoise/src/kiss_fft_unittest.cc
index 3132445..f7d1bb0 100644
--- a/third_party/rnnoise/src/kiss_fft_unittest.cc
+++ b/third_party/rnnoise/src/kiss_fft_unittest.cc
@@ -77,20 +77,20 @@
                  tolerance);
 }
 
-INSTANTIATE_TEST_CASE_P(FftPoints,
-                        RnnVadTest,
-                        ::testing::Values(std::make_tuple(1.f, 240, 3e-7f),
-                                          std::make_tuple(1.f, 256, 3e-7f),
-                                          std::make_tuple(1.f, 480, 3e-7f),
-                                          std::make_tuple(1.f, 512, 3e-7f),
-                                          std::make_tuple(1.f, 960, 4e-7f),
-                                          std::make_tuple(1.f, 1024, 3e-7f),
-                                          std::make_tuple(30.f, 240, 5e-6f),
-                                          std::make_tuple(30.f, 256, 5e-6f),
-                                          std::make_tuple(30.f, 480, 6e-6f),
-                                          std::make_tuple(30.f, 512, 6e-6f),
-                                          std::make_tuple(30.f, 960, 8e-6f),
-                                          std::make_tuple(30.f, 1024, 6e-6f)));
+INSTANTIATE_TEST_SUITE_P(FftPoints,
+                         RnnVadTest,
+                         ::testing::Values(std::make_tuple(1.f, 240, 3e-7f),
+                                           std::make_tuple(1.f, 256, 3e-7f),
+                                           std::make_tuple(1.f, 480, 3e-7f),
+                                           std::make_tuple(1.f, 512, 3e-7f),
+                                           std::make_tuple(1.f, 960, 4e-7f),
+                                           std::make_tuple(1.f, 1024, 3e-7f),
+                                           std::make_tuple(30.f, 240, 5e-6f),
+                                           std::make_tuple(30.f, 256, 5e-6f),
+                                           std::make_tuple(30.f, 480, 6e-6f),
+                                           std::make_tuple(30.f, 512, 6e-6f),
+                                           std::make_tuple(30.f, 960, 8e-6f),
+                                           std::make_tuple(30.f, 1024, 6e-6f)));
 
 TEST(RnnVadTest, KissFftBitExactness) {
   constexpr std::array<float, 32> samples = {
diff --git a/webrtc_apm.cc b/webrtc_apm.cc
index ce8f8ee..e3e6fe0 100644
--- a/webrtc_apm.cc
+++ b/webrtc_apm.cc
@@ -4,6 +4,7 @@
  */
 
 #include "api/audio/echo_canceller3_factory.h"
+#include "api/task_queue/default_task_queue_factory.h"
 #include "cras-config/aec_config.h"
 #include "cras-config/apm_config.h"
 #include "modules/audio_processing/aec_dump/aec_dump_factory.h"