Reland: Add ability to emulate degraded network in Call via field trial

This is especially useful in Chrome, allowing use to emulate network
conditions in incoming or outgoing media without the need for platform
specific tools or hacks. It also doesn't interfere with the rest of the
network traffic.

Also includes some refactorings.

TBR=stefan@webrtc.org, philipel@webrtc.org

Originally reviewed on: https://webrtc-review.googlesource.com/33013

Bug: webrtc:8910
Change-Id: I162dde5fa20a260b41e5187fcf30b49f5e6fb0e0
Reviewed-on: https://webrtc-review.googlesource.com/61782
Commit-Queue: Erik Språng <sprang@webrtc.org>
Reviewed-by: Niels Moller <nisse@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#22430}
diff --git a/call/callfactory.cc b/call/callfactory.cc
index 0f2eecb..4ab5b89 100644
--- a/call/callfactory.cc
+++ b/call/callfactory.cc
@@ -11,12 +11,74 @@
 #include "call/callfactory.h"
 
 #include <memory>
+#include <string>
+#include <utility>
 
+#include "api/optional.h"
 #include "call/call.h"
+#include "call/degraded_call.h"
+#include "call/fake_network_pipe.h"
+#include "system_wrappers/include/field_trial.h"
 
 namespace webrtc {
+namespace {
+bool ParseConfigParam(std::string exp_name, int* field) {
+  std::string group = field_trial::FindFullName(exp_name);
+  if (group == "")
+    return false;
+
+  return (sscanf(group.c_str(), "%d", field) == 1);
+}
+
+rtc::Optional<webrtc::FakeNetworkPipe::Config> ParseDegradationConfig(
+    bool send) {
+  std::string exp_prefix = "WebRTCFakeNetwork";
+  if (send) {
+    exp_prefix += "Send";
+  } else {
+    exp_prefix += "Receive";
+  }
+
+  webrtc::FakeNetworkPipe::Config config;
+  bool configured = false;
+  configured |=
+      ParseConfigParam(exp_prefix + "DelayMs", &config.queue_delay_ms);
+  configured |= ParseConfigParam(exp_prefix + "DelayStdDevMs",
+                                 &config.delay_standard_deviation_ms);
+  int queue_length = 0;
+  if (ParseConfigParam(exp_prefix + "QueueLength", &queue_length)) {
+    RTC_CHECK_GE(queue_length, 0);
+    config.queue_length_packets = queue_length;
+    configured = true;
+  }
+  configured |=
+      ParseConfigParam(exp_prefix + "CapacityKbps", &config.link_capacity_kbps);
+  configured |=
+      ParseConfigParam(exp_prefix + "LossPercent", &config.loss_percent);
+  int allow_reordering = 0;
+  if (ParseConfigParam(exp_prefix + "AllowReordering", &allow_reordering)) {
+    config.allow_reordering = true;
+    configured = true;
+  }
+  configured |= ParseConfigParam(exp_prefix + "AvgBurstLossLength",
+                                 &config.avg_burst_loss_length);
+  return configured ? rtc::Optional<webrtc::FakeNetworkPipe::Config>(config)
+                    : rtc::nullopt;
+}
+}  // namespace
 
 Call* CallFactory::CreateCall(const Call::Config& config) {
+  rtc::Optional<webrtc::FakeNetworkPipe::Config> send_degradation_config =
+      ParseDegradationConfig(true);
+  rtc::Optional<webrtc::FakeNetworkPipe::Config> receive_degradation_config =
+      ParseDegradationConfig(false);
+
+  if (send_degradation_config || receive_degradation_config) {
+    return new DegradedCall(std::unique_ptr<Call>(Call::Create(config)),
+                            send_degradation_config,
+                            receive_degradation_config);
+  }
+
   return Call::Create(config);
 }