Integrate fake_network_pipe into direct_transport.

TEST=trybots
R=mflodman@webrtc.org, pbos@webrtc.org

Review URL: https://webrtc-codereview.appspot.com/5529004

git-svn-id: http://webrtc.googlecode.com/svn/trunk/webrtc@5321 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/test/direct_transport.cc b/test/direct_transport.cc
index 7b3ff22..96852ed 100644
--- a/test/direct_transport.cc
+++ b/test/direct_transport.cc
@@ -23,20 +23,19 @@
       thread_(ThreadWrapper::CreateThread(NetworkProcess, this)),
       clock_(Clock::GetRealTimeClock()),
       shutting_down_(false),
-      receiver_(NULL),
-      delay_ms_(0) {
+      fake_network_(FakeNetworkPipe::Config()) {
   unsigned int thread_id;
   EXPECT_TRUE(thread_->Start(thread_id));
 }
 
-DirectTransport::DirectTransport(int delay_ms)
+DirectTransport::DirectTransport(
+    const FakeNetworkPipe::Config& config)
     : lock_(CriticalSectionWrapper::CreateCriticalSection()),
       packet_event_(EventWrapper::Create()),
       thread_(ThreadWrapper::CreateThread(NetworkProcess, this)),
       clock_(Clock::GetRealTimeClock()),
       shutting_down_(false),
-      receiver_(NULL),
-      delay_ms_(delay_ms) {
+      fake_network_(config) {
   unsigned int thread_id;
   EXPECT_TRUE(thread_->Start(thread_id));
 }
@@ -54,37 +53,19 @@
 }
 
 void DirectTransport::SetReceiver(PacketReceiver* receiver) {
-  receiver_ = receiver;
+  fake_network_.SetReceiver(receiver);
 }
 
 bool DirectTransport::SendRtp(const uint8_t* data, size_t length) {
-  QueuePacket(data, length, clock_->TimeInMilliseconds() + delay_ms_);
+  fake_network_.SendPacket(data, length);
+  packet_event_->Set();
   return true;
 }
 
 bool DirectTransport::SendRtcp(const uint8_t* data, size_t length) {
-  QueuePacket(data, length, clock_->TimeInMilliseconds() + delay_ms_);
-  return true;
-}
-
-DirectTransport::Packet::Packet() : length(0), delivery_time_ms(0) {}
-
-DirectTransport::Packet::Packet(const uint8_t* data,
-                                size_t length,
-                                int64_t delivery_time_ms)
-    : length(length), delivery_time_ms(delivery_time_ms) {
-  EXPECT_LE(length, sizeof(this->data));
-  memcpy(this->data, data, length);
-}
-
-void DirectTransport::QueuePacket(const uint8_t* data,
-                                  size_t length,
-                                  int64_t delivery_time_ms) {
-  CriticalSectionScoped crit(lock_.get());
-  if (receiver_ == NULL)
-    return;
-  packet_queue_.push_back(Packet(data, length, delivery_time_ms));
+  fake_network_.SendPacket(data, length);
   packet_event_->Set();
+  return true;
 }
 
 bool DirectTransport::NetworkProcess(void* transport) {
@@ -92,44 +73,20 @@
 }
 
 bool DirectTransport::SendPackets() {
-  while (true) {
-    Packet p;
-    {
-      CriticalSectionScoped crit(lock_.get());
-      if (packet_queue_.empty())
+  fake_network_.Process();
+  int wait_time_ms = fake_network_.TimeUntilNextProcess();
+  if (wait_time_ms > 0) {
+    switch (packet_event_->Wait(wait_time_ms)) {
+      case kEventSignaled:
+        packet_event_->Reset();
         break;
-      p = packet_queue_.front();
-      if (p.delivery_time_ms > clock_->TimeInMilliseconds())
+      case kEventTimeout:
         break;
-      packet_queue_.pop_front();
-    }
-    receiver_->DeliverPacket(p.data, p.length);
-  }
-  uint32_t time_until_next_delivery = WEBRTC_EVENT_INFINITE;
-  {
-    CriticalSectionScoped crit(lock_.get());
-    if (!packet_queue_.empty()) {
-      int64_t now_ms = clock_->TimeInMilliseconds();
-      const int64_t delivery_time_ms = packet_queue_.front().delivery_time_ms;
-      if (delivery_time_ms > now_ms) {
-        time_until_next_delivery = delivery_time_ms - now_ms;
-      } else {
-        time_until_next_delivery = 0;
-      }
+      case kEventError:
+        // TODO(pbos): Log a warning here?
+        return true;
     }
   }
-
-  switch (packet_event_->Wait(time_until_next_delivery)) {
-    case kEventSignaled:
-      packet_event_->Reset();
-      break;
-    case kEventTimeout:
-      break;
-    case kEventError:
-      // TODO(pbos): Log a warning here?
-      return true;
-  }
-
   CriticalSectionScoped crit(lock_.get());
   return shutting_down_ ? false : true;
 }
diff --git a/test/direct_transport.h b/test/direct_transport.h
index b6021cb..660ffec 100644
--- a/test/direct_transport.h
+++ b/test/direct_transport.h
@@ -18,6 +18,7 @@
 #include "webrtc/system_wrappers/interface/event_wrapper.h"
 #include "webrtc/system_wrappers/interface/scoped_ptr.h"
 #include "webrtc/system_wrappers/interface/thread_wrapper.h"
+#include "webrtc/test/fake_network_pipe.h"
 #include "webrtc/transport.h"
 
 namespace webrtc {
@@ -30,7 +31,7 @@
 class DirectTransport : public newapi::Transport {
  public:
   DirectTransport();
-  explicit DirectTransport(int delay_ms);
+  explicit DirectTransport(const FakeNetworkPipe::Config& config);
   ~DirectTransport();
 
   virtual void StopSending();
@@ -40,19 +41,6 @@
   virtual bool SendRtcp(const uint8_t* data, size_t length) OVERRIDE;
 
  private:
-  struct Packet {
-    Packet();
-    Packet(const uint8_t* data, size_t length, int64_t delivery_time_ms);
-
-    uint8_t data[1500];
-    size_t length;
-    int64_t delivery_time_ms;
-  };
-
-  void QueuePacket(const uint8_t* data,
-                   size_t length,
-                   int64_t delivery_time_ms);
-
   static bool NetworkProcess(void* transport);
   bool SendPackets();
 
@@ -63,10 +51,7 @@
 
   bool shutting_down_;
 
-  std::deque<Packet> packet_queue_;
-  PacketReceiver* receiver_;
-  // TODO(stefan): Replace this with FakeNetworkPipe.
-  const int delay_ms_;
+  FakeNetworkPipe fake_network_;
 };
 }  // namespace test
 }  // namespace webrtc
diff --git a/test/fake_network_pipe.cc b/test/fake_network_pipe.cc
new file mode 100644
index 0000000..5a2424e
--- /dev/null
+++ b/test/fake_network_pipe.cc
@@ -0,0 +1,203 @@
+/*
+ *  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.
+ */
+
+#include "webrtc/test/fake_network_pipe.h"
+
+#include <assert.h>
+#include <math.h>
+#include <string.h>
+#include <algorithm>
+
+#include "webrtc/call.h"
+#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
+#include "webrtc/system_wrappers/interface/tick_util.h"
+
+namespace webrtc {
+
+const double kPi = 3.14159265;
+const int kDefaultProcessIntervalMs = 30;
+
+static int GaussianRandom(int mean_delay_ms, int standard_deviation_ms) {
+  // Creating a Normal distribution variable from two independent uniform
+  // variables based on the Box-Muller transform.
+  double uniform1 = (rand() + 1.0) / (RAND_MAX + 1.0);  // NOLINT
+  double uniform2 = (rand() + 1.0) / (RAND_MAX + 1.0);  // NOLINT
+  return static_cast<int>(mean_delay_ms + standard_deviation_ms *
+                          sqrt(-2 * log(uniform1)) * cos(2 * kPi * uniform2));
+}
+
+class NetworkPacket {
+ public:
+  NetworkPacket(const uint8_t* data, size_t length, int64_t send_time,
+      int64_t arrival_time)
+      : data_(NULL),
+        data_length_(length),
+        send_time_(send_time),
+        arrival_time_(arrival_time) {
+    data_ = new uint8_t[length];
+    memcpy(data_, data, length);
+  }
+  ~NetworkPacket() {
+    delete [] data_;
+  }
+
+  uint8_t* data() const { return data_; }
+  size_t data_length() const { return data_length_; }
+  int64_t send_time() const { return send_time_; }
+  int64_t arrival_time() const { return arrival_time_; }
+  void IncrementArrivalTime(int64_t extra_delay) {
+    arrival_time_+= extra_delay;
+  }
+
+ private:
+  // The packet data.
+  uint8_t* data_;
+  // Length of data_.
+  size_t data_length_;
+  // The time the packet was sent out on the network.
+  const int64_t send_time_;
+  // The time the packet should arrive at the reciver.
+  int64_t arrival_time_;
+};
+
+FakeNetworkPipe::FakeNetworkPipe(
+    const FakeNetworkPipe::Config& config)
+    : lock_(CriticalSectionWrapper::CreateCriticalSection()),
+      packet_receiver_(NULL),
+      config_(config),
+      dropped_packets_(0),
+      sent_packets_(0),
+      total_packet_delay_(0),
+      next_process_time_(TickTime::MillisecondTimestamp()) {
+}
+
+FakeNetworkPipe::~FakeNetworkPipe() {
+  while (!capacity_link_.empty()) {
+    delete capacity_link_.front();
+    capacity_link_.pop();
+  }
+  while (!delay_link_.empty()) {
+    delete delay_link_.front();
+    delay_link_.pop();
+  }
+}
+
+void FakeNetworkPipe::SetReceiver(PacketReceiver* receiver) {
+  packet_receiver_ = receiver;
+}
+
+void FakeNetworkPipe::SendPacket(const uint8_t* data, size_t data_length) {
+  // A NULL packet_receiver_ means that this pipe will terminate the flow of
+  // packets.
+  if (packet_receiver_ == NULL)
+    return;
+  CriticalSectionScoped crit(lock_.get());
+  if (config_.queue_length > 0 &&
+      capacity_link_.size() >= config_.queue_length) {
+    // Too many packet on the link, drop this one.
+    ++dropped_packets_;
+    return;
+  }
+
+  int64_t time_now = TickTime::MillisecondTimestamp();
+
+  // Delay introduced by the link capacity.
+  int64_t capacity_delay_ms = 0;
+  if (config_.link_capacity_kbps > 0)
+    capacity_delay_ms = data_length / (config_.link_capacity_kbps / 8);
+  int64_t network_start_time = time_now;
+
+  // Check if there already are packets on the link and change network start
+  // time if there is.
+  if (capacity_link_.size() > 0)
+    network_start_time = capacity_link_.back()->arrival_time();
+
+  int64_t arrival_time = network_start_time + capacity_delay_ms;
+  NetworkPacket* packet = new NetworkPacket(data, data_length, time_now,
+                                            arrival_time);
+  capacity_link_.push(packet);
+}
+
+float FakeNetworkPipe::PercentageLoss() {
+  CriticalSectionScoped crit(lock_.get());
+  if (sent_packets_ == 0)
+    return 0;
+
+  return static_cast<float>(dropped_packets_) /
+      (sent_packets_ + dropped_packets_);
+}
+
+int FakeNetworkPipe::AverageDelay() {
+  CriticalSectionScoped crit(lock_.get());
+  if (sent_packets_ == 0)
+    return 0;
+
+  return total_packet_delay_ / static_cast<int>(sent_packets_);
+}
+
+void FakeNetworkPipe::Process() {
+  int64_t time_now = TickTime::MillisecondTimestamp();
+  std::queue<NetworkPacket*> packets_to_deliver;
+  {
+    CriticalSectionScoped crit(lock_.get());
+    // Check the capacity link first.
+    while (capacity_link_.size() > 0 &&
+           time_now >= capacity_link_.front()->arrival_time()) {
+      // Time to get this packet.
+      NetworkPacket* packet = capacity_link_.front();
+      capacity_link_.pop();
+
+      // Add extra delay and jitter, but make sure the arrival time is not
+      // earlier than the last packet in the queue.
+      int extra_delay = GaussianRandom(config_.queue_delay_ms,
+                                       config_.delay_standard_deviation_ms);
+      if (delay_link_.size() > 0 &&
+          packet->arrival_time() + extra_delay <
+          delay_link_.back()->arrival_time()) {
+        extra_delay = delay_link_.back()->arrival_time() -
+            packet->arrival_time();
+      }
+      packet->IncrementArrivalTime(extra_delay);
+      if (packet->arrival_time() < next_process_time_)
+        next_process_time_ = packet->arrival_time();
+      delay_link_.push(packet);
+    }
+
+    // Check the extra delay queue.
+    while (delay_link_.size() > 0 &&
+           time_now >= delay_link_.front()->arrival_time()) {
+      // Deliver this packet.
+      NetworkPacket* packet = delay_link_.front();
+      packets_to_deliver.push(packet);
+      delay_link_.pop();
+      // |time_now| might be later than when the packet should have arrived, due
+      // to NetworkProcess being called too late. For stats, use the time it
+      // should have been on the link.
+      total_packet_delay_ += packet->arrival_time() - packet->send_time();
+    }
+    sent_packets_ += packets_to_deliver.size();
+  }
+  while (!packets_to_deliver.empty()) {
+    NetworkPacket* packet = packets_to_deliver.front();
+    packets_to_deliver.pop();
+    packet_receiver_->DeliverPacket(packet->data(), packet->data_length());
+    delete packet;
+  }
+}
+
+int FakeNetworkPipe::TimeUntilNextProcess() const {
+  CriticalSectionScoped crit(lock_.get());
+  if (capacity_link_.size() == 0 || delay_link_.size() == 0)
+    return kDefaultProcessIntervalMs;
+  return std::max(static_cast<int>(next_process_time_ -
+      TickTime::MillisecondTimestamp()), 0);
+}
+
+}  // namespace webrtc
diff --git a/video_engine/test/libvietest/include/fake_network_pipe.h b/test/fake_network_pipe.h
similarity index 60%
rename from video_engine/test/libvietest/include/fake_network_pipe.h
rename to test/fake_network_pipe.h
index ece1472..e750457 100644
--- a/video_engine/test/libvietest/include/fake_network_pipe.h
+++ b/test/fake_network_pipe.h
@@ -8,12 +8,13 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#ifndef WEBRTC_VIDEO_ENGINE_TEST_LIBVIETEST_INCLUDE_FAKE_NETWORK_PIPE_H_
-#define WEBRTC_VIDEO_ENGINE_TEST_LIBVIETEST_INCLUDE_FAKE_NETWORK_PIPE_H_
+#ifndef WEBRTC_TEST_FAKE_NETWORK_PIPE_H_
+#define WEBRTC_TEST_FAKE_NETWORK_PIPE_H_
 
 #include <queue>
 
 #include "webrtc/system_wrappers/interface/constructor_magic.h"
+#include "webrtc/system_wrappers/interface/event_wrapper.h"
 #include "webrtc/system_wrappers/interface/scoped_ptr.h"
 #include "webrtc/typedefs.h"
 
@@ -21,14 +22,7 @@
 
 class CriticalSectionWrapper;
 class NetworkPacket;
-
-class PacketReceiver {
- public:
-  // Delivers a new packet to the receive side of the network pipe. The
-  // implementor of PacketReceiver now owns the memory.
-  virtual void IncomingPacket(uint8_t* packet, int length) = 0;
-  virtual ~PacketReceiver() {}
-};
+class PacketReceiver;
 
 // Class faking a network link. This is a simple and naive solution just faking
 // capacity and adding an extra transport delay in addition to the capacity
@@ -37,18 +31,15 @@
 // TODO(mflodman) Add random and bursty packet loss.
 class FakeNetworkPipe {
  public:
-  struct Configuration {
-    Configuration()
-        : packet_receiver(NULL),
-          queue_length(0),
+  struct Config {
+    Config()
+        : queue_length(0),
           queue_delay_ms(0),
           delay_standard_deviation_ms(0),
           link_capacity_kbps(0),
           loss_percent(0) {
     }
-    // Callback to deliver received packets.
-    PacketReceiver* packet_receiver;
-    // Queue lenght in number of packets.
+    // Queue length in number of packets.
     size_t queue_length;
     // Delay in addition to capacity induced delay.
     int queue_delay_ms;
@@ -60,44 +51,45 @@
     int loss_percent;
   };
 
-  explicit FakeNetworkPipe(const FakeNetworkPipe::Configuration& configuration);
+  explicit FakeNetworkPipe(const FakeNetworkPipe::Config& config);
   ~FakeNetworkPipe();
 
+  // Must not be called in parallel with SendPacket or Process.
+  void SetReceiver(PacketReceiver* receiver);
+
   // Sends a new packet to the link.
-  void SendPacket(void* packet, int packet_length);
+  void SendPacket(const uint8_t* packet, size_t packet_length);
 
   // Processes the network queues and trigger PacketReceiver::IncomingPacket for
   // packets ready to be delivered.
-  void NetworkProcess();
+  void Process();
+  int TimeUntilNextProcess() const;
 
   // Get statistics.
   float PercentageLoss();
   int AverageDelay();
-  int dropped_packets() { return dropped_packets_; }
-  int sent_packets() { return sent_packets_; }
+  size_t dropped_packets() { return dropped_packets_; }
+  size_t sent_packets() { return sent_packets_; }
 
  private:
+  scoped_ptr<CriticalSectionWrapper> lock_;
   PacketReceiver* packet_receiver_;
-  scoped_ptr<CriticalSectionWrapper> link_cs_;
   std::queue<NetworkPacket*> capacity_link_;
   std::queue<NetworkPacket*> delay_link_;
 
   // Link configuration.
-  const size_t queue_length_;
-  const int queue_delay_ms_;
-  const int queue_delay_deviation_ms_;
-  const int link_capacity_bytes_ms_;  // In bytes per ms.
-
-  const int loss_percent_;
+  Config config_;
 
   // Statistics.
-  int dropped_packets_;
-  int sent_packets_;
+  size_t dropped_packets_;
+  size_t sent_packets_;
   int total_packet_delay_;
 
+  int64_t next_process_time_;
+
   DISALLOW_COPY_AND_ASSIGN(FakeNetworkPipe);
 };
 
 }  // namespace webrtc
 
-#endif  // WEBRTC_VIDEO_ENGINE_TEST_LIBVIETEST_INCLUDE_FAKE_NETWORK_PIPE_H_
+#endif  // WEBRTC_TEST_FAKE_NETWORK_PIPE_H_
diff --git a/video_engine/test/libvietest/testbed/fake_network_pipe_unittest.cc b/test/fake_network_pipe_unittest.cc
similarity index 79%
rename from video_engine/test/libvietest/testbed/fake_network_pipe_unittest.cc
rename to test/fake_network_pipe_unittest.cc
index 7747302..1245f61 100644
--- a/video_engine/test/libvietest/testbed/fake_network_pipe_unittest.cc
+++ b/test/fake_network_pipe_unittest.cc
@@ -11,9 +11,10 @@
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
+#include "webrtc/call.h"
 #include "webrtc/system_wrappers/interface/scoped_ptr.h"
 #include "webrtc/system_wrappers/interface/tick_util.h"
-#include "webrtc/video_engine/test/libvietest/include/fake_network_pipe.h"
+#include "webrtc/test/fake_network_pipe.h"
 
 using ::testing::_;
 using ::testing::AnyNumber;
@@ -27,12 +28,12 @@
   MockReceiver() {}
   virtual ~MockReceiver() {}
 
-  void IncomingPacket(uint8_t* data, int length) {
-    IncomingData(data, length);
+  void IncomingPacket(const uint8_t* data, size_t length) {
+    DeliverPacket(data, length);
     delete [] data;
   }
 
-  MOCK_METHOD2(IncomingData, void(uint8_t*, int));
+  MOCK_METHOD2(DeliverPacket, bool(const uint8_t*, size_t));
 };
 
 class FakeNetworkPipeTest : public ::testing::Test {
@@ -63,11 +64,11 @@
 
 // Test the capacity link and verify we get as many packets as we expect.
 TEST_F(FakeNetworkPipeTest, CapacityTest) {
-  FakeNetworkPipe::Configuration config;
-  config.packet_receiver = receiver_.get();
+  FakeNetworkPipe::Config config;
   config.queue_length = 20;
   config.link_capacity_kbps = 80;
   scoped_ptr<FakeNetworkPipe> pipe(new FakeNetworkPipe(config));
+  pipe->SetReceiver(receiver_.get());
 
   // Add 10 packets of 1000 bytes, = 80 kb, and verify it takes one second to
   // get through the pipe.
@@ -80,37 +81,37 @@
                                          kPacketSize);
 
   // Time haven't increased yet, so we souldn't get any packets.
-  EXPECT_CALL(*receiver_, IncomingData(_, _))
+  EXPECT_CALL(*receiver_, DeliverPacket(_, _))
       .Times(0);
-  pipe->NetworkProcess();
+  pipe->Process();
 
   // Advance enough time to release one packet.
   TickTime::AdvanceFakeClock(kPacketTimeMs);
-  EXPECT_CALL(*receiver_, IncomingData(_, _))
+  EXPECT_CALL(*receiver_, DeliverPacket(_, _))
       .Times(1);
-  pipe->NetworkProcess();
+  pipe->Process();
 
   // Release all but one packet
   TickTime::AdvanceFakeClock(9 * kPacketTimeMs - 1);
-  EXPECT_CALL(*receiver_, IncomingData(_, _))
+  EXPECT_CALL(*receiver_, DeliverPacket(_, _))
       .Times(8);
-  pipe->NetworkProcess();
+  pipe->Process();
 
   // And the last one.
   TickTime::AdvanceFakeClock(1);
-  EXPECT_CALL(*receiver_, IncomingData(_, _))
+  EXPECT_CALL(*receiver_, DeliverPacket(_, _))
       .Times(1);
-  pipe->NetworkProcess();
+  pipe->Process();
 }
 
 // Test the extra network delay.
 TEST_F(FakeNetworkPipeTest, ExtraDelayTest) {
-  FakeNetworkPipe::Configuration config;
-  config.packet_receiver = receiver_.get();
+  FakeNetworkPipe::Config config;
   config.queue_length = 20;
   config.queue_delay_ms = 100;
   config.link_capacity_kbps = 80;
   scoped_ptr<FakeNetworkPipe> pipe(new FakeNetworkPipe(config));
+  pipe->SetReceiver(receiver_.get());
 
   const int kNumPackets = 2;
   const int kPacketSize = 1000;
@@ -122,31 +123,31 @@
 
   // Increase more than kPacketTimeMs, but not more than the extra delay.
   TickTime::AdvanceFakeClock(kPacketTimeMs);
-  EXPECT_CALL(*receiver_, IncomingData(_, _))
+  EXPECT_CALL(*receiver_, DeliverPacket(_, _))
       .Times(0);
-  pipe->NetworkProcess();
+  pipe->Process();
 
   // Advance the network delay to get the first packet.
   TickTime::AdvanceFakeClock(config.queue_delay_ms);
-  EXPECT_CALL(*receiver_, IncomingData(_, _))
+  EXPECT_CALL(*receiver_, DeliverPacket(_, _))
       .Times(1);
-  pipe->NetworkProcess();
+  pipe->Process();
 
   // Advance one more kPacketTimeMs to get the last packet.
   TickTime::AdvanceFakeClock(kPacketTimeMs);
-  EXPECT_CALL(*receiver_, IncomingData(_, _))
+  EXPECT_CALL(*receiver_, DeliverPacket(_, _))
       .Times(1);
-  pipe->NetworkProcess();
+  pipe->Process();
 }
 
 // Test the number of buffers and packets are dropped when sending too many
 // packets too quickly.
 TEST_F(FakeNetworkPipeTest, QueueLengthTest) {
-  FakeNetworkPipe::Configuration config;
-  config.packet_receiver = receiver_.get();
+  FakeNetworkPipe::Config config;
   config.queue_length = 2;
   config.link_capacity_kbps = 80;
   scoped_ptr<FakeNetworkPipe> pipe(new FakeNetworkPipe(config));
+  pipe->SetReceiver(receiver_.get());
 
   const int kPacketSize = 1000;
   const int kPacketTimeMs = PacketTimeMs(config.link_capacity_kbps,
@@ -158,19 +159,19 @@
   // Increase time enough to deliver all three packets, verify only two are
   // delivered.
   TickTime::AdvanceFakeClock(3 * kPacketTimeMs);
-  EXPECT_CALL(*receiver_, IncomingData(_, _))
+  EXPECT_CALL(*receiver_, DeliverPacket(_, _))
       .Times(2);
-  pipe->NetworkProcess();
+  pipe->Process();
 }
 
 // Test we get statistics as expected.
 TEST_F(FakeNetworkPipeTest, StatisticsTest) {
-  FakeNetworkPipe::Configuration config;
-  config.packet_receiver = receiver_.get();
+  FakeNetworkPipe::Config config;
   config.queue_length = 2;
   config.queue_delay_ms = 20;
   config.link_capacity_kbps = 80;
   scoped_ptr<FakeNetworkPipe> pipe(new FakeNetworkPipe(config));
+  pipe->SetReceiver(receiver_.get());
 
   const int kPacketSize = 1000;
   const int kPacketTimeMs = PacketTimeMs(config.link_capacity_kbps,
@@ -180,15 +181,15 @@
   SendPackets(pipe.get(), 3, kPacketSize);
   TickTime::AdvanceFakeClock(3 * kPacketTimeMs + config.queue_delay_ms);
 
-  EXPECT_CALL(*receiver_, IncomingData(_, _))
+  EXPECT_CALL(*receiver_, DeliverPacket(_, _))
       .Times(2);
-  pipe->NetworkProcess();
+  pipe->Process();
 
   // Packet 1: kPacketTimeMs + config.queue_delay_ms,
   // packet 2: 2 * kPacketTimeMs + config.queue_delay_ms => 170 ms average.
   EXPECT_EQ(pipe->AverageDelay(), 170);
-  EXPECT_EQ(pipe->sent_packets(), 2);
-  EXPECT_EQ(pipe->dropped_packets(), 1);
+  EXPECT_EQ(pipe->sent_packets(), 2u);
+  EXPECT_EQ(pipe->dropped_packets(), 1u);
   EXPECT_EQ(pipe->PercentageLoss(), 1/3.f);
 }
 
diff --git a/test/rtp_rtcp_observer.h b/test/rtp_rtcp_observer.h
index 56c96fa..3b4ad7b 100644
--- a/test/rtp_rtcp_observer.h
+++ b/test/rtp_rtcp_observer.h
@@ -49,7 +49,8 @@
   }
 
  protected:
-  RtpRtcpObserver(unsigned int event_timeout_ms, int delay_ms)
+  RtpRtcpObserver(unsigned int event_timeout_ms,
+      const FakeNetworkPipe::Config& configuration)
       : lock_(CriticalSectionWrapper::CreateCriticalSection()),
         observation_complete_(EventWrapper::Create()),
         parser_(RtpHeaderParser::Create()),
@@ -57,12 +58,12 @@
                         this,
                         &RtpRtcpObserver::OnSendRtp,
                         &RtpRtcpObserver::OnSendRtcp,
-                        delay_ms),
+                        configuration),
         receive_transport_(lock_.get(),
                            this,
                            &RtpRtcpObserver::OnReceiveRtp,
                            &RtpRtcpObserver::OnReceiveRtcp,
-                           delay_ms),
+                           configuration),
         timeout_ms_(event_timeout_ms) {}
 
   explicit RtpRtcpObserver(unsigned int event_timeout_ms)
@@ -73,12 +74,12 @@
                         this,
                         &RtpRtcpObserver::OnSendRtp,
                         &RtpRtcpObserver::OnSendRtcp,
-                        0),
+                        FakeNetworkPipe::Config()),
         receive_transport_(lock_.get(),
                            this,
                            &RtpRtcpObserver::OnReceiveRtp,
                            &RtpRtcpObserver::OnReceiveRtcp,
-                           0),
+                           FakeNetworkPipe::Config()),
         timeout_ms_(event_timeout_ms) {}
 
   enum Action {
@@ -113,8 +114,8 @@
                     RtpRtcpObserver* observer,
                     PacketTransportAction on_rtp,
                     PacketTransportAction on_rtcp,
-                    int delay_ms)
-        : test::DirectTransport(delay_ms),
+                    const FakeNetworkPipe::Config& configuration)
+        : test::DirectTransport(configuration),
           lock_(lock),
           observer_(observer),
           on_rtp_(on_rtp),
diff --git a/test/webrtc_test_common.gyp b/test/webrtc_test_common.gyp
index eae66a0..eac8b97 100644
--- a/test/webrtc_test_common.gyp
+++ b/test/webrtc_test_common.gyp
@@ -24,6 +24,8 @@
         'fake_decoder.h',
         'fake_encoder.cc',
         'fake_encoder.h',
+        'fake_network_pipe.cc',
+        'fake_network_pipe.h',
         'flags.cc',
         'flags.h',
         'frame_generator_capturer.cc',
@@ -124,4 +126,23 @@
       ],
     },
   ],
+  'conditions': [
+    ['include_tests==1', {
+      'targets': [
+        {
+          'target_name': 'webrtc_test_common_unittests',
+          'type': '<(gtest_target_type)',
+          'dependencies': [
+            'webrtc_test_common',
+            '<(DEPTH)/testing/gtest.gyp:gtest',
+            '<(DEPTH)/testing/gmock.gyp:gmock',
+            '<(webrtc_root)/test/test.gyp:test_support_main',
+          ],
+          'sources': [
+            'fake_network_pipe_unittest.cc',
+          ],
+        },
+      ],  #targets
+    }],  # include_tests
+  ],  # conditions
 }
diff --git a/video/call_perf_tests.cc b/video/call_perf_tests.cc
index 49c6488..0637ec3 100644
--- a/video/call_perf_tests.cc
+++ b/video/call_perf_tests.cc
@@ -49,8 +49,8 @@
 
 class SyncRtcpObserver : public test::RtpRtcpObserver {
  public:
-  explicit SyncRtcpObserver(int delay_ms)
-      : test::RtpRtcpObserver(kLongTimeoutMs, delay_ms),
+  explicit SyncRtcpObserver(const FakeNetworkPipe::Config& config)
+      : test::RtpRtcpObserver(kLongTimeoutMs, config),
         critical_section_(CriticalSectionWrapper::CreateCriticalSection()) {}
 
   virtual Action OnSendRtcp(const uint8_t* packet, size_t length) OVERRIDE {
@@ -119,7 +119,7 @@
                            int voe_channel,
                            VoEVideoSync* voe_sync,
                            SyncRtcpObserver* audio_observer)
-      : SyncRtcpObserver(0),
+      : SyncRtcpObserver(FakeNetworkPipe::Config()),
         clock_(clock),
         voe_channel_(voe_channel),
         voe_sync_(voe_sync),
@@ -189,8 +189,9 @@
   EXPECT_EQ(0, voe_base->Init(&fake_audio_device, NULL));
   int channel = voe_base->CreateChannel();
 
-  const int kVoiceDelayMs = 500;
-  SyncRtcpObserver audio_observer(kVoiceDelayMs);
+  FakeNetworkPipe::Config net_config;
+  net_config.queue_delay_ms = 500;
+  SyncRtcpObserver audio_observer(net_config);
   VideoRtcpAndSyncObserver observer(
       Clock::GetRealTimeClock(), channel, voe_sync, &audio_observer);
 
diff --git a/video_engine/test/libvietest/libvietest.gypi b/video_engine/test/libvietest/libvietest.gypi
index a3ba22e..33d0b0f 100644
--- a/video_engine/test/libvietest/libvietest.gypi
+++ b/video_engine/test/libvietest/libvietest.gypi
@@ -28,14 +28,12 @@
         'helpers/vie_to_file_renderer.cc',
 
         # Testbed classes
-        'include/fake_network_pipe.h',
         'include/tb_capture_device.h',
         'include/tb_external_transport.h',
         'include/tb_I420_codec.h',
         'include/tb_interfaces.h',
         'include/tb_video_channel.h',
 
-        'testbed/fake_network_pipe.cc',
         'testbed/tb_capture_device.cc',
         'testbed/tb_external_transport.cc',
         'testbed/tb_I420_codec.cc',
@@ -48,23 +46,4 @@
       ],
     },
   ],
-  'conditions': [
-    ['include_tests==1', {
-      'targets': [
-        {
-          'target_name': 'libvietest_unittests',
-          'type': 'executable',
-          'dependencies': [
-            'libvietest',
-            '<(DEPTH)/testing/gtest.gyp:gtest',
-            '<(DEPTH)/testing/gmock.gyp:gmock',
-            '<(webrtc_root)/test/test.gyp:test_support_main',
-          ],
-          'sources': [
-            'testbed/fake_network_pipe_unittest.cc',
-          ],
-        },
-      ], #targets
-    }], # include_tests
-  ], # conditions
 }
diff --git a/video_engine/test/libvietest/testbed/fake_network_pipe.cc b/video_engine/test/libvietest/testbed/fake_network_pipe.cc
deleted file mode 100644
index b1c8eb2..0000000
--- a/video_engine/test/libvietest/testbed/fake_network_pipe.cc
+++ /dev/null
@@ -1,173 +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.
- */
-
-#include "webrtc/video_engine/test/libvietest/include/fake_network_pipe.h"
-
-#include <assert.h>
-#include <math.h>
-#include <string.h>
-
-#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
-#include "webrtc/system_wrappers/interface/tick_util.h"
-
-namespace webrtc {
-
-const double kPi = 3.14159265;
-
-static int GaussianRandom(int mean_delay_ms, int standard_deviation_ms) {
-  // Creating a Normal distribution variable from two independent uniform
-  // variables based on the Box-Muller transform.
-  double uniform1 = (rand() + 1.0) / (RAND_MAX + 1.0);  // NOLINT
-  double uniform2 = (rand() + 1.0) / (RAND_MAX + 1.0);  // NOLINT
-  return static_cast<int>(mean_delay_ms + standard_deviation_ms *
-                          sqrt(-2 * log(uniform1)) * cos(2 * kPi * uniform2));
-}
-
-class NetworkPacket {
- public:
-  NetworkPacket(void* data, int length, int64_t send_time, int64_t arrival_time)
-      : data_(NULL),
-        data_length_(length),
-        send_time_(send_time),
-        arrival_time_(arrival_time) {
-    data_ = new uint8_t[length];
-    memcpy(data_, data, length);
-  }
-  ~NetworkPacket() {}
-
-  void ReleaseData() {
-    delete [] data_;
-    data_ = NULL;
-  }
-  uint8_t* data() const { return data_; }
-  int data_length() const { return data_length_; }
-  int64_t send_time() const { return send_time_; }
-  int64_t arrival_time() const { return arrival_time_; }
-  void IncrementArrivalTime(int64_t extra_delay) {
-    arrival_time_+= extra_delay;
-  }
-
- private:
-  // The packet data.
-  uint8_t* data_;
-  // Length of data_.
-  int data_length_;
-  // The time the packet was sent out on the network.
-  const int64_t send_time_;
-  // The time the packet should arrive at the reciver.
-  int64_t arrival_time_;
-};
-
-FakeNetworkPipe::FakeNetworkPipe(
-    const FakeNetworkPipe::Configuration& configuration)
-    : packet_receiver_(configuration.packet_receiver),
-      link_cs_(CriticalSectionWrapper::CreateCriticalSection()),
-      queue_length_(configuration.queue_length),
-      queue_delay_ms_(configuration.queue_delay_ms),
-      queue_delay_deviation_ms_(configuration.delay_standard_deviation_ms),
-      link_capacity_bytes_ms_(configuration.link_capacity_kbps / 8),
-      loss_percent_(configuration.loss_percent),
-      dropped_packets_(0),
-      sent_packets_(0),
-      total_packet_delay_(0) {
-  assert(link_capacity_bytes_ms_ > 0);
-  assert(packet_receiver_ != NULL);
-}
-
-FakeNetworkPipe::~FakeNetworkPipe() {
-}
-
-void FakeNetworkPipe::SendPacket(void* data, int data_length) {
-  CriticalSectionScoped cs(link_cs_.get());
-  if (capacity_link_.size() >= queue_length_) {
-    // Too many packet on the link, drop this one.
-    ++dropped_packets_;
-    return;
-  }
-
-  int64_t time_now = TickTime::MillisecondTimestamp();
-
-  // Delay introduced by the link capacity.
-  int64_t capacity_delay_ms = data_length / link_capacity_bytes_ms_;
-  int64_t network_start_time = time_now;
-
-  // Check if there already are packets on the link and change network start
-  // time if there is.
-  if (capacity_link_.size() > 0)
-    network_start_time = capacity_link_.back()->arrival_time();
-
-  int64_t arrival_time = network_start_time + capacity_delay_ms;
-  NetworkPacket* packet = new NetworkPacket(data, data_length, time_now,
-                                            arrival_time);
-  capacity_link_.push(packet);
-}
-
-float FakeNetworkPipe::PercentageLoss() {
-  CriticalSectionScoped cs(link_cs_.get());
-  if (sent_packets_ == 0)
-    return 0;
-
-  return static_cast<float>(dropped_packets_) /
-      (sent_packets_ + dropped_packets_);
-}
-
-int FakeNetworkPipe::AverageDelay() {
-  CriticalSectionScoped cs(link_cs_.get());
-  if (sent_packets_ == 0)
-    return 0;
-
-  return total_packet_delay_ / sent_packets_;
-}
-
-void FakeNetworkPipe::NetworkProcess() {
-  CriticalSectionScoped cs(link_cs_.get());
-  if (capacity_link_.size() == 0 && delay_link_.size() == 0)
-    return;
-
-  int64_t time_now = TickTime::MillisecondTimestamp();
-
-  // Check the capacity link first.
-  while (capacity_link_.size() > 0 &&
-         time_now >= capacity_link_.front()->arrival_time()) {
-    // Time to get this packet.
-    NetworkPacket* packet = capacity_link_.front();
-    capacity_link_.pop();
-
-    // Add extra delay and jitter, but make sure the arrival time is not earlier
-    // than the last packet in the queue.
-    int extra_delay = GaussianRandom(queue_delay_ms_,
-                                     queue_delay_deviation_ms_);
-    if (delay_link_.size() > 0 &&
-        packet->arrival_time() + extra_delay <
-        delay_link_.back()->arrival_time()) {
-      extra_delay = delay_link_.back()->arrival_time() - packet->arrival_time();
-    }
-    packet->IncrementArrivalTime(extra_delay);
-    delay_link_.push(packet);
-  }
-
-  // Check the extra delay queue.
-  while (delay_link_.size() > 0 &&
-         time_now >= delay_link_.front()->arrival_time()) {
-    // Deliver this packet.
-    NetworkPacket* packet = delay_link_.front();
-    delay_link_.pop();
-    packet_receiver_->IncomingPacket(packet->data(), packet->data_length());
-    ++sent_packets_;
-
-    // |time_now| might be later than when the packet should have arrived, due
-    // to NetworkProcess being called too late. For stats, use the time it
-    // should have been on the link.
-    total_packet_delay_ += packet->arrival_time() - packet->send_time();
-    delete packet;
-  }
-}
-
-}  // namespace webrtc
diff --git a/webrtc.gyp b/webrtc.gyp
index ed101b6..e78dba6 100644
--- a/webrtc.gyp
+++ b/webrtc.gyp
@@ -43,6 +43,7 @@
             'system_wrappers/source/system_wrappers_tests.gyp:*',
             'test/metrics.gyp:*',
             'test/test.gyp:*',
+            'test/webrtc_test_common.gyp:webrtc_test_common_unittests',
             'tools/tools.gyp:*',
             'webrtc_tests',
           ],