Add base class NetworkPredictor and NetworkPredictorFactory and wire up.

Add base class NetworkPredictor and NetworkPredictorFactory in /api, make it possible to inject customized NetworkPredictor in PeerConnectionFactory level. The NetworkPredictor object will be pass down to GoogCCNetworkControl and DelayBasedBwe.

Bug: webrtc:10492
Change-Id: Iceeadbe1c9388b11ce4ac01ee56554cb0bf64d04
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/130201
Commit-Queue: Ying Wang <yinwa@webrtc.org>
Reviewed-by: Per Kjellander <perkj@webrtc.org>
Reviewed-by: Stefan Holmer <stefan@webrtc.org>
Reviewed-by: Sami Kalliomäki <sakal@webrtc.org>
Reviewed-by: Christoffer Rodbro <crodbro@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#27543}
diff --git a/api/BUILD.gn b/api/BUILD.gn
index 28ddff1..84b0c0e 100644
--- a/api/BUILD.gn
+++ b/api/BUILD.gn
@@ -45,6 +45,7 @@
     ":callfactory_api",
     ":fec_controller_api",
     ":libjingle_peerconnection_api",
+    ":network_state_predictor_api",
     ":scoped_refptr",
     "../logging:rtc_event_log_api",
     "../logging:rtc_event_log_impl_base",
@@ -140,6 +141,7 @@
     ":callfactory_api",
     ":fec_controller_api",
     ":libjingle_logging_api",
+    ":network_state_predictor_api",
     ":rtc_stats_api",
     ":scoped_refptr",
     "audio:audio_mixer_api",
@@ -187,6 +189,7 @@
   deps = [
     ":fec_controller_api",
     ":libjingle_peerconnection_api",
+    ":network_state_predictor_api",
     ":simulated_network_api",
     "../call:fake_network",
     "../call:rtp_interfaces",
@@ -259,6 +262,7 @@
     ":fec_controller_api",
     ":function_view",
     ":libjingle_peerconnection_api",
+    ":network_state_predictor_api",
     ":simulated_network_api",
     ":video_quality_analyzer_api",
     "../logging:rtc_event_log_api",
@@ -296,6 +300,7 @@
     ]
     deps = [
       ":fec_controller_api",
+      ":network_state_predictor_api",
       ":scoped_refptr",
       ":video_quality_test_fixture_api",
       "../video:video_quality_test",
@@ -443,6 +448,13 @@
   ]
 }
 
+rtc_source_set("network_state_predictor_api") {
+  visibility = [ "*" ]
+  sources = [
+    "network_state_predictor.h",
+  ]
+}
+
 rtc_source_set("array_view") {
   visibility = [ "*" ]
   sources = [
diff --git a/api/network_state_predictor.h b/api/network_state_predictor.h
new file mode 100644
index 0000000..9cf5ab6
--- /dev/null
+++ b/api/network_state_predictor.h
@@ -0,0 +1,56 @@
+/*
+ *  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_NETWORK_STATE_PREDICTOR_H_
+#define API_NETWORK_STATE_PREDICTOR_H_
+
+#include <memory>
+#include <vector>
+
+namespace webrtc {
+
+enum class BandwidthUsage {
+  kBwNormal = 0,
+  kBwUnderusing = 1,
+  kBwOverusing = 2,
+  kLast
+};
+
+// TODO(yinwa): work in progress. API in class NetworkStatePredictor should not
+// be used by other users until this comment is removed.
+
+// NetworkStatePredictor predict network state based on current network metrics.
+// Usage:
+// Setup by calling Initialize.
+// For each update, call Update. Update returns network state
+// prediction.
+class NetworkStatePredictor {
+ public:
+  virtual ~NetworkStatePredictor() {}
+
+  // Returns current network state prediction.
+  // Inputs:  send_time_ms - packet send time.
+  //          arrival_time_ms - packet arrival time.
+  //          network_state - computed network state.
+  virtual BandwidthUsage Update(int64_t send_time_ms,
+                                int64_t arrival_time_ms,
+                                BandwidthUsage network_state) = 0;
+};
+
+class NetworkStatePredictorFactoryInterface {
+ public:
+  virtual std::unique_ptr<NetworkStatePredictor>
+  CreateNetworkStatePredictor() = 0;
+  virtual ~NetworkStatePredictorFactoryInterface() = default;
+};
+
+}  // namespace webrtc
+
+#endif  // API_NETWORK_STATE_PREDICTOR_H_
diff --git a/api/peer_connection_interface.h b/api/peer_connection_interface.h
index 661c5aa..36f2bcd 100644
--- a/api/peer_connection_interface.h
+++ b/api/peer_connection_interface.h
@@ -83,6 +83,7 @@
 #include "api/jsep.h"
 #include "api/media_stream_interface.h"
 #include "api/media_transport_interface.h"
+#include "api/network_state_predictor.h"
 #include "api/rtc_error.h"
 #include "api/rtc_event_log_output.h"
 #include "api/rtp_receiver_interface.h"
@@ -1248,6 +1249,8 @@
   std::unique_ptr<CallFactoryInterface> call_factory;
   std::unique_ptr<RtcEventLogFactoryInterface> event_log_factory;
   std::unique_ptr<FecControllerFactoryInterface> fec_controller_factory;
+  std::unique_ptr<NetworkStatePredictorFactoryInterface>
+      network_state_predictor_factory;
   std::unique_ptr<NetworkControllerFactoryInterface> network_controller_factory;
   std::unique_ptr<MediaTransportFactory> media_transport_factory;
 };
@@ -1427,6 +1430,8 @@
     std::unique_ptr<CallFactoryInterface> call_factory,
     std::unique_ptr<RtcEventLogFactoryInterface> event_log_factory,
     std::unique_ptr<FecControllerFactoryInterface> fec_controller_factory,
+    std::unique_ptr<NetworkStatePredictorFactoryInterface>
+        network_state_predictor_factory,
     std::unique_ptr<NetworkControllerFactoryInterface>
         network_controller_factory = nullptr);
 
diff --git a/api/transport/BUILD.gn b/api/transport/BUILD.gn
index 47146d8..5c40deb 100644
--- a/api/transport/BUILD.gn
+++ b/api/transport/BUILD.gn
@@ -78,6 +78,7 @@
   deps = [
     ":network_control",
     ":webrtc_key_value_config",
+    "..:network_state_predictor_api",
     "../../modules/congestion_controller/goog_cc",
     "//third_party/abseil-cpp/absl/memory",
   ]
diff --git a/api/transport/goog_cc_factory.cc b/api/transport/goog_cc_factory.cc
index 92fd4d1..00f6a2e 100644
--- a/api/transport/goog_cc_factory.cc
+++ b/api/transport/goog_cc_factory.cc
@@ -18,11 +18,21 @@
 namespace webrtc {
 GoogCcNetworkControllerFactory::GoogCcNetworkControllerFactory(
     RtcEventLog* event_log)
-    : event_log_(event_log) {}
+    : event_log_(event_log), network_state_predictor_factory_(nullptr) {}
+
+GoogCcNetworkControllerFactory::GoogCcNetworkControllerFactory(
+    RtcEventLog* event_log,
+    NetworkStatePredictorFactoryInterface* network_state_predictor_factory)
+    : event_log_(event_log),
+      network_state_predictor_factory_(network_state_predictor_factory) {}
 
 std::unique_ptr<NetworkControllerInterface>
 GoogCcNetworkControllerFactory::Create(NetworkControllerConfig config) {
-  return absl::make_unique<GoogCcNetworkController>(event_log_, config, false);
+  return absl::make_unique<GoogCcNetworkController>(
+      event_log_, config, false,
+      network_state_predictor_factory_
+          ? network_state_predictor_factory_->CreateNetworkStatePredictor()
+          : nullptr);
 }
 
 TimeDelta GoogCcNetworkControllerFactory::GetProcessInterval() const {
@@ -36,7 +46,8 @@
 
 std::unique_ptr<NetworkControllerInterface>
 GoogCcFeedbackNetworkControllerFactory::Create(NetworkControllerConfig config) {
-  return absl::make_unique<GoogCcNetworkController>(event_log_, config, true);
+  return absl::make_unique<GoogCcNetworkController>(event_log_, config, true,
+                                                    nullptr);
 }
 
 TimeDelta GoogCcFeedbackNetworkControllerFactory::GetProcessInterval() const {
diff --git a/api/transport/goog_cc_factory.h b/api/transport/goog_cc_factory.h
index 2e3b317..dbf4fe1 100644
--- a/api/transport/goog_cc_factory.h
+++ b/api/transport/goog_cc_factory.h
@@ -12,6 +12,7 @@
 #define API_TRANSPORT_GOOG_CC_FACTORY_H_
 #include <memory>
 
+#include "api/network_state_predictor.h"
 #include "api/transport/network_control.h"
 
 namespace webrtc {
@@ -20,13 +21,17 @@
 class GoogCcNetworkControllerFactory
     : public NetworkControllerFactoryInterface {
  public:
-  explicit GoogCcNetworkControllerFactory(RtcEventLog*);
+  explicit GoogCcNetworkControllerFactory(RtcEventLog* event_log);
+  explicit GoogCcNetworkControllerFactory(
+      RtcEventLog* event_log,
+      NetworkStatePredictorFactoryInterface* network_state_predictor_factory);
   std::unique_ptr<NetworkControllerInterface> Create(
       NetworkControllerConfig config) override;
   TimeDelta GetProcessInterval() const override;
 
  private:
   RtcEventLog* const event_log_;
+  NetworkStatePredictorFactoryInterface* const network_state_predictor_factory_;
 };
 
 // Factory to create packet feedback only GoogCC, this can be used for
@@ -34,7 +39,7 @@
 class GoogCcFeedbackNetworkControllerFactory
     : public NetworkControllerFactoryInterface {
  public:
-  explicit GoogCcFeedbackNetworkControllerFactory(RtcEventLog*);
+  explicit GoogCcFeedbackNetworkControllerFactory(RtcEventLog* event_log);
   std::unique_ptr<NetworkControllerInterface> Create(
       NetworkControllerConfig config) override;
   TimeDelta GetProcessInterval() const override;
diff --git a/audio/test/media_transport_test.cc b/audio/test/media_transport_test.cc
index c48a1f6..7794b43 100644
--- a/audio/test/media_transport_test.cc
+++ b/audio/test/media_transport_test.cc
@@ -125,7 +125,7 @@
   std::unique_ptr<TaskQueueFactory> task_queue_factory =
       CreateDefaultTaskQueueFactory();
   RtpTransportControllerSend rtp_transport(
-      Clock::GetRealTimeClock(), null_event_log.get(), nullptr,
+      Clock::GetRealTimeClock(), null_event_log.get(), nullptr, nullptr,
       BitrateConstraints(), ProcessThread::Create("Pacer"),
       task_queue_factory.get());
   webrtc::internal::AudioSendStream send_stream(
diff --git a/call/BUILD.gn b/call/BUILD.gn
index 346cbe2..6ddaf6e 100644
--- a/call/BUILD.gn
+++ b/call/BUILD.gn
@@ -32,6 +32,7 @@
     ":video_stream_api",
     "../api:fec_controller_api",
     "../api:libjingle_peerconnection_api",
+    "../api:network_state_predictor_api",
     "../api:rtp_headers",
     "../api:scoped_refptr",
     "../api:transport_api",
@@ -124,6 +125,7 @@
     ":bitrate_configurator",
     ":rtp_interfaces",
     "../api:fec_controller_api",
+    "../api:network_state_predictor_api",
     "../api:transport_api",
     "../api/transport:field_trial_based_config",
     "../api/transport:goog_cc",
diff --git a/call/call.cc b/call/call.cc
index 84f29d8..ee6cbc6 100644
--- a/call/call.cc
+++ b/call/call.cc
@@ -439,8 +439,9 @@
   return new internal::Call(
       clock, config,
       absl::make_unique<RtpTransportControllerSend>(
-          clock, config.event_log, config.network_controller_factory,
-          config.bitrate_config, std::move(pacer_thread), task_queue_factory),
+          clock, config.event_log, config.network_state_predictor_factory,
+          config.network_controller_factory, config.bitrate_config,
+          std::move(pacer_thread), task_queue_factory),
       std::move(call_thread), task_queue_factory);
 }
 
diff --git a/call/call_config.h b/call/call_config.h
index eaac16b..d111b53 100644
--- a/call/call_config.h
+++ b/call/call_config.h
@@ -12,6 +12,7 @@
 
 #include "api/bitrate_constraints.h"
 #include "api/fec_controller.h"
+#include "api/network_state_predictor.h"
 #include "api/rtc_error.h"
 #include "api/task_queue/task_queue_factory.h"
 #include "api/transport/network_control.h"
@@ -49,6 +50,10 @@
   // Task Queue Factory to be used in this call.
   TaskQueueFactory* task_queue_factory = nullptr;
 
+  // NetworkStatePredictor to use for this call.
+  NetworkStatePredictorFactoryInterface* network_state_predictor_factory =
+      nullptr;
+
   // Network controller factory to use for this call.
   NetworkControllerFactoryInterface* network_controller_factory = nullptr;
 };
diff --git a/call/rtp_transport_controller_send.cc b/call/rtp_transport_controller_send.cc
index ab95907..11e35a9 100644
--- a/call/rtp_transport_controller_send.cc
+++ b/call/rtp_transport_controller_send.cc
@@ -58,6 +58,7 @@
 RtpTransportControllerSend::RtpTransportControllerSend(
     Clock* clock,
     webrtc::RtcEventLog* event_log,
+    NetworkStatePredictorFactoryInterface* predictor_factory,
     NetworkControllerFactoryInterface* controller_factory,
     const BitrateConstraints& bitrate_config,
     std::unique_ptr<ProcessThread> process_thread,
@@ -69,7 +70,8 @@
       observer_(nullptr),
       controller_factory_override_(controller_factory),
       controller_factory_fallback_(
-          absl::make_unique<GoogCcNetworkControllerFactory>(event_log)),
+          absl::make_unique<GoogCcNetworkControllerFactory>(event_log,
+                                                            predictor_factory)),
       process_interval_(controller_factory_fallback_->GetProcessInterval()),
       last_report_block_time_(Timestamp::ms(clock_->TimeInMilliseconds())),
       reset_feedback_on_route_change_(
diff --git a/call/rtp_transport_controller_send.h b/call/rtp_transport_controller_send.h
index c8a9f2c..43dc1a0 100644
--- a/call/rtp_transport_controller_send.h
+++ b/call/rtp_transport_controller_send.h
@@ -17,6 +17,7 @@
 #include <string>
 #include <vector>
 
+#include "api/network_state_predictor.h"
 #include "api/transport/network_control.h"
 #include "call/rtp_bitrate_configurator.h"
 #include "call/rtp_transport_controller_send_interface.h"
@@ -47,6 +48,7 @@
   RtpTransportControllerSend(
       Clock* clock,
       RtcEventLog* event_log,
+      NetworkStatePredictorFactoryInterface* predictor_factory,
       NetworkControllerFactoryInterface* controller_factory,
       const BitrateConstraints& bitrate_config,
       std::unique_ptr<ProcessThread> process_thread,
diff --git a/call/rtp_video_sender_unittest.cc b/call/rtp_video_sender_unittest.cc
index d1c7714..0b0b3fe 100644
--- a/call/rtp_video_sender_unittest.cc
+++ b/call/rtp_video_sender_unittest.cc
@@ -83,6 +83,7 @@
         transport_controller_(&clock_,
                               &event_log_,
                               nullptr,
+                              nullptr,
                               bitrate_config_,
                               ProcessThread::Create("PacerThread"),
                               &GlobalTaskQueueFactory()),
diff --git a/modules/congestion_controller/OWNERS b/modules/congestion_controller/OWNERS
index de51596..a9a7075 100644
--- a/modules/congestion_controller/OWNERS
+++ b/modules/congestion_controller/OWNERS
@@ -3,6 +3,7 @@
 terelius@webrtc.org
 philipel@webrtc.org
 mflodman@webrtc.org
+yinwa@webrtc.org
 
 # These are for the common case of adding or renaming files. If you're doing
 # structural changes, please get a review from a reviewer in this file.
diff --git a/modules/congestion_controller/goog_cc/BUILD.gn b/modules/congestion_controller/goog_cc/BUILD.gn
index 0124514..d9749bc 100644
--- a/modules/congestion_controller/goog_cc/BUILD.gn
+++ b/modules/congestion_controller/goog_cc/BUILD.gn
@@ -30,6 +30,8 @@
     ":probe_controller",
     ":pushback_controller",
     "../..:module_api",
+    "../../..:webrtc_common",
+    "../../../api:network_state_predictor_api",
     "../../../api/transport:field_trial_based_config",
     "../../../api/transport:network_control",
     "../../../api/transport:webrtc_key_value_config",
@@ -116,6 +118,7 @@
   ]
 
   deps = [
+    "../../../api:network_state_predictor_api",
     "../../../api/transport:webrtc_key_value_config",
     "../../../api/units:data_rate",
     "../../../logging:rtc_event_bwe",
@@ -143,6 +146,7 @@
 
   deps = [
     ":estimators",
+    "../../../api:network_state_predictor_api",
     "../../../api/transport:network_control",
     "../../../api/transport:webrtc_key_value_config",
     "../../../logging:rtc_event_bwe",
diff --git a/modules/congestion_controller/goog_cc/delay_based_bwe.cc b/modules/congestion_controller/goog_cc/delay_based_bwe.cc
index e152521..f551ca5 100644
--- a/modules/congestion_controller/goog_cc/delay_based_bwe.cc
+++ b/modules/congestion_controller/goog_cc/delay_based_bwe.cc
@@ -83,7 +83,8 @@
 DelayBasedBwe::Result::~Result() {}
 
 DelayBasedBwe::DelayBasedBwe(const WebRtcKeyValueConfig* key_value_config,
-                             RtcEventLog* event_log)
+                             RtcEventLog* event_log,
+                             NetworkStatePredictor* network_state_predictor)
     : event_log_(event_log),
       inter_arrival_(),
       delay_detector_(),
@@ -100,13 +101,14 @@
       prev_state_(BandwidthUsage::kBwNormal),
       alr_limited_backoff_enabled_(
           key_value_config->Lookup("WebRTC-Bwe-AlrLimitedBackoff")
-              .find("Enabled") == 0) {
+              .find("Enabled") == 0),
+      network_state_predictor_(network_state_predictor) {
   RTC_LOG(LS_INFO)
       << "Using Trendline filter for delay change estimation with window size "
       << trendline_window_size_;
-  delay_detector_.reset(new TrendlineEstimator(trendline_window_size_,
-                                               trendline_smoothing_coeff_,
-                                               trendline_threshold_gain_));
+  delay_detector_.reset(new TrendlineEstimator(
+      trendline_window_size_, trendline_smoothing_coeff_,
+      trendline_threshold_gain_, network_state_predictor_));
 }
 
 DelayBasedBwe::~DelayBasedBwe() {}
@@ -169,9 +171,9 @@
     inter_arrival_.reset(
         new InterArrival((kTimestampGroupLengthMs << kInterArrivalShift) / 1000,
                          kTimestampToMs, true));
-    delay_detector_.reset(new TrendlineEstimator(trendline_window_size_,
-                                                 trendline_smoothing_coeff_,
-                                                 trendline_threshold_gain_));
+    delay_detector_.reset(new TrendlineEstimator(
+        trendline_window_size_, trendline_smoothing_coeff_,
+        trendline_threshold_gain_, network_state_predictor_));
   }
   last_seen_packet_ = at_time;
 
@@ -189,13 +191,12 @@
   uint32_t ts_delta = 0;
   int64_t t_delta = 0;
   int size_delta = 0;
-  if (inter_arrival_->ComputeDeltas(timestamp, packet_feedback.arrival_time_ms,
-                                    at_time.ms(), packet_feedback.payload_size,
-                                    &ts_delta, &t_delta, &size_delta)) {
-    double ts_delta_ms = (1000.0 * ts_delta) / (1 << kInterArrivalShift);
-    delay_detector_->Update(t_delta, ts_delta_ms,
-                            packet_feedback.arrival_time_ms);
-  }
+  bool calculated_deltas = inter_arrival_->ComputeDeltas(
+      timestamp, packet_feedback.arrival_time_ms, at_time.ms(),
+      packet_feedback.payload_size, &ts_delta, &t_delta, &size_delta);
+  double ts_delta_ms = (1000.0 * ts_delta) / (1 << kInterArrivalShift);
+  delay_detector_->Update(t_delta, ts_delta_ms, packet_feedback.send_time_ms,
+                          packet_feedback.arrival_time_ms, calculated_deltas);
 }
 
 DelayBasedBwe::Result DelayBasedBwe::MaybeUpdateEstimate(
diff --git a/modules/congestion_controller/goog_cc/delay_based_bwe.h b/modules/congestion_controller/goog_cc/delay_based_bwe.h
index c891afc..34d356e 100644
--- a/modules/congestion_controller/goog_cc/delay_based_bwe.h
+++ b/modules/congestion_controller/goog_cc/delay_based_bwe.h
@@ -17,6 +17,7 @@
 #include <vector>
 
 #include "absl/types/optional.h"
+#include "api/network_state_predictor.h"
 #include "api/transport/webrtc_key_value_config.h"
 #include "modules/congestion_controller/goog_cc/delay_increase_detector_interface.h"
 #include "modules/congestion_controller/goog_cc/probe_bitrate_estimator.h"
@@ -44,7 +45,8 @@
   };
 
   explicit DelayBasedBwe(const WebRtcKeyValueConfig* key_value_config,
-                         RtcEventLog* event_log);
+                         RtcEventLog* event_log,
+                         NetworkStatePredictor* network_state_predictor);
   virtual ~DelayBasedBwe();
 
   Result IncomingPacketFeedbackVector(
@@ -88,6 +90,7 @@
   DataRate prev_bitrate_;
   BandwidthUsage prev_state_;
   bool alr_limited_backoff_enabled_;
+  NetworkStatePredictor* network_state_predictor_;
 
   RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(DelayBasedBwe);
 };
diff --git a/modules/congestion_controller/goog_cc/delay_based_bwe_unittest_helper.cc b/modules/congestion_controller/goog_cc/delay_based_bwe_unittest_helper.cc
index c057656..3611fee 100644
--- a/modules/congestion_controller/goog_cc/delay_based_bwe_unittest_helper.cc
+++ b/modules/congestion_controller/goog_cc/delay_based_bwe_unittest_helper.cc
@@ -155,7 +155,8 @@
           absl::make_unique<AcknowledgedBitrateEstimator>(
               &field_trial_config_)),
       probe_bitrate_estimator_(new ProbeBitrateEstimator(nullptr)),
-      bitrate_estimator_(new DelayBasedBwe(&field_trial_config_, nullptr)),
+      bitrate_estimator_(
+          new DelayBasedBwe(&field_trial_config_, nullptr, nullptr)),
       stream_generator_(new test::StreamGenerator(1e6,  // Capacity.
                                                   clock_.TimeInMicroseconds())),
       arrival_time_offset_ms_(0),
@@ -169,7 +170,8 @@
           absl::make_unique<AcknowledgedBitrateEstimator>(
               &field_trial_config_)),
       probe_bitrate_estimator_(new ProbeBitrateEstimator(nullptr)),
-      bitrate_estimator_(new DelayBasedBwe(&field_trial_config_, nullptr)),
+      bitrate_estimator_(
+          new DelayBasedBwe(&field_trial_config_, nullptr, nullptr)),
       stream_generator_(new test::StreamGenerator(1e6,  // Capacity.
                                                   clock_.TimeInMicroseconds())),
       arrival_time_offset_ms_(0),
diff --git a/modules/congestion_controller/goog_cc/delay_increase_detector_interface.h b/modules/congestion_controller/goog_cc/delay_increase_detector_interface.h
index 40d945d..d1d7496 100644
--- a/modules/congestion_controller/goog_cc/delay_increase_detector_interface.h
+++ b/modules/congestion_controller/goog_cc/delay_increase_detector_interface.h
@@ -26,7 +26,9 @@
   // between timestamp groups as defined by the InterArrival class.
   virtual void Update(double recv_delta_ms,
                       double send_delta_ms,
-                      int64_t arrival_time_ms) = 0;
+                      int64_t send_time_ms,
+                      int64_t arrival_time_ms,
+                      bool calculated_deltas) = 0;
 
   virtual BandwidthUsage State() const = 0;
 
diff --git a/modules/congestion_controller/goog_cc/goog_cc_network_control.cc b/modules/congestion_controller/goog_cc/goog_cc_network_control.cc
index e3e1dcc..06d94fe 100644
--- a/modules/congestion_controller/goog_cc/goog_cc_network_control.cc
+++ b/modules/congestion_controller/goog_cc/goog_cc_network_control.cc
@@ -17,6 +17,7 @@
 #include <memory>
 #include <numeric>
 #include <string>
+#include <utility>
 #include <vector>
 
 #include "absl/memory/memory.h"
@@ -77,9 +78,11 @@
 }
 }  // namespace
 
-GoogCcNetworkController::GoogCcNetworkController(RtcEventLog* event_log,
-                                                 NetworkControllerConfig config,
-                                                 bool feedback_only)
+GoogCcNetworkController::GoogCcNetworkController(
+    RtcEventLog* event_log,
+    NetworkControllerConfig config,
+    bool feedback_only,
+    std::unique_ptr<NetworkStatePredictor> network_state_predictor)
     : key_value_config_(config.key_value_config ? config.key_value_config
                                                 : &trial_based_config_),
       event_log_(event_log),
@@ -104,7 +107,9 @@
           absl::make_unique<SendSideBandwidthEstimation>(event_log_)),
       alr_detector_(absl::make_unique<AlrDetector>()),
       probe_bitrate_estimator_(new ProbeBitrateEstimator(event_log)),
-      delay_based_bwe_(new DelayBasedBwe(key_value_config_, event_log_)),
+      delay_based_bwe_(new DelayBasedBwe(key_value_config_,
+                                         event_log_,
+                                         network_state_predictor.get())),
       acknowledged_bitrate_estimator_(
           absl::make_unique<AcknowledgedBitrateEstimator>(key_value_config_)),
       initial_config_(config),
@@ -117,7 +122,8 @@
               DataRate::Zero())),
       max_padding_rate_(config.stream_based_config.max_padding_rate.value_or(
           DataRate::Zero())),
-      max_total_allocated_bitrate_(DataRate::Zero()) {
+      max_total_allocated_bitrate_(DataRate::Zero()),
+      network_state_predictor_(std::move(network_state_predictor)) {
   RTC_DCHECK(config.constraints.at_time.IsFinite());
   ParseFieldTrial(
       {&safe_reset_on_route_change_, &safe_reset_acknowledged_rate_},
@@ -164,7 +170,8 @@
   acknowledged_bitrate_estimator_.reset(
       new AcknowledgedBitrateEstimator(key_value_config_));
   probe_bitrate_estimator_.reset(new ProbeBitrateEstimator(event_log_));
-  delay_based_bwe_.reset(new DelayBasedBwe(key_value_config_, event_log_));
+  delay_based_bwe_.reset(new DelayBasedBwe(key_value_config_, event_log_,
+                                           network_state_predictor_.get()));
   bandwidth_estimation_->OnRouteChange();
   probe_controller_->Reset(msg.at_time.ms());
   NetworkControlUpdate update;
diff --git a/modules/congestion_controller/goog_cc/goog_cc_network_control.h b/modules/congestion_controller/goog_cc/goog_cc_network_control.h
index 09e0649..c4e8409 100644
--- a/modules/congestion_controller/goog_cc/goog_cc_network_control.h
+++ b/modules/congestion_controller/goog_cc/goog_cc_network_control.h
@@ -17,6 +17,7 @@
 #include <vector>
 
 #include "absl/types/optional.h"
+#include "api/network_state_predictor.h"
 #include "api/transport/field_trial_based_config.h"
 #include "api/transport/network_control.h"
 #include "api/transport/network_types.h"
@@ -40,9 +41,11 @@
 
 class GoogCcNetworkController : public NetworkControllerInterface {
  public:
-  GoogCcNetworkController(RtcEventLog* event_log,
-                          NetworkControllerConfig config,
-                          bool feedback_only);
+  GoogCcNetworkController(
+      RtcEventLog* event_log,
+      NetworkControllerConfig config,
+      bool feedback_only,
+      std::unique_ptr<NetworkStatePredictor> network_state_predictor);
   ~GoogCcNetworkController() override;
 
   // NetworkControllerInterface
@@ -121,6 +124,8 @@
 
   absl::optional<DataSize> current_data_window_;
 
+  std::unique_ptr<NetworkStatePredictor> network_state_predictor_;
+
   RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(GoogCcNetworkController);
 };
 
diff --git a/modules/congestion_controller/goog_cc/goog_cc_network_control_unittest.cc b/modules/congestion_controller/goog_cc/goog_cc_network_control_unittest.cc
index 1831f5d..a7bc235 100644
--- a/modules/congestion_controller/goog_cc/goog_cc_network_control_unittest.cc
+++ b/modules/congestion_controller/goog_cc/goog_cc_network_control_unittest.cc
@@ -110,7 +110,7 @@
 class GoogCcNetworkControllerTest : public ::testing::Test {
  protected:
   GoogCcNetworkControllerTest()
-      : current_time_(Timestamp::ms(123456)), factory_(&event_log_) {}
+      : current_time_(Timestamp::ms(123456)), factory_(&event_log_, nullptr) {}
   ~GoogCcNetworkControllerTest() override {}
 
   void SetUp() override {
diff --git a/modules/congestion_controller/goog_cc/test/goog_cc_printer.cc b/modules/congestion_controller/goog_cc/test/goog_cc_printer.cc
index aba3cec..51ff387 100644
--- a/modules/congestion_controller/goog_cc/test/goog_cc_printer.cc
+++ b/modules/congestion_controller/goog_cc/test/goog_cc_printer.cc
@@ -60,7 +60,7 @@
 
 GoogCcDebugFactory::GoogCcDebugFactory(RtcEventLog* event_log,
                                        GoogCcStatePrinter* printer)
-    : GoogCcNetworkControllerFactory(event_log), printer_(printer) {}
+    : GoogCcNetworkControllerFactory(event_log, nullptr), printer_(printer) {}
 
 std::unique_ptr<NetworkControllerInterface> GoogCcDebugFactory::Create(
     NetworkControllerConfig config) {
diff --git a/modules/congestion_controller/goog_cc/trendline_estimator.cc b/modules/congestion_controller/goog_cc/trendline_estimator.cc
index e6fff8e..7db15a4 100644
--- a/modules/congestion_controller/goog_cc/trendline_estimator.cc
+++ b/modules/congestion_controller/goog_cc/trendline_estimator.cc
@@ -15,6 +15,7 @@
 #include <algorithm>
 
 #include "absl/types/optional.h"
+#include "modules/remote_bitrate_estimator/include/bwe_defines.h"
 #include "modules/remote_bitrate_estimator/test/bwe_test_logging.h"
 #include "rtc_base/checks.h"
 #include "rtc_base/numerics/safe_minmax.h"
@@ -53,9 +54,11 @@
 
 }  // namespace
 
-TrendlineEstimator::TrendlineEstimator(size_t window_size,
-                                       double smoothing_coef,
-                                       double threshold_gain)
+TrendlineEstimator::TrendlineEstimator(
+    size_t window_size,
+    double smoothing_coef,
+    double threshold_gain,
+    NetworkStatePredictor* network_state_predictor)
     : window_size_(window_size),
       smoothing_coef_(smoothing_coef),
       threshold_gain_(threshold_gain),
@@ -73,51 +76,61 @@
       prev_trend_(0.0),
       time_over_using_(-1),
       overuse_counter_(0),
-      hypothesis_(BandwidthUsage::kBwNormal) {}
+      hypothesis_(BandwidthUsage::kBwNormal),
+      hypothesis_predicted_(BandwidthUsage::kBwNormal),
+      network_state_predictor_(network_state_predictor) {}
 
 TrendlineEstimator::~TrendlineEstimator() {}
 
 void TrendlineEstimator::Update(double recv_delta_ms,
                                 double send_delta_ms,
-                                int64_t arrival_time_ms) {
-  const double delta_ms = recv_delta_ms - send_delta_ms;
-  ++num_of_deltas_;
-  num_of_deltas_ = std::min(num_of_deltas_, kDeltaCounterMax);
-  if (first_arrival_time_ms_ == -1)
-    first_arrival_time_ms_ = arrival_time_ms;
+                                int64_t send_time_ms,
+                                int64_t arrival_time_ms,
+                                bool calculated_deltas) {
+  if (calculated_deltas) {
+    const double delta_ms = recv_delta_ms - send_delta_ms;
+    ++num_of_deltas_;
+    num_of_deltas_ = std::min(num_of_deltas_, kDeltaCounterMax);
+    if (first_arrival_time_ms_ == -1)
+      first_arrival_time_ms_ = arrival_time_ms;
 
-  // Exponential backoff filter.
-  accumulated_delay_ += delta_ms;
-  BWE_TEST_LOGGING_PLOT(1, "accumulated_delay_ms", arrival_time_ms,
-                        accumulated_delay_);
-  smoothed_delay_ = smoothing_coef_ * smoothed_delay_ +
-                    (1 - smoothing_coef_) * accumulated_delay_;
-  BWE_TEST_LOGGING_PLOT(1, "smoothed_delay_ms", arrival_time_ms,
-                        smoothed_delay_);
+    // Exponential backoff filter.
+    accumulated_delay_ += delta_ms;
+    BWE_TEST_LOGGING_PLOT(1, "accumulated_delay_ms", arrival_time_ms,
+                          accumulated_delay_);
+    smoothed_delay_ = smoothing_coef_ * smoothed_delay_ +
+                      (1 - smoothing_coef_) * accumulated_delay_;
+    BWE_TEST_LOGGING_PLOT(1, "smoothed_delay_ms", arrival_time_ms,
+                          smoothed_delay_);
 
-  // Simple linear regression.
-  delay_hist_.push_back(std::make_pair(
-      static_cast<double>(arrival_time_ms - first_arrival_time_ms_),
-      smoothed_delay_));
-  if (delay_hist_.size() > window_size_)
-    delay_hist_.pop_front();
-  double trend = prev_trend_;
-  if (delay_hist_.size() == window_size_) {
-    // Update trend_ if it is possible to fit a line to the data. The delay
-    // trend can be seen as an estimate of (send_rate - capacity)/capacity.
-    // 0 < trend < 1   ->  the delay increases, queues are filling up
-    //   trend == 0    ->  the delay does not change
-    //   trend < 0     ->  the delay decreases, queues are being emptied
-    trend = LinearFitSlope(delay_hist_).value_or(trend);
+    // Simple linear regression.
+    delay_hist_.push_back(std::make_pair(
+        static_cast<double>(arrival_time_ms - first_arrival_time_ms_),
+        smoothed_delay_));
+    if (delay_hist_.size() > window_size_)
+      delay_hist_.pop_front();
+    double trend = prev_trend_;
+    if (delay_hist_.size() == window_size_) {
+      // Update trend_ if it is possible to fit a line to the data. The delay
+      // trend can be seen as an estimate of (send_rate - capacity)/capacity.
+      // 0 < trend < 1   ->  the delay increases, queues are filling up
+      //   trend == 0    ->  the delay does not change
+      //   trend < 0     ->  the delay decreases, queues are being emptied
+      trend = LinearFitSlope(delay_hist_).value_or(trend);
+    }
+
+    BWE_TEST_LOGGING_PLOT(1, "trendline_slope", arrival_time_ms, trend);
+
+    Detect(trend, send_delta_ms, arrival_time_ms);
   }
-
-  BWE_TEST_LOGGING_PLOT(1, "trendline_slope", arrival_time_ms, trend);
-
-  Detect(trend, send_delta_ms, arrival_time_ms);
+  if (network_state_predictor_) {
+    hypothesis_predicted_ = network_state_predictor_->Update(
+        send_time_ms, arrival_time_ms, hypothesis_);
+  }
 }
 
 BandwidthUsage TrendlineEstimator::State() const {
-  return hypothesis_;
+  return network_state_predictor_ ? hypothesis_predicted_ : hypothesis_;
 }
 
 void TrendlineEstimator::Detect(double trend, double ts_delta, int64_t now_ms) {
diff --git a/modules/congestion_controller/goog_cc/trendline_estimator.h b/modules/congestion_controller/goog_cc/trendline_estimator.h
index 260cd03..f85c0fc 100644
--- a/modules/congestion_controller/goog_cc/trendline_estimator.h
+++ b/modules/congestion_controller/goog_cc/trendline_estimator.h
@@ -15,6 +15,7 @@
 #include <deque>
 #include <utility>
 
+#include "api/network_state_predictor.h"
 #include "modules/congestion_controller/goog_cc/delay_increase_detector_interface.h"
 #include "modules/remote_bitrate_estimator/include/bwe_defines.h"
 #include "rtc_base/constructor_magic.h"
@@ -28,10 +29,12 @@
   // the trend line. |threshold_gain| is used to scale the trendline slope for
   // comparison to the old threshold. Once the old estimator has been removed
   // (or the thresholds been merged into the estimators), we can just set the
-  // threshold instead of setting a gain.
+  // threshold instead of setting a gain.|network_state_predictor| is used to
+  // bettter predict network state.
   TrendlineEstimator(size_t window_size,
                      double smoothing_coef,
-                     double threshold_gain);
+                     double threshold_gain,
+                     NetworkStatePredictor* network_state_predictor);
 
   ~TrendlineEstimator() override;
 
@@ -39,7 +42,9 @@
   // between timestamp groups as defined by the InterArrival class.
   void Update(double recv_delta_ms,
               double send_delta_ms,
-              int64_t arrival_time_ms) override;
+              int64_t send_time_ms,
+              int64_t arrival_time_ms,
+              bool calculated_deltas) override;
 
   BandwidthUsage State() const override;
 
@@ -78,6 +83,8 @@
   double time_over_using_;
   int overuse_counter_;
   BandwidthUsage hypothesis_;
+  BandwidthUsage hypothesis_predicted_;
+  NetworkStatePredictor* network_state_predictor_;
 
   RTC_DISALLOW_COPY_AND_ASSIGN(TrendlineEstimator);
 };
diff --git a/modules/congestion_controller/goog_cc/trendline_estimator_unittest.cc b/modules/congestion_controller/goog_cc/trendline_estimator_unittest.cc
index 7140763..d2e6cf0 100644
--- a/modules/congestion_controller/goog_cc/trendline_estimator_unittest.cc
+++ b/modules/congestion_controller/goog_cc/trendline_estimator_unittest.cc
@@ -26,7 +26,7 @@
   using TrendlineEstimator::modified_trend;
 };
 void TestEstimator(double slope, double jitter_stddev, double tolerance) {
-  TrendlineEstimatorForTest estimator(kWindowSize, kSmoothing, kGain);
+  TrendlineEstimatorForTest estimator(kWindowSize, kSmoothing, kGain, nullptr);
   Random random(0x1234567);
   int64_t send_times[kPacketCount];
   int64_t recv_times[kPacketCount];
@@ -41,7 +41,7 @@
   for (size_t i = 1; i < kPacketCount; ++i) {
     double recv_delta = recv_times[i] - recv_times[i - 1];
     double send_delta = send_times[i] - send_times[i - 1];
-    estimator.Update(recv_delta, send_delta, recv_times[i]);
+    estimator.Update(recv_delta, send_delta, 0, recv_times[i], true);
     if (i < kWindowSize)
       EXPECT_NEAR(estimator.modified_trend(), 0, 0.001);
     else
diff --git a/modules/congestion_controller/send_side_congestion_controller.cc b/modules/congestion_controller/send_side_congestion_controller.cc
index 1080f9b..cf5b7a2 100644
--- a/modules/congestion_controller/send_side_congestion_controller.cc
+++ b/modules/congestion_controller/send_side_congestion_controller.cc
@@ -104,7 +104,8 @@
       pacer_paused_(false),
       min_bitrate_bps_(congestion_controller::GetMinBitrateBps()),
       probe_bitrate_estimator_(new ProbeBitrateEstimator(event_log_)),
-      delay_based_bwe_(new DelayBasedBwe(key_value_config_, event_log_)),
+      delay_based_bwe_(
+          new DelayBasedBwe(key_value_config_, event_log_, nullptr)),
       was_in_alr_(false),
       send_side_bwe_with_overhead_(
           key_value_config_->Lookup("WebRTC-SendSideBwe-WithOverhead")
@@ -235,7 +236,8 @@
     transport_overhead_bytes_per_packet_ = network_route.packet_overhead;
     min_bitrate_bps_ = min_bitrate_bps;
     probe_bitrate_estimator_.reset(new ProbeBitrateEstimator(event_log_));
-    delay_based_bwe_.reset(new DelayBasedBwe(key_value_config_, event_log_));
+    delay_based_bwe_.reset(
+        new DelayBasedBwe(key_value_config_, event_log_, nullptr));
     acknowledged_bitrate_estimator_.reset(
         new AcknowledgedBitrateEstimator(key_value_config_));
     if (bitrate_bps > 0) {
diff --git a/modules/remote_bitrate_estimator/BUILD.gn b/modules/remote_bitrate_estimator/BUILD.gn
index 91e8a77..3094e8c 100644
--- a/modules/remote_bitrate_estimator/BUILD.gn
+++ b/modules/remote_bitrate_estimator/BUILD.gn
@@ -41,6 +41,7 @@
 
   deps = [
     "../..:webrtc_common",
+    "../../api:network_state_predictor_api",
     "../../api:rtp_headers",
     "../../api/units:data_rate",
     "../../api/units:timestamp",
diff --git a/modules/remote_bitrate_estimator/include/bwe_defines.h b/modules/remote_bitrate_estimator/include/bwe_defines.h
index 5223a6b..40fbfe0 100644
--- a/modules/remote_bitrate_estimator/include/bwe_defines.h
+++ b/modules/remote_bitrate_estimator/include/bwe_defines.h
@@ -14,6 +14,7 @@
 #include <stdint.h>
 
 #include "absl/types/optional.h"
+#include "api/network_state_predictor.h"
 #include "api/units/data_rate.h"
 
 #define BWE_MAX(a, b) ((a) > (b) ? (a) : (b))
@@ -38,13 +39,6 @@
   kBweNamesMax = 4
 };
 
-enum class BandwidthUsage {
-  kBwNormal = 0,
-  kBwUnderusing = 1,
-  kBwOverusing = 2,
-  kLast
-};
-
 enum RateControlState { kRcHold, kRcIncrease, kRcDecrease };
 
 struct RateControlInput {
diff --git a/modules/remote_bitrate_estimator/test/estimators/send_side.cc b/modules/remote_bitrate_estimator/test/estimators/send_side.cc
index 7b33cd4..c4b81c7 100644
--- a/modules/remote_bitrate_estimator/test/estimators/send_side.cc
+++ b/modules/remote_bitrate_estimator/test/estimators/send_side.cc
@@ -38,7 +38,7 @@
           absl::make_unique<AcknowledgedBitrateEstimator>(
               &field_trial_config_)),
       probe_bitrate_estimator_(new ProbeBitrateEstimator(nullptr)),
-      bwe_(new DelayBasedBwe(&field_trial_config_, nullptr)),
+      bwe_(new DelayBasedBwe(&field_trial_config_, nullptr, nullptr)),
       feedback_observer_(bitrate_controller_.get()),
       clock_(clock),
       send_time_history_(10000),
diff --git a/pc/BUILD.gn b/pc/BUILD.gn
index 48c864b1..7326409 100644
--- a/pc/BUILD.gn
+++ b/pc/BUILD.gn
@@ -196,6 +196,7 @@
     "../api:call_api",
     "../api:fec_controller_api",
     "../api:libjingle_peerconnection_api",
+    "../api:network_state_predictor_api",
     "../api:rtc_stats_api",
     "../api:scoped_refptr",
     "../api/task_queue",
diff --git a/pc/peer_connection_factory.cc b/pc/peer_connection_factory.cc
index dd403ed..ce1797b 100644
--- a/pc/peer_connection_factory.cc
+++ b/pc/peer_connection_factory.cc
@@ -10,6 +10,7 @@
 
 #include "pc/peer_connection_factory.h"
 
+#include <memory>
 #include <utility>
 #include <vector>
 
@@ -18,6 +19,7 @@
 #include "api/media_stream_proxy.h"
 #include "api/media_stream_track_proxy.h"
 #include "api/media_transport_interface.h"
+#include "api/network_state_predictor.h"
 #include "api/peer_connection_factory_proxy.h"
 #include "api/peer_connection_proxy.h"
 #include "api/turn_customizer.h"
@@ -25,16 +27,16 @@
 #include "logging/rtc_event_log/rtc_event_log.h"
 #include "media/base/rtp_data_engine.h"
 #include "media/sctp/sctp_transport.h"
-#include "pc/rtp_parameters_conversion.h"
-#include "rtc_base/bind.h"
-#include "rtc_base/checks.h"
 #include "p2p/base/basic_packet_socket_factory.h"
 #include "p2p/client/basic_port_allocator.h"
 #include "pc/audio_track.h"
 #include "pc/local_audio_source.h"
 #include "pc/media_stream.h"
 #include "pc/peer_connection.h"
+#include "pc/rtp_parameters_conversion.h"
 #include "pc/video_track.h"
+#include "rtc_base/bind.h"
+#include "rtc_base/checks.h"
 #include "system_wrappers/include/field_trial.h"
 
 namespace webrtc {
@@ -66,6 +68,8 @@
     std::unique_ptr<CallFactoryInterface> call_factory,
     std::unique_ptr<RtcEventLogFactoryInterface> event_log_factory,
     std::unique_ptr<FecControllerFactoryInterface> fec_controller_factory,
+    std::unique_ptr<NetworkStatePredictorFactoryInterface>
+        network_state_predictor_factory,
     std::unique_ptr<NetworkControllerFactoryInterface>
         network_controller_factory) {
   PeerConnectionFactoryDependencies dependencies;
@@ -76,6 +80,8 @@
   dependencies.call_factory = std::move(call_factory);
   dependencies.event_log_factory = std::move(event_log_factory);
   dependencies.fec_controller_factory = std::move(fec_controller_factory);
+  dependencies.network_state_predictor_factory =
+      std::move(network_state_predictor_factory);
   dependencies.network_controller_factory =
       std::move(network_controller_factory);
   return CreateModularPeerConnectionFactory(std::move(dependencies));
@@ -111,6 +117,8 @@
       call_factory_(std::move(dependencies.call_factory)),
       event_log_factory_(std::move(dependencies.event_log_factory)),
       fec_controller_factory_(std::move(dependencies.fec_controller_factory)),
+      network_state_predictor_factory_(
+          std::move(dependencies.network_state_predictor_factory)),
       injected_network_controller_factory_(
           std::move(dependencies.network_controller_factory)),
       media_transport_factory_(
@@ -388,6 +396,8 @@
 
   call_config.fec_controller_factory = fec_controller_factory_.get();
   call_config.task_queue_factory = task_queue_factory_.get();
+  call_config.network_state_predictor_factory =
+      network_state_predictor_factory_.get();
 
   if (field_trial::IsEnabled("WebRTC-Bwe-InjectedCongestionController")) {
     RTC_LOG(LS_INFO) << "Using injected network controller factory";
diff --git a/pc/peer_connection_factory.h b/pc/peer_connection_factory.h
index fd9db27..9b2ce67 100644
--- a/pc/peer_connection_factory.h
+++ b/pc/peer_connection_factory.h
@@ -122,6 +122,8 @@
   std::unique_ptr<webrtc::CallFactoryInterface> call_factory_;
   std::unique_ptr<RtcEventLogFactoryInterface> event_log_factory_;
   std::unique_ptr<FecControllerFactoryInterface> fec_controller_factory_;
+  std::unique_ptr<NetworkStatePredictorFactoryInterface>
+      network_state_predictor_factory_;
   std::unique_ptr<NetworkControllerFactoryInterface>
       injected_network_controller_factory_;
   std::unique_ptr<MediaTransportFactory> media_transport_factory_;
diff --git a/sdk/android/BUILD.gn b/sdk/android/BUILD.gn
index 920503a..edf88a8 100644
--- a/sdk/android/BUILD.gn
+++ b/sdk/android/BUILD.gn
@@ -295,6 +295,7 @@
       "api/org/webrtc/DataChannel.java",
       "api/org/webrtc/DtmfSender.java",
       "api/org/webrtc/FecControllerFactoryFactoryInterface.java",
+      "api/org/webrtc/NetworkStatePredictorFactoryFactory.java",
       "api/org/webrtc/MediaTransportFactoryFactory.java",
       "api/org/webrtc/FrameDecryptor.java",
       "api/org/webrtc/FrameEncryptor.java",
diff --git a/sdk/android/api/org/webrtc/NetworkStatePredictorFactoryFactory.java b/sdk/android/api/org/webrtc/NetworkStatePredictorFactoryFactory.java
new file mode 100644
index 0000000..bf965bc
--- /dev/null
+++ b/sdk/android/api/org/webrtc/NetworkStatePredictorFactoryFactory.java
@@ -0,0 +1,20 @@
+/*
+ *  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.
+ */
+
+package org.webrtc;
+
+/** Factory for creating webrtc::NetworkStatePredictorFactory instances. */
+public interface NetworkStatePredictorFactoryFactory {
+  /**
+   * Dynamically allocates a webrtc::NetworkStatePredictorFactory instance and returns a pointer to
+   * it. The caller takes ownership of the object.
+   */
+  public long createNativeNetworkStatePredictorFactory();
+}
diff --git a/sdk/android/api/org/webrtc/PeerConnectionFactory.java b/sdk/android/api/org/webrtc/PeerConnectionFactory.java
index 6aa68c2..909d691 100644
--- a/sdk/android/api/org/webrtc/PeerConnectionFactory.java
+++ b/sdk/android/api/org/webrtc/PeerConnectionFactory.java
@@ -173,6 +173,7 @@
     @Nullable private VideoDecoderFactory videoDecoderFactory;
     @Nullable private AudioProcessingFactory audioProcessingFactory;
     @Nullable private FecControllerFactoryFactoryInterface fecControllerFactoryFactory;
+    @Nullable private NetworkStatePredictorFactoryFactory networkStatePredictorFactoryFactory;
     @Nullable private MediaTransportFactoryFactory mediaTransportFactoryFactory;
 
     private Builder() {}
@@ -232,6 +233,12 @@
       return this;
     }
 
+    public Builder NetworkStatePredictorFactoryFactory(
+        NetworkStatePredictorFactoryFactory networkStatePredictorFactoryFactory) {
+      this.networkStatePredictorFactoryFactory = networkStatePredictorFactoryFactory;
+      return this;
+    }
+
     /** Sets a MediaTransportFactoryFactory for a PeerConnectionFactory. */
     public Builder setMediaTransportFactoryFactory(
         MediaTransportFactoryFactory mediaTransportFactoryFactory) {
@@ -252,6 +259,9 @@
           videoDecoderFactory,
           audioProcessingFactory == null ? 0 : audioProcessingFactory.createNative(),
           fecControllerFactoryFactory == null ? 0 : fecControllerFactoryFactory.createNative(),
+          networkStatePredictorFactoryFactory == null
+              ? 0
+              : networkStatePredictorFactoryFactory.createNativeNetworkStatePredictorFactory(),
           mediaTransportFactoryFactory == null
               ? 0
               : mediaTransportFactoryFactory.createNativeMediaTransportFactory());
@@ -575,7 +585,8 @@
       Options options, long nativeAudioDeviceModule, long audioEncoderFactory,
       long audioDecoderFactory, VideoEncoderFactory encoderFactory,
       VideoDecoderFactory decoderFactory, long nativeAudioProcessor,
-      long nativeFecControllerFactory, long mediaTransportFactory);
+      long nativeFecControllerFactory, long nativeNetworkStatePredictorFactory,
+      long mediaTransportFactory);
 
   private static native long nativeCreatePeerConnection(long factory,
       PeerConnection.RTCConfiguration rtcConfig, MediaConstraints constraints, long nativeObserver,
diff --git a/sdk/android/src/jni/pc/peer_connection_factory.cc b/sdk/android/src/jni/pc/peer_connection_factory.cc
index 378d129..c6d8ae8 100644
--- a/sdk/android/src/jni/pc/peer_connection_factory.cc
+++ b/sdk/android/src/jni/pc/peer_connection_factory.cc
@@ -240,7 +240,8 @@
 
 // Following parameters are optional:
 // |audio_device_module|, |jencoder_factory|, |jdecoder_factory|,
-// |audio_processor|, |media_transport_factory|, |fec_controller_factory|.
+// |audio_processor|, |media_transport_factory|, |fec_controller_factory|,
+// |network_state_predictor_factory|.
 ScopedJavaLocalRef<jobject> CreatePeerConnectionFactoryForJava(
     JNIEnv* jni,
     const JavaParamRef<jobject>& jcontext,
@@ -252,6 +253,8 @@
     const JavaParamRef<jobject>& jdecoder_factory,
     rtc::scoped_refptr<AudioProcessing> audio_processor,
     std::unique_ptr<FecControllerFactoryInterface> fec_controller_factory,
+    std::unique_ptr<NetworkStatePredictorFactoryInterface>
+        network_state_predictor_factory,
     std::unique_ptr<MediaTransportFactory> media_transport_factory) {
   // talk/ assumes pretty widely that the current Thread is ThreadManager'd, but
   // ThreadManager only WrapCurrentThread()s the thread where it is first
@@ -305,6 +308,8 @@
   dependencies.call_factory = std::move(call_factory);
   dependencies.event_log_factory = std::move(rtc_event_log_factory);
   dependencies.fec_controller_factory = std::move(fec_controller_factory);
+  dependencies.network_state_predictor_factory =
+      std::move(network_state_predictor_factory);
   dependencies.media_transport_factory = std::move(media_transport_factory);
 
   rtc::scoped_refptr<PeerConnectionFactoryInterface> factory(
@@ -334,6 +339,7 @@
     const JavaParamRef<jobject>& jdecoder_factory,
     jlong native_audio_processor,
     jlong native_fec_controller_factory,
+    jlong native_network_state_predictor_factory,
     jlong native_media_transport_factory) {
   rtc::scoped_refptr<AudioProcessing> audio_processor =
       reinterpret_cast<AudioProcessing*>(native_audio_processor);
@@ -346,6 +352,8 @@
       audio_processor ? audio_processor : CreateAudioProcessing(),
       TakeOwnershipOfUniquePtr<FecControllerFactoryInterface>(
           native_fec_controller_factory),
+      TakeOwnershipOfUniquePtr<NetworkStatePredictorFactoryInterface>(
+          native_network_state_predictor_factory),
       TakeOwnershipOfUniquePtr<MediaTransportFactory>(
           native_media_transport_factory));
 }