Refactor Call-based tests.

Greatly reduces duplication of constants and setup code for tests based
on the new webrtc::Call APIs. It also makes it significantly easier to
convert sender-only to end-to-end tests as they share more code.

BUG=3035
R=kjellander@webrtc.org, stefan@webrtc.org

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

git-svn-id: http://webrtc.googlecode.com/svn/trunk@6551 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/tools/valgrind-webrtc/gtest_exclude/video_engine_tests.gtest-drmemory_win32.txt b/tools/valgrind-webrtc/gtest_exclude/video_engine_tests.gtest-drmemory_win32.txt
index bfc6b54..6a213a2 100644
--- a/tools/valgrind-webrtc/gtest_exclude/video_engine_tests.gtest-drmemory_win32.txt
+++ b/tools/valgrind-webrtc/gtest_exclude/video_engine_tests.gtest-drmemory_win32.txt
@@ -1,6 +1,6 @@
 # Never completes on Dr Memory Full.
 # https://code.google.com/p/webrtc/issues/detail?id=3159
-CallTest.SendsAndReceivesMultipleStreams
-CallTest.ReceivesAndRetransmitsNack
+EndToEndTest.SendsAndReceivesMultipleStreams
+EndToEndTest.ReceivesAndRetransmitsNack
 # https://code.google.com/p/webrtc/issues/detail?id=3471
 VideoSendStreamTest.RetransmitsNackOverRtxWithPacing
diff --git a/tools/valgrind-webrtc/gtest_exclude/video_engine_tests.gtest-tsan.txt b/tools/valgrind-webrtc/gtest_exclude/video_engine_tests.gtest-tsan.txt
deleted file mode 100644
index 6dab6251..0000000
--- a/tools/valgrind-webrtc/gtest_exclude/video_engine_tests.gtest-tsan.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-# https://code.google.com/p/webrtc/issues/detail?id=2908
-CallTest.ReceivesAndRetransmitsNack
diff --git a/webrtc/test/call_test.cc b/webrtc/test/call_test.cc
new file mode 100644
index 0000000..ad2416f
--- /dev/null
+++ b/webrtc/test/call_test.cc
@@ -0,0 +1,216 @@
+/*
+ *  Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+#include "webrtc/test/call_test.h"
+
+#include "webrtc/test/encoder_settings.h"
+
+namespace webrtc {
+namespace test {
+
+CallTest::CallTest()
+    : send_stream_(NULL),
+      receive_stream_(NULL),
+      fake_encoder_(Clock::GetRealTimeClock()) {
+}
+CallTest::~CallTest() {
+}
+
+void CallTest::RunBaseTest(BaseTest* test) {
+  CreateSenderCall(test->GetSenderCallConfig());
+  if (test->ShouldCreateReceivers())
+    CreateReceiverCall(test->GetReceiverCallConfig());
+  test->OnCallsCreated(sender_call_.get(), receiver_call_.get());
+
+  if (test->ShouldCreateReceivers()) {
+    test->SetReceivers(receiver_call_->Receiver(), sender_call_->Receiver());
+  } else {
+    // Sender-only call delivers to itself.
+    test->SetReceivers(sender_call_->Receiver(), NULL);
+  }
+
+  CreateSendConfig(test->GetNumStreams());
+  if (test->ShouldCreateReceivers()) {
+    CreateMatchingReceiveConfigs();
+  }
+  test->ModifyConfigs(&send_config_, &receive_config_, &video_streams_);
+  CreateStreams();
+  test->OnStreamsCreated(send_stream_, receive_stream_);
+
+  CreateFrameGeneratorCapturer();
+  test->OnFrameGeneratorCapturerCreated(frame_generator_capturer_.get());
+
+  Start();
+  test->PerformTest();
+  test->StopSending();
+  Stop();
+
+  DestroyStreams();
+}
+
+void CallTest::Start() {
+  send_stream_->Start();
+  if (receive_stream_ != NULL)
+    receive_stream_->Start();
+  frame_generator_capturer_->Start();
+}
+
+void CallTest::Stop() {
+  frame_generator_capturer_->Stop();
+  if (receive_stream_ != NULL)
+    receive_stream_->Stop();
+  send_stream_->Stop();
+}
+
+void CallTest::CreateCalls(const Call::Config& sender_config,
+                           const Call::Config& receiver_config) {
+  CreateSenderCall(sender_config);
+  CreateReceiverCall(receiver_config);
+}
+
+void CallTest::CreateSenderCall(const Call::Config& config) {
+  sender_call_.reset(Call::Create(config));
+}
+
+void CallTest::CreateReceiverCall(const Call::Config& config) {
+  receiver_call_.reset(Call::Create(config));
+}
+
+void CallTest::CreateSendConfig(size_t num_streams) {
+  assert(num_streams <= kNumSsrcs);
+  send_config_ = sender_call_->GetDefaultSendConfig();
+  send_config_.encoder_settings.encoder = &fake_encoder_;
+  send_config_.encoder_settings.payload_name = "FAKE";
+  send_config_.encoder_settings.payload_type = kFakeSendPayloadType;
+  video_streams_ = test::CreateVideoStreams(num_streams);
+  for (size_t i = 0; i < num_streams; ++i)
+    send_config_.rtp.ssrcs.push_back(kSendSsrcs[i]);
+}
+
+// TODO(pbos): Make receive configs into a vector.
+void CallTest::CreateMatchingReceiveConfigs() {
+  assert(send_config_.rtp.ssrcs.size() == 1);
+  receive_config_ = receiver_call_->GetDefaultReceiveConfig();
+  VideoCodec codec =
+      test::CreateDecoderVideoCodec(send_config_.encoder_settings);
+  receive_config_.codecs.push_back(codec);
+  if (send_config_.encoder_settings.encoder == &fake_encoder_) {
+    ExternalVideoDecoder decoder;
+    decoder.decoder = &fake_decoder_;
+    decoder.payload_type = send_config_.encoder_settings.payload_type;
+    receive_config_.external_decoders.push_back(decoder);
+  }
+  receive_config_.rtp.remote_ssrc = send_config_.rtp.ssrcs[0];
+  receive_config_.rtp.local_ssrc = kReceiverLocalSsrc;
+}
+
+void CallTest::CreateFrameGeneratorCapturer() {
+  VideoStream stream = video_streams_.back();
+  frame_generator_capturer_.reset(
+      test::FrameGeneratorCapturer::Create(send_stream_->Input(),
+                                           stream.width,
+                                           stream.height,
+                                           stream.max_framerate,
+                                           Clock::GetRealTimeClock()));
+}
+void CallTest::CreateStreams() {
+  assert(send_stream_ == NULL);
+  assert(receive_stream_ == NULL);
+
+  send_stream_ =
+      sender_call_->CreateVideoSendStream(send_config_, video_streams_, NULL);
+
+  if (receiver_call_.get() != NULL)
+    receive_stream_ = receiver_call_->CreateVideoReceiveStream(receive_config_);
+}
+
+void CallTest::DestroyStreams() {
+  if (send_stream_ != NULL)
+    sender_call_->DestroyVideoSendStream(send_stream_);
+  if (receive_stream_ != NULL)
+    receiver_call_->DestroyVideoReceiveStream(receive_stream_);
+  send_stream_ = NULL;
+  receive_stream_ = NULL;
+}
+
+const unsigned int CallTest::kDefaultTimeoutMs = 30 * 1000;
+const unsigned int CallTest::kLongTimeoutMs = 120 * 1000;
+const uint8_t CallTest::kSendPayloadType = 100;
+const uint8_t CallTest::kFakeSendPayloadType = 125;
+const uint8_t CallTest::kSendRtxPayloadType = 98;
+const uint32_t CallTest::kSendRtxSsrc = 0xBADCAFE;
+const uint32_t CallTest::kSendSsrcs[kNumSsrcs] = {0xC0FFED, 0xC0FFEE, 0xC0FFEF};
+const uint32_t CallTest::kReceiverLocalSsrc = 0x123456;
+const int CallTest::kNackRtpHistoryMs = 1000;
+
+BaseTest::BaseTest(unsigned int timeout_ms) : RtpRtcpObserver(timeout_ms) {
+}
+
+BaseTest::BaseTest(unsigned int timeout_ms,
+                   const FakeNetworkPipe::Config& config)
+    : RtpRtcpObserver(timeout_ms, config) {
+}
+
+BaseTest::~BaseTest() {
+}
+
+Call::Config BaseTest::GetSenderCallConfig() {
+  return Call::Config(SendTransport());
+}
+
+Call::Config BaseTest::GetReceiverCallConfig() {
+  return Call::Config(ReceiveTransport());
+}
+
+void BaseTest::OnCallsCreated(Call* sender_call, Call* receiver_call) {
+}
+
+size_t BaseTest::GetNumStreams() const {
+  return 1;
+}
+
+void BaseTest::ModifyConfigs(VideoSendStream::Config* send_config,
+                             VideoReceiveStream::Config* receive_config,
+                             std::vector<VideoStream>* video_streams) {
+}
+
+void BaseTest::OnStreamsCreated(VideoSendStream* send_stream,
+                                VideoReceiveStream* receive_stream) {
+}
+
+void BaseTest::OnFrameGeneratorCapturerCreated(
+    FrameGeneratorCapturer* frame_generator_capturer) {
+}
+
+SendTest::SendTest(unsigned int timeout_ms) : BaseTest(timeout_ms) {
+}
+
+SendTest::SendTest(unsigned int timeout_ms,
+                   const FakeNetworkPipe::Config& config)
+    : BaseTest(timeout_ms, config) {
+}
+
+bool SendTest::ShouldCreateReceivers() const {
+  return false;
+}
+
+EndToEndTest::EndToEndTest(unsigned int timeout_ms) : BaseTest(timeout_ms) {
+}
+
+EndToEndTest::EndToEndTest(unsigned int timeout_ms,
+                           const FakeNetworkPipe::Config& config)
+    : BaseTest(timeout_ms, config) {
+}
+
+bool EndToEndTest::ShouldCreateReceivers() const {
+  return true;
+}
+
+}  // namespace test
+}  // namespace webrtc
diff --git a/webrtc/test/call_test.h b/webrtc/test/call_test.h
new file mode 100644
index 0000000..94ac2fa
--- /dev/null
+++ b/webrtc/test/call_test.h
@@ -0,0 +1,119 @@
+/*
+ *  Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+#ifndef WEBRTC_TEST_COMMON_CALL_TEST_H_
+#define WEBRTC_TEST_COMMON_CALL_TEST_H_
+
+#include <vector>
+
+#include "webrtc/call.h"
+#include "webrtc/test/fake_decoder.h"
+#include "webrtc/test/fake_encoder.h"
+#include "webrtc/test/frame_generator_capturer.h"
+#include "webrtc/test/rtp_rtcp_observer.h"
+
+namespace webrtc {
+namespace test {
+
+class BaseTest;
+
+class CallTest : public ::testing::Test {
+ public:
+  CallTest();
+  ~CallTest();
+
+  static const size_t kNumSsrcs = 3;
+
+  static const unsigned int kDefaultTimeoutMs;
+  static const unsigned int kLongTimeoutMs;
+  static const uint8_t kSendPayloadType;
+  static const uint8_t kSendRtxPayloadType;
+  static const uint8_t kFakeSendPayloadType;
+  static const uint32_t kSendRtxSsrc;
+  static const uint32_t kSendSsrcs[kNumSsrcs];
+  static const uint32_t kReceiverLocalSsrc;
+  static const int kNackRtpHistoryMs;
+
+ protected:
+  void RunBaseTest(BaseTest* test);
+
+  void CreateCalls(const Call::Config& sender_config,
+                   const Call::Config& receiver_config);
+  void CreateSenderCall(const Call::Config& config);
+  void CreateReceiverCall(const Call::Config& config);
+
+  void CreateSendConfig(size_t num_streams);
+  void CreateMatchingReceiveConfigs();
+
+  void CreateFrameGeneratorCapturer();
+
+  void CreateStreams();
+  void Start();
+  void Stop();
+  void DestroyStreams();
+
+  scoped_ptr<Call> sender_call_;
+  VideoSendStream::Config send_config_;
+  std::vector<VideoStream> video_streams_;
+  VideoSendStream* send_stream_;
+
+  scoped_ptr<Call> receiver_call_;
+  VideoReceiveStream::Config receive_config_;
+  VideoReceiveStream* receive_stream_;
+
+  scoped_ptr<test::FrameGeneratorCapturer> frame_generator_capturer_;
+  test::FakeEncoder fake_encoder_;
+  test::FakeDecoder fake_decoder_;
+};
+
+class BaseTest : public RtpRtcpObserver {
+ public:
+  explicit BaseTest(unsigned int timeout_ms);
+  BaseTest(unsigned int timeout_ms, const FakeNetworkPipe::Config& config);
+  virtual ~BaseTest();
+
+  virtual void PerformTest() = 0;
+  virtual bool ShouldCreateReceivers() const = 0;
+
+  virtual size_t GetNumStreams() const;
+
+  virtual Call::Config GetSenderCallConfig();
+  virtual Call::Config GetReceiverCallConfig();
+  virtual void OnCallsCreated(Call* sender_call, Call* receiver_call);
+
+  virtual void ModifyConfigs(VideoSendStream::Config* send_config,
+                             VideoReceiveStream::Config* receive_config,
+                             std::vector<VideoStream>* video_streams);
+  virtual void OnStreamsCreated(VideoSendStream* send_stream,
+                                VideoReceiveStream* receive_stream);
+
+  virtual void OnFrameGeneratorCapturerCreated(
+      FrameGeneratorCapturer* frame_generator_capturer);
+};
+
+class SendTest : public BaseTest {
+ public:
+  explicit SendTest(unsigned int timeout_ms);
+  SendTest(unsigned int timeout_ms, const FakeNetworkPipe::Config& config);
+
+  virtual bool ShouldCreateReceivers() const OVERRIDE;
+};
+
+class EndToEndTest : public BaseTest {
+ public:
+  explicit EndToEndTest(unsigned int timeout_ms);
+  EndToEndTest(unsigned int timeout_ms, const FakeNetworkPipe::Config& config);
+
+  virtual bool ShouldCreateReceivers() const OVERRIDE;
+};
+
+}  // namespace test
+}  // namespace webrtc
+
+#endif  // WEBRTC_TEST_COMMON_CALL_TEST_H_
diff --git a/webrtc/test/rtp_rtcp_observer.h b/webrtc/test/rtp_rtcp_observer.h
index e448653..670a29d 100644
--- a/webrtc/test/rtp_rtcp_observer.h
+++ b/webrtc/test/rtp_rtcp_observer.h
@@ -16,6 +16,7 @@
 #include "testing/gtest/include/gtest/gtest.h"
 
 #include "webrtc/modules/rtp_rtcp/interface/rtp_header_parser.h"
+#include "webrtc/test/direct_transport.h"
 #include "webrtc/typedefs.h"
 #include "webrtc/video_send_stream.h"
 
diff --git a/webrtc/test/webrtc_test_common.gyp b/webrtc/test/webrtc_test_common.gyp
index 556a445..8c8774f 100644
--- a/webrtc/test/webrtc_test_common.gyp
+++ b/webrtc/test/webrtc_test_common.gyp
@@ -14,6 +14,8 @@
       'target_name': 'webrtc_test_common',
       'type': 'static_library',
       'sources': [
+        'call_test.cc',
+        'call_test.h',
         'configurable_frame_size_encoder.cc',
         'configurable_frame_size_encoder.h',
         'direct_transport.cc',
@@ -54,10 +56,11 @@
       'dependencies': [
         '<(DEPTH)/testing/gtest.gyp:gtest',
         '<(DEPTH)/third_party/gflags/gflags.gyp:gflags',
-        '<(webrtc_root)/modules/modules.gyp:video_capture_module',
         '<(webrtc_root)/modules/modules.gyp:media_file',
+        '<(webrtc_root)/modules/modules.gyp:video_capture_module',
         '<(webrtc_root)/test/test.gyp:frame_generator',
         '<(webrtc_root)/test/test.gyp:test_support',
+        '<(webrtc_root)/webrtc.gyp:webrtc',
       ],
     },
     {
diff --git a/webrtc/video/bitrate_estimator_tests.cc b/webrtc/video/bitrate_estimator_tests.cc
index f8b9060..d21de17 100644
--- a/webrtc/video/bitrate_estimator_tests.cc
+++ b/webrtc/video/bitrate_estimator_tests.cc
@@ -19,6 +19,7 @@
 #include "webrtc/system_wrappers/interface/scoped_ptr.h"
 #include "webrtc/system_wrappers/interface/thread_annotations.h"
 #include "webrtc/system_wrappers/interface/trace.h"
+#include "webrtc/test/call_test.h"
 #include "webrtc/test/direct_transport.h"
 #include "webrtc/test/encoder_settings.h"
 #include "webrtc/test/fake_decoder.h"
@@ -30,12 +31,7 @@
 static const int kTOFExtensionId = 4;
 static const int kASTExtensionId = 5;
 
-static unsigned int kDefaultTimeoutMs = 30 * 1000;
-static const uint32_t kSendSsrc = 0x654321;
-static const uint32_t kReceiverLocalSsrc = 0x123456;
-static const uint8_t kSendPayloadType = 125;
-
-class BitrateEstimatorTest : public ::testing::Test {
+class BitrateEstimatorTest : public test::CallTest {
  public:
   BitrateEstimatorTest()
       : receiver_trace_(),
@@ -43,7 +39,6 @@
         receive_transport_(),
         sender_call_(),
         receiver_call_(),
-        send_config_(),
         receive_config_(),
         streams_() {
   }
@@ -68,11 +63,11 @@
     receive_transport_.SetReceiver(sender_call_->Receiver());
 
     send_config_ = sender_call_->GetDefaultSendConfig();
-    send_config_.rtp.ssrcs.push_back(kSendSsrc);
+    send_config_.rtp.ssrcs.push_back(kSendSsrcs[0]);
     // Encoders will be set separately per stream.
     send_config_.encoder_settings.encoder = NULL;
     send_config_.encoder_settings.payload_name = "FAKE";
-    send_config_.encoder_settings.payload_type = kSendPayloadType;
+    send_config_.encoder_settings.payload_type = kFakeSendPayloadType;
     video_streams_ = test::CreateVideoStreams(1);
 
     receive_config_ = receiver_call_->GetDefaultReceiveConfig();
@@ -228,8 +223,6 @@
   test::DirectTransport receive_transport_;
   scoped_ptr<Call> sender_call_;
   scoped_ptr<Call> receiver_call_;
-  VideoSendStream::Config send_config_;
-  std::vector<VideoStream> video_streams_;
   VideoReceiveStream::Config receive_config_;
   std::vector<Stream*> streams_;
 };
diff --git a/webrtc/video/call_perf_tests.cc b/webrtc/video/call_perf_tests.cc
index fa3f238..b6e2b34 100644
--- a/webrtc/video/call_perf_tests.cc
+++ b/webrtc/video/call_perf_tests.cc
@@ -23,6 +23,7 @@
 #include "webrtc/system_wrappers/interface/rtp_to_ntp.h"
 #include "webrtc/system_wrappers/interface/scoped_ptr.h"
 #include "webrtc/system_wrappers/interface/thread_annotations.h"
+#include "webrtc/test/call_test.h"
 #include "webrtc/test/direct_transport.h"
 #include "webrtc/test/encoder_settings.h"
 #include "webrtc/test/fake_audio_device.h"
@@ -42,61 +43,20 @@
 
 namespace webrtc {
 
-static unsigned int kLongTimeoutMs = 120 * 1000;
-static const uint32_t kSendSsrc = 0x654321;
-static const uint32_t kReceiverLocalSsrc = 0x123456;
-static const uint8_t kSendPayloadType = 125;
-
-class CallPerfTest : public ::testing::Test {
- public:
-  CallPerfTest()
-      : send_stream_(NULL), fake_encoder_(Clock::GetRealTimeClock()) {}
-
+class CallPerfTest : public test::CallTest {
  protected:
-  void CreateTestConfig(Call* call) {
-    send_config_ = call->GetDefaultSendConfig();
-    send_config_.rtp.ssrcs.push_back(kSendSsrc);
-    send_config_.encoder_settings.encoder = &fake_encoder_;
-    send_config_.encoder_settings.payload_type = kSendPayloadType;
-    send_config_.encoder_settings.payload_name = "FAKE";
-    video_streams_ = test::CreateVideoStreams(1);
-  }
-
-  void RunVideoSendTest(Call* call,
-                        const VideoSendStream::Config& config,
-                        test::RtpRtcpObserver* observer) {
-    send_stream_ = call->CreateVideoSendStream(config, video_streams_, NULL);
-    scoped_ptr<test::FrameGeneratorCapturer> frame_generator_capturer(
-        test::FrameGeneratorCapturer::Create(
-            send_stream_->Input(), 320, 240, 30, Clock::GetRealTimeClock()));
-    send_stream_->Start();
-    frame_generator_capturer->Start();
-
-    EXPECT_EQ(kEventSignaled, observer->Wait());
-
-    observer->StopSending();
-    frame_generator_capturer->Stop();
-    send_stream_->Stop();
-    call->DestroyVideoSendStream(send_stream_);
-  }
-
   void TestMinTransmitBitrate(bool pad_to_min_bitrate);
 
   void TestCaptureNtpTime(const FakeNetworkPipe::Config& net_config,
                           int threshold_ms,
                           int start_time_ms,
                           int run_time_ms);
-
-  VideoSendStream::Config send_config_;
-  std::vector<VideoStream> video_streams_;
-  VideoSendStream* send_stream_;
-  test::FakeEncoder fake_encoder_;
 };
 
 class SyncRtcpObserver : public test::RtpRtcpObserver {
  public:
   explicit SyncRtcpObserver(const FakeNetworkPipe::Config& config)
-      : test::RtpRtcpObserver(kLongTimeoutMs, config),
+      : test::RtpRtcpObserver(CallPerfTest::kLongTimeoutMs, config),
         crit_(CriticalSectionWrapper::CreateCriticalSection()) {}
 
   virtual Action OnSendRtcp(const uint8_t* packet, size_t length) OVERRIDE {
@@ -226,6 +186,31 @@
 };
 
 TEST_F(CallPerfTest, PlaysOutAudioAndVideoInSync) {
+  class AudioPacketReceiver : public PacketReceiver {
+   public:
+    AudioPacketReceiver(int channel, VoENetwork* voe_network)
+        : channel_(channel),
+          voe_network_(voe_network),
+          parser_(RtpHeaderParser::Create()) {}
+    virtual DeliveryStatus DeliverPacket(const uint8_t* packet,
+                                         size_t length) OVERRIDE {
+      int ret;
+      if (parser_->IsRtcp(packet, static_cast<int>(length))) {
+        ret = voe_network_->ReceivedRTCPPacket(
+            channel_, packet, static_cast<unsigned int>(length));
+      } else {
+        ret = voe_network_->ReceivedRTPPacket(
+            channel_, packet, static_cast<unsigned int>(length), PacketTime());
+      }
+      return ret == 0 ? DELIVERY_OK : DELIVERY_PACKET_ERROR;
+    }
+
+   private:
+    int channel_;
+    VoENetwork* voe_network_;
+    scoped_ptr<RtpHeaderParser> parser_;
+  };
+
   VoiceEngine* voice_engine = VoiceEngine::Create();
   VoEBase* voe_base = VoEBase::GetInterface(voice_engine);
   VoECodec* voe_codec = VoECodec::GetInterface(voice_engine);
@@ -249,37 +234,12 @@
 
   Call::Config receiver_config(observer.ReceiveTransport());
   receiver_config.voice_engine = voice_engine;
-  scoped_ptr<Call> sender_call(
-      Call::Create(Call::Config(observer.SendTransport())));
-  scoped_ptr<Call> receiver_call(Call::Create(receiver_config));
+  CreateCalls(Call::Config(observer.SendTransport()), receiver_config);
+
   CodecInst isac = {103, "ISAC", 16000, 480, 1, 32000};
   EXPECT_EQ(0, voe_codec->SetSendCodec(channel, isac));
 
-  class VoicePacketReceiver : public PacketReceiver {
-   public:
-    VoicePacketReceiver(int channel, VoENetwork* voe_network)
-        : channel_(channel),
-          voe_network_(voe_network),
-          parser_(RtpHeaderParser::Create()) {}
-    virtual DeliveryStatus DeliverPacket(const uint8_t* packet,
-                                         size_t length) OVERRIDE {
-      int ret;
-      if (parser_->IsRtcp(packet, static_cast<int>(length))) {
-        ret = voe_network_->ReceivedRTCPPacket(
-            channel_, packet, static_cast<unsigned int>(length));
-      } else {
-        ret = voe_network_->ReceivedRTPPacket(
-            channel_, packet, static_cast<unsigned int>(length), PacketTime());
-      }
-      return ret == 0 ? DELIVERY_OK : DELIVERY_PACKET_ERROR;
-    }
-
-   private:
-    int channel_;
-    VoENetwork* voe_network_;
-    scoped_ptr<RtpHeaderParser> parser_;
-  } voe_packet_receiver(channel, voe_network);
-
+  AudioPacketReceiver voe_packet_receiver(channel, voe_network);
   audio_observer.SetReceivers(&voe_packet_receiver, &voe_packet_receiver);
 
   internal::TransportAdapter transport_adapter(audio_observer.SendTransport());
@@ -287,41 +247,21 @@
   EXPECT_EQ(0,
             voe_network->RegisterExternalTransport(channel, transport_adapter));
 
-  observer.SetReceivers(receiver_call->Receiver(), sender_call->Receiver());
+  observer.SetReceivers(receiver_call_->Receiver(), sender_call_->Receiver());
 
   test::FakeDecoder fake_decoder;
 
-  CreateTestConfig(sender_call.get());
+  CreateSendConfig(1);
+  CreateMatchingReceiveConfigs();
 
-  VideoReceiveStream::Config receive_config =
-      receiver_call->GetDefaultReceiveConfig();
-  assert(receive_config.codecs.empty());
-  VideoCodec codec =
-      test::CreateDecoderVideoCodec(send_config_.encoder_settings);
-  receive_config.codecs.push_back(codec);
-  assert(receive_config.external_decoders.empty());
-  ExternalVideoDecoder decoder;
-  decoder.decoder = &fake_decoder;
-  decoder.payload_type = send_config_.encoder_settings.payload_type;
-  receive_config.external_decoders.push_back(decoder);
-  receive_config.rtp.remote_ssrc = send_config_.rtp.ssrcs[0];
-  receive_config.rtp.local_ssrc = kReceiverLocalSsrc;
-  receive_config.renderer = &observer;
-  receive_config.audio_channel_id = channel;
+  receive_config_.renderer = &observer;
+  receive_config_.audio_channel_id = channel;
 
-  VideoSendStream* send_stream =
-      sender_call->CreateVideoSendStream(send_config_, video_streams_, NULL);
-  VideoReceiveStream* receive_stream =
-      receiver_call->CreateVideoReceiveStream(receive_config);
-  scoped_ptr<test::FrameGeneratorCapturer> capturer(
-      test::FrameGeneratorCapturer::Create(send_stream->Input(),
-                                           video_streams_[0].width,
-                                           video_streams_[0].height,
-                                           30,
-                                           Clock::GetRealTimeClock()));
-  receive_stream->Start();
-  send_stream->Start();
-  capturer->Start();
+  CreateStreams();
+
+  CreateFrameGeneratorCapturer();
+
+  Start();
 
   fake_audio_device.Start();
   EXPECT_EQ(0, voe_base->StartPlayout(channel));
@@ -336,9 +276,7 @@
   EXPECT_EQ(0, voe_base->StopPlayout(channel));
   fake_audio_device.Stop();
 
-  capturer->Stop();
-  send_stream->Stop();
-  receive_stream->Stop();
+  Stop();
   observer.StopSending();
   audio_observer.StopSending();
 
@@ -347,174 +285,126 @@
   voe_codec->Release();
   voe_network->Release();
   voe_sync->Release();
-  sender_call->DestroyVideoSendStream(send_stream);
-  receiver_call->DestroyVideoReceiveStream(receive_stream);
+
+  DestroyStreams();
+
   VoiceEngine::Delete(voice_engine);
 }
 
-class CaptureNtpTimeObserver : public test::RtpRtcpObserver,
-                               public VideoRenderer {
- public:
-  CaptureNtpTimeObserver(Clock* clock,
-                         const FakeNetworkPipe::Config& config,
-                         int threshold_ms,
-                         int start_time_ms,
-                         int run_time_ms)
-      : RtpRtcpObserver(kLongTimeoutMs, config),
-        clock_(clock),
-        threshold_ms_(threshold_ms),
-        start_time_ms_(start_time_ms),
-        run_time_ms_(run_time_ms),
-        creation_time_ms_(clock_->TimeInMilliseconds()),
-        capturer_(NULL),
-        rtp_start_timestamp_set_(false),
-        rtp_start_timestamp_(0) {}
-
-  virtual void RenderFrame(const I420VideoFrame& video_frame,
-                           int time_to_render_ms) OVERRIDE {
-    if (video_frame.ntp_time_ms() <= 0) {
-      // Haven't got enough RTCP SR in order to calculate the capture ntp time.
-      return;
-    }
-
-    int64_t now_ms = clock_->TimeInMilliseconds();
-    int64_t time_since_creation = now_ms - creation_time_ms_;
-    if (time_since_creation < start_time_ms_) {
-      // Wait for |start_time_ms_| before start measuring.
-      return;
-    }
-
-    if (time_since_creation > run_time_ms_) {
-      observation_complete_->Set();
-    }
-
-    FrameCaptureTimeList::iterator iter =
-        capture_time_list_.find(video_frame.timestamp());
-    EXPECT_TRUE(iter != capture_time_list_.end());
-
-    // The real capture time has been wrapped to uint32_t before converted
-    // to rtp timestamp in the sender side. So here we convert the estimated
-    // capture time to a uint32_t 90k timestamp also for comparing.
-    uint32_t estimated_capture_timestamp =
-        90 * static_cast<uint32_t>(video_frame.ntp_time_ms());
-    uint32_t real_capture_timestamp = iter->second;
-    int time_offset_ms = real_capture_timestamp - estimated_capture_timestamp;
-    time_offset_ms = time_offset_ms / 90;
-    std::stringstream ss;
-    ss << time_offset_ms;
-
-    webrtc::test::PrintResult("capture_ntp_time",
-                              "",
-                              "real - estimated",
-                              ss.str(),
-                              "ms",
-                              true);
-    EXPECT_TRUE(std::abs(time_offset_ms) < threshold_ms_);
-  }
-
-  virtual Action OnSendRtp(const uint8_t* packet, size_t length) {
-    RTPHeader header;
-    EXPECT_TRUE(parser_->Parse(packet, static_cast<int>(length), &header));
-
-    if (!rtp_start_timestamp_set_) {
-      // Calculate the rtp timestamp offset in order to calculate the real
-      // capture time.
-      uint32_t first_capture_timestamp =
-          90 * static_cast<uint32_t>(capturer_->first_frame_capture_time());
-      rtp_start_timestamp_ = header.timestamp - first_capture_timestamp;
-      rtp_start_timestamp_set_ = true;
-    }
-
-    uint32_t capture_timestamp = header.timestamp - rtp_start_timestamp_;
-    capture_time_list_.insert(capture_time_list_.end(),
-                              std::make_pair(header.timestamp,
-                                             capture_timestamp));
-    return SEND_PACKET;
-  }
-
-  void SetCapturer(test::FrameGeneratorCapturer* capturer) {
-    capturer_ = capturer;
-  }
-
- private:
-  Clock* clock_;
-  int threshold_ms_;
-  int start_time_ms_;
-  int run_time_ms_;
-  int64_t creation_time_ms_;
-  test::FrameGeneratorCapturer* capturer_;
-  bool rtp_start_timestamp_set_;
-  uint32_t rtp_start_timestamp_;
-  typedef std::map<uint32_t, uint32_t> FrameCaptureTimeList;
-  FrameCaptureTimeList capture_time_list_;
-};
-
 void CallPerfTest::TestCaptureNtpTime(const FakeNetworkPipe::Config& net_config,
                                       int threshold_ms,
                                       int start_time_ms,
                                       int run_time_ms) {
-  CaptureNtpTimeObserver observer(Clock::GetRealTimeClock(),
-                                  net_config,
-                                  threshold_ms,
-                                  start_time_ms,
-                                  run_time_ms);
+  class CaptureNtpTimeObserver : public test::EndToEndTest,
+                                 public VideoRenderer {
+   public:
+    CaptureNtpTimeObserver(const FakeNetworkPipe::Config& config,
+                           int threshold_ms,
+                           int start_time_ms,
+                           int run_time_ms)
+        : EndToEndTest(kLongTimeoutMs, config),
+          clock_(Clock::GetRealTimeClock()),
+          threshold_ms_(threshold_ms),
+          start_time_ms_(start_time_ms),
+          run_time_ms_(run_time_ms),
+          creation_time_ms_(clock_->TimeInMilliseconds()),
+          capturer_(NULL),
+          rtp_start_timestamp_set_(false),
+          rtp_start_timestamp_(0) {}
 
-  // Sender/receiver call.
-  Call::Config receiver_config(observer.ReceiveTransport());
-  scoped_ptr<Call> receiver_call(Call::Create(receiver_config));
-  scoped_ptr<Call> sender_call(
-      Call::Create(Call::Config(observer.SendTransport())));
-  observer.SetReceivers(receiver_call->Receiver(), sender_call->Receiver());
+   private:
+    virtual void RenderFrame(const I420VideoFrame& video_frame,
+                             int time_to_render_ms) OVERRIDE {
+      if (video_frame.ntp_time_ms() <= 0) {
+        // Haven't got enough RTCP SR in order to calculate the capture ntp
+        // time.
+        return;
+      }
 
-  // Configure send stream.
-  CreateTestConfig(sender_call.get());
-  VideoSendStream* send_stream =
-      sender_call->CreateVideoSendStream(send_config_, video_streams_, NULL);
-  scoped_ptr<test::FrameGeneratorCapturer> capturer(
-      test::FrameGeneratorCapturer::Create(send_stream->Input(),
-                                           video_streams_[0].width,
-                                           video_streams_[0].height,
-                                           30,
-                                           Clock::GetRealTimeClock()));
-  observer.SetCapturer(capturer.get());
+      int64_t now_ms = clock_->TimeInMilliseconds();
+      int64_t time_since_creation = now_ms - creation_time_ms_;
+      if (time_since_creation < start_time_ms_) {
+        // Wait for |start_time_ms_| before start measuring.
+        return;
+      }
 
-  // Configure receive stream.
-  VideoReceiveStream::Config receive_config =
-      receiver_call->GetDefaultReceiveConfig();
-  assert(receive_config.codecs.empty());
-  VideoCodec codec =
-      test::CreateDecoderVideoCodec(send_config_.encoder_settings);
-  receive_config.codecs.push_back(codec);
-  assert(receive_config.external_decoders.empty());
-  ExternalVideoDecoder decoder;
-  test::FakeDecoder fake_decoder;
-  decoder.decoder = &fake_decoder;
-  decoder.payload_type = send_config_.encoder_settings.payload_type;
-  receive_config.external_decoders.push_back(decoder);
-  receive_config.rtp.remote_ssrc = send_config_.rtp.ssrcs[0];
-  receive_config.rtp.local_ssrc = kReceiverLocalSsrc;
-  receive_config.renderer = &observer;
-  // Enable the receiver side rtt calculation.
-  receive_config.rtp.rtcp_xr.receiver_reference_time_report = true;
-  VideoReceiveStream* receive_stream =
-      receiver_call->CreateVideoReceiveStream(receive_config);
+      if (time_since_creation > run_time_ms_) {
+        observation_complete_->Set();
+      }
 
-  // Start the test
-  receive_stream->Start();
-  send_stream->Start();
-  capturer->Start();
+      FrameCaptureTimeList::iterator iter =
+          capture_time_list_.find(video_frame.timestamp());
+      EXPECT_TRUE(iter != capture_time_list_.end());
 
-  EXPECT_EQ(kEventSignaled, observer.Wait())
-      << "Timed out while waiting for estimated capture ntp time to be "
-      << "within bounds.";
+      // The real capture time has been wrapped to uint32_t before converted
+      // to rtp timestamp in the sender side. So here we convert the estimated
+      // capture time to a uint32_t 90k timestamp also for comparing.
+      uint32_t estimated_capture_timestamp =
+          90 * static_cast<uint32_t>(video_frame.ntp_time_ms());
+      uint32_t real_capture_timestamp = iter->second;
+      int time_offset_ms = real_capture_timestamp - estimated_capture_timestamp;
+      time_offset_ms = time_offset_ms / 90;
+      std::stringstream ss;
+      ss << time_offset_ms;
 
-  capturer->Stop();
-  send_stream->Stop();
-  receive_stream->Stop();
-  observer.StopSending();
+      webrtc::test::PrintResult(
+          "capture_ntp_time", "", "real - estimated", ss.str(), "ms", true);
+      EXPECT_TRUE(std::abs(time_offset_ms) < threshold_ms_);
+    }
 
-  sender_call->DestroyVideoSendStream(send_stream);
-  receiver_call->DestroyVideoReceiveStream(receive_stream);
+    virtual Action OnSendRtp(const uint8_t* packet, size_t length) {
+      RTPHeader header;
+      EXPECT_TRUE(parser_->Parse(packet, static_cast<int>(length), &header));
+
+      if (!rtp_start_timestamp_set_) {
+        // Calculate the rtp timestamp offset in order to calculate the real
+        // capture time.
+        uint32_t first_capture_timestamp =
+            90 * static_cast<uint32_t>(capturer_->first_frame_capture_time());
+        rtp_start_timestamp_ = header.timestamp - first_capture_timestamp;
+        rtp_start_timestamp_set_ = true;
+      }
+
+      uint32_t capture_timestamp = header.timestamp - rtp_start_timestamp_;
+      capture_time_list_.insert(
+          capture_time_list_.end(),
+          std::make_pair(header.timestamp, capture_timestamp));
+      return SEND_PACKET;
+    }
+
+    virtual void OnFrameGeneratorCapturerCreated(
+        test::FrameGeneratorCapturer* frame_generator_capturer) OVERRIDE {
+      capturer_ = frame_generator_capturer;
+    }
+
+    virtual void ModifyConfigs(
+        VideoSendStream::Config* send_config,
+        VideoReceiveStream::Config* receive_config,
+        std::vector<VideoStream>* video_streams) OVERRIDE {
+      receive_config->renderer = this;
+      // Enable the receiver side rtt calculation.
+      receive_config->rtp.rtcp_xr.receiver_reference_time_report = true;
+    }
+
+    virtual void PerformTest() OVERRIDE {
+      EXPECT_EQ(kEventSignaled, Wait()) << "Timed out while waiting for "
+                                           "estimated capture NTP time to be "
+                                           "within bounds.";
+    }
+
+    Clock* clock_;
+    int threshold_ms_;
+    int start_time_ms_;
+    int run_time_ms_;
+    int64_t creation_time_ms_;
+    test::FrameGeneratorCapturer* capturer_;
+    bool rtp_start_timestamp_set_;
+    uint32_t rtp_start_timestamp_;
+    typedef std::map<uint32_t, uint32_t> FrameCaptureTimeList;
+    FrameCaptureTimeList capture_time_list_;
+  } test(net_config, threshold_ms, start_time_ms, run_time_ms);
+
+  RunBaseTest(&test);
 }
 
 TEST_F(CallPerfTest, CaptureNtpTimeWithNetworkDelay) {
@@ -542,26 +432,32 @@
 
 TEST_F(CallPerfTest, RegisterCpuOveruseObserver) {
   // Verifies that either a normal or overuse callback is triggered.
-  class OveruseCallbackObserver : public test::RtpRtcpObserver,
+  class OveruseCallbackObserver : public test::SendTest,
                                   public webrtc::OveruseCallback {
    public:
-    OveruseCallbackObserver() : RtpRtcpObserver(kLongTimeoutMs) {}
+    OveruseCallbackObserver() : SendTest(kLongTimeoutMs) {}
 
     virtual void OnOveruse() OVERRIDE {
       observation_complete_->Set();
     }
+
     virtual void OnNormalUse() OVERRIDE {
       observation_complete_->Set();
     }
-  };
 
-  OveruseCallbackObserver observer;
-  Call::Config call_config(observer.SendTransport());
-  call_config.overuse_callback = &observer;
-  scoped_ptr<Call> call(Call::Create(call_config));
+    virtual Call::Config GetSenderCallConfig() OVERRIDE {
+      Call::Config config(SendTransport());
+      config.overuse_callback = this;
+      return config;
+    }
 
-  CreateTestConfig(call.get());
-  RunVideoSendTest(call.get(), send_config_, &observer);
+    virtual void PerformTest() OVERRIDE {
+      EXPECT_EQ(kEventSignaled, Wait())
+          << "Timed out before receiving an overuse callback.";
+    }
+  } test;
+
+  RunBaseTest(&test);
 }
 
 void CallPerfTest::TestMinTransmitBitrate(bool pad_to_min_bitrate) {
@@ -570,15 +466,16 @@
   static const int kMinAcceptableTransmitBitrate = 130;
   static const int kMaxAcceptableTransmitBitrate = 170;
   static const int kNumBitrateObservationsInRange = 100;
-  class BitrateObserver : public test::RtpRtcpObserver, public PacketReceiver {
+  class BitrateObserver : public test::EndToEndTest, public PacketReceiver {
    public:
     explicit BitrateObserver(bool using_min_transmit_bitrate)
-        : test::RtpRtcpObserver(kLongTimeoutMs),
+        : EndToEndTest(kLongTimeoutMs),
           send_stream_(NULL),
           send_transport_receiver_(NULL),
-          using_min_transmit_bitrate_(using_min_transmit_bitrate),
+          pad_to_min_bitrate_(using_min_transmit_bitrate),
           num_bitrate_observations_in_range_(0) {}
 
+   private:
     virtual void SetReceivers(PacketReceiver* send_transport_receiver,
                               PacketReceiver* receive_transport_receiver)
         OVERRIDE {
@@ -586,11 +483,6 @@
       test::RtpRtcpObserver::SetReceivers(this, receive_transport_receiver);
     }
 
-    void SetSendStream(VideoSendStream* send_stream) {
-      send_stream_ = send_stream;
-    }
-
-   private:
     virtual DeliveryStatus DeliverPacket(const uint8_t* packet,
                                          size_t length) OVERRIDE {
       VideoSendStream::Stats stats = send_stream_->GetStats();
@@ -600,13 +492,13 @@
         if (bitrate_kbps > 0) {
           test::PrintResult(
               "bitrate_stats_",
-              (using_min_transmit_bitrate_ ? "min_transmit_bitrate"
-                                           : "without_min_transmit_bitrate"),
+              (pad_to_min_bitrate_ ? "min_transmit_bitrate"
+                                   : "without_min_transmit_bitrate"),
               "bitrate_kbps",
               static_cast<size_t>(bitrate_kbps),
               "kbps",
               false);
-          if (using_min_transmit_bitrate_) {
+          if (pad_to_min_bitrate_) {
             if (bitrate_kbps > kMinAcceptableTransmitBitrate &&
                 bitrate_kbps < kMaxAcceptableTransmitBitrate) {
               ++num_bitrate_observations_in_range_;
@@ -626,66 +518,35 @@
       return send_transport_receiver_->DeliverPacket(packet, length);
     }
 
+    virtual void OnStreamsCreated(VideoSendStream* send_stream,
+                                  VideoReceiveStream* receive_stream) {
+      send_stream_ = send_stream;
+    }
+
+    virtual void ModifyConfigs(
+        VideoSendStream::Config* send_config,
+        VideoReceiveStream::Config* receive_config,
+        std::vector<VideoStream>* video_streams) OVERRIDE {
+      if (pad_to_min_bitrate_) {
+        send_config->rtp.min_transmit_bitrate_bps = kMinTransmitBitrateBps;
+      } else {
+        assert(send_config->rtp.min_transmit_bitrate_bps == 0);
+      }
+    }
+
+    virtual void PerformTest() OVERRIDE {
+      EXPECT_EQ(kEventSignaled, Wait())
+          << "Timeout while waiting for send-bitrate stats.";
+    }
+
     VideoSendStream* send_stream_;
     PacketReceiver* send_transport_receiver_;
-    const bool using_min_transmit_bitrate_;
+    const bool pad_to_min_bitrate_;
     int num_bitrate_observations_in_range_;
-  } observer(pad_to_min_bitrate);
+  } test(pad_to_min_bitrate);
 
-  scoped_ptr<Call> sender_call(
-      Call::Create(Call::Config(observer.SendTransport())));
-  scoped_ptr<Call> receiver_call(
-      Call::Create(Call::Config(observer.ReceiveTransport())));
-
-  CreateTestConfig(sender_call.get());
   fake_encoder_.SetMaxBitrate(kMaxEncodeBitrateKbps);
-
-  observer.SetReceivers(receiver_call->Receiver(), sender_call->Receiver());
-
-  if (pad_to_min_bitrate) {
-    send_config_.rtp.min_transmit_bitrate_bps = kMinTransmitBitrateBps;
-  } else {
-    assert(send_config_.rtp.min_transmit_bitrate_bps == 0);
-  }
-
-  VideoReceiveStream::Config receive_config =
-      receiver_call->GetDefaultReceiveConfig();
-  receive_config.codecs.clear();
-  VideoCodec codec =
-      test::CreateDecoderVideoCodec(send_config_.encoder_settings);
-  receive_config.codecs.push_back(codec);
-  test::FakeDecoder fake_decoder;
-  ExternalVideoDecoder decoder;
-  decoder.decoder = &fake_decoder;
-  decoder.payload_type = send_config_.encoder_settings.payload_type;
-  receive_config.external_decoders.push_back(decoder);
-  receive_config.rtp.remote_ssrc = send_config_.rtp.ssrcs[0];
-  receive_config.rtp.local_ssrc = kReceiverLocalSsrc;
-
-  VideoSendStream* send_stream =
-      sender_call->CreateVideoSendStream(send_config_, video_streams_, NULL);
-  VideoReceiveStream* receive_stream =
-      receiver_call->CreateVideoReceiveStream(receive_config);
-  scoped_ptr<test::FrameGeneratorCapturer> capturer(
-      test::FrameGeneratorCapturer::Create(send_stream->Input(),
-                                           video_streams_[0].width,
-                                           video_streams_[0].height,
-                                           30,
-                                           Clock::GetRealTimeClock()));
-  observer.SetSendStream(send_stream);
-  receive_stream->Start();
-  send_stream->Start();
-  capturer->Start();
-
-  EXPECT_EQ(kEventSignaled, observer.Wait())
-      << "Timeout while waiting for send-bitrate stats.";
-
-  send_stream->Stop();
-  receive_stream->Stop();
-  observer.StopSending();
-  capturer->Stop();
-  sender_call->DestroyVideoSendStream(send_stream);
-  receiver_call->DestroyVideoReceiveStream(receive_stream);
+  RunBaseTest(&test);
 }
 
 TEST_F(CallPerfTest, PadsToMinTransmitBitrate) { TestMinTransmitBitrate(true); }
diff --git a/webrtc/video/call_tests.cc b/webrtc/video/call_tests.cc
deleted file mode 100644
index 5bcf115..0000000
--- a/webrtc/video/call_tests.cc
+++ /dev/null
@@ -1,1612 +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.
- */
-#include <assert.h>
-
-#include <algorithm>
-#include <map>
-#include <sstream>
-#include <string>
-
-#include "testing/gtest/include/gtest/gtest.h"
-
-#include "webrtc/call.h"
-#include "webrtc/frame_callback.h"
-#include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h"
-#include "webrtc/modules/video_coding/codecs/vp8/include/vp8.h"
-#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
-#include "webrtc/system_wrappers/interface/event_wrapper.h"
-#include "webrtc/system_wrappers/interface/scoped_ptr.h"
-#include "webrtc/system_wrappers/interface/sleep.h"
-#include "webrtc/test/direct_transport.h"
-#include "webrtc/test/encoder_settings.h"
-#include "webrtc/test/fake_audio_device.h"
-#include "webrtc/test/fake_decoder.h"
-#include "webrtc/test/fake_encoder.h"
-#include "webrtc/test/frame_generator.h"
-#include "webrtc/test/frame_generator_capturer.h"
-#include "webrtc/test/null_transport.h"
-#include "webrtc/test/rtp_rtcp_observer.h"
-#include "webrtc/test/testsupport/fileutils.h"
-#include "webrtc/test/testsupport/perf_test.h"
-#include "webrtc/video/transport_adapter.h"
-
-namespace webrtc {
-
-static unsigned int kDefaultTimeoutMs = 30 * 1000;
-static unsigned int kLongTimeoutMs = 120 * 1000;
-static const uint32_t kSendSsrc = 0x654321;
-static const uint32_t kSendRtxSsrc = 0x424242;
-static const uint32_t kReceiverLocalSsrc = 0x123456;
-static const uint8_t kSendPayloadType = 125;
-static const uint8_t kSendRtxPayloadType = 126;
-static const int kRedPayloadType = 118;
-static const int kUlpfecPayloadType = 119;
-
-class CallTest : public ::testing::Test {
- public:
-  CallTest()
-      : send_stream_(NULL),
-        receive_stream_(NULL),
-        fake_encoder_(Clock::GetRealTimeClock()) {}
-
-  virtual ~CallTest() {
-    EXPECT_EQ(NULL, send_stream_);
-    EXPECT_EQ(NULL, receive_stream_);
-  }
-
- protected:
-  void CreateCalls(const Call::Config& sender_config,
-                   const Call::Config& receiver_config) {
-    sender_call_.reset(Call::Create(sender_config));
-    receiver_call_.reset(Call::Create(receiver_config));
-  }
-
-  void CreateTestConfigs() {
-    send_config_ = sender_call_->GetDefaultSendConfig();
-    receive_config_ = receiver_call_->GetDefaultReceiveConfig();
-
-    send_config_.rtp.ssrcs.push_back(kSendSsrc);
-    send_config_.encoder_settings.encoder = &fake_encoder_;
-    send_config_.encoder_settings.payload_name = "FAKE";
-    send_config_.encoder_settings.payload_type = kSendPayloadType;
-    video_streams_ = test::CreateVideoStreams(1);
-
-    assert(receive_config_.codecs.empty());
-    VideoCodec codec =
-        test::CreateDecoderVideoCodec(send_config_.encoder_settings);
-    receive_config_.codecs.push_back(codec);
-    ExternalVideoDecoder decoder;
-    decoder.decoder = &fake_decoder_;
-    decoder.payload_type = send_config_.encoder_settings.payload_type;
-    receive_config_.external_decoders.push_back(decoder);
-    receive_config_.rtp.remote_ssrc = send_config_.rtp.ssrcs[0];
-    receive_config_.rtp.local_ssrc = kReceiverLocalSsrc;
-  }
-
-  void CreateStreams() {
-    assert(send_stream_ == NULL);
-    assert(receive_stream_ == NULL);
-
-    send_stream_ =
-        sender_call_->CreateVideoSendStream(send_config_, video_streams_, NULL);
-    receive_stream_ = receiver_call_->CreateVideoReceiveStream(receive_config_);
-  }
-
-  void CreateFrameGenerator() {
-    frame_generator_capturer_.reset(
-        test::FrameGeneratorCapturer::Create(send_stream_->Input(),
-                                             video_streams_[0].width,
-                                             video_streams_[0].height,
-                                             30,
-                                             Clock::GetRealTimeClock()));
-  }
-
-  void StartSending() {
-    receive_stream_->Start();
-    send_stream_->Start();
-    if (frame_generator_capturer_.get() != NULL)
-      frame_generator_capturer_->Start();
-  }
-
-  void StopSending() {
-    if (frame_generator_capturer_.get() != NULL)
-      frame_generator_capturer_->Stop();
-    if (send_stream_ != NULL)
-      send_stream_->Stop();
-    if (receive_stream_ != NULL)
-      receive_stream_->Stop();
-  }
-
-  void DestroyStreams() {
-    if (send_stream_ != NULL)
-      sender_call_->DestroyVideoSendStream(send_stream_);
-    if (receive_stream_ != NULL)
-      receiver_call_->DestroyVideoReceiveStream(receive_stream_);
-    send_stream_ = NULL;
-    receive_stream_ = NULL;
-  }
-
-  void DecodesRetransmittedFrame(bool retransmit_over_rtx);
-  void ReceivesPliAndRecovers(int rtp_history_ms);
-  void RespectsRtcpMode(newapi::RtcpMode rtcp_mode);
-  void TestXrReceiverReferenceTimeReport(bool enable_rrtr);
-
-  scoped_ptr<Call> sender_call_;
-  scoped_ptr<Call> receiver_call_;
-
-  VideoSendStream::Config send_config_;
-  std::vector<VideoStream> video_streams_;
-  VideoReceiveStream::Config receive_config_;
-
-  VideoSendStream* send_stream_;
-  VideoReceiveStream* receive_stream_;
-
-  scoped_ptr<test::FrameGeneratorCapturer> frame_generator_capturer_;
-
-  test::FakeEncoder fake_encoder_;
-  test::FakeDecoder fake_decoder_;
-};
-
-class NackObserver : public test::RtpRtcpObserver {
-  static const int kNumberOfNacksToObserve = 2;
-  static const int kLossBurstSize = 2;
-  static const int kPacketsBetweenLossBursts = 9;
-
- public:
-  NackObserver()
-      : test::RtpRtcpObserver(kLongTimeoutMs),
-        rtp_parser_(RtpHeaderParser::Create()),
-        sent_rtp_packets_(0),
-        packets_left_to_drop_(0),
-        nacks_left_(kNumberOfNacksToObserve) {}
-
- private:
-  virtual Action OnSendRtp(const uint8_t* packet, size_t length) OVERRIDE {
-    RTPHeader header;
-    EXPECT_TRUE(rtp_parser_->Parse(packet, static_cast<int>(length), &header));
-
-    // Never drop retransmitted packets.
-    if (dropped_packets_.find(header.sequenceNumber) !=
-        dropped_packets_.end()) {
-      retransmitted_packets_.insert(header.sequenceNumber);
-      if (nacks_left_ == 0 &&
-          retransmitted_packets_.size() == dropped_packets_.size()) {
-        observation_complete_->Set();
-      }
-      return SEND_PACKET;
-    }
-
-    ++sent_rtp_packets_;
-
-    // Enough NACKs received, stop dropping packets.
-    if (nacks_left_ == 0)
-      return SEND_PACKET;
-
-    // Check if it's time for a new loss burst.
-    if (sent_rtp_packets_ % kPacketsBetweenLossBursts == 0)
-      packets_left_to_drop_ = kLossBurstSize;
-
-    if (packets_left_to_drop_ > 0) {
-      --packets_left_to_drop_;
-      dropped_packets_.insert(header.sequenceNumber);
-      return DROP_PACKET;
-    }
-
-    return SEND_PACKET;
-  }
-
-  virtual Action OnReceiveRtcp(const uint8_t* packet, size_t length) OVERRIDE {
-    RTCPUtility::RTCPParserV2 parser(packet, length, true);
-    EXPECT_TRUE(parser.IsValid());
-
-    RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
-    while (packet_type != RTCPUtility::kRtcpNotValidCode) {
-      if (packet_type == RTCPUtility::kRtcpRtpfbNackCode) {
-        --nacks_left_;
-        break;
-      }
-      packet_type = parser.Iterate();
-    }
-    return SEND_PACKET;
-  }
-
- private:
-  scoped_ptr<RtpHeaderParser> rtp_parser_;
-  std::set<uint16_t> dropped_packets_;
-  std::set<uint16_t> retransmitted_packets_;
-  uint64_t sent_rtp_packets_;
-  int packets_left_to_drop_;
-  int nacks_left_;
-};
-
-TEST_F(CallTest, ReceiverCanBeStartedTwice) {
-  test::NullTransport transport;
-  CreateCalls(Call::Config(&transport), Call::Config(&transport));
-
-  CreateTestConfigs();
-  CreateStreams();
-
-  receive_stream_->Start();
-  receive_stream_->Start();
-
-  DestroyStreams();
-}
-
-TEST_F(CallTest, ReceiverCanBeStoppedTwice) {
-  test::NullTransport transport;
-  CreateCalls(Call::Config(&transport), Call::Config(&transport));
-
-  CreateTestConfigs();
-  CreateStreams();
-
-  receive_stream_->Stop();
-  receive_stream_->Stop();
-
-  DestroyStreams();
-}
-
-TEST_F(CallTest, RendersSingleDelayedFrame) {
-  static const int kWidth = 320;
-  static const int kHeight = 240;
-  // This constant is chosen to be higher than the timeout in the video_render
-  // module. This makes sure that frames aren't dropped if there are no other
-  // frames in the queue.
-  static const int kDelayRenderCallbackMs = 1000;
-
-  class Renderer : public VideoRenderer {
-   public:
-    Renderer() : event_(EventWrapper::Create()) {}
-
-    virtual void RenderFrame(const I420VideoFrame& video_frame,
-                             int /*time_to_render_ms*/) OVERRIDE {
-      event_->Set();
-    }
-
-    EventTypeWrapper Wait() { return event_->Wait(kDefaultTimeoutMs); }
-
-    scoped_ptr<EventWrapper> event_;
-  } renderer;
-
-  class TestFrameCallback : public I420FrameCallback {
-   public:
-    TestFrameCallback() : event_(EventWrapper::Create()) {}
-
-    EventTypeWrapper Wait() { return event_->Wait(kDefaultTimeoutMs); }
-
-   private:
-    virtual void FrameCallback(I420VideoFrame* frame) OVERRIDE {
-      SleepMs(kDelayRenderCallbackMs);
-      event_->Set();
-    }
-
-    scoped_ptr<EventWrapper> event_;
-  };
-
-  test::DirectTransport sender_transport, receiver_transport;
-
-  CreateCalls(Call::Config(&sender_transport),
-              Call::Config(&receiver_transport));
-
-  sender_transport.SetReceiver(receiver_call_->Receiver());
-  receiver_transport.SetReceiver(sender_call_->Receiver());
-
-  CreateTestConfigs();
-
-  TestFrameCallback pre_render_callback;
-  receive_config_.pre_render_callback = &pre_render_callback;
-  receive_config_.renderer = &renderer;
-
-  CreateStreams();
-  StartSending();
-
-  // Create frames that are smaller than the send width/height, this is done to
-  // check that the callbacks are done after processing video.
-  scoped_ptr<test::FrameGenerator> frame_generator(
-      test::FrameGenerator::Create(kWidth, kHeight));
-  send_stream_->Input()->SwapFrame(frame_generator->NextFrame());
-  EXPECT_EQ(kEventSignaled, pre_render_callback.Wait())
-      << "Timed out while waiting for pre-render callback.";
-  EXPECT_EQ(kEventSignaled, renderer.Wait())
-      << "Timed out while waiting for the frame to render.";
-
-  StopSending();
-
-  sender_transport.StopSending();
-  receiver_transport.StopSending();
-
-  DestroyStreams();
-}
-
-TEST_F(CallTest, TransmitsFirstFrame) {
-  class Renderer : public VideoRenderer {
-   public:
-    Renderer() : event_(EventWrapper::Create()) {}
-
-    virtual void RenderFrame(const I420VideoFrame& video_frame,
-                             int /*time_to_render_ms*/) OVERRIDE {
-      event_->Set();
-    }
-
-    EventTypeWrapper Wait() { return event_->Wait(kDefaultTimeoutMs); }
-
-    scoped_ptr<EventWrapper> event_;
-  } renderer;
-
-  test::DirectTransport sender_transport, receiver_transport;
-
-  CreateCalls(Call::Config(&sender_transport),
-              Call::Config(&receiver_transport));
-
-  sender_transport.SetReceiver(receiver_call_->Receiver());
-  receiver_transport.SetReceiver(sender_call_->Receiver());
-
-  CreateTestConfigs();
-  receive_config_.renderer = &renderer;
-
-  CreateStreams();
-  StartSending();
-
-  scoped_ptr<test::FrameGenerator> frame_generator(test::FrameGenerator::Create(
-      video_streams_[0].width, video_streams_[0].height));
-  send_stream_->Input()->SwapFrame(frame_generator->NextFrame());
-
-  EXPECT_EQ(kEventSignaled, renderer.Wait())
-      << "Timed out while waiting for the frame to render.";
-
-  StopSending();
-
-  sender_transport.StopSending();
-  receiver_transport.StopSending();
-
-  DestroyStreams();
-}
-
-TEST_F(CallTest, ReceiverUsesLocalSsrc) {
-  class SyncRtcpObserver : public test::RtpRtcpObserver {
-   public:
-    SyncRtcpObserver() : test::RtpRtcpObserver(kDefaultTimeoutMs) {}
-
-    virtual Action OnReceiveRtcp(const uint8_t* packet,
-                                 size_t length) OVERRIDE {
-      RTCPUtility::RTCPParserV2 parser(packet, length, true);
-      EXPECT_TRUE(parser.IsValid());
-      uint32_t ssrc = 0;
-      ssrc |= static_cast<uint32_t>(packet[4]) << 24;
-      ssrc |= static_cast<uint32_t>(packet[5]) << 16;
-      ssrc |= static_cast<uint32_t>(packet[6]) << 8;
-      ssrc |= static_cast<uint32_t>(packet[7]) << 0;
-      EXPECT_EQ(kReceiverLocalSsrc, ssrc);
-      observation_complete_->Set();
-
-      return SEND_PACKET;
-    }
-  } observer;
-
-  CreateCalls(Call::Config(observer.SendTransport()),
-              Call::Config(observer.ReceiveTransport()));
-
-  observer.SetReceivers(receiver_call_->Receiver(), sender_call_->Receiver());
-
-  CreateTestConfigs();
-
-  CreateStreams();
-  CreateFrameGenerator();
-  StartSending();
-
-  EXPECT_EQ(kEventSignaled, observer.Wait())
-      << "Timed out while waiting for a receiver RTCP packet to be sent.";
-
-  StopSending();
-
-  observer.StopSending();
-
-  DestroyStreams();
-}
-
-TEST_F(CallTest, ReceivesAndRetransmitsNack) {
-  NackObserver observer;
-
-  CreateCalls(Call::Config(observer.SendTransport()),
-              Call::Config(observer.ReceiveTransport()));
-
-  observer.SetReceivers(receiver_call_->Receiver(), sender_call_->Receiver());
-
-  CreateTestConfigs();
-  int rtp_history_ms = 1000;
-  send_config_.rtp.nack.rtp_history_ms = rtp_history_ms;
-  receive_config_.rtp.nack.rtp_history_ms = rtp_history_ms;
-
-  CreateStreams();
-  CreateFrameGenerator();
-  StartSending();
-
-  // Wait() waits for an event triggered when NACKs have been received, NACKed
-  // packets retransmitted and frames rendered again.
-  EXPECT_EQ(kEventSignaled, observer.Wait());
-
-  StopSending();
-
-  observer.StopSending();
-
-  DestroyStreams();
-}
-
-// TODO(pbos): Flaky, webrtc:3269
-TEST_F(CallTest, DISABLED_CanReceiveFec) {
-  class FecRenderObserver : public test::RtpRtcpObserver, public VideoRenderer {
-   public:
-    FecRenderObserver()
-        : RtpRtcpObserver(kDefaultTimeoutMs),
-          state_(kFirstPacket),
-          protected_sequence_number_(0),
-          protected_frame_timestamp_(0) {}
-
-   private:
-    virtual Action OnSendRtp(const uint8_t* packet, size_t length) OVERRIDE
-        EXCLUSIVE_LOCKS_REQUIRED(crit_) {
-      RTPHeader header;
-      EXPECT_TRUE(parser_->Parse(packet, static_cast<int>(length), &header));
-
-      EXPECT_EQ(kRedPayloadType, header.payloadType);
-      int encapsulated_payload_type =
-          static_cast<int>(packet[header.headerLength]);
-      if (encapsulated_payload_type != kSendPayloadType)
-        EXPECT_EQ(kUlpfecPayloadType, encapsulated_payload_type);
-
-      switch(state_) {
-        case kFirstPacket:
-          state_ = kDropEveryOtherPacketUntilFec;
-          break;
-        case kDropEveryOtherPacketUntilFec:
-          if (encapsulated_payload_type == kUlpfecPayloadType) {
-            state_ = kDropNextMediaPacket;
-            return SEND_PACKET;
-          }
-          if (header.sequenceNumber % 2 == 0)
-            return DROP_PACKET;
-          break;
-        case kDropNextMediaPacket:
-          if (encapsulated_payload_type == kSendPayloadType) {
-            protected_sequence_number_ = header.sequenceNumber;
-            protected_frame_timestamp_ = header.timestamp;
-            state_ = kProtectedPacketDropped;
-            return DROP_PACKET;
-          }
-          break;
-        case kProtectedPacketDropped:
-          EXPECT_NE(header.sequenceNumber, protected_sequence_number_)
-              << "Protected packet retransmitted. Should not happen with FEC.";
-          break;
-      }
-
-      return SEND_PACKET;
-    }
-
-    virtual void RenderFrame(const I420VideoFrame& video_frame,
-                             int time_to_render_ms) OVERRIDE {
-      CriticalSectionScoped lock(crit_.get());
-      // Rendering frame with timestamp associated with dropped packet -> FEC
-      // protection worked.
-      if (state_ == kProtectedPacketDropped &&
-          video_frame.timestamp() == protected_frame_timestamp_) {
-        observation_complete_->Set();
-      }
-    }
-
-    enum {
-      kFirstPacket,
-      kDropEveryOtherPacketUntilFec,
-      kDropNextMediaPacket,
-      kProtectedPacketDropped,
-    } state_;
-
-    uint32_t protected_sequence_number_ GUARDED_BY(crit_);
-    uint32_t protected_frame_timestamp_ GUARDED_BY(crit_);
-  } observer;
-
-  CreateCalls(Call::Config(observer.SendTransport()),
-              Call::Config(observer.ReceiveTransport()));
-
-  observer.SetReceivers(receiver_call_->Receiver(), sender_call_->Receiver());
-
-  CreateTestConfigs();
-  // TODO(pbos): Run this test with combined NACK/FEC enabled as well.
-  // int rtp_history_ms = 1000;
-  // receive_config_.rtp.nack.rtp_history_ms = rtp_history_ms;
-  // send_config_.rtp.nack.rtp_history_ms = rtp_history_ms;
-  send_config_.rtp.fec.red_payload_type = kRedPayloadType;
-  send_config_.rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
-
-  receive_config_.rtp.fec.red_payload_type = kRedPayloadType;
-  receive_config_.rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
-  receive_config_.renderer = &observer;
-
-  CreateStreams();
-  CreateFrameGenerator();
-  StartSending();
-
-  // Wait() waits for an event triggered when NACKs have been received, NACKed
-  // packets retransmitted and frames rendered again.
-  EXPECT_EQ(kEventSignaled, observer.Wait());
-
-  StopSending();
-
-  observer.StopSending();
-
-  DestroyStreams();
-}
-
-// This test drops second RTP packet with a marker bit set, makes sure it's
-// retransmitted and renders. Retransmission SSRCs are also checked.
-void CallTest::DecodesRetransmittedFrame(bool retransmit_over_rtx) {
-  static const int kDroppedFrameNumber = 2;
-  class RetransmissionObserver : public test::RtpRtcpObserver,
-                                 public I420FrameCallback {
-   public:
-    RetransmissionObserver(bool expect_rtx)
-        : RtpRtcpObserver(kDefaultTimeoutMs),
-          retransmission_ssrc_(expect_rtx ? kSendRtxSsrc : kSendSsrc),
-          retransmission_payload_type_(expect_rtx ? kSendRtxPayloadType
-                                                  : kSendPayloadType),
-          marker_bits_observed_(0),
-          retransmitted_timestamp_(0),
-          frame_retransmitted_(false) {}
-
-   private:
-    virtual Action OnSendRtp(const uint8_t* packet, size_t length) OVERRIDE {
-      RTPHeader header;
-      EXPECT_TRUE(parser_->Parse(packet, static_cast<int>(length), &header));
-
-      if (header.timestamp == retransmitted_timestamp_) {
-        EXPECT_EQ(retransmission_ssrc_, header.ssrc);
-        EXPECT_EQ(retransmission_payload_type_, header.payloadType);
-        frame_retransmitted_ = true;
-        return SEND_PACKET;
-      }
-
-      EXPECT_EQ(kSendSsrc, header.ssrc);
-      EXPECT_EQ(kSendPayloadType, header.payloadType);
-
-      // Found the second frame's final packet, drop this and expect a
-      // retransmission.
-      if (header.markerBit && ++marker_bits_observed_ == kDroppedFrameNumber) {
-        retransmitted_timestamp_ = header.timestamp;
-        return DROP_PACKET;
-      }
-
-      return SEND_PACKET;
-    }
-
-    virtual void FrameCallback(I420VideoFrame* frame) OVERRIDE {
-      CriticalSectionScoped lock(crit_.get());
-      if (frame->timestamp() == retransmitted_timestamp_) {
-        EXPECT_TRUE(frame_retransmitted_);
-        observation_complete_->Set();
-      }
-    }
-
-    const uint32_t retransmission_ssrc_;
-    const int retransmission_payload_type_;
-    int marker_bits_observed_;
-    uint32_t retransmitted_timestamp_;
-    bool frame_retransmitted_;
-  } observer(retransmit_over_rtx);
-
-  CreateCalls(Call::Config(observer.SendTransport()),
-              Call::Config(observer.ReceiveTransport()));
-
-  observer.SetReceivers(receiver_call_->Receiver(), sender_call_->Receiver());
-
-  CreateTestConfigs();
-  send_config_.rtp.nack.rtp_history_ms =
-      receive_config_.rtp.nack.rtp_history_ms = 1000;
-  if (retransmit_over_rtx) {
-    send_config_.rtp.rtx.ssrcs.push_back(kSendRtxSsrc);
-    send_config_.rtp.rtx.payload_type = kSendRtxPayloadType;
-    int payload_type = send_config_.encoder_settings.payload_type;
-    receive_config_.rtp.rtx[payload_type].ssrc = kSendRtxSsrc;
-    receive_config_.rtp.rtx[payload_type].payload_type = kSendRtxPayloadType;
-  }
-  receive_config_.pre_render_callback = &observer;
-
-  CreateStreams();
-  CreateFrameGenerator();
-  StartSending();
-
-  EXPECT_EQ(kEventSignaled, observer.Wait())
-      << "Timed out while waiting for retransmission to render.";
-
-  StopSending();
-  observer.StopSending();
-  DestroyStreams();
-}
-
-TEST_F(CallTest, DecodesRetransmittedFrame) {
-  DecodesRetransmittedFrame(false);
-}
-
-TEST_F(CallTest, DecodesRetransmittedFrameOverRtx) {
-  DecodesRetransmittedFrame(true);
-}
-
-TEST_F(CallTest, UsesFrameCallbacks) {
-  static const int kWidth = 320;
-  static const int kHeight = 240;
-
-  class Renderer : public VideoRenderer {
-   public:
-    Renderer() : event_(EventWrapper::Create()) {}
-
-    virtual void RenderFrame(const I420VideoFrame& video_frame,
-                             int /*time_to_render_ms*/) OVERRIDE {
-      EXPECT_EQ(0, *video_frame.buffer(kYPlane))
-          << "Rendered frame should have zero luma which is applied by the "
-             "pre-render callback.";
-      event_->Set();
-    }
-
-    EventTypeWrapper Wait() { return event_->Wait(kDefaultTimeoutMs); }
-    scoped_ptr<EventWrapper> event_;
-  } renderer;
-
-  class TestFrameCallback : public I420FrameCallback {
-   public:
-    TestFrameCallback(int expected_luma_byte, int next_luma_byte)
-        : event_(EventWrapper::Create()),
-          expected_luma_byte_(expected_luma_byte),
-          next_luma_byte_(next_luma_byte) {}
-
-    EventTypeWrapper Wait() { return event_->Wait(kDefaultTimeoutMs); }
-
-   private:
-    virtual void FrameCallback(I420VideoFrame* frame) {
-      EXPECT_EQ(kWidth, frame->width())
-          << "Width not as expected, callback done before resize?";
-      EXPECT_EQ(kHeight, frame->height())
-          << "Height not as expected, callback done before resize?";
-
-      // Previous luma specified, observed luma should be fairly close.
-      if (expected_luma_byte_ != -1) {
-        EXPECT_NEAR(expected_luma_byte_, *frame->buffer(kYPlane), 10);
-      }
-
-      memset(frame->buffer(kYPlane),
-             next_luma_byte_,
-             frame->allocated_size(kYPlane));
-
-      event_->Set();
-    }
-
-    scoped_ptr<EventWrapper> event_;
-    int expected_luma_byte_;
-    int next_luma_byte_;
-  };
-
-  TestFrameCallback pre_encode_callback(-1, 255);  // Changes luma to 255.
-  TestFrameCallback pre_render_callback(255, 0);  // Changes luma from 255 to 0.
-
-  test::DirectTransport sender_transport, receiver_transport;
-
-  CreateCalls(Call::Config(&sender_transport),
-              Call::Config(&receiver_transport));
-
-  sender_transport.SetReceiver(receiver_call_->Receiver());
-  receiver_transport.SetReceiver(sender_call_->Receiver());
-
-  CreateTestConfigs();
-  scoped_ptr<VP8Encoder> encoder(VP8Encoder::Create());
-  send_config_.encoder_settings.encoder = encoder.get();
-  send_config_.encoder_settings.payload_name = "VP8";
-  ASSERT_EQ(1u, video_streams_.size()) << "Test setup error.";
-  video_streams_[0].width = kWidth;
-  video_streams_[0].height = kHeight;
-  send_config_.pre_encode_callback = &pre_encode_callback;
-  receive_config_.codecs.clear();
-  VideoCodec codec =
-      test::CreateDecoderVideoCodec(send_config_.encoder_settings);
-  receive_config_.external_decoders.clear();
-  receive_config_.codecs.push_back(codec);
-  receive_config_.pre_render_callback = &pre_render_callback;
-  receive_config_.renderer = &renderer;
-
-  CreateStreams();
-  StartSending();
-
-  // Create frames that are smaller than the send width/height, this is done to
-  // check that the callbacks are done after processing video.
-  scoped_ptr<test::FrameGenerator> frame_generator(
-      test::FrameGenerator::Create(kWidth / 2, kHeight / 2));
-  send_stream_->Input()->SwapFrame(frame_generator->NextFrame());
-
-  EXPECT_EQ(kEventSignaled, pre_encode_callback.Wait())
-      << "Timed out while waiting for pre-encode callback.";
-  EXPECT_EQ(kEventSignaled, pre_render_callback.Wait())
-      << "Timed out while waiting for pre-render callback.";
-  EXPECT_EQ(kEventSignaled, renderer.Wait())
-      << "Timed out while waiting for the frame to render.";
-
-  StopSending();
-
-  sender_transport.StopSending();
-  receiver_transport.StopSending();
-
-  DestroyStreams();
-}
-
-class PliObserver : public test::RtpRtcpObserver, public VideoRenderer {
-  static const int kInverseDropProbability = 16;
-
- public:
-  explicit PliObserver(bool nack_enabled)
-      : test::RtpRtcpObserver(kLongTimeoutMs),
-        nack_enabled_(nack_enabled),
-        highest_dropped_timestamp_(0),
-        frames_to_drop_(0),
-        received_pli_(false) {}
-
-  virtual Action OnSendRtp(const uint8_t* packet, size_t length) OVERRIDE {
-    RTPHeader header;
-    EXPECT_TRUE(parser_->Parse(packet, static_cast<int>(length), &header));
-
-    // Drop all retransmitted packets to force a PLI.
-    if (header.timestamp <= highest_dropped_timestamp_)
-      return DROP_PACKET;
-
-    if (frames_to_drop_ > 0) {
-      highest_dropped_timestamp_ = header.timestamp;
-      --frames_to_drop_;
-      return DROP_PACKET;
-    }
-
-    return SEND_PACKET;
-  }
-
-  virtual Action OnReceiveRtcp(const uint8_t* packet, size_t length) OVERRIDE {
-    RTCPUtility::RTCPParserV2 parser(packet, length, true);
-    EXPECT_TRUE(parser.IsValid());
-
-    for (RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
-         packet_type != RTCPUtility::kRtcpNotValidCode;
-         packet_type = parser.Iterate()) {
-      if (!nack_enabled_)
-        EXPECT_NE(packet_type, RTCPUtility::kRtcpRtpfbNackCode);
-
-      if (packet_type == RTCPUtility::kRtcpPsfbPliCode) {
-        received_pli_ = true;
-        break;
-      }
-    }
-    return SEND_PACKET;
-  }
-
-  virtual void RenderFrame(const I420VideoFrame& video_frame,
-                           int time_to_render_ms) OVERRIDE {
-    CriticalSectionScoped lock(crit_.get());
-    if (received_pli_ && video_frame.timestamp() > highest_dropped_timestamp_) {
-      observation_complete_->Set();
-    }
-    if (!received_pli_)
-      frames_to_drop_ = kPacketsToDrop;
-  }
-
- private:
-  static const int kPacketsToDrop = 1;
-
-  bool nack_enabled_;
-  uint32_t highest_dropped_timestamp_;
-  int frames_to_drop_;
-  bool received_pli_;
-};
-
-void CallTest::ReceivesPliAndRecovers(int rtp_history_ms) {
-  PliObserver observer(rtp_history_ms > 0);
-
-  CreateCalls(Call::Config(observer.SendTransport()),
-              Call::Config(observer.ReceiveTransport()));
-
-  observer.SetReceivers(receiver_call_->Receiver(), sender_call_->Receiver());
-
-  CreateTestConfigs();
-  send_config_.rtp.nack.rtp_history_ms = rtp_history_ms;
-  receive_config_.rtp.nack.rtp_history_ms = rtp_history_ms;
-  receive_config_.renderer = &observer;
-
-  CreateStreams();
-  CreateFrameGenerator();
-  StartSending();
-
-  // Wait() waits for an event triggered when Pli has been received and frames
-  // have been rendered afterwards.
-  EXPECT_EQ(kEventSignaled, observer.Wait());
-
-  StopSending();
-
-  observer.StopSending();
-
-  DestroyStreams();
-}
-
-TEST_F(CallTest, ReceivesPliAndRecoversWithNack) {
-  ReceivesPliAndRecovers(1000);
-}
-
-// TODO(pbos): Enable this when 2250 is resolved.
-TEST_F(CallTest, DISABLED_ReceivesPliAndRecoversWithoutNack) {
-  ReceivesPliAndRecovers(0);
-}
-
-TEST_F(CallTest, UnknownRtpPacketGivesUnknownSsrcReturnCode) {
-  class PacketInputObserver : public PacketReceiver {
-   public:
-    explicit PacketInputObserver(PacketReceiver* receiver)
-        : receiver_(receiver), delivered_packet_(EventWrapper::Create()) {}
-
-    EventTypeWrapper Wait() {
-      return delivered_packet_->Wait(kDefaultTimeoutMs);
-    }
-
-   private:
-    virtual DeliveryStatus DeliverPacket(const uint8_t* packet,
-                                         size_t length) OVERRIDE {
-      if (RtpHeaderParser::IsRtcp(packet, static_cast<int>(length))) {
-        return receiver_->DeliverPacket(packet, length);
-      } else {
-        DeliveryStatus delivery_status =
-            receiver_->DeliverPacket(packet, length);
-        EXPECT_EQ(DELIVERY_UNKNOWN_SSRC, delivery_status);
-        delivered_packet_->Set();
-        return delivery_status;
-      }
-    }
-
-    PacketReceiver* receiver_;
-    scoped_ptr<EventWrapper> delivered_packet_;
-  };
-
-  test::DirectTransport send_transport, receive_transport;
-
-  CreateCalls(Call::Config(&send_transport), Call::Config(&receive_transport));
-  PacketInputObserver input_observer(receiver_call_->Receiver());
-
-  send_transport.SetReceiver(&input_observer);
-  receive_transport.SetReceiver(sender_call_->Receiver());
-
-  CreateTestConfigs();
-
-  CreateStreams();
-  CreateFrameGenerator();
-  StartSending();
-
-  receiver_call_->DestroyVideoReceiveStream(receive_stream_);
-  receive_stream_ = NULL;
-
-  // Wait() waits for a received packet.
-  EXPECT_EQ(kEventSignaled, input_observer.Wait());
-
-  StopSending();
-
-  DestroyStreams();
-
-  send_transport.StopSending();
-  receive_transport.StopSending();
-}
-
-void CallTest::RespectsRtcpMode(newapi::RtcpMode rtcp_mode) {
-  static const int kRtpHistoryMs = 1000;
-  static const int kNumCompoundRtcpPacketsToObserve = 10;
-  class RtcpModeObserver : public test::RtpRtcpObserver {
-   public:
-    explicit RtcpModeObserver(newapi::RtcpMode rtcp_mode)
-        : test::RtpRtcpObserver(kDefaultTimeoutMs),
-          rtcp_mode_(rtcp_mode),
-          sent_rtp_(0),
-          sent_rtcp_(0) {}
-
-   private:
-    virtual Action OnSendRtp(const uint8_t* packet, size_t length) OVERRIDE {
-      if (++sent_rtp_ % 3 == 0)
-        return DROP_PACKET;
-
-      return SEND_PACKET;
-    }
-
-    virtual Action OnReceiveRtcp(const uint8_t* packet,
-                                 size_t length) OVERRIDE {
-      ++sent_rtcp_;
-      RTCPUtility::RTCPParserV2 parser(packet, length, true);
-      EXPECT_TRUE(parser.IsValid());
-
-      RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
-      bool has_report_block = false;
-      while (packet_type != RTCPUtility::kRtcpNotValidCode) {
-        EXPECT_NE(RTCPUtility::kRtcpSrCode, packet_type);
-        if (packet_type == RTCPUtility::kRtcpRrCode) {
-          has_report_block = true;
-          break;
-        }
-        packet_type = parser.Iterate();
-      }
-
-      switch (rtcp_mode_) {
-        case newapi::kRtcpCompound:
-          if (!has_report_block) {
-            ADD_FAILURE() << "Received RTCP packet without receiver report for "
-                             "kRtcpCompound.";
-            observation_complete_->Set();
-          }
-
-          if (sent_rtcp_ >= kNumCompoundRtcpPacketsToObserve)
-            observation_complete_->Set();
-
-          break;
-        case newapi::kRtcpReducedSize:
-          if (!has_report_block)
-            observation_complete_->Set();
-          break;
-      }
-
-      return SEND_PACKET;
-    }
-
-    newapi::RtcpMode rtcp_mode_;
-    int sent_rtp_;
-    int sent_rtcp_;
-  } observer(rtcp_mode);
-
-  CreateCalls(Call::Config(observer.SendTransport()),
-              Call::Config(observer.ReceiveTransport()));
-
-  observer.SetReceivers(receiver_call_->Receiver(), sender_call_->Receiver());
-
-  CreateTestConfigs();
-  send_config_.rtp.nack.rtp_history_ms = kRtpHistoryMs;
-  receive_config_.rtp.nack.rtp_history_ms = kRtpHistoryMs;
-  receive_config_.rtp.rtcp_mode = rtcp_mode;
-
-  CreateStreams();
-  CreateFrameGenerator();
-  StartSending();
-
-  EXPECT_EQ(kEventSignaled, observer.Wait())
-      << (rtcp_mode == newapi::kRtcpCompound
-              ? "Timed out before observing enough compound packets."
-              : "Timed out before receiving a non-compound RTCP packet.");
-
-  StopSending();
-  observer.StopSending();
-  DestroyStreams();
-}
-
-TEST_F(CallTest, UsesRtcpCompoundMode) {
-  RespectsRtcpMode(newapi::kRtcpCompound);
-}
-
-TEST_F(CallTest, UsesRtcpReducedSizeMode) {
-  RespectsRtcpMode(newapi::kRtcpReducedSize);
-}
-
-// Test sets up a Call multiple senders with different resolutions and SSRCs.
-// Another is set up to receive all three of these with different renderers.
-// Each renderer verifies that it receives the expected resolution, and as soon
-// as every renderer has received a frame, the test finishes.
-TEST_F(CallTest, SendsAndReceivesMultipleStreams) {
-  static const size_t kNumStreams = 3;
-
-  class VideoOutputObserver : public VideoRenderer {
-   public:
-    VideoOutputObserver(test::FrameGeneratorCapturer** capturer,
-                        int width,
-                        int height)
-        : capturer_(capturer),
-          width_(width),
-          height_(height),
-          done_(EventWrapper::Create()) {}
-
-    virtual void RenderFrame(const I420VideoFrame& video_frame,
-                             int time_to_render_ms) OVERRIDE {
-      EXPECT_EQ(width_, video_frame.width());
-      EXPECT_EQ(height_, video_frame.height());
-      (*capturer_)->Stop();
-      done_->Set();
-    }
-
-    EventTypeWrapper Wait() { return done_->Wait(kDefaultTimeoutMs); }
-
-   private:
-    test::FrameGeneratorCapturer** capturer_;
-    int width_;
-    int height_;
-    scoped_ptr<EventWrapper> done_;
-  };
-
-  struct {
-    uint32_t ssrc;
-    int width;
-    int height;
-  } codec_settings[kNumStreams] = {{1, 640, 480}, {2, 320, 240}, {3, 240, 160}};
-
-  test::DirectTransport sender_transport, receiver_transport;
-  scoped_ptr<Call> sender_call(Call::Create(Call::Config(&sender_transport)));
-  scoped_ptr<Call> receiver_call(
-      Call::Create(Call::Config(&receiver_transport)));
-  sender_transport.SetReceiver(receiver_call->Receiver());
-  receiver_transport.SetReceiver(sender_call->Receiver());
-
-  VideoSendStream* send_streams[kNumStreams];
-  VideoReceiveStream* receive_streams[kNumStreams];
-
-  VideoOutputObserver* observers[kNumStreams];
-  test::FrameGeneratorCapturer* frame_generators[kNumStreams];
-
-  scoped_ptr<VP8Encoder> encoders[kNumStreams];
-  for (size_t i = 0; i < kNumStreams; ++i)
-    encoders[i].reset(VP8Encoder::Create());
-
-  for (size_t i = 0; i < kNumStreams; ++i) {
-    uint32_t ssrc = codec_settings[i].ssrc;
-    int width = codec_settings[i].width;
-    int height = codec_settings[i].height;
-    observers[i] = new VideoOutputObserver(&frame_generators[i], width, height);
-
-    VideoSendStream::Config send_config = sender_call->GetDefaultSendConfig();
-    send_config.rtp.ssrcs.push_back(ssrc);
-    send_config.encoder_settings.encoder = encoders[i].get();
-    send_config.encoder_settings.payload_name = "VP8";
-    send_config.encoder_settings.payload_type = 124;
-    std::vector<VideoStream> video_streams = test::CreateVideoStreams(1);
-    VideoStream* stream = &video_streams[0];
-    stream->width = width;
-    stream->height = height;
-    stream->max_framerate = 5;
-    stream->min_bitrate_bps = stream->target_bitrate_bps =
-        stream->max_bitrate_bps = 100000;
-    send_streams[i] =
-        sender_call->CreateVideoSendStream(send_config, video_streams, NULL);
-    send_streams[i]->Start();
-
-    VideoReceiveStream::Config receive_config =
-        receiver_call->GetDefaultReceiveConfig();
-    receive_config.renderer = observers[i];
-    receive_config.rtp.remote_ssrc = ssrc;
-    receive_config.rtp.local_ssrc = kReceiverLocalSsrc;
-    VideoCodec codec =
-        test::CreateDecoderVideoCodec(send_config.encoder_settings);
-    receive_config.codecs.push_back(codec);
-    receive_streams[i] =
-        receiver_call->CreateVideoReceiveStream(receive_config);
-    receive_streams[i]->Start();
-
-    frame_generators[i] = test::FrameGeneratorCapturer::Create(
-        send_streams[i]->Input(), width, height, 30, Clock::GetRealTimeClock());
-    frame_generators[i]->Start();
-  }
-
-  for (size_t i = 0; i < kNumStreams; ++i) {
-    EXPECT_EQ(kEventSignaled, observers[i]->Wait())
-        << "Timed out while waiting for observer " << i << " to render.";
-  }
-
-  for (size_t i = 0; i < kNumStreams; ++i) {
-    frame_generators[i]->Stop();
-    sender_call->DestroyVideoSendStream(send_streams[i]);
-    receiver_call->DestroyVideoReceiveStream(receive_streams[i]);
-    delete frame_generators[i];
-    delete observers[i];
-  }
-
-  sender_transport.StopSending();
-  receiver_transport.StopSending();
-};
-
-TEST_F(CallTest, ObserversEncodedFrames) {
-  class EncodedFrameTestObserver : public EncodedFrameObserver {
-   public:
-    EncodedFrameTestObserver()
-        : length_(0),
-          frame_type_(kFrameEmpty),
-          called_(EventWrapper::Create()) {}
-    virtual ~EncodedFrameTestObserver() {}
-
-    virtual void EncodedFrameCallback(const EncodedFrame& encoded_frame) {
-      frame_type_ = encoded_frame.frame_type_;
-      length_ = encoded_frame.length_;
-      buffer_.reset(new uint8_t[length_]);
-      memcpy(buffer_.get(), encoded_frame.data_, length_);
-      called_->Set();
-    }
-
-    EventTypeWrapper Wait() { return called_->Wait(kDefaultTimeoutMs); }
-
-    void ExpectEqualFrames(const EncodedFrameTestObserver& observer) {
-      ASSERT_EQ(length_, observer.length_)
-          << "Observed frames are of different lengths.";
-      EXPECT_EQ(frame_type_, observer.frame_type_)
-          << "Observed frames have different frame types.";
-      EXPECT_EQ(0, memcmp(buffer_.get(), observer.buffer_.get(), length_))
-          << "Observed encoded frames have different content.";
-    }
-
-   private:
-    scoped_ptr<uint8_t[]> buffer_;
-    size_t length_;
-    FrameType frame_type_;
-    scoped_ptr<EventWrapper> called_;
-  };
-
-  EncodedFrameTestObserver post_encode_observer;
-  EncodedFrameTestObserver pre_decode_observer;
-
-  test::DirectTransport sender_transport, receiver_transport;
-
-  CreateCalls(Call::Config(&sender_transport),
-              Call::Config(&receiver_transport));
-
-  sender_transport.SetReceiver(receiver_call_->Receiver());
-  receiver_transport.SetReceiver(sender_call_->Receiver());
-
-  CreateTestConfigs();
-  send_config_.post_encode_callback = &post_encode_observer;
-  receive_config_.pre_decode_callback = &pre_decode_observer;
-
-  CreateStreams();
-  StartSending();
-
-  scoped_ptr<test::FrameGenerator> frame_generator(test::FrameGenerator::Create(
-      video_streams_[0].width, video_streams_[0].height));
-  send_stream_->Input()->SwapFrame(frame_generator->NextFrame());
-
-  EXPECT_EQ(kEventSignaled, post_encode_observer.Wait())
-      << "Timed out while waiting for send-side encoded-frame callback.";
-
-  EXPECT_EQ(kEventSignaled, pre_decode_observer.Wait())
-      << "Timed out while waiting for pre-decode encoded-frame callback.";
-
-  post_encode_observer.ExpectEqualFrames(pre_decode_observer);
-
-  StopSending();
-
-  sender_transport.StopSending();
-  receiver_transport.StopSending();
-
-  DestroyStreams();
-}
-
-TEST_F(CallTest, ReceiveStreamSendsRemb) {
-  class RembObserver : public test::RtpRtcpObserver {
-   public:
-    RembObserver() : test::RtpRtcpObserver(kDefaultTimeoutMs) {}
-
-    virtual Action OnReceiveRtcp(const uint8_t* packet,
-                                 size_t length) OVERRIDE {
-      RTCPUtility::RTCPParserV2 parser(packet, length, true);
-      EXPECT_TRUE(parser.IsValid());
-
-      bool received_psfb = false;
-      bool received_remb = false;
-      RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
-      while (packet_type != RTCPUtility::kRtcpNotValidCode) {
-        if (packet_type == RTCPUtility::kRtcpPsfbRembCode) {
-          const RTCPUtility::RTCPPacket& packet = parser.Packet();
-          EXPECT_EQ(packet.PSFBAPP.SenderSSRC, kReceiverLocalSsrc);
-          received_psfb = true;
-        } else if (packet_type == RTCPUtility::kRtcpPsfbRembItemCode) {
-          const RTCPUtility::RTCPPacket& packet = parser.Packet();
-          EXPECT_GT(packet.REMBItem.BitRate, 0u);
-          EXPECT_EQ(packet.REMBItem.NumberOfSSRCs, 1u);
-          EXPECT_EQ(packet.REMBItem.SSRCs[0], kSendSsrc);
-          received_remb = true;
-        }
-        packet_type = parser.Iterate();
-      }
-      if (received_psfb && received_remb)
-        observation_complete_->Set();
-      return SEND_PACKET;
-    }
-  } observer;
-
-  CreateCalls(Call::Config(observer.SendTransport()),
-              Call::Config(observer.ReceiveTransport()));
-  observer.SetReceivers(receiver_call_->Receiver(), sender_call_->Receiver());
-  CreateTestConfigs();
-  CreateStreams();
-  CreateFrameGenerator();
-  StartSending();
-
-  EXPECT_EQ(kEventSignaled, observer.Wait())
-      << "Timed out while waiting for a receiver RTCP REMB packet to be sent.";
-
-  StopSending();
-  observer.StopSending();
-  DestroyStreams();
-}
-
-void CallTest::TestXrReceiverReferenceTimeReport(bool enable_rrtr) {
-  static const int kNumRtcpReportPacketsToObserve = 5;
-  class RtcpXrObserver : public test::RtpRtcpObserver {
-   public:
-    explicit RtcpXrObserver(bool enable_rrtr)
-        : test::RtpRtcpObserver(kDefaultTimeoutMs),
-          enable_rrtr_(enable_rrtr),
-          sent_rtcp_sr_(0),
-          sent_rtcp_rr_(0),
-          sent_rtcp_rrtr_(0),
-          sent_rtcp_dlrr_(0) {}
-
-   private:
-    // Receive stream should send RR packets (and RRTR packets if enabled).
-    virtual Action OnReceiveRtcp(const uint8_t* packet,
-                                 size_t length) OVERRIDE {
-      RTCPUtility::RTCPParserV2 parser(packet, length, true);
-      EXPECT_TRUE(parser.IsValid());
-
-      RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
-      while (packet_type != RTCPUtility::kRtcpNotValidCode) {
-        if (packet_type == RTCPUtility::kRtcpRrCode) {
-          ++sent_rtcp_rr_;
-        } else if (packet_type ==
-                   RTCPUtility::kRtcpXrReceiverReferenceTimeCode) {
-          ++sent_rtcp_rrtr_;
-        }
-        EXPECT_NE(packet_type, RTCPUtility::kRtcpSrCode);
-        EXPECT_NE(packet_type, RTCPUtility::kRtcpXrDlrrReportBlockItemCode);
-        packet_type = parser.Iterate();
-      }
-      return SEND_PACKET;
-    }
-    // Send stream should send SR packets (and DLRR packets if enabled).
-    virtual Action OnSendRtcp(const uint8_t* packet, size_t length) {
-      RTCPUtility::RTCPParserV2 parser(packet, length, true);
-      EXPECT_TRUE(parser.IsValid());
-
-      RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
-      while (packet_type != RTCPUtility::kRtcpNotValidCode) {
-        if (packet_type == RTCPUtility::kRtcpSrCode) {
-          ++sent_rtcp_sr_;
-        } else if (packet_type == RTCPUtility::kRtcpXrDlrrReportBlockItemCode) {
-          ++sent_rtcp_dlrr_;
-        }
-        EXPECT_NE(packet_type, RTCPUtility::kRtcpXrReceiverReferenceTimeCode);
-        packet_type = parser.Iterate();
-      }
-      if (sent_rtcp_sr_ > kNumRtcpReportPacketsToObserve &&
-          sent_rtcp_rr_ > kNumRtcpReportPacketsToObserve) {
-        if (enable_rrtr_) {
-          EXPECT_GT(sent_rtcp_rrtr_, 0);
-          EXPECT_GT(sent_rtcp_dlrr_, 0);
-        } else {
-          EXPECT_EQ(0, sent_rtcp_rrtr_);
-          EXPECT_EQ(0, sent_rtcp_dlrr_);
-        }
-        observation_complete_->Set();
-      }
-      return SEND_PACKET;
-    }
-    bool enable_rrtr_;
-    int sent_rtcp_sr_;
-    int sent_rtcp_rr_;
-    int sent_rtcp_rrtr_;
-    int sent_rtcp_dlrr_;
-  } observer(enable_rrtr);
-
-  CreateCalls(Call::Config(observer.SendTransport()),
-              Call::Config(observer.ReceiveTransport()));
-  observer.SetReceivers(receiver_call_->Receiver(), sender_call_->Receiver());
-
-  CreateTestConfigs();
-  receive_config_.rtp.rtcp_mode = newapi::kRtcpReducedSize;
-  receive_config_.rtp.rtcp_xr.receiver_reference_time_report = enable_rrtr;
-
-  CreateStreams();
-  CreateFrameGenerator();
-  StartSending();
-
-  EXPECT_EQ(kEventSignaled, observer.Wait())
-      << "Timed out while waiting for RTCP SR/RR packets to be sent.";
-
-  StopSending();
-  observer.StopSending();
-  DestroyStreams();
-}
-
-class StatsObserver : public test::RtpRtcpObserver, public I420FrameCallback {
- public:
-  StatsObserver()
-      : test::RtpRtcpObserver(kLongTimeoutMs),
-        receive_stream_(NULL),
-        send_stream_(NULL),
-        expected_receive_ssrc_(),
-        expected_send_ssrcs_(),
-        check_stats_event_(EventWrapper::Create()) {}
-
-  void SetExpectedReceiveSsrc(uint32_t ssrc) { expected_receive_ssrc_ = ssrc; }
-
-  void SetExpectedSendSsrcs(const std::vector<uint32_t>& ssrcs) {
-    for (std::vector<uint32_t>::const_iterator it = ssrcs.begin();
-         it != ssrcs.end();
-         ++it) {
-      expected_send_ssrcs_.insert(*it);
-    }
-  }
-
-  void SetExpectedCName(std::string cname) { expected_cname_ = cname; }
-
-  void SetReceiveStream(VideoReceiveStream* stream) {
-    receive_stream_ = stream;
-  }
-
-  void SetSendStream(VideoSendStream* stream) { send_stream_ = stream; }
-
-  void WaitForFilledStats() {
-    Clock* clock = Clock::GetRealTimeClock();
-    int64_t now = clock->TimeInMilliseconds();
-    int64_t stop_time = now + kLongTimeoutMs;
-    bool receive_ok = false;
-    bool send_ok = false;
-
-    while (now < stop_time) {
-      if (!receive_ok)
-        receive_ok = CheckReceiveStats();
-      if (!send_ok)
-        send_ok = CheckSendStats();
-
-      if (receive_ok && send_ok)
-        return;
-
-      int64_t time_until_timout_ = stop_time - now;
-      if (time_until_timout_ > 0)
-        check_stats_event_->Wait(time_until_timout_);
-      now = clock->TimeInMilliseconds();
-    }
-
-    ADD_FAILURE() << "Timed out waiting for filled stats.";
-    for (std::map<std::string, bool>::const_iterator it =
-             receive_stats_filled_.begin();
-         it != receive_stats_filled_.end();
-         ++it) {
-      if (!it->second) {
-        ADD_FAILURE() << "Missing receive stats: " << it->first;
-      }
-    }
-
-    for (std::map<std::string, bool>::const_iterator it =
-             send_stats_filled_.begin();
-         it != send_stats_filled_.end();
-         ++it) {
-      if (!it->second) {
-        ADD_FAILURE() << "Missing send stats: " << it->first;
-      }
-    }
-  }
-
- private:
-  virtual Action OnSendRtp(const uint8_t* packet, size_t length) OVERRIDE {
-    check_stats_event_->Set();
-    return SEND_PACKET;
-  }
-
-  virtual Action OnSendRtcp(const uint8_t* packet, size_t length) OVERRIDE {
-    check_stats_event_->Set();
-    return SEND_PACKET;
-  }
-
-  virtual Action OnReceiveRtp(const uint8_t* packet, size_t length) OVERRIDE {
-    check_stats_event_->Set();
-    return SEND_PACKET;
-  }
-
-  virtual Action OnReceiveRtcp(const uint8_t* packet, size_t length) OVERRIDE {
-    check_stats_event_->Set();
-    return SEND_PACKET;
-  }
-
-  virtual void FrameCallback(I420VideoFrame* video_frame) OVERRIDE {
-    // Ensure that we have at least 5ms send side delay.
-    int64_t render_time = video_frame->render_time_ms();
-    if (render_time > 0)
-      video_frame->set_render_time_ms(render_time - 5);
-  }
-
-  bool CheckReceiveStats() {
-    assert(receive_stream_ != NULL);
-    VideoReceiveStream::Stats stats = receive_stream_->GetStats();
-    EXPECT_EQ(expected_receive_ssrc_, stats.ssrc);
-
-    // Make sure all fields have been populated.
-
-    receive_stats_filled_["IncomingRate"] |=
-        stats.network_frame_rate != 0 || stats.bitrate_bps != 0;
-
-    receive_stats_filled_["FrameCallback"] |= stats.decode_frame_rate != 0;
-
-    receive_stats_filled_["FrameRendered"] |= stats.render_frame_rate != 0;
-
-    receive_stats_filled_["StatisticsUpdated"] |=
-        stats.rtcp_stats.cumulative_lost != 0 ||
-        stats.rtcp_stats.extended_max_sequence_number != 0 ||
-        stats.rtcp_stats.fraction_lost != 0 || stats.rtcp_stats.jitter != 0;
-
-    receive_stats_filled_["DataCountersUpdated"] |=
-        stats.rtp_stats.bytes != 0 || stats.rtp_stats.fec_packets != 0 ||
-        stats.rtp_stats.header_bytes != 0 || stats.rtp_stats.packets != 0 ||
-        stats.rtp_stats.padding_bytes != 0 ||
-        stats.rtp_stats.retransmitted_packets != 0;
-
-    receive_stats_filled_["CodecStats"] |=
-        stats.avg_delay_ms != 0 || stats.discarded_packets != 0 ||
-        stats.key_frames != 0 || stats.delta_frames != 0;
-
-    receive_stats_filled_["CName"] |= stats.c_name == expected_cname_;
-
-    return AllStatsFilled(receive_stats_filled_);
-  }
-
-  bool CheckSendStats() {
-    assert(send_stream_ != NULL);
-    VideoSendStream::Stats stats = send_stream_->GetStats();
-
-    send_stats_filled_["NumStreams"] |=
-        stats.substreams.size() == expected_send_ssrcs_.size();
-
-    send_stats_filled_["Delay"] |=
-        stats.avg_delay_ms != 0 || stats.max_delay_ms != 0;
-
-    receive_stats_filled_["CName"] |= stats.c_name == expected_cname_;
-
-    for (std::map<uint32_t, StreamStats>::const_iterator it =
-             stats.substreams.begin();
-         it != stats.substreams.end();
-         ++it) {
-      EXPECT_TRUE(expected_send_ssrcs_.find(it->first) !=
-                  expected_send_ssrcs_.end());
-
-      send_stats_filled_[CompoundKey("IncomingRate", it->first)] |=
-          stats.input_frame_rate != 0;
-
-      const StreamStats& stream_stats = it->second;
-
-      send_stats_filled_[CompoundKey("StatisticsUpdated", it->first)] |=
-          stream_stats.rtcp_stats.cumulative_lost != 0 ||
-          stream_stats.rtcp_stats.extended_max_sequence_number != 0 ||
-          stream_stats.rtcp_stats.fraction_lost != 0;
-
-      send_stats_filled_[CompoundKey("DataCountersUpdated", it->first)] |=
-          stream_stats.rtp_stats.fec_packets != 0 ||
-          stream_stats.rtp_stats.padding_bytes != 0 ||
-          stream_stats.rtp_stats.retransmitted_packets != 0 ||
-          stream_stats.rtp_stats.packets != 0;
-
-      send_stats_filled_[CompoundKey("BitrateStatisticsObserver", it->first)] |=
-          stream_stats.bitrate_bps != 0;
-
-      send_stats_filled_[CompoundKey("FrameCountObserver", it->first)] |=
-          stream_stats.delta_frames != 0 || stream_stats.key_frames != 0;
-
-      send_stats_filled_[CompoundKey("OutgoingRate", it->first)] |=
-          stats.encode_frame_rate != 0;
-    }
-
-    return AllStatsFilled(send_stats_filled_);
-  }
-
-  std::string CompoundKey(const char* name, uint32_t ssrc) {
-    std::ostringstream oss;
-    oss << name << "_" << ssrc;
-    return oss.str();
-  }
-
-  bool AllStatsFilled(const std::map<std::string, bool>& stats_map) {
-    for (std::map<std::string, bool>::const_iterator it = stats_map.begin();
-         it != stats_map.end();
-         ++it) {
-      if (!it->second)
-        return false;
-    }
-    return true;
-  }
-
-  VideoReceiveStream* receive_stream_;
-  std::map<std::string, bool> receive_stats_filled_;
-
-  VideoSendStream* send_stream_;
-  std::map<std::string, bool> send_stats_filled_;
-
-  uint32_t expected_receive_ssrc_;
-  std::set<uint32_t> expected_send_ssrcs_;
-  std::string expected_cname_;
-
-  scoped_ptr<EventWrapper> check_stats_event_;
-};
-
-TEST_F(CallTest, GetStats) {
-  StatsObserver observer;
-
-  CreateCalls(Call::Config(observer.SendTransport()),
-              Call::Config(observer.ReceiveTransport()));
-
-  observer.SetReceivers(receiver_call_->Receiver(), sender_call_->Receiver());
-
-  CreateTestConfigs();
-  send_config_.pre_encode_callback = &observer;  // Used to inject delay.
-  send_config_.rtp.c_name = "SomeCName";
-
-  observer.SetExpectedReceiveSsrc(receive_config_.rtp.local_ssrc);
-  observer.SetExpectedSendSsrcs(send_config_.rtp.ssrcs);
-  observer.SetExpectedCName(send_config_.rtp.c_name);
-
-  CreateStreams();
-  observer.SetReceiveStream(receive_stream_);
-  observer.SetSendStream(send_stream_);
-  CreateFrameGenerator();
-  StartSending();
-
-  observer.WaitForFilledStats();
-
-  StopSending();
-  observer.StopSending();
-  DestroyStreams();
-}
-
-TEST_F(CallTest, ReceiverReferenceTimeReportEnabled) {
-  TestXrReceiverReferenceTimeReport(true);
-}
-
-TEST_F(CallTest, ReceiverReferenceTimeReportDisabled) {
-  TestXrReceiverReferenceTimeReport(false);
-}
-
-TEST_F(CallTest, TestReceivedRtpPacketStats) {
-  static const size_t kNumRtpPacketsToSend = 5;
-  class ReceivedRtpStatsObserver : public test::RtpRtcpObserver {
-   public:
-    ReceivedRtpStatsObserver()
-        : test::RtpRtcpObserver(kDefaultTimeoutMs),
-          receive_stream_(NULL),
-          sent_rtp_(0) {}
-
-    void SetReceiveStream(VideoReceiveStream* stream) {
-      receive_stream_ = stream;
-    }
-
-   private:
-    virtual Action OnSendRtp(const uint8_t* packet, size_t length) OVERRIDE {
-      if (sent_rtp_ >= kNumRtpPacketsToSend) {
-        VideoReceiveStream::Stats stats = receive_stream_->GetStats();
-        if (kNumRtpPacketsToSend == stats.rtp_stats.packets) {
-          observation_complete_->Set();
-        }
-        return DROP_PACKET;
-      }
-      ++sent_rtp_;
-      return SEND_PACKET;
-    }
-
-    VideoReceiveStream* receive_stream_;
-    uint32_t sent_rtp_;
-  } observer;
-
-  CreateCalls(Call::Config(observer.SendTransport()),
-              Call::Config(observer.ReceiveTransport()));
-  observer.SetReceivers(receiver_call_->Receiver(), sender_call_->Receiver());
-
-  CreateTestConfigs();
-  CreateStreams();
-  observer.SetReceiveStream(receive_stream_);
-  CreateFrameGenerator();
-  StartSending();
-
-  EXPECT_EQ(kEventSignaled, observer.Wait())
-      << "Timed out while verifying number of received RTP packets.";
-
-  StopSending();
-  observer.StopSending();
-  DestroyStreams();
-}
-
-}  // namespace webrtc
diff --git a/webrtc/video/end_to_end_tests.cc b/webrtc/video/end_to_end_tests.cc
new file mode 100644
index 0000000..0f6f2dc
--- /dev/null
+++ b/webrtc/video/end_to_end_tests.cc
@@ -0,0 +1,1459 @@
+/*
+ *  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.
+ */
+#include <assert.h>
+
+#include <algorithm>
+#include <map>
+#include <sstream>
+#include <string>
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+#include "webrtc/call.h"
+#include "webrtc/frame_callback.h"
+#include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h"
+#include "webrtc/modules/video_coding/codecs/vp8/include/vp8.h"
+#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
+#include "webrtc/system_wrappers/interface/event_wrapper.h"
+#include "webrtc/system_wrappers/interface/scoped_ptr.h"
+#include "webrtc/system_wrappers/interface/sleep.h"
+#include "webrtc/test/call_test.h"
+#include "webrtc/test/direct_transport.h"
+#include "webrtc/test/encoder_settings.h"
+#include "webrtc/test/fake_audio_device.h"
+#include "webrtc/test/fake_decoder.h"
+#include "webrtc/test/fake_encoder.h"
+#include "webrtc/test/frame_generator.h"
+#include "webrtc/test/frame_generator_capturer.h"
+#include "webrtc/test/null_transport.h"
+#include "webrtc/test/rtp_rtcp_observer.h"
+#include "webrtc/test/testsupport/fileutils.h"
+#include "webrtc/test/testsupport/perf_test.h"
+#include "webrtc/video/transport_adapter.h"
+
+namespace webrtc {
+
+static const int kRedPayloadType = 118;
+static const int kUlpfecPayloadType = 119;
+
+class EndToEndTest : public test::CallTest {
+ public:
+  EndToEndTest() {}
+
+  virtual ~EndToEndTest() {
+    EXPECT_EQ(NULL, send_stream_);
+    EXPECT_EQ(NULL, receive_stream_);
+  }
+
+ protected:
+  void CreateFrameGenerator() {
+    frame_generator_capturer_.reset(
+        test::FrameGeneratorCapturer::Create(send_stream_->Input(),
+                                             video_streams_[0].width,
+                                             video_streams_[0].height,
+                                             30,
+                                             Clock::GetRealTimeClock()));
+  }
+
+  void StartSending() {
+    receive_stream_->Start();
+    send_stream_->Start();
+    if (frame_generator_capturer_.get() != NULL)
+      frame_generator_capturer_->Start();
+  }
+
+  void StopSending() {
+    if (frame_generator_capturer_.get() != NULL)
+      frame_generator_capturer_->Stop();
+    if (send_stream_ != NULL)
+      send_stream_->Stop();
+    if (receive_stream_ != NULL)
+      receive_stream_->Stop();
+  }
+
+  void DecodesRetransmittedFrame(bool retransmit_over_rtx);
+  void ReceivesPliAndRecovers(int rtp_history_ms);
+  void RespectsRtcpMode(newapi::RtcpMode rtcp_mode);
+  void TestXrReceiverReferenceTimeReport(bool enable_rrtr);
+};
+
+TEST_F(EndToEndTest, ReceiverCanBeStartedTwice) {
+  test::NullTransport transport;
+  CreateCalls(Call::Config(&transport), Call::Config(&transport));
+
+  CreateSendConfig(1);
+  CreateMatchingReceiveConfigs();
+
+  CreateStreams();
+
+  receive_stream_->Start();
+  receive_stream_->Start();
+
+  DestroyStreams();
+}
+
+TEST_F(EndToEndTest, ReceiverCanBeStoppedTwice) {
+  test::NullTransport transport;
+  CreateCalls(Call::Config(&transport), Call::Config(&transport));
+
+  CreateSendConfig(1);
+  CreateMatchingReceiveConfigs();
+
+  CreateStreams();
+
+  receive_stream_->Stop();
+  receive_stream_->Stop();
+
+  DestroyStreams();
+}
+
+TEST_F(EndToEndTest, RendersSingleDelayedFrame) {
+  static const int kWidth = 320;
+  static const int kHeight = 240;
+  // This constant is chosen to be higher than the timeout in the video_render
+  // module. This makes sure that frames aren't dropped if there are no other
+  // frames in the queue.
+  static const int kDelayRenderCallbackMs = 1000;
+
+  class Renderer : public VideoRenderer {
+   public:
+    Renderer() : event_(EventWrapper::Create()) {}
+
+    virtual void RenderFrame(const I420VideoFrame& video_frame,
+                             int /*time_to_render_ms*/) OVERRIDE {
+      event_->Set();
+    }
+
+    EventTypeWrapper Wait() { return event_->Wait(kDefaultTimeoutMs); }
+
+    scoped_ptr<EventWrapper> event_;
+  } renderer;
+
+  class TestFrameCallback : public I420FrameCallback {
+   public:
+    TestFrameCallback() : event_(EventWrapper::Create()) {}
+
+    EventTypeWrapper Wait() { return event_->Wait(kDefaultTimeoutMs); }
+
+   private:
+    virtual void FrameCallback(I420VideoFrame* frame) OVERRIDE {
+      SleepMs(kDelayRenderCallbackMs);
+      event_->Set();
+    }
+
+    scoped_ptr<EventWrapper> event_;
+  };
+
+  test::DirectTransport sender_transport, receiver_transport;
+
+  CreateCalls(Call::Config(&sender_transport),
+              Call::Config(&receiver_transport));
+
+  sender_transport.SetReceiver(receiver_call_->Receiver());
+  receiver_transport.SetReceiver(sender_call_->Receiver());
+
+  CreateSendConfig(1);
+  CreateMatchingReceiveConfigs();
+
+  TestFrameCallback pre_render_callback;
+  receive_config_.pre_render_callback = &pre_render_callback;
+  receive_config_.renderer = &renderer;
+
+  CreateStreams();
+  StartSending();
+
+  // Create frames that are smaller than the send width/height, this is done to
+  // check that the callbacks are done after processing video.
+  scoped_ptr<test::FrameGenerator> frame_generator(
+      test::FrameGenerator::Create(kWidth, kHeight));
+  send_stream_->Input()->SwapFrame(frame_generator->NextFrame());
+  EXPECT_EQ(kEventSignaled, pre_render_callback.Wait())
+      << "Timed out while waiting for pre-render callback.";
+  EXPECT_EQ(kEventSignaled, renderer.Wait())
+      << "Timed out while waiting for the frame to render.";
+
+  StopSending();
+
+  sender_transport.StopSending();
+  receiver_transport.StopSending();
+
+  DestroyStreams();
+}
+
+TEST_F(EndToEndTest, TransmitsFirstFrame) {
+  class Renderer : public VideoRenderer {
+   public:
+    Renderer() : event_(EventWrapper::Create()) {}
+
+    virtual void RenderFrame(const I420VideoFrame& video_frame,
+                             int /*time_to_render_ms*/) OVERRIDE {
+      event_->Set();
+    }
+
+    EventTypeWrapper Wait() { return event_->Wait(kDefaultTimeoutMs); }
+
+    scoped_ptr<EventWrapper> event_;
+  } renderer;
+
+  test::DirectTransport sender_transport, receiver_transport;
+
+  CreateCalls(Call::Config(&sender_transport),
+              Call::Config(&receiver_transport));
+
+  sender_transport.SetReceiver(receiver_call_->Receiver());
+  receiver_transport.SetReceiver(sender_call_->Receiver());
+
+  CreateSendConfig(1);
+  CreateMatchingReceiveConfigs();
+  receive_config_.renderer = &renderer;
+
+  CreateStreams();
+  StartSending();
+
+  scoped_ptr<test::FrameGenerator> frame_generator(test::FrameGenerator::Create(
+      video_streams_[0].width, video_streams_[0].height));
+  send_stream_->Input()->SwapFrame(frame_generator->NextFrame());
+
+  EXPECT_EQ(kEventSignaled, renderer.Wait())
+      << "Timed out while waiting for the frame to render.";
+
+  StopSending();
+
+  sender_transport.StopSending();
+  receiver_transport.StopSending();
+
+  DestroyStreams();
+}
+
+TEST_F(EndToEndTest, ReceiverUsesLocalSsrc) {
+  class SyncRtcpObserver : public test::EndToEndTest {
+   public:
+    SyncRtcpObserver() : EndToEndTest(kDefaultTimeoutMs) {}
+
+    virtual Action OnReceiveRtcp(const uint8_t* packet,
+                                 size_t length) OVERRIDE {
+      RTCPUtility::RTCPParserV2 parser(packet, length, true);
+      EXPECT_TRUE(parser.IsValid());
+      uint32_t ssrc = 0;
+      ssrc |= static_cast<uint32_t>(packet[4]) << 24;
+      ssrc |= static_cast<uint32_t>(packet[5]) << 16;
+      ssrc |= static_cast<uint32_t>(packet[6]) << 8;
+      ssrc |= static_cast<uint32_t>(packet[7]) << 0;
+      EXPECT_EQ(kReceiverLocalSsrc, ssrc);
+      observation_complete_->Set();
+
+      return SEND_PACKET;
+    }
+
+    virtual void PerformTest() OVERRIDE {
+      EXPECT_EQ(kEventSignaled, Wait())
+          << "Timed out while waiting for a receiver RTCP packet to be sent.";
+    }
+  } test;
+
+  RunBaseTest(&test);
+}
+
+TEST_F(EndToEndTest, ReceivesAndRetransmitsNack) {
+  static const int kNumberOfNacksToObserve = 2;
+  static const int kLossBurstSize = 2;
+  static const int kPacketsBetweenLossBursts = 9;
+  class NackObserver : public test::EndToEndTest {
+   public:
+    NackObserver()
+        : EndToEndTest(kLongTimeoutMs),
+          rtp_parser_(RtpHeaderParser::Create()),
+          sent_rtp_packets_(0),
+          packets_left_to_drop_(0),
+          nacks_left_(kNumberOfNacksToObserve) {}
+
+   private:
+    virtual Action OnSendRtp(const uint8_t* packet, size_t length) OVERRIDE {
+      RTPHeader header;
+      EXPECT_TRUE(
+          rtp_parser_->Parse(packet, static_cast<int>(length), &header));
+
+      // Never drop retransmitted packets.
+      if (dropped_packets_.find(header.sequenceNumber) !=
+          dropped_packets_.end()) {
+        retransmitted_packets_.insert(header.sequenceNumber);
+        if (nacks_left_ == 0 &&
+            retransmitted_packets_.size() == dropped_packets_.size()) {
+          observation_complete_->Set();
+        }
+        return SEND_PACKET;
+      }
+
+      ++sent_rtp_packets_;
+
+      // Enough NACKs received, stop dropping packets.
+      if (nacks_left_ == 0)
+        return SEND_PACKET;
+
+      // Check if it's time for a new loss burst.
+      if (sent_rtp_packets_ % kPacketsBetweenLossBursts == 0)
+        packets_left_to_drop_ = kLossBurstSize;
+
+      if (packets_left_to_drop_ > 0) {
+        --packets_left_to_drop_;
+        dropped_packets_.insert(header.sequenceNumber);
+        return DROP_PACKET;
+      }
+
+      return SEND_PACKET;
+    }
+
+    virtual Action OnReceiveRtcp(const uint8_t* packet,
+                                 size_t length) OVERRIDE {
+      RTCPUtility::RTCPParserV2 parser(packet, length, true);
+      EXPECT_TRUE(parser.IsValid());
+
+      RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
+      while (packet_type != RTCPUtility::kRtcpNotValidCode) {
+        if (packet_type == RTCPUtility::kRtcpRtpfbNackCode) {
+          --nacks_left_;
+          break;
+        }
+        packet_type = parser.Iterate();
+      }
+      return SEND_PACKET;
+    }
+
+    virtual void ModifyConfigs(
+        VideoSendStream::Config* send_config,
+        VideoReceiveStream::Config* receive_config,
+        std::vector<VideoStream>* video_streams) OVERRIDE {
+      send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
+      receive_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
+    }
+
+    virtual void PerformTest() OVERRIDE {
+      EXPECT_EQ(kEventSignaled, Wait())
+          << "Timed out waiting for packets to be NACKed, retransmitted and "
+             "rendered.";
+    }
+
+    scoped_ptr<RtpHeaderParser> rtp_parser_;
+    std::set<uint16_t> dropped_packets_;
+    std::set<uint16_t> retransmitted_packets_;
+    uint64_t sent_rtp_packets_;
+    int packets_left_to_drop_;
+    int nacks_left_;
+  } test;
+
+  RunBaseTest(&test);
+}
+
+// TODO(pbos): Flaky, webrtc:3269
+TEST_F(EndToEndTest, DISABLED_CanReceiveFec) {
+  class FecRenderObserver : public test::EndToEndTest, public VideoRenderer {
+   public:
+    FecRenderObserver()
+        : EndToEndTest(kDefaultTimeoutMs),
+          state_(kFirstPacket),
+          protected_sequence_number_(0),
+          protected_frame_timestamp_(0) {}
+
+   private:
+    virtual Action OnSendRtp(const uint8_t* packet, size_t length) OVERRIDE
+        EXCLUSIVE_LOCKS_REQUIRED(crit_) {
+      RTPHeader header;
+      EXPECT_TRUE(parser_->Parse(packet, static_cast<int>(length), &header));
+
+      EXPECT_EQ(kRedPayloadType, header.payloadType);
+      int encapsulated_payload_type =
+          static_cast<int>(packet[header.headerLength]);
+      if (encapsulated_payload_type != kFakeSendPayloadType)
+        EXPECT_EQ(kUlpfecPayloadType, encapsulated_payload_type);
+
+      switch (state_) {
+        case kFirstPacket:
+          state_ = kDropEveryOtherPacketUntilFec;
+          break;
+        case kDropEveryOtherPacketUntilFec:
+          if (encapsulated_payload_type == kUlpfecPayloadType) {
+            state_ = kDropNextMediaPacket;
+            return SEND_PACKET;
+          }
+          if (header.sequenceNumber % 2 == 0)
+            return DROP_PACKET;
+          break;
+        case kDropNextMediaPacket:
+          if (encapsulated_payload_type == kFakeSendPayloadType) {
+            protected_sequence_number_ = header.sequenceNumber;
+            protected_frame_timestamp_ = header.timestamp;
+            state_ = kProtectedPacketDropped;
+            return DROP_PACKET;
+          }
+          break;
+        case kProtectedPacketDropped:
+          EXPECT_NE(header.sequenceNumber, protected_sequence_number_)
+              << "Protected packet retransmitted. Should not happen with FEC.";
+          break;
+      }
+
+      return SEND_PACKET;
+    }
+
+    virtual void RenderFrame(const I420VideoFrame& video_frame,
+                             int time_to_render_ms) OVERRIDE {
+      CriticalSectionScoped lock(crit_.get());
+      // Rendering frame with timestamp associated with dropped packet -> FEC
+      // protection worked.
+      if (state_ == kProtectedPacketDropped &&
+          video_frame.timestamp() == protected_frame_timestamp_) {
+        observation_complete_->Set();
+      }
+    }
+
+    enum {
+      kFirstPacket,
+      kDropEveryOtherPacketUntilFec,
+      kDropNextMediaPacket,
+      kProtectedPacketDropped,
+    } state_;
+
+    virtual void ModifyConfigs(
+        VideoSendStream::Config* send_config,
+        VideoReceiveStream::Config* receive_config,
+        std::vector<VideoStream>* video_streams) OVERRIDE {
+      // TODO(pbos): Run this test with combined NACK/FEC enabled as well.
+      // int rtp_history_ms = 1000;
+      // receive_config->rtp.nack.rtp_history_ms = rtp_history_ms;
+      // send_config->rtp.nack.rtp_history_ms = rtp_history_ms;
+      send_config->rtp.fec.red_payload_type = kRedPayloadType;
+      send_config->rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
+
+      receive_config->rtp.fec.red_payload_type = kRedPayloadType;
+      receive_config->rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
+      receive_config->renderer = this;
+    }
+
+    virtual void PerformTest() OVERRIDE {
+      EXPECT_EQ(kEventSignaled, Wait())
+          << "Timed out while waiting for retransmitted NACKed frames to be "
+             "rendered again.";
+    }
+
+    uint32_t protected_sequence_number_ GUARDED_BY(crit_);
+    uint32_t protected_frame_timestamp_ GUARDED_BY(crit_);
+  } test;
+
+  RunBaseTest(&test);
+}
+
+// This test drops second RTP packet with a marker bit set, makes sure it's
+// retransmitted and renders. Retransmission SSRCs are also checked.
+void EndToEndTest::DecodesRetransmittedFrame(bool retransmit_over_rtx) {
+  static const int kDroppedFrameNumber = 2;
+  class RetransmissionObserver : public test::EndToEndTest,
+                                 public I420FrameCallback {
+   public:
+    explicit RetransmissionObserver(bool expect_rtx)
+        : EndToEndTest(kDefaultTimeoutMs),
+          retransmission_ssrc_(expect_rtx ? kSendRtxSsrc : kSendSsrcs[0]),
+          retransmission_payload_type_(expect_rtx ? kSendRtxPayloadType
+                                                  : kFakeSendPayloadType),
+          marker_bits_observed_(0),
+          retransmitted_timestamp_(0),
+          frame_retransmitted_(false) {}
+
+   private:
+    virtual Action OnSendRtp(const uint8_t* packet, size_t length) OVERRIDE {
+      RTPHeader header;
+      EXPECT_TRUE(parser_->Parse(packet, static_cast<int>(length), &header));
+
+      if (header.timestamp == retransmitted_timestamp_) {
+        EXPECT_EQ(retransmission_ssrc_, header.ssrc);
+        EXPECT_EQ(retransmission_payload_type_, header.payloadType);
+        frame_retransmitted_ = true;
+        return SEND_PACKET;
+      }
+
+      EXPECT_EQ(kSendSsrcs[0], header.ssrc);
+      EXPECT_EQ(kFakeSendPayloadType, header.payloadType);
+
+      // Found the second frame's final packet, drop this and expect a
+      // retransmission.
+      if (header.markerBit && ++marker_bits_observed_ == kDroppedFrameNumber) {
+        retransmitted_timestamp_ = header.timestamp;
+        return DROP_PACKET;
+      }
+
+      return SEND_PACKET;
+    }
+
+    virtual void FrameCallback(I420VideoFrame* frame) OVERRIDE {
+      CriticalSectionScoped lock(crit_.get());
+      if (frame->timestamp() == retransmitted_timestamp_) {
+        EXPECT_TRUE(frame_retransmitted_);
+        observation_complete_->Set();
+      }
+    }
+
+    virtual void ModifyConfigs(
+        VideoSendStream::Config* send_config,
+        VideoReceiveStream::Config* receive_config,
+        std::vector<VideoStream>* video_streams) OVERRIDE {
+      send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
+      receive_config->pre_render_callback = this;
+      receive_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
+      if (retransmission_ssrc_ == kSendRtxSsrc) {
+        send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrc);
+        send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
+        receive_config->rtp.rtx[kSendRtxPayloadType].ssrc = kSendRtxSsrc;
+        receive_config->rtp.rtx[kSendRtxPayloadType].payload_type =
+            kSendRtxPayloadType;
+      }
+    }
+
+    virtual void PerformTest() OVERRIDE {
+      EXPECT_EQ(kEventSignaled, Wait())
+          << "Timed out while waiting for retransmission to render.";
+    }
+
+    const uint32_t retransmission_ssrc_;
+    const int retransmission_payload_type_;
+    int marker_bits_observed_;
+    uint32_t retransmitted_timestamp_;
+    bool frame_retransmitted_;
+  } test(retransmit_over_rtx);
+
+  RunBaseTest(&test);
+}
+
+TEST_F(EndToEndTest, DecodesRetransmittedFrame) {
+  DecodesRetransmittedFrame(false);
+}
+
+TEST_F(EndToEndTest, DecodesRetransmittedFrameOverRtx) {
+  DecodesRetransmittedFrame(true);
+}
+
+TEST_F(EndToEndTest, UsesFrameCallbacks) {
+  static const int kWidth = 320;
+  static const int kHeight = 240;
+
+  class Renderer : public VideoRenderer {
+   public:
+    Renderer() : event_(EventWrapper::Create()) {}
+
+    virtual void RenderFrame(const I420VideoFrame& video_frame,
+                             int /*time_to_render_ms*/) OVERRIDE {
+      EXPECT_EQ(0, *video_frame.buffer(kYPlane))
+          << "Rendered frame should have zero luma which is applied by the "
+             "pre-render callback.";
+      event_->Set();
+    }
+
+    EventTypeWrapper Wait() { return event_->Wait(kDefaultTimeoutMs); }
+    scoped_ptr<EventWrapper> event_;
+  } renderer;
+
+  class TestFrameCallback : public I420FrameCallback {
+   public:
+    TestFrameCallback(int expected_luma_byte, int next_luma_byte)
+        : event_(EventWrapper::Create()),
+          expected_luma_byte_(expected_luma_byte),
+          next_luma_byte_(next_luma_byte) {}
+
+    EventTypeWrapper Wait() { return event_->Wait(kDefaultTimeoutMs); }
+
+   private:
+    virtual void FrameCallback(I420VideoFrame* frame) {
+      EXPECT_EQ(kWidth, frame->width())
+          << "Width not as expected, callback done before resize?";
+      EXPECT_EQ(kHeight, frame->height())
+          << "Height not as expected, callback done before resize?";
+
+      // Previous luma specified, observed luma should be fairly close.
+      if (expected_luma_byte_ != -1) {
+        EXPECT_NEAR(expected_luma_byte_, *frame->buffer(kYPlane), 10);
+      }
+
+      memset(frame->buffer(kYPlane),
+             next_luma_byte_,
+             frame->allocated_size(kYPlane));
+
+      event_->Set();
+    }
+
+    scoped_ptr<EventWrapper> event_;
+    int expected_luma_byte_;
+    int next_luma_byte_;
+  };
+
+  TestFrameCallback pre_encode_callback(-1, 255);  // Changes luma to 255.
+  TestFrameCallback pre_render_callback(255, 0);  // Changes luma from 255 to 0.
+
+  test::DirectTransport sender_transport, receiver_transport;
+
+  CreateCalls(Call::Config(&sender_transport),
+              Call::Config(&receiver_transport));
+
+  sender_transport.SetReceiver(receiver_call_->Receiver());
+  receiver_transport.SetReceiver(sender_call_->Receiver());
+
+  CreateSendConfig(1);
+  scoped_ptr<VP8Encoder> encoder(VP8Encoder::Create());
+  send_config_.encoder_settings.encoder = encoder.get();
+  send_config_.encoder_settings.payload_name = "VP8";
+  ASSERT_EQ(1u, video_streams_.size()) << "Test setup error.";
+  video_streams_[0].width = kWidth;
+  video_streams_[0].height = kHeight;
+  send_config_.pre_encode_callback = &pre_encode_callback;
+
+  CreateMatchingReceiveConfigs();
+  receive_config_.pre_render_callback = &pre_render_callback;
+  receive_config_.renderer = &renderer;
+
+  CreateStreams();
+  StartSending();
+
+  // Create frames that are smaller than the send width/height, this is done to
+  // check that the callbacks are done after processing video.
+  scoped_ptr<test::FrameGenerator> frame_generator(
+      test::FrameGenerator::Create(kWidth / 2, kHeight / 2));
+  send_stream_->Input()->SwapFrame(frame_generator->NextFrame());
+
+  EXPECT_EQ(kEventSignaled, pre_encode_callback.Wait())
+      << "Timed out while waiting for pre-encode callback.";
+  EXPECT_EQ(kEventSignaled, pre_render_callback.Wait())
+      << "Timed out while waiting for pre-render callback.";
+  EXPECT_EQ(kEventSignaled, renderer.Wait())
+      << "Timed out while waiting for the frame to render.";
+
+  StopSending();
+
+  sender_transport.StopSending();
+  receiver_transport.StopSending();
+
+  DestroyStreams();
+}
+
+void EndToEndTest::ReceivesPliAndRecovers(int rtp_history_ms) {
+  static const int kPacketsToDrop = 1;
+
+  class PliObserver : public test::EndToEndTest, public VideoRenderer {
+   public:
+    explicit PliObserver(int rtp_history_ms)
+        : EndToEndTest(kLongTimeoutMs),
+          rtp_history_ms_(rtp_history_ms),
+          nack_enabled_(rtp_history_ms > 0),
+          highest_dropped_timestamp_(0),
+          frames_to_drop_(0),
+          received_pli_(false) {}
+
+   private:
+    virtual Action OnSendRtp(const uint8_t* packet, size_t length) OVERRIDE {
+      RTPHeader header;
+      EXPECT_TRUE(parser_->Parse(packet, static_cast<int>(length), &header));
+
+      // Drop all retransmitted packets to force a PLI.
+      if (header.timestamp <= highest_dropped_timestamp_)
+        return DROP_PACKET;
+
+      if (frames_to_drop_ > 0) {
+        highest_dropped_timestamp_ = header.timestamp;
+        --frames_to_drop_;
+        return DROP_PACKET;
+      }
+
+      return SEND_PACKET;
+    }
+
+    virtual Action OnReceiveRtcp(const uint8_t* packet,
+                                 size_t length) OVERRIDE {
+      RTCPUtility::RTCPParserV2 parser(packet, length, true);
+      EXPECT_TRUE(parser.IsValid());
+
+      for (RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
+           packet_type != RTCPUtility::kRtcpNotValidCode;
+           packet_type = parser.Iterate()) {
+        if (!nack_enabled_)
+          EXPECT_NE(packet_type, RTCPUtility::kRtcpRtpfbNackCode);
+
+        if (packet_type == RTCPUtility::kRtcpPsfbPliCode) {
+          received_pli_ = true;
+          break;
+        }
+      }
+      return SEND_PACKET;
+    }
+
+    virtual void RenderFrame(const I420VideoFrame& video_frame,
+                             int time_to_render_ms) OVERRIDE {
+      CriticalSectionScoped lock(crit_.get());
+      if (received_pli_ &&
+          video_frame.timestamp() > highest_dropped_timestamp_) {
+        observation_complete_->Set();
+      }
+      if (!received_pli_)
+        frames_to_drop_ = kPacketsToDrop;
+    }
+
+    virtual void ModifyConfigs(
+        VideoSendStream::Config* send_config,
+        VideoReceiveStream::Config* receive_config,
+        std::vector<VideoStream>* video_streams) OVERRIDE {
+      send_config->rtp.nack.rtp_history_ms = rtp_history_ms_;
+      receive_config->rtp.nack.rtp_history_ms = rtp_history_ms_;
+      receive_config->renderer = this;
+    }
+
+    virtual void PerformTest() OVERRIDE {
+      EXPECT_EQ(kEventSignaled, Wait()) << "Timed out waiting for PLI to be "
+                                           "received and a frame to be "
+                                           "rendered afterwards.";
+    }
+
+    int rtp_history_ms_;
+    bool nack_enabled_;
+    uint32_t highest_dropped_timestamp_;
+    int frames_to_drop_;
+    bool received_pli_;
+  } test(rtp_history_ms);
+
+  RunBaseTest(&test);
+}
+
+TEST_F(EndToEndTest, ReceivesPliAndRecoversWithNack) {
+  ReceivesPliAndRecovers(1000);
+}
+
+// TODO(pbos): Enable this when 2250 is resolved.
+TEST_F(EndToEndTest, DISABLED_ReceivesPliAndRecoversWithoutNack) {
+  ReceivesPliAndRecovers(0);
+}
+
+TEST_F(EndToEndTest, UnknownRtpPacketGivesUnknownSsrcReturnCode) {
+  class PacketInputObserver : public PacketReceiver {
+   public:
+    explicit PacketInputObserver(PacketReceiver* receiver)
+        : receiver_(receiver), delivered_packet_(EventWrapper::Create()) {}
+
+    EventTypeWrapper Wait() {
+      return delivered_packet_->Wait(kDefaultTimeoutMs);
+    }
+
+   private:
+    virtual DeliveryStatus DeliverPacket(const uint8_t* packet,
+                                         size_t length) OVERRIDE {
+      if (RtpHeaderParser::IsRtcp(packet, static_cast<int>(length))) {
+        return receiver_->DeliverPacket(packet, length);
+      } else {
+        DeliveryStatus delivery_status =
+            receiver_->DeliverPacket(packet, length);
+        EXPECT_EQ(DELIVERY_UNKNOWN_SSRC, delivery_status);
+        delivered_packet_->Set();
+        return delivery_status;
+      }
+    }
+
+    PacketReceiver* receiver_;
+    scoped_ptr<EventWrapper> delivered_packet_;
+  };
+
+  test::DirectTransport send_transport, receive_transport;
+
+  CreateCalls(Call::Config(&send_transport), Call::Config(&receive_transport));
+  PacketInputObserver input_observer(receiver_call_->Receiver());
+
+  send_transport.SetReceiver(&input_observer);
+  receive_transport.SetReceiver(sender_call_->Receiver());
+
+  CreateSendConfig(1);
+  CreateMatchingReceiveConfigs();
+
+  CreateStreams();
+  CreateFrameGenerator();
+  StartSending();
+
+  receiver_call_->DestroyVideoReceiveStream(receive_stream_);
+  receive_stream_ = NULL;
+
+  // Wait() waits for a received packet.
+  EXPECT_EQ(kEventSignaled, input_observer.Wait());
+
+  StopSending();
+
+  DestroyStreams();
+
+  send_transport.StopSending();
+  receive_transport.StopSending();
+}
+
+void EndToEndTest::RespectsRtcpMode(newapi::RtcpMode rtcp_mode) {
+  static const int kNumCompoundRtcpPacketsToObserve = 10;
+  class RtcpModeObserver : public test::EndToEndTest {
+   public:
+    explicit RtcpModeObserver(newapi::RtcpMode rtcp_mode)
+        : EndToEndTest(kDefaultTimeoutMs),
+          rtcp_mode_(rtcp_mode),
+          sent_rtp_(0),
+          sent_rtcp_(0) {}
+
+   private:
+    virtual Action OnSendRtp(const uint8_t* packet, size_t length) OVERRIDE {
+      if (++sent_rtp_ % 3 == 0)
+        return DROP_PACKET;
+
+      return SEND_PACKET;
+    }
+
+    virtual Action OnReceiveRtcp(const uint8_t* packet,
+                                 size_t length) OVERRIDE {
+      ++sent_rtcp_;
+      RTCPUtility::RTCPParserV2 parser(packet, length, true);
+      EXPECT_TRUE(parser.IsValid());
+
+      RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
+      bool has_report_block = false;
+      while (packet_type != RTCPUtility::kRtcpNotValidCode) {
+        EXPECT_NE(RTCPUtility::kRtcpSrCode, packet_type);
+        if (packet_type == RTCPUtility::kRtcpRrCode) {
+          has_report_block = true;
+          break;
+        }
+        packet_type = parser.Iterate();
+      }
+
+      switch (rtcp_mode_) {
+        case newapi::kRtcpCompound:
+          if (!has_report_block) {
+            ADD_FAILURE() << "Received RTCP packet without receiver report for "
+                             "kRtcpCompound.";
+            observation_complete_->Set();
+          }
+
+          if (sent_rtcp_ >= kNumCompoundRtcpPacketsToObserve)
+            observation_complete_->Set();
+
+          break;
+        case newapi::kRtcpReducedSize:
+          if (!has_report_block)
+            observation_complete_->Set();
+          break;
+      }
+
+      return SEND_PACKET;
+    }
+
+    virtual void ModifyConfigs(
+        VideoSendStream::Config* send_config,
+        VideoReceiveStream::Config* receive_config,
+        std::vector<VideoStream>* video_streams) OVERRIDE {
+      send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
+      receive_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
+      receive_config->rtp.rtcp_mode = rtcp_mode_;
+    }
+
+    virtual void PerformTest() OVERRIDE {
+      EXPECT_EQ(kEventSignaled, Wait())
+          << (rtcp_mode_ == newapi::kRtcpCompound
+                  ? "Timed out before observing enough compound packets."
+                  : "Timed out before receiving a non-compound RTCP packet.");
+    }
+
+    newapi::RtcpMode rtcp_mode_;
+    int sent_rtp_;
+    int sent_rtcp_;
+  } test(rtcp_mode);
+
+  RunBaseTest(&test);
+}
+
+TEST_F(EndToEndTest, UsesRtcpCompoundMode) {
+  RespectsRtcpMode(newapi::kRtcpCompound);
+}
+
+TEST_F(EndToEndTest, UsesRtcpReducedSizeMode) {
+  RespectsRtcpMode(newapi::kRtcpReducedSize);
+}
+
+// Test sets up a Call multiple senders with different resolutions and SSRCs.
+// Another is set up to receive all three of these with different renderers.
+// Each renderer verifies that it receives the expected resolution, and as soon
+// as every renderer has received a frame, the test finishes.
+TEST_F(EndToEndTest, SendsAndReceivesMultipleStreams) {
+  static const size_t kNumStreams = 3;
+
+  class VideoOutputObserver : public VideoRenderer {
+   public:
+    VideoOutputObserver(test::FrameGeneratorCapturer** capturer,
+                        int width,
+                        int height)
+        : capturer_(capturer),
+          width_(width),
+          height_(height),
+          done_(EventWrapper::Create()) {}
+
+    virtual void RenderFrame(const I420VideoFrame& video_frame,
+                             int time_to_render_ms) OVERRIDE {
+      EXPECT_EQ(width_, video_frame.width());
+      EXPECT_EQ(height_, video_frame.height());
+      (*capturer_)->Stop();
+      done_->Set();
+    }
+
+    EventTypeWrapper Wait() { return done_->Wait(kDefaultTimeoutMs); }
+
+   private:
+    test::FrameGeneratorCapturer** capturer_;
+    int width_;
+    int height_;
+    scoped_ptr<EventWrapper> done_;
+  };
+
+  struct {
+    uint32_t ssrc;
+    int width;
+    int height;
+  } codec_settings[kNumStreams] = {{1, 640, 480}, {2, 320, 240}, {3, 240, 160}};
+
+  test::DirectTransport sender_transport, receiver_transport;
+  scoped_ptr<Call> sender_call(Call::Create(Call::Config(&sender_transport)));
+  scoped_ptr<Call> receiver_call(
+      Call::Create(Call::Config(&receiver_transport)));
+  sender_transport.SetReceiver(receiver_call->Receiver());
+  receiver_transport.SetReceiver(sender_call->Receiver());
+
+  VideoSendStream* send_streams[kNumStreams];
+  VideoReceiveStream* receive_streams[kNumStreams];
+
+  VideoOutputObserver* observers[kNumStreams];
+  test::FrameGeneratorCapturer* frame_generators[kNumStreams];
+
+  scoped_ptr<VP8Encoder> encoders[kNumStreams];
+  for (size_t i = 0; i < kNumStreams; ++i)
+    encoders[i].reset(VP8Encoder::Create());
+
+  for (size_t i = 0; i < kNumStreams; ++i) {
+    uint32_t ssrc = codec_settings[i].ssrc;
+    int width = codec_settings[i].width;
+    int height = codec_settings[i].height;
+    observers[i] = new VideoOutputObserver(&frame_generators[i], width, height);
+
+    VideoSendStream::Config send_config = sender_call->GetDefaultSendConfig();
+    send_config.rtp.ssrcs.push_back(ssrc);
+    send_config.encoder_settings.encoder = encoders[i].get();
+    send_config.encoder_settings.payload_name = "VP8";
+    send_config.encoder_settings.payload_type = 124;
+    std::vector<VideoStream> video_streams = test::CreateVideoStreams(1);
+    VideoStream* stream = &video_streams[0];
+    stream->width = width;
+    stream->height = height;
+    stream->max_framerate = 5;
+    stream->min_bitrate_bps = stream->target_bitrate_bps =
+        stream->max_bitrate_bps = 100000;
+    send_streams[i] =
+        sender_call->CreateVideoSendStream(send_config, video_streams, NULL);
+    send_streams[i]->Start();
+
+    VideoReceiveStream::Config receive_config =
+        receiver_call->GetDefaultReceiveConfig();
+    receive_config.renderer = observers[i];
+    receive_config.rtp.remote_ssrc = ssrc;
+    receive_config.rtp.local_ssrc = kReceiverLocalSsrc;
+    VideoCodec codec =
+        test::CreateDecoderVideoCodec(send_config.encoder_settings);
+    receive_config.codecs.push_back(codec);
+    receive_streams[i] =
+        receiver_call->CreateVideoReceiveStream(receive_config);
+    receive_streams[i]->Start();
+
+    frame_generators[i] = test::FrameGeneratorCapturer::Create(
+        send_streams[i]->Input(), width, height, 30, Clock::GetRealTimeClock());
+    frame_generators[i]->Start();
+  }
+
+  for (size_t i = 0; i < kNumStreams; ++i) {
+    EXPECT_EQ(kEventSignaled, observers[i]->Wait())
+        << "Timed out while waiting for observer " << i << " to render.";
+  }
+
+  for (size_t i = 0; i < kNumStreams; ++i) {
+    frame_generators[i]->Stop();
+    sender_call->DestroyVideoSendStream(send_streams[i]);
+    receiver_call->DestroyVideoReceiveStream(receive_streams[i]);
+    delete frame_generators[i];
+    delete observers[i];
+  }
+
+  sender_transport.StopSending();
+  receiver_transport.StopSending();
+}
+
+TEST_F(EndToEndTest, ObserversEncodedFrames) {
+  class EncodedFrameTestObserver : public EncodedFrameObserver {
+   public:
+    EncodedFrameTestObserver()
+        : length_(0),
+          frame_type_(kFrameEmpty),
+          called_(EventWrapper::Create()) {}
+    virtual ~EncodedFrameTestObserver() {}
+
+    virtual void EncodedFrameCallback(const EncodedFrame& encoded_frame) {
+      frame_type_ = encoded_frame.frame_type_;
+      length_ = encoded_frame.length_;
+      buffer_.reset(new uint8_t[length_]);
+      memcpy(buffer_.get(), encoded_frame.data_, length_);
+      called_->Set();
+    }
+
+    EventTypeWrapper Wait() { return called_->Wait(kDefaultTimeoutMs); }
+
+    void ExpectEqualFrames(const EncodedFrameTestObserver& observer) {
+      ASSERT_EQ(length_, observer.length_)
+          << "Observed frames are of different lengths.";
+      EXPECT_EQ(frame_type_, observer.frame_type_)
+          << "Observed frames have different frame types.";
+      EXPECT_EQ(0, memcmp(buffer_.get(), observer.buffer_.get(), length_))
+          << "Observed encoded frames have different content.";
+    }
+
+   private:
+    scoped_ptr<uint8_t[]> buffer_;
+    size_t length_;
+    FrameType frame_type_;
+    scoped_ptr<EventWrapper> called_;
+  };
+
+  EncodedFrameTestObserver post_encode_observer;
+  EncodedFrameTestObserver pre_decode_observer;
+
+  test::DirectTransport sender_transport, receiver_transport;
+
+  CreateCalls(Call::Config(&sender_transport),
+              Call::Config(&receiver_transport));
+
+  sender_transport.SetReceiver(receiver_call_->Receiver());
+  receiver_transport.SetReceiver(sender_call_->Receiver());
+
+  CreateSendConfig(1);
+  CreateMatchingReceiveConfigs();
+  send_config_.post_encode_callback = &post_encode_observer;
+  receive_config_.pre_decode_callback = &pre_decode_observer;
+
+  CreateStreams();
+  StartSending();
+
+  scoped_ptr<test::FrameGenerator> frame_generator(test::FrameGenerator::Create(
+      video_streams_[0].width, video_streams_[0].height));
+  send_stream_->Input()->SwapFrame(frame_generator->NextFrame());
+
+  EXPECT_EQ(kEventSignaled, post_encode_observer.Wait())
+      << "Timed out while waiting for send-side encoded-frame callback.";
+
+  EXPECT_EQ(kEventSignaled, pre_decode_observer.Wait())
+      << "Timed out while waiting for pre-decode encoded-frame callback.";
+
+  post_encode_observer.ExpectEqualFrames(pre_decode_observer);
+
+  StopSending();
+
+  sender_transport.StopSending();
+  receiver_transport.StopSending();
+
+  DestroyStreams();
+}
+
+TEST_F(EndToEndTest, ReceiveStreamSendsRemb) {
+  class RembObserver : public test::EndToEndTest {
+   public:
+    RembObserver() : EndToEndTest(kDefaultTimeoutMs) {}
+
+    virtual Action OnReceiveRtcp(const uint8_t* packet,
+                                 size_t length) OVERRIDE {
+      RTCPUtility::RTCPParserV2 parser(packet, length, true);
+      EXPECT_TRUE(parser.IsValid());
+
+      bool received_psfb = false;
+      bool received_remb = false;
+      RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
+      while (packet_type != RTCPUtility::kRtcpNotValidCode) {
+        if (packet_type == RTCPUtility::kRtcpPsfbRembCode) {
+          const RTCPUtility::RTCPPacket& packet = parser.Packet();
+          EXPECT_EQ(packet.PSFBAPP.SenderSSRC, kReceiverLocalSsrc);
+          received_psfb = true;
+        } else if (packet_type == RTCPUtility::kRtcpPsfbRembItemCode) {
+          const RTCPUtility::RTCPPacket& packet = parser.Packet();
+          EXPECT_GT(packet.REMBItem.BitRate, 0u);
+          EXPECT_EQ(packet.REMBItem.NumberOfSSRCs, 1u);
+          EXPECT_EQ(packet.REMBItem.SSRCs[0], kSendSsrcs[0]);
+          received_remb = true;
+        }
+        packet_type = parser.Iterate();
+      }
+      if (received_psfb && received_remb)
+        observation_complete_->Set();
+      return SEND_PACKET;
+    }
+    virtual void PerformTest() OVERRIDE {
+      EXPECT_EQ(kEventSignaled, Wait()) << "Timed out while waiting for a "
+                                           "receiver RTCP REMB packet to be "
+                                           "sent.";
+    }
+  } test;
+
+  RunBaseTest(&test);
+}
+
+void EndToEndTest::TestXrReceiverReferenceTimeReport(bool enable_rrtr) {
+  static const int kNumRtcpReportPacketsToObserve = 5;
+  class RtcpXrObserver : public test::EndToEndTest {
+   public:
+    explicit RtcpXrObserver(bool enable_rrtr)
+        : EndToEndTest(kDefaultTimeoutMs),
+          enable_rrtr_(enable_rrtr),
+          sent_rtcp_sr_(0),
+          sent_rtcp_rr_(0),
+          sent_rtcp_rrtr_(0),
+          sent_rtcp_dlrr_(0) {}
+
+   private:
+    // Receive stream should send RR packets (and RRTR packets if enabled).
+    virtual Action OnReceiveRtcp(const uint8_t* packet,
+                                 size_t length) OVERRIDE {
+      RTCPUtility::RTCPParserV2 parser(packet, length, true);
+      EXPECT_TRUE(parser.IsValid());
+
+      RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
+      while (packet_type != RTCPUtility::kRtcpNotValidCode) {
+        if (packet_type == RTCPUtility::kRtcpRrCode) {
+          ++sent_rtcp_rr_;
+        } else if (packet_type ==
+                   RTCPUtility::kRtcpXrReceiverReferenceTimeCode) {
+          ++sent_rtcp_rrtr_;
+        }
+        EXPECT_NE(packet_type, RTCPUtility::kRtcpSrCode);
+        EXPECT_NE(packet_type, RTCPUtility::kRtcpXrDlrrReportBlockItemCode);
+        packet_type = parser.Iterate();
+      }
+      return SEND_PACKET;
+    }
+    // Send stream should send SR packets (and DLRR packets if enabled).
+    virtual Action OnSendRtcp(const uint8_t* packet, size_t length) {
+      RTCPUtility::RTCPParserV2 parser(packet, length, true);
+      EXPECT_TRUE(parser.IsValid());
+
+      RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
+      while (packet_type != RTCPUtility::kRtcpNotValidCode) {
+        if (packet_type == RTCPUtility::kRtcpSrCode) {
+          ++sent_rtcp_sr_;
+        } else if (packet_type == RTCPUtility::kRtcpXrDlrrReportBlockItemCode) {
+          ++sent_rtcp_dlrr_;
+        }
+        EXPECT_NE(packet_type, RTCPUtility::kRtcpXrReceiverReferenceTimeCode);
+        packet_type = parser.Iterate();
+      }
+      if (sent_rtcp_sr_ > kNumRtcpReportPacketsToObserve &&
+          sent_rtcp_rr_ > kNumRtcpReportPacketsToObserve) {
+        if (enable_rrtr_) {
+          EXPECT_GT(sent_rtcp_rrtr_, 0);
+          EXPECT_GT(sent_rtcp_dlrr_, 0);
+        } else {
+          EXPECT_EQ(0, sent_rtcp_rrtr_);
+          EXPECT_EQ(0, sent_rtcp_dlrr_);
+        }
+        observation_complete_->Set();
+      }
+      return SEND_PACKET;
+    }
+
+    virtual void ModifyConfigs(
+        VideoSendStream::Config* send_config,
+        VideoReceiveStream::Config* receive_config,
+        std::vector<VideoStream>* video_streams) OVERRIDE {
+      receive_config->rtp.rtcp_mode = newapi::kRtcpReducedSize;
+      receive_config->rtp.rtcp_xr.receiver_reference_time_report = enable_rrtr_;
+    }
+
+    virtual void PerformTest() OVERRIDE {
+      EXPECT_EQ(kEventSignaled, Wait())
+          << "Timed out while waiting for RTCP SR/RR packets to be sent.";
+    }
+
+    bool enable_rrtr_;
+    int sent_rtcp_sr_;
+    int sent_rtcp_rr_;
+    int sent_rtcp_rrtr_;
+    int sent_rtcp_dlrr_;
+  } test(enable_rrtr);
+
+  RunBaseTest(&test);
+}
+
+TEST_F(EndToEndTest, GetStats) {
+  class StatsObserver : public test::EndToEndTest, public I420FrameCallback {
+   public:
+    StatsObserver()
+        : EndToEndTest(kLongTimeoutMs),
+          receive_stream_(NULL),
+          send_stream_(NULL),
+          expected_receive_ssrc_(),
+          expected_send_ssrcs_(),
+          check_stats_event_(EventWrapper::Create()) {}
+
+   private:
+    virtual Action OnSendRtp(const uint8_t* packet, size_t length) OVERRIDE {
+      check_stats_event_->Set();
+      return SEND_PACKET;
+    }
+
+    virtual Action OnSendRtcp(const uint8_t* packet, size_t length) OVERRIDE {
+      check_stats_event_->Set();
+      return SEND_PACKET;
+    }
+
+    virtual Action OnReceiveRtp(const uint8_t* packet, size_t length) OVERRIDE {
+      check_stats_event_->Set();
+      return SEND_PACKET;
+    }
+
+    virtual Action OnReceiveRtcp(const uint8_t* packet,
+                                 size_t length) OVERRIDE {
+      check_stats_event_->Set();
+      return SEND_PACKET;
+    }
+
+    virtual void FrameCallback(I420VideoFrame* video_frame) OVERRIDE {
+      // Ensure that we have at least 5ms send side delay.
+      int64_t render_time = video_frame->render_time_ms();
+      if (render_time > 0)
+        video_frame->set_render_time_ms(render_time - 5);
+    }
+
+    bool CheckReceiveStats() {
+      assert(receive_stream_ != NULL);
+      VideoReceiveStream::Stats stats = receive_stream_->GetStats();
+      EXPECT_EQ(expected_receive_ssrc_, stats.ssrc);
+
+      // Make sure all fields have been populated.
+
+      receive_stats_filled_["IncomingRate"] |=
+          stats.network_frame_rate != 0 || stats.bitrate_bps != 0;
+
+      receive_stats_filled_["FrameCallback"] |= stats.decode_frame_rate != 0;
+
+      receive_stats_filled_["FrameRendered"] |= stats.render_frame_rate != 0;
+
+      receive_stats_filled_["StatisticsUpdated"] |=
+          stats.rtcp_stats.cumulative_lost != 0 ||
+          stats.rtcp_stats.extended_max_sequence_number != 0 ||
+          stats.rtcp_stats.fraction_lost != 0 || stats.rtcp_stats.jitter != 0;
+
+      receive_stats_filled_["DataCountersUpdated"] |=
+          stats.rtp_stats.bytes != 0 || stats.rtp_stats.fec_packets != 0 ||
+          stats.rtp_stats.header_bytes != 0 || stats.rtp_stats.packets != 0 ||
+          stats.rtp_stats.padding_bytes != 0 ||
+          stats.rtp_stats.retransmitted_packets != 0;
+
+      receive_stats_filled_["CodecStats"] |=
+          stats.avg_delay_ms != 0 || stats.discarded_packets != 0 ||
+          stats.key_frames != 0 || stats.delta_frames != 0;
+
+      receive_stats_filled_["CName"] |= stats.c_name == expected_cname_;
+
+      return AllStatsFilled(receive_stats_filled_);
+    }
+
+    bool CheckSendStats() {
+      assert(send_stream_ != NULL);
+      VideoSendStream::Stats stats = send_stream_->GetStats();
+
+      send_stats_filled_["NumStreams"] |=
+          stats.substreams.size() == expected_send_ssrcs_.size();
+
+      send_stats_filled_["Delay"] |=
+          stats.avg_delay_ms != 0 || stats.max_delay_ms != 0;
+
+      receive_stats_filled_["CName"] |= stats.c_name == expected_cname_;
+
+      for (std::map<uint32_t, StreamStats>::const_iterator it =
+               stats.substreams.begin();
+           it != stats.substreams.end();
+           ++it) {
+        EXPECT_TRUE(expected_send_ssrcs_.find(it->first) !=
+                    expected_send_ssrcs_.end());
+
+        send_stats_filled_[CompoundKey("IncomingRate", it->first)] |=
+            stats.input_frame_rate != 0;
+
+        const StreamStats& stream_stats = it->second;
+
+        send_stats_filled_[CompoundKey("StatisticsUpdated", it->first)] |=
+            stream_stats.rtcp_stats.cumulative_lost != 0 ||
+            stream_stats.rtcp_stats.extended_max_sequence_number != 0 ||
+            stream_stats.rtcp_stats.fraction_lost != 0;
+
+        send_stats_filled_[CompoundKey("DataCountersUpdated", it->first)] |=
+            stream_stats.rtp_stats.fec_packets != 0 ||
+            stream_stats.rtp_stats.padding_bytes != 0 ||
+            stream_stats.rtp_stats.retransmitted_packets != 0 ||
+            stream_stats.rtp_stats.packets != 0;
+
+        send_stats_filled_[CompoundKey("BitrateStatisticsObserver",
+                                       it->first)] |=
+            stream_stats.bitrate_bps != 0;
+
+        send_stats_filled_[CompoundKey("FrameCountObserver", it->first)] |=
+            stream_stats.delta_frames != 0 || stream_stats.key_frames != 0;
+
+        send_stats_filled_[CompoundKey("OutgoingRate", it->first)] |=
+            stats.encode_frame_rate != 0;
+      }
+
+      return AllStatsFilled(send_stats_filled_);
+    }
+
+    std::string CompoundKey(const char* name, uint32_t ssrc) {
+      std::ostringstream oss;
+      oss << name << "_" << ssrc;
+      return oss.str();
+    }
+
+    bool AllStatsFilled(const std::map<std::string, bool>& stats_map) {
+      for (std::map<std::string, bool>::const_iterator it = stats_map.begin();
+           it != stats_map.end();
+           ++it) {
+        if (!it->second)
+          return false;
+      }
+      return true;
+    }
+
+    virtual void ModifyConfigs(
+        VideoSendStream::Config* send_config,
+        VideoReceiveStream::Config* receive_config,
+        std::vector<VideoStream>* video_streams) OVERRIDE {
+      send_config->pre_encode_callback = this;  // Used to inject delay.
+      send_config->rtp.c_name = "SomeCName";
+
+      expected_receive_ssrc_ = receive_config->rtp.local_ssrc;
+      const std::vector<uint32_t>& ssrcs = send_config->rtp.ssrcs;
+      for (size_t i = 0; i < ssrcs.size(); ++i)
+        expected_send_ssrcs_.insert(ssrcs[i]);
+
+      expected_cname_ = send_config->rtp.c_name;
+    }
+
+    virtual void OnStreamsCreated(VideoSendStream* send_stream,
+                                  VideoReceiveStream* receive_stream) OVERRIDE {
+      send_stream_ = send_stream;
+      receive_stream_ = receive_stream;
+    }
+
+    virtual void PerformTest() OVERRIDE {
+      Clock* clock = Clock::GetRealTimeClock();
+      int64_t now = clock->TimeInMilliseconds();
+      int64_t stop_time = now + test::CallTest::kLongTimeoutMs;
+      bool receive_ok = false;
+      bool send_ok = false;
+
+      while (now < stop_time) {
+        if (!receive_ok)
+          receive_ok = CheckReceiveStats();
+        if (!send_ok)
+          send_ok = CheckSendStats();
+
+        if (receive_ok && send_ok)
+          return;
+
+        int64_t time_until_timout_ = stop_time - now;
+        if (time_until_timout_ > 0)
+          check_stats_event_->Wait(time_until_timout_);
+        now = clock->TimeInMilliseconds();
+      }
+
+      ADD_FAILURE() << "Timed out waiting for filled stats.";
+      for (std::map<std::string, bool>::const_iterator it =
+               receive_stats_filled_.begin();
+           it != receive_stats_filled_.end();
+           ++it) {
+        if (!it->second) {
+          ADD_FAILURE() << "Missing receive stats: " << it->first;
+        }
+      }
+
+      for (std::map<std::string, bool>::const_iterator it =
+               send_stats_filled_.begin();
+           it != send_stats_filled_.end();
+           ++it) {
+        if (!it->second) {
+          ADD_FAILURE() << "Missing send stats: " << it->first;
+        }
+      }
+    }
+
+    VideoReceiveStream* receive_stream_;
+    std::map<std::string, bool> receive_stats_filled_;
+
+    VideoSendStream* send_stream_;
+    std::map<std::string, bool> send_stats_filled_;
+
+    uint32_t expected_receive_ssrc_;
+    std::set<uint32_t> expected_send_ssrcs_;
+    std::string expected_cname_;
+
+    scoped_ptr<EventWrapper> check_stats_event_;
+  } test;
+
+  RunBaseTest(&test);
+}
+
+TEST_F(EndToEndTest, ReceiverReferenceTimeReportEnabled) {
+  TestXrReceiverReferenceTimeReport(true);
+}
+
+TEST_F(EndToEndTest, ReceiverReferenceTimeReportDisabled) {
+  TestXrReceiverReferenceTimeReport(false);
+}
+
+TEST_F(EndToEndTest, TestReceivedRtpPacketStats) {
+  static const size_t kNumRtpPacketsToSend = 5;
+  class ReceivedRtpStatsObserver : public test::EndToEndTest {
+   public:
+    ReceivedRtpStatsObserver()
+        : EndToEndTest(kDefaultTimeoutMs),
+          receive_stream_(NULL),
+          sent_rtp_(0) {}
+
+   private:
+    virtual void OnStreamsCreated(VideoSendStream* send_stream,
+                                  VideoReceiveStream* receive_stream) OVERRIDE {
+      receive_stream_ = receive_stream;
+    }
+
+    virtual Action OnSendRtp(const uint8_t* packet, size_t length) OVERRIDE {
+      if (sent_rtp_ >= kNumRtpPacketsToSend) {
+        VideoReceiveStream::Stats stats = receive_stream_->GetStats();
+        if (kNumRtpPacketsToSend == stats.rtp_stats.packets) {
+          observation_complete_->Set();
+        }
+        return DROP_PACKET;
+      }
+      ++sent_rtp_;
+      return SEND_PACKET;
+    }
+
+    virtual void PerformTest() OVERRIDE {
+      EXPECT_EQ(kEventSignaled, Wait())
+          << "Timed out while verifying number of received RTP packets.";
+    }
+
+    VideoReceiveStream* receive_stream_;
+    uint32_t sent_rtp_;
+  } test;
+
+  RunBaseTest(&test);
+}
+
+}  // namespace webrtc
diff --git a/webrtc/video/full_stack.cc b/webrtc/video/full_stack.cc
index 6b21cbe..1c03042 100644
--- a/webrtc/video/full_stack.cc
+++ b/webrtc/video/full_stack.cc
@@ -24,6 +24,7 @@
 #include "webrtc/system_wrappers/interface/scoped_ptr.h"
 #include "webrtc/system_wrappers/interface/sleep.h"
 #include "webrtc/system_wrappers/interface/thread_annotations.h"
+#include "webrtc/test/call_test.h"
 #include "webrtc/test/direct_transport.h"
 #include "webrtc/test/encoder_settings.h"
 #include "webrtc/test/fake_encoder.h"
@@ -34,7 +35,6 @@
 
 namespace webrtc {
 
-static const uint32_t kSendSsrc = 0x654321;
 static const int kFullStackTestDurationSecs = 10;
 
 struct FullStackTestParams {
@@ -49,20 +49,9 @@
   double avg_ssim_threshold;
 };
 
-FullStackTestParams paris_qcif = {
-    "net_delay_0_0_plr_0", {"paris_qcif", 176, 144, 30}, 300, 36.0, 0.96};
-
-// TODO(pbos): Decide on psnr/ssim thresholds for foreman_cif.
-FullStackTestParams foreman_cif = {
-    "foreman_cif_net_delay_0_0_plr_0",
-    {"foreman_cif", 352, 288, 30},
-    700,
-    0.0,
-    0.0};
-
-class FullStackTest : public ::testing::TestWithParam<FullStackTestParams> {
+class FullStackTest : public test::CallTest {
  protected:
-  std::map<uint32_t, bool> reserved_ssrcs_;
+  void TestWithoutPacketLoss(const FullStackTestParams& params);
 };
 
 class VideoAnalyzer : public PacketReceiver,
@@ -200,7 +189,9 @@
     last_rendered_frame_.CopyFrame(video_frame);
   }
 
-  void Wait() { done_->Wait(120 * 1000); }
+  void Wait() {
+    EXPECT_EQ(kEventSignaled, done_->Wait(FullStackTest::kLongTimeoutMs));
+  }
 
   VideoSendStreamInput* input_;
   Transport* transport_;
@@ -376,10 +367,7 @@
   const scoped_ptr<EventWrapper> done_;
 };
 
-TEST_P(FullStackTest, NoPacketLoss) {
-  static const uint32_t kReceiverLocalSsrc = 0x123456;
-  FullStackTestParams params = GetParam();
-
+void FullStackTest::TestWithoutPacketLoss(const FullStackTestParams& params) {
   test::DirectTransport transport;
   VideoAnalyzer analyzer(NULL,
                          &transport,
@@ -388,32 +376,32 @@
                          params.avg_ssim_threshold,
                          kFullStackTestDurationSecs * params.clip.fps);
 
-  Call::Config call_config(&analyzer);
+  CreateCalls(Call::Config(&analyzer), Call::Config(&analyzer));
 
-  scoped_ptr<Call> call(Call::Create(call_config));
-  analyzer.SetReceiver(call->Receiver());
+  analyzer.SetReceiver(receiver_call_->Receiver());
   transport.SetReceiver(&analyzer);
 
-  VideoSendStream::Config send_config = call->GetDefaultSendConfig();
-  send_config.rtp.ssrcs.push_back(kSendSsrc);
+  CreateSendConfig(1);
 
   scoped_ptr<VP8Encoder> encoder(VP8Encoder::Create());
-  send_config.encoder_settings.encoder = encoder.get();
-  send_config.encoder_settings.payload_name = "VP8";
-  send_config.encoder_settings.payload_type = 124;
-  std::vector<VideoStream> video_streams = test::CreateVideoStreams(1);
-  VideoStream* stream = &video_streams[0];
+  send_config_.encoder_settings.encoder = encoder.get();
+  send_config_.encoder_settings.payload_name = "VP8";
+  send_config_.encoder_settings.payload_type = 124;
+
+  VideoStream* stream = &video_streams_[0];
   stream->width = params.clip.width;
   stream->height = params.clip.height;
   stream->min_bitrate_bps = stream->target_bitrate_bps =
       stream->max_bitrate_bps = params.bitrate * 1000;
   stream->max_framerate = params.clip.fps;
 
-  VideoSendStream* send_stream =
-      call->CreateVideoSendStream(send_config, video_streams, NULL);
-  analyzer.input_ = send_stream->Input();
+  CreateMatchingReceiveConfigs();
+  receive_config_.renderer = &analyzer;
 
-  scoped_ptr<test::FrameGeneratorCapturer> file_capturer(
+  CreateStreams();
+  analyzer.input_ = send_stream_->Input();
+
+  frame_generator_capturer_.reset(
       test::FrameGeneratorCapturer::CreateFromYuvFile(
           &analyzer,
           test::ResourcePath(params.clip.name, "yuv").c_str(),
@@ -421,39 +409,41 @@
           params.clip.height,
           params.clip.fps,
           Clock::GetRealTimeClock()));
-  ASSERT_TRUE(file_capturer.get() != NULL)
+
+  ASSERT_TRUE(frame_generator_capturer_.get() != NULL)
       << "Could not create capturer for " << params.clip.name
       << ".yuv. Is this resource file present?";
 
-  VideoReceiveStream::Config receive_config = call->GetDefaultReceiveConfig();
-  VideoCodec codec =
-      test::CreateDecoderVideoCodec(send_config.encoder_settings);
-  receive_config.codecs.push_back(codec);
-  receive_config.rtp.remote_ssrc = send_config.rtp.ssrcs[0];
-  receive_config.rtp.local_ssrc = kReceiverLocalSsrc;
-  receive_config.renderer = &analyzer;
-
-  VideoReceiveStream* receive_stream =
-      call->CreateVideoReceiveStream(receive_config);
-
-  receive_stream->Start();
-  send_stream->Start();
-  file_capturer->Start();
+  Start();
 
   analyzer.Wait();
 
-  file_capturer->Stop();
-  send_stream->Stop();
-  receive_stream->Stop();
-
-  call->DestroyVideoReceiveStream(receive_stream);
-  call->DestroyVideoSendStream(send_stream);
-
   transport.StopSending();
+
+  Stop();
+
+  DestroyStreams();
 }
 
-INSTANTIATE_TEST_CASE_P(FullStack,
-                        FullStackTest,
-                        ::testing::Values(paris_qcif, foreman_cif));
+FullStackTestParams paris_qcif = {"net_delay_0_0_plr_0",
+                                  {"paris_qcif", 176, 144, 30},
+                                  300,
+                                  36.0,
+                                  0.96};
+
+// TODO(pbos): Decide on psnr/ssim thresholds for foreman_cif.
+FullStackTestParams foreman_cif = {"foreman_cif_net_delay_0_0_plr_0",
+                                   {"foreman_cif", 352, 288, 30},
+                                   700,
+                                   0.0,
+                                   0.0};
+
+TEST_F(FullStackTest, ParisQcifWithoutPacketLoss) {
+  TestWithoutPacketLoss(paris_qcif);
+}
+
+TEST_F(FullStackTest, ForemanCifWithoutPacketLoss) {
+  TestWithoutPacketLoss(foreman_cif);
+}
 
 }  // namespace webrtc
diff --git a/webrtc/video/rampup_tests.cc b/webrtc/video/rampup_tests.cc
index 94f1c19..5529f92 100644
--- a/webrtc/video/rampup_tests.cc
+++ b/webrtc/video/rampup_tests.cc
@@ -27,6 +27,7 @@
 #include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
 #include "webrtc/system_wrappers/interface/event_wrapper.h"
 #include "webrtc/system_wrappers/interface/scoped_ptr.h"
+#include "webrtc/test/call_test.h"
 #include "webrtc/test/direct_transport.h"
 #include "webrtc/test/encoder_settings.h"
 #include "webrtc/test/fake_decoder.h"
@@ -388,7 +389,9 @@
     }
   }
 
-  EventTypeWrapper Wait() { return test_done_->Wait(120 * 1000); }
+  EventTypeWrapper Wait() {
+    return test_done_->Wait(test::CallTest::kLongTimeoutMs);
+  }
 
  private:
   static const unsigned int kHighBandwidthLimitBps = 80000;
@@ -420,10 +423,7 @@
 };
 }  // namespace
 
-class RampUpTest : public ::testing::Test {
- public:
-  virtual void SetUp() { reserved_ssrcs_.clear(); }
-
+class RampUpTest : public test::CallTest {
  protected:
   void RunRampUpTest(bool rtx,
                      size_t num_streams,
@@ -445,33 +445,26 @@
       call_config.start_bitrate_bps = start_bitrate_bps;
       stream_observer.set_start_bitrate_bps(start_bitrate_bps);
     }
-    scoped_ptr<Call> call(Call::Create(call_config));
-    VideoSendStream::Config send_config = call->GetDefaultSendConfig();
 
-    receiver_transport.SetReceiver(call->Receiver());
+    CreateSenderCall(call_config);
+    CreateSendConfig(num_streams);
 
-    test::FakeEncoder encoder(Clock::GetRealTimeClock());
-    send_config.encoder_settings.encoder = &encoder;
-    send_config.encoder_settings.payload_type = 125;
-    send_config.encoder_settings.payload_name = "FAKE";
-    std::vector<VideoStream> video_streams =
-        test::CreateVideoStreams(num_streams);
+    receiver_transport.SetReceiver(sender_call_->Receiver());
 
     if (num_streams == 1) {
-      video_streams[0].target_bitrate_bps = 2000000;
-      video_streams[0].max_bitrate_bps = 2000000;
+      video_streams_[0].target_bitrate_bps = 2000000;
+      video_streams_[0].max_bitrate_bps = 2000000;
     }
 
-    send_config.rtp.nack.rtp_history_ms = 1000;
-    send_config.rtp.ssrcs = ssrcs;
+    send_config_.rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
+    send_config_.rtp.ssrcs = ssrcs;
     if (rtx) {
-      send_config.rtp.rtx.payload_type = 96;
-      send_config.rtp.rtx.ssrcs = rtx_ssrcs;
-      send_config.rtp.rtx.pad_with_redundant_payloads = true;
+      send_config_.rtp.rtx.payload_type = kSendRtxPayloadType;
+      send_config_.rtp.rtx.ssrcs = rtx_ssrcs;
+      send_config_.rtp.rtx.pad_with_redundant_payloads = true;
     }
-    send_config.rtp.extensions.push_back(
-        RtpExtension(RtpExtension::kTOffset,
-                     kTransmissionTimeOffsetExtensionId));
+    send_config_.rtp.extensions.push_back(RtpExtension(
+        RtpExtension::kTOffset, kTransmissionTimeOffsetExtensionId));
 
     if (num_streams == 1) {
       // For single stream rampup until 1mbps
@@ -480,32 +473,22 @@
       // For multi stream rampup until all streams are being sent. That means
       // enough birate to send all the target streams plus the min bitrate of
       // the last one.
-      int expected_bitrate_bps = video_streams.back().min_bitrate_bps;
-      for (size_t i = 0; i < video_streams.size() - 1; ++i) {
-        expected_bitrate_bps += video_streams[i].target_bitrate_bps;
+      int expected_bitrate_bps = video_streams_.back().min_bitrate_bps;
+      for (size_t i = 0; i < video_streams_.size() - 1; ++i) {
+        expected_bitrate_bps += video_streams_[i].target_bitrate_bps;
       }
       stream_observer.set_expected_bitrate_bps(expected_bitrate_bps);
     }
 
-    VideoSendStream* send_stream =
-        call->CreateVideoSendStream(send_config, video_streams, NULL);
+    CreateStreams();
+    CreateFrameGeneratorCapturer();
 
-    scoped_ptr<test::FrameGeneratorCapturer> frame_generator_capturer(
-        test::FrameGeneratorCapturer::Create(send_stream->Input(),
-                                             video_streams.back().width,
-                                             video_streams.back().height,
-                                             video_streams.back().max_framerate,
-                                             Clock::GetRealTimeClock()));
-
-    send_stream->Start();
-    frame_generator_capturer->Start();
+    Start();
 
     EXPECT_EQ(kEventSignaled, stream_observer.Wait());
 
-    frame_generator_capturer->Stop();
-    send_stream->Stop();
-
-    call->DestroyVideoSendStream(send_stream);
+    Stop();
+    DestroyStreams();
   }
 
   void RunRampUpDownUpTest(size_t number_of_streams, bool rtx) {
@@ -520,59 +503,27 @@
     webrtc::Config webrtc_config;
     call_config.webrtc_config = &webrtc_config;
     webrtc_config.Set<PaddingStrategy>(new PaddingStrategy(rtx));
-    scoped_ptr<Call> call(Call::Create(call_config));
-    VideoSendStream::Config send_config = call->GetDefaultSendConfig();
+    CreateSenderCall(call_config);
+    receiver_transport.SetReceiver(sender_call_->Receiver());
 
-    receiver_transport.SetReceiver(call->Receiver());
+    CreateSendConfig(number_of_streams);
 
-    test::FakeEncoder encoder(Clock::GetRealTimeClock());
-    send_config.encoder_settings.encoder = &encoder;
-    send_config.encoder_settings.payload_type = 125;
-    send_config.encoder_settings.payload_name = "FAKE";
-    std::vector<VideoStream> video_streams =
-        test::CreateVideoStreams(number_of_streams);
+    send_config_.rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
+    send_config_.rtp.extensions.push_back(RtpExtension(
+        RtpExtension::kTOffset, kTransmissionTimeOffsetExtensionId));
+    send_config_.suspend_below_min_bitrate = true;
 
-    send_config.rtp.nack.rtp_history_ms = 1000;
-    send_config.rtp.ssrcs.insert(
-        send_config.rtp.ssrcs.begin(), ssrcs.begin(), ssrcs.end());
-    send_config.rtp.extensions.push_back(
-        RtpExtension(RtpExtension::kTOffset,
-                     kTransmissionTimeOffsetExtensionId));
-    send_config.suspend_below_min_bitrate = true;
+    CreateStreams();
+    stream_observer.SetSendStream(send_stream_);
 
-    VideoSendStream* send_stream =
-        call->CreateVideoSendStream(send_config, video_streams, NULL);
-    stream_observer.SetSendStream(send_stream);
+    CreateFrameGeneratorCapturer();
 
-    size_t width = 0;
-    size_t height = 0;
-    for (size_t i = 0; i < video_streams.size(); ++i) {
-      size_t stream_width = video_streams[i].width;
-      size_t stream_height = video_streams[i].height;
-      if (stream_width > width)
-        width = stream_width;
-      if (stream_height > height)
-        height = stream_height;
-    }
-
-    scoped_ptr<test::FrameGeneratorCapturer> frame_generator_capturer(
-        test::FrameGeneratorCapturer::Create(send_stream->Input(),
-                                             width,
-                                             height,
-                                             30,
-                                             Clock::GetRealTimeClock()));
-
-    send_stream->Start();
-    frame_generator_capturer->Start();
+    Start();
 
     EXPECT_EQ(kEventSignaled, stream_observer.Wait());
 
-    stream_observer.StopSending();
-    receiver_transport.StopSending();
-    frame_generator_capturer->Stop();
-    send_stream->Stop();
-
-    call->DestroyVideoSendStream(send_stream);
+    Stop();
+    DestroyStreams();
   }
 
  private:
@@ -583,8 +534,6 @@
       ssrcs.push_back(static_cast<uint32_t>(ssrc_offset + i));
     return ssrcs;
   }
-
-  std::map<uint32_t, bool> reserved_ssrcs_;
 };
 
 TEST_F(RampUpTest, SingleStream) {
diff --git a/webrtc/video/video_send_stream_tests.cc b/webrtc/video/video_send_stream_tests.cc
index 3ae15d4..2d9bf5b 100644
--- a/webrtc/video/video_send_stream_tests.cc
+++ b/webrtc/video/video_send_stream_tests.cc
@@ -27,13 +27,9 @@
 #include "webrtc/system_wrappers/interface/scoped_vector.h"
 #include "webrtc/system_wrappers/interface/sleep.h"
 #include "webrtc/system_wrappers/interface/thread_wrapper.h"
-#include "webrtc/test/direct_transport.h"
+#include "webrtc/test/call_test.h"
 #include "webrtc/test/configurable_frame_size_encoder.h"
-#include "webrtc/test/encoder_settings.h"
-#include "webrtc/test/fake_encoder.h"
-#include "webrtc/test/frame_generator_capturer.h"
 #include "webrtc/test/null_transport.h"
-#include "webrtc/test/rtp_rtcp_observer.h"
 #include "webrtc/test/testsupport/perf_test.h"
 #include "webrtc/video/transport_adapter.h"
 #include "webrtc/video_send_stream.h"
@@ -59,94 +55,43 @@
   virtual void* GetHandle() { return NULL; }
 };
 
-class VideoSendStreamTest : public ::testing::Test {
- public:
-  VideoSendStreamTest()
-      : send_stream_(NULL), fake_encoder_(Clock::GetRealTimeClock()) {}
-
+class VideoSendStreamTest : public test::CallTest {
  protected:
-  void RunSendTest(Call* call,
-                   test::RtpRtcpObserver* observer) {
-    send_stream_ =
-        call->CreateVideoSendStream(send_config_, video_streams_, NULL);
-    scoped_ptr<test::FrameGeneratorCapturer> frame_generator_capturer(
-        test::FrameGeneratorCapturer::Create(
-            send_stream_->Input(), 320, 240, 30, Clock::GetRealTimeClock()));
-    send_stream_->Start();
-    frame_generator_capturer->Start();
-
-    EXPECT_EQ(kEventSignaled, observer->Wait());
-
-    observer->StopSending();
-    frame_generator_capturer->Stop();
-    send_stream_->Stop();
-    call->DestroyVideoSendStream(send_stream_);
-  }
-
-  void CreateTestConfig(Call* call, size_t num_streams) {
-    assert(num_streams <= kNumSendSsrcs);
-    send_config_ = call->GetDefaultSendConfig();
-    send_config_.encoder_settings.encoder = &fake_encoder_;
-    send_config_.encoder_settings.payload_name = "FAKE";
-    send_config_.encoder_settings.payload_type = kFakeSendPayloadType;
-    video_streams_ = test::CreateVideoStreams(num_streams);
-    send_config_.encoder_settings.payload_type = kFakeSendPayloadType;
-    for (size_t i = 0; i < num_streams; ++i)
-      send_config_.rtp.ssrcs.push_back(kSendSsrcs[i]);
-  }
-
   void TestNackRetransmission(uint32_t retransmit_ssrc,
                               uint8_t retransmit_payload_type);
-
   void TestPacketFragmentationSize(VideoFormat format, bool with_fec);
-
   void SendsSetSsrcs(size_t num_ssrcs, bool send_single_ssrc_first);
 
-  enum { kNumSendSsrcs = 3 };
-  static const uint8_t kSendPayloadType;
-  static const uint8_t kSendRtxPayloadType;
-  static const uint8_t kFakeSendPayloadType;
-  static const uint32_t kSendSsrc;
-  static const uint32_t kSendRtxSsrc;
-  static const uint32_t kSendSsrcs[kNumSendSsrcs];
-
-  VideoSendStream::Config send_config_;
-  std::vector<VideoStream> video_streams_;
-  VideoSendStream* send_stream_;
-  test::FakeEncoder fake_encoder_;
 };
 
-const uint8_t VideoSendStreamTest::kSendPayloadType = 100;
-const uint8_t VideoSendStreamTest::kFakeSendPayloadType = 125;
-const uint8_t VideoSendStreamTest::kSendRtxPayloadType = 98;
-const uint32_t VideoSendStreamTest::kSendRtxSsrc = 0xBADCAFE;
-const uint32_t VideoSendStreamTest::kSendSsrcs[kNumSendSsrcs] = {
-    0xC0FFED, 0xC0FFEE, 0xC0FFEF};
-const uint32_t VideoSendStreamTest::kSendSsrc =
-    VideoSendStreamTest::kSendSsrcs[0];
-
 void VideoSendStreamTest::SendsSetSsrcs(size_t num_ssrcs,
                                         bool send_single_ssrc_first) {
-  class SendSsrcObserver : public test::RtpRtcpObserver {
+  class SendsSetSsrcs : public test::SendTest {
    public:
-    SendSsrcObserver(const uint32_t* ssrcs,
-                     size_t num_ssrcs,
-                     bool send_single_ssrc_first)
-        : RtpRtcpObserver(30 * 1000),
+    SendsSetSsrcs(const uint32_t* ssrcs,
+                  size_t num_ssrcs,
+                  bool send_single_ssrc_first)
+        : SendTest(kDefaultTimeoutMs),
+          num_ssrcs_(num_ssrcs),
+          send_single_ssrc_first_(send_single_ssrc_first),
           ssrcs_to_observe_(num_ssrcs),
           expect_single_ssrc_(send_single_ssrc_first) {
       for (size_t i = 0; i < num_ssrcs; ++i)
         valid_ssrcs_[ssrcs[i]] = true;
     }
 
+   private:
     virtual Action OnSendRtp(const uint8_t* packet, size_t length) OVERRIDE {
       RTPHeader header;
       EXPECT_TRUE(parser_->Parse(packet, static_cast<int>(length), &header));
 
       // TODO(pbos): Reenable this part of the test when #1695 is resolved and
-      //             all SSRCs are allocated on startup. This test was observed
-      //             to fail on TSan as the codec gets set before the SSRCs are
-      //             set up and some frames are sent on a random-generated SSRC
+      //             all SSRCs are allocated on startup. This test was
+      //             observed
+      //             to fail on TSan as the codec gets set before the SSRCs
+      //             are
+      //             set up and some frames are sent on a random-generated
+      //             SSRC
       //             before the correct SSRC gets set.
       // EXPECT_TRUE(valid_ssrcs_[header.ssrc])
       //    << "Received unknown SSRC: " << header.ssrc;
@@ -169,98 +114,100 @@
       return SEND_PACKET;
     }
 
+    virtual void ModifyConfigs(
+        VideoSendStream::Config* send_config,
+        VideoReceiveStream::Config* receive_config,
+        std::vector<VideoStream>* video_streams) OVERRIDE {
+      if (num_ssrcs_ > 1) {
+        // Set low simulcast bitrates to not have to wait for bandwidth ramp-up.
+        for (size_t i = 0; i < video_streams->size(); ++i) {
+          (*video_streams)[i].min_bitrate_bps = 10000;
+          (*video_streams)[i].target_bitrate_bps = 10000;
+          (*video_streams)[i].max_bitrate_bps = 10000;
+        }
+      }
+
+      all_streams_ = *video_streams;
+      if (send_single_ssrc_first_)
+        video_streams->resize(1);
+    }
+
+    virtual void OnStreamsCreated(VideoSendStream* send_stream,
+                                  VideoReceiveStream* receive_stream) OVERRIDE {
+      send_stream_ = send_stream;
+    }
+
+    virtual void PerformTest() OVERRIDE {
+      EXPECT_EQ(kEventSignaled, Wait())
+          << "Timed out while waiting for "
+          << (send_single_ssrc_first_ ? "first SSRC." : "SSRCs.");
+
+      if (send_single_ssrc_first_) {
+        // Set full simulcast and continue with the rest of the SSRCs.
+        send_stream_->ReconfigureVideoEncoder(all_streams_, NULL);
+        EXPECT_EQ(kEventSignaled, Wait())
+            << "Timed out while waiting on additional SSRCs.";
+      }
+    }
+
    private:
     std::map<uint32_t, bool> valid_ssrcs_;
     std::map<uint32_t, bool> is_observed_;
+
+    const size_t num_ssrcs_;
+    const bool send_single_ssrc_first_;
+
     size_t ssrcs_to_observe_;
     bool expect_single_ssrc_;
-  } observer(kSendSsrcs, num_ssrcs, send_single_ssrc_first);
 
-  Call::Config call_config(observer.SendTransport());
-  scoped_ptr<Call> call(Call::Create(call_config));
+    VideoSendStream* send_stream_;
+    std::vector<VideoStream> all_streams_;
+  } test(kSendSsrcs, num_ssrcs, send_single_ssrc_first);
 
-  CreateTestConfig(call.get(), num_ssrcs);
-
-  if (num_ssrcs > 1) {
-    // Set low simulcast bitrates to not have to wait for bandwidth ramp-up.
-    for (size_t i = 0; i < video_streams_.size(); ++i) {
-      video_streams_[i].min_bitrate_bps = 10000;
-      video_streams_[i].target_bitrate_bps = 10000;
-      video_streams_[i].max_bitrate_bps = 10000;
-    }
-  }
-
-  std::vector<VideoStream> all_streams = video_streams_;
-  if (send_single_ssrc_first)
-    video_streams_.resize(1);
-
-  send_stream_ =
-      call->CreateVideoSendStream(send_config_, video_streams_, NULL);
-  scoped_ptr<test::FrameGeneratorCapturer> frame_generator_capturer(
-      test::FrameGeneratorCapturer::Create(
-          send_stream_->Input(), 320, 240, 30, Clock::GetRealTimeClock()));
-  send_stream_->Start();
-  frame_generator_capturer->Start();
-
-  EXPECT_EQ(kEventSignaled, observer.Wait())
-      << "Timed out while waiting for "
-      << (send_single_ssrc_first ? "first SSRC." : "SSRCs.");
-
-  if (send_single_ssrc_first) {
-    // Set full simulcast and continue with the rest of the SSRCs.
-    send_stream_->ReconfigureVideoEncoder(all_streams, NULL);
-    EXPECT_EQ(kEventSignaled, observer.Wait())
-        << "Timed out while waiting on additional SSRCs.";
-  }
-
-  observer.StopSending();
-  frame_generator_capturer->Stop();
-  send_stream_->Stop();
-  call->DestroyVideoSendStream(send_stream_);
+  RunBaseTest(&test);
 }
 
 TEST_F(VideoSendStreamTest, CanStartStartedStream) {
   test::NullTransport transport;
   Call::Config call_config(&transport);
-  scoped_ptr<Call> call(Call::Create(call_config));
+  CreateSenderCall(call_config);
 
-  CreateTestConfig(call.get(), 1);
-  VideoSendStream* stream =
-      call->CreateVideoSendStream(send_config_, video_streams_, NULL);
-  stream->Start();
-  stream->Start();
-  call->DestroyVideoSendStream(stream);
+  CreateSendConfig(1);
+  CreateStreams();
+  send_stream_->Start();
+  send_stream_->Start();
+  DestroyStreams();
 }
 
 TEST_F(VideoSendStreamTest, CanStopStoppedStream) {
   test::NullTransport transport;
   Call::Config call_config(&transport);
-  scoped_ptr<Call> call(Call::Create(call_config));
+  CreateSenderCall(call_config);
 
-  CreateTestConfig(call.get(), 1);
-  VideoSendStream* stream =
-      call->CreateVideoSendStream(send_config_, video_streams_, NULL);
-  stream->Stop();
-  stream->Stop();
-  call->DestroyVideoSendStream(stream);
+  CreateSendConfig(1);
+  CreateStreams();
+  send_stream_->Stop();
+  send_stream_->Stop();
+  DestroyStreams();
 }
 
 TEST_F(VideoSendStreamTest, SendsSetSsrc) { SendsSetSsrcs(1, false); }
 
 TEST_F(VideoSendStreamTest, DISABLED_SendsSetSimulcastSsrcs) {
-  SendsSetSsrcs(kNumSendSsrcs, false);
+  SendsSetSsrcs(kNumSsrcs, false);
 }
 
 TEST_F(VideoSendStreamTest, DISABLED_CanSwitchToUseAllSsrcs) {
-  SendsSetSsrcs(kNumSendSsrcs, true);
+  SendsSetSsrcs(kNumSsrcs, true);
 }
 
 TEST_F(VideoSendStreamTest, SupportsCName) {
   static std::string kCName = "PjQatC14dGfbVwGPUOA9IH7RlsFDbWl4AhXEiDsBizo=";
-  class CNameObserver : public test::RtpRtcpObserver {
+  class CNameObserver : public test::SendTest {
    public:
-    CNameObserver() : RtpRtcpObserver(30 * 1000) {}
+    CNameObserver() : SendTest(kDefaultTimeoutMs) {}
 
+   private:
     virtual Action OnSendRtcp(const uint8_t* packet, size_t length) OVERRIDE {
       RTCPUtility::RTCPParserV2 parser(packet, length, true);
       EXPECT_TRUE(parser.IsValid());
@@ -277,22 +224,28 @@
 
       return SEND_PACKET;
     }
-  } observer;
 
-  Call::Config call_config(observer.SendTransport());
-  scoped_ptr<Call> call(Call::Create(call_config));
+    virtual void ModifyConfigs(
+        VideoSendStream::Config* send_config,
+        VideoReceiveStream::Config* receive_config,
+        std::vector<VideoStream>* video_streams) OVERRIDE {
+      send_config->rtp.c_name = kCName;
+    }
 
-  CreateTestConfig(call.get(), 1);
-  send_config_.rtp.c_name = kCName;
+    virtual void PerformTest() OVERRIDE {
+      EXPECT_EQ(kEventSignaled, Wait())
+          << "Timed out while waiting for RTCP with CNAME.";
+    }
+  } test;
 
-  RunSendTest(call.get(), &observer);
+  RunBaseTest(&test);
 }
 
 TEST_F(VideoSendStreamTest, SupportsAbsoluteSendTime) {
   static const uint8_t kAbsSendTimeExtensionId = 13;
-  class AbsoluteSendTimeObserver : public test::RtpRtcpObserver {
+  class AbsoluteSendTimeObserver : public test::SendTest {
    public:
-    AbsoluteSendTimeObserver() : RtpRtcpObserver(30 * 1000) {
+    AbsoluteSendTimeObserver() : SendTest(kDefaultTimeoutMs) {
       EXPECT_TRUE(parser_->RegisterRtpHeaderExtension(
           kRtpExtensionAbsoluteSendTime, kAbsSendTimeExtensionId));
     }
@@ -309,41 +262,35 @@
 
       return SEND_PACKET;
     }
-  } observer;
 
-  Call::Config call_config(observer.SendTransport());
-  scoped_ptr<Call> call(Call::Create(call_config));
+    virtual void ModifyConfigs(
+        VideoSendStream::Config* send_config,
+        VideoReceiveStream::Config* receive_config,
+        std::vector<VideoStream>* video_streams) OVERRIDE {
+      send_config->rtp.extensions.push_back(
+          RtpExtension(RtpExtension::kAbsSendTime, kAbsSendTimeExtensionId));
+    }
+    virtual void PerformTest() OVERRIDE {
+      EXPECT_EQ(kEventSignaled, Wait())
+          << "Timed out while waiting for single RTP packet.";
+    }
 
-  CreateTestConfig(call.get(), 1);
-  send_config_.rtp.extensions.push_back(
-      RtpExtension(RtpExtension::kAbsSendTime, kAbsSendTimeExtensionId));
+  } test;
 
-  RunSendTest(call.get(), &observer);
+  RunBaseTest(&test);
 }
 
 TEST_F(VideoSendStreamTest, SupportsTransmissionTimeOffset) {
   static const uint8_t kTOffsetExtensionId = 13;
-  class DelayedEncoder : public test::FakeEncoder {
+  class TransmissionTimeOffsetObserver : public test::SendTest {
    public:
-    explicit DelayedEncoder(Clock* clock) : test::FakeEncoder(clock) {}
-    virtual int32_t Encode(const I420VideoFrame& input_image,
-                           const CodecSpecificInfo* codec_specific_info,
-                           const std::vector<VideoFrameType>* frame_types)
-        OVERRIDE {
-      // A delay needs to be introduced to assure that we get a timestamp
-      // offset.
-      SleepMs(5);
-      return FakeEncoder::Encode(input_image, codec_specific_info, frame_types);
-    }
-  } encoder(Clock::GetRealTimeClock());
-
-  class TransmissionTimeOffsetObserver : public test::RtpRtcpObserver {
-   public:
-    TransmissionTimeOffsetObserver() : RtpRtcpObserver(30 * 1000) {
+    TransmissionTimeOffsetObserver()
+        : SendTest(kDefaultTimeoutMs), encoder_(Clock::GetRealTimeClock()) {
       EXPECT_TRUE(parser_->RegisterRtpHeaderExtension(
           kRtpExtensionTransmissionTimeOffset, kTOffsetExtensionId));
     }
 
+   private:
     virtual Action OnSendRtp(const uint8_t* packet, size_t length) OVERRIDE {
       RTPHeader header;
       EXPECT_TRUE(parser_->Parse(packet, static_cast<int>(length), &header));
@@ -356,17 +303,40 @@
 
       return SEND_PACKET;
     }
-  } observer;
 
-  Call::Config call_config(observer.SendTransport());
-  scoped_ptr<Call> call(Call::Create(call_config));
+    virtual void ModifyConfigs(
+        VideoSendStream::Config* send_config,
+        VideoReceiveStream::Config* receive_config,
+        std::vector<VideoStream>* video_streams) OVERRIDE {
+      send_config->encoder_settings.encoder = &encoder_;
+      send_config->rtp.extensions.push_back(
+          RtpExtension(RtpExtension::kTOffset, kTOffsetExtensionId));
+    }
 
-  CreateTestConfig(call.get(), 1);
-  send_config_.encoder_settings.encoder = &encoder;
-  send_config_.rtp.extensions.push_back(
-      RtpExtension(RtpExtension::kTOffset, kTOffsetExtensionId));
+    virtual void PerformTest() OVERRIDE {
+      EXPECT_EQ(kEventSignaled, Wait())
+          << "Timed out while waiting single RTP packet.";
+    }
 
-  RunSendTest(call.get(), &observer);
+    class DelayedEncoder : public test::FakeEncoder {
+     public:
+      explicit DelayedEncoder(Clock* clock) : test::FakeEncoder(clock) {}
+      virtual int32_t Encode(
+          const I420VideoFrame& input_image,
+          const CodecSpecificInfo* codec_specific_info,
+          const std::vector<VideoFrameType>* frame_types) OVERRIDE {
+        // A delay needs to be introduced to assure that we get a timestamp
+        // offset.
+        SleepMs(5);
+        return FakeEncoder::Encode(
+            input_image, codec_specific_info, frame_types);
+      }
+    };
+
+    DelayedEncoder encoder_;
+  } test;
+
+  RunBaseTest(&test);
 }
 
 class FakeReceiveStatistics : public NullReceiveStatistics {
@@ -433,32 +403,31 @@
 
   test::NullTransport transport;
   Call::Config call_config(&transport);
-  scoped_ptr<Call> call(Call::Create(call_config));
+  CreateSenderCall(call_config);
 
-  CreateTestConfig(call.get(), 1);
-  VideoSendStream* video_send_stream =
-      call->CreateVideoSendStream(send_config_, video_streams_, NULL);
-  video_send_stream->Start();
+  CreateSendConfig(1);
+  CreateStreams();
+  send_stream_->Start();
 
   I420VideoFrame frame;
   frame.CreateEmptyFrame(
       kWidth, kHeight, kWidth, (kWidth + 1) / 2, (kWidth + 1) / 2);
   uint8_t* old_y_buffer = frame.buffer(kYPlane);
 
-  video_send_stream->Input()->SwapFrame(&frame);
+  send_stream_->Input()->SwapFrame(&frame);
 
   EXPECT_NE(frame.buffer(kYPlane), old_y_buffer);
 
-  call->DestroyVideoSendStream(video_send_stream);
+  DestroyStreams();
 }
 
 TEST_F(VideoSendStreamTest, SupportsFec) {
   static const int kRedPayloadType = 118;
   static const int kUlpfecPayloadType = 119;
-  class FecObserver : public test::RtpRtcpObserver {
+  class FecObserver : public test::SendTest {
    public:
     FecObserver()
-        : RtpRtcpObserver(30 * 1000),
+        : SendTest(kDefaultTimeoutMs),
           transport_adapter_(SendTransport()),
           send_count_(0),
           received_media_(false),
@@ -466,6 +435,7 @@
       transport_adapter_.Enable();
     }
 
+   private:
     virtual Action OnSendRtp(const uint8_t* packet, size_t length) OVERRIDE {
       RTPHeader header;
       EXPECT_TRUE(parser_->Parse(packet, static_cast<int>(length), &header));
@@ -474,13 +444,13 @@
       if (send_count_++ % 2 != 0) {
         // Receive statistics reporting having lost 50% of the packets.
         FakeReceiveStatistics lossy_receive_stats(
-            kSendSsrc, header.sequenceNumber, send_count_ / 2, 127);
+            kSendSsrcs[0], header.sequenceNumber, send_count_ / 2, 127);
         RTCPSender rtcp_sender(
             0, false, Clock::GetRealTimeClock(), &lossy_receive_stats);
         EXPECT_EQ(0, rtcp_sender.RegisterSendTransport(&transport_adapter_));
 
         rtcp_sender.SetRTCPStatus(kRtcpNonCompound);
-        rtcp_sender.SetRemoteSSRC(kSendSsrc);
+        rtcp_sender.SetRemoteSSRC(kSendSsrcs[0]);
 
         RTCPSender::FeedbackState feedback_state;
 
@@ -503,33 +473,35 @@
       return SEND_PACKET;
     }
 
-   private:
+    virtual void ModifyConfigs(
+        VideoSendStream::Config* send_config,
+        VideoReceiveStream::Config* receive_config,
+        std::vector<VideoStream>* video_streams) OVERRIDE {
+      send_config->rtp.fec.red_payload_type = kRedPayloadType;
+      send_config->rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
+    }
+
+    virtual void PerformTest() OVERRIDE {
+      EXPECT_TRUE(Wait()) << "Timed out waiting for FEC and media packets.";
+    }
+
     internal::TransportAdapter transport_adapter_;
     int send_count_;
     bool received_media_;
     bool received_fec_;
-  } observer;
+  } test;
 
-  Call::Config call_config(observer.SendTransport());
-  scoped_ptr<Call> call(Call::Create(call_config));
-
-  observer.SetReceivers(call->Receiver(), NULL);
-
-  CreateTestConfig(call.get(), 1);
-  send_config_.rtp.fec.red_payload_type = kRedPayloadType;
-  send_config_.rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
-
-  RunSendTest(call.get(), &observer);
+  RunBaseTest(&test);
 }
 
 void VideoSendStreamTest::TestNackRetransmission(
     uint32_t retransmit_ssrc,
     uint8_t retransmit_payload_type) {
-  class NackObserver : public test::RtpRtcpObserver {
+  class NackObserver : public test::SendTest {
    public:
     explicit NackObserver(uint32_t retransmit_ssrc,
                           uint8_t retransmit_payload_type)
-        : RtpRtcpObserver(30 * 1000),
+        : SendTest(kDefaultTimeoutMs),
           transport_adapter_(SendTransport()),
           send_count_(0),
           retransmit_ssrc_(retransmit_ssrc),
@@ -538,6 +510,7 @@
       transport_adapter_.Enable();
     }
 
+   private:
     virtual Action OnSendRtp(const uint8_t* packet, size_t length) OVERRIDE {
       RTPHeader header;
       EXPECT_TRUE(parser_->Parse(packet, static_cast<int>(length), &header));
@@ -552,7 +525,7 @@
         EXPECT_EQ(0, rtcp_sender.RegisterSendTransport(&transport_adapter_));
 
         rtcp_sender.SetRTCPStatus(kRtcpNonCompound);
-        rtcp_sender.SetRemoteSSRC(kSendSsrc);
+        rtcp_sender.SetRemoteSSRC(kSendSsrcs[0]);
 
         RTCPSender::FeedbackState feedback_state;
 
@@ -563,8 +536,10 @@
 
       uint16_t sequence_number = header.sequenceNumber;
 
-      if (header.ssrc == retransmit_ssrc_ && retransmit_ssrc_ != kSendSsrc) {
-        // Not kSendSsrc, assume correct RTX packet. Extract sequence number.
+      if (header.ssrc == retransmit_ssrc_ &&
+          retransmit_ssrc_ != kSendSsrcs[0]) {
+        // Not kSendSsrcs[0], assume correct RTX packet. Extract sequence
+        // number.
         const uint8_t* rtx_header = packet + header.headerLength;
         sequence_number = (rtx_header[0] << 8) + rtx_header[1];
       }
@@ -578,30 +553,34 @@
       return SEND_PACKET;
     }
 
-   private:
+    virtual void ModifyConfigs(
+        VideoSendStream::Config* send_config,
+        VideoReceiveStream::Config* receive_config,
+        std::vector<VideoStream>* video_streams) OVERRIDE {
+      send_config->rtp.nack.rtp_history_ms = 1000;
+      send_config->rtp.rtx.payload_type = retransmit_payload_type_;
+      if (retransmit_ssrc_ != kSendSsrcs[0])
+        send_config->rtp.rtx.ssrcs.push_back(retransmit_ssrc_);
+    }
+
+    virtual void PerformTest() OVERRIDE {
+      EXPECT_EQ(kEventSignaled, Wait())
+          << "Timed out while waiting for NACK retransmission.";
+    }
+
     internal::TransportAdapter transport_adapter_;
     int send_count_;
     uint32_t retransmit_ssrc_;
     uint8_t retransmit_payload_type_;
     int nacked_sequence_number_;
-  } observer(retransmit_ssrc, retransmit_payload_type);
+  } test(retransmit_ssrc, retransmit_payload_type);
 
-  Call::Config call_config(observer.SendTransport());
-  scoped_ptr<Call> call(Call::Create(call_config));
-  observer.SetReceivers(call->Receiver(), NULL);
-
-  CreateTestConfig(call.get(), 1);
-  send_config_.rtp.nack.rtp_history_ms = 1000;
-  send_config_.rtp.rtx.payload_type = retransmit_payload_type;
-  if (retransmit_ssrc != kSendSsrc)
-    send_config_.rtp.rtx.ssrcs.push_back(retransmit_ssrc);
-
-  RunSendTest(call.get(), &observer);
+  RunBaseTest(&test);
 }
 
 TEST_F(VideoSendStreamTest, RetransmitsNack) {
   // Normal NACKs should use the send SSRC.
-  TestNackRetransmission(kSendSsrc, kFakeSendPayloadType);
+  TestNackRetransmission(kSendSsrcs[0], kFakeSendPayloadType);
 }
 
 TEST_F(VideoSendStreamTest, RetransmitsNackOverRtx) {
@@ -611,22 +590,28 @@
 
 void VideoSendStreamTest::TestPacketFragmentationSize(VideoFormat format,
                                                       bool with_fec) {
+  // Use a fake encoder to output a frame of every size in the range [90, 290],
+  // for each size making sure that the exact number of payload bytes received
+  // is correct and that packets are fragmented to respect max packet size.
+  static const uint32_t kMaxPacketSize = 128;
+  static const uint32_t start = 90;
+  static const uint32_t stop = 290;
+
   static const int kRedPayloadType = 118;
   static const int kUlpfecPayloadType = 119;
   // Observer that verifies that the expected number of packets and bytes
   // arrive for each frame size, from start_size to stop_size.
-  class FrameFragmentationObserver : public test::RtpRtcpObserver,
-                                     public EncodedFrameObserver {
+  class FrameFragmentationTest : public test::SendTest,
+                                 public EncodedFrameObserver {
    public:
-    FrameFragmentationObserver(uint32_t max_packet_size,
-                               uint32_t start_size,
-                               uint32_t stop_size,
-                               test::ConfigurableFrameSizeEncoder* encoder,
-                               bool test_generic_packetization,
-                               bool use_fec)
-        : RtpRtcpObserver(120 * 1000),  // Timeout after two minutes.
+    FrameFragmentationTest(uint32_t max_packet_size,
+                           uint32_t start_size,
+                           uint32_t stop_size,
+                           bool test_generic_packetization,
+                           bool use_fec)
+        : SendTest(kLongTimeoutMs),
           transport_adapter_(SendTransport()),
-          encoder_(encoder),
+          encoder_(stop),
           max_packet_size_(max_packet_size),
           stop_size_(stop_size),
           test_generic_packetization_(test_generic_packetization),
@@ -638,10 +623,12 @@
           current_size_rtp_(start_size),
           current_size_frame_(start_size) {
       // Fragmentation required, this test doesn't make sense without it.
+      encoder_.SetFrameSize(start);
       assert(stop_size > max_packet_size);
       transport_adapter_.Enable();
     }
 
+   private:
     virtual Action OnSendRtp(const uint8_t* packet, size_t size) OVERRIDE {
       uint32_t length = static_cast<int>(size);
       RTPHeader header;
@@ -717,13 +704,13 @@
       if (packet_count_++ % 2 != 0) {
         // Receive statistics reporting having lost 50% of the packets.
         FakeReceiveStatistics lossy_receive_stats(
-            kSendSsrc, header.sequenceNumber, packet_count_ / 2, 127);
+            kSendSsrcs[0], header.sequenceNumber, packet_count_ / 2, 127);
         RTCPSender rtcp_sender(
             0, false, Clock::GetRealTimeClock(), &lossy_receive_stats);
         EXPECT_EQ(0, rtcp_sender.RegisterSendTransport(&transport_adapter_));
 
         rtcp_sender.SetRTCPStatus(kRtcpNonCompound);
-        rtcp_sender.SetRemoteSSRC(kSendSsrc);
+        rtcp_sender.SetRemoteSSRC(kSendSsrcs[0]);
 
         RTCPSender::FeedbackState feedback_state;
 
@@ -738,12 +725,39 @@
           current_size_frame_.Value() < static_cast<int32_t>(stop_size_)) {
         ++current_size_frame_;
       }
-      encoder_->SetFrameSize(current_size_frame_.Value());
+      encoder_.SetFrameSize(current_size_frame_.Value());
     }
 
-   private:
+    virtual void ModifyConfigs(
+        VideoSendStream::Config* send_config,
+        VideoReceiveStream::Config* receive_config,
+        std::vector<VideoStream>* video_streams) OVERRIDE {
+      if (use_fec_) {
+        send_config->rtp.fec.red_payload_type = kRedPayloadType;
+        send_config->rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
+      }
+
+      if (!test_generic_packetization_)
+        send_config->encoder_settings.payload_name = "VP8";
+
+      send_config->encoder_settings.encoder = &encoder_;
+      send_config->rtp.max_packet_size = kMaxPacketSize;
+      send_config->post_encode_callback = this;
+
+      // Add an extension header, to make the RTP header larger than the base
+      // length of 12 bytes.
+      static const uint8_t kAbsSendTimeExtensionId = 13;
+      send_config->rtp.extensions.push_back(
+          RtpExtension(RtpExtension::kAbsSendTime, kAbsSendTimeExtensionId));
+    }
+
+    virtual void PerformTest() OVERRIDE {
+      EXPECT_EQ(kEventSignaled, Wait())
+          << "Timed out while observing incoming RTP packets.";
+    }
+
     internal::TransportAdapter transport_adapter_;
-    test::ConfigurableFrameSizeEncoder* const encoder_;
+    test::ConfigurableFrameSizeEncoder encoder_;
 
     const uint32_t max_packet_size_;
     const uint32_t stop_size_;
@@ -759,45 +773,12 @@
     Atomic32 current_size_frame_;
   };
 
-  // Use a fake encoder to output a frame of every size in the range [90, 290],
-  // for each size making sure that the exact number of payload bytes received
-  // is correct and that packets are fragmented to respect max packet size.
-  static const uint32_t kMaxPacketSize = 128;
-  static const uint32_t start = 90;
-  static const uint32_t stop = 290;
-
   // Don't auto increment if FEC is used; continue sending frame size until
   // a FEC packet has been received.
-  test::ConfigurableFrameSizeEncoder encoder(stop);
-  encoder.SetFrameSize(start);
+  FrameFragmentationTest test(
+      kMaxPacketSize, start, stop, format == kGeneric, with_fec);
 
-  FrameFragmentationObserver observer(
-      kMaxPacketSize, start, stop, &encoder, format == kGeneric, with_fec);
-  Call::Config call_config(observer.SendTransport());
-  scoped_ptr<Call> call(Call::Create(call_config));
-
-  observer.SetReceivers(call->Receiver(), NULL);
-
-  CreateTestConfig(call.get(), 1);
-  if (with_fec) {
-    send_config_.rtp.fec.red_payload_type = kRedPayloadType;
-    send_config_.rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
-  }
-
-  if (format == kVP8)
-    send_config_.encoder_settings.payload_name = "VP8";
-
-  send_config_.encoder_settings.encoder = &encoder;
-  send_config_.rtp.max_packet_size = kMaxPacketSize;
-  send_config_.post_encode_callback = &observer;
-
-  // Add an extension header, to make the RTP header larger than the base
-  // length of 12 bytes.
-  static const uint8_t kAbsSendTimeExtensionId = 13;
-  send_config_.rtp.extensions.push_back(
-      RtpExtension(RtpExtension::kAbsSendTime, kAbsSendTimeExtensionId));
-
-  RunSendTest(call.get(), &observer);
+  RunBaseTest(&test);
 }
 
 // TODO(sprang): Is there any way of speeding up these tests?
@@ -829,13 +810,12 @@
 TEST_F(VideoSendStreamTest, SuspendBelowMinBitrate) {
   static const int kSuspendTimeFrames = 60;  // Suspend for 2 seconds @ 30 fps.
 
-  class RembObserver : public test::RtpRtcpObserver, public I420FrameCallback {
+  class RembObserver : public test::SendTest, public I420FrameCallback {
    public:
-    RembObserver(VideoSendStream** send_stream_ptr)
-        : RtpRtcpObserver(30 * 1000),  // Timeout after 30 seconds.
+    RembObserver()
+        : SendTest(kDefaultTimeoutMs),
           transport_adapter_(&transport_),
           clock_(Clock::GetRealTimeClock()),
-          send_stream_ptr_(send_stream_ptr),
           crit_(CriticalSectionWrapper::CreateCriticalSection()),
           test_state_(kBeforeSuspend),
           rtp_count_(0),
@@ -846,10 +826,7 @@
       transport_adapter_.Enable();
     }
 
-    void SetReceiver(PacketReceiver* receiver) {
-      transport_.SetReceiver(receiver);
-    }
-
+   private:
     virtual Action OnSendRtcp(const uint8_t* packet, size_t length) OVERRIDE {
       // Receive statistics reporting having lost 0% of the packets.
       // This is needed for the send-side bitrate controller to work properly.
@@ -882,8 +859,7 @@
           test_state_ = kWaitingForStats;
         }
       } else if (test_state_ == kWaitingForStats) {
-        assert(*send_stream_ptr_);
-        VideoSendStream::Stats stats = (*send_stream_ptr_)->GetStats();
+        VideoSendStream::Stats stats = stream_->GetStats();
         if (stats.suspended == false) {
           // Stats flipped to false. Test is complete.
           observation_complete_->Set();
@@ -898,8 +874,7 @@
       CriticalSectionScoped lock(crit_.get());
       if (test_state_ == kDuringSuspend &&
           ++suspended_frame_count_ > kSuspendTimeFrames) {
-        assert(*send_stream_ptr_);
-        VideoSendStream::Stats stats = (*send_stream_ptr_)->GetStats();
+        VideoSendStream::Stats stats = stream_->GetStats();
         EXPECT_TRUE(stats.suspended);
         SendRtcpFeedback(high_remb_bps_);
         test_state_ = kWaitingForPacket;
@@ -916,9 +891,38 @@
       high_remb_bps_ = value;
     }
 
-    void Stop() { transport_.StopSending(); }
+    virtual void SetReceivers(
+        PacketReceiver* send_transport_receiver,
+        PacketReceiver* receive_transport_receiver) OVERRIDE {
+      transport_.SetReceiver(send_transport_receiver);
+    }
 
-   private:
+    virtual void OnStreamsCreated(VideoSendStream* send_stream,
+                                  VideoReceiveStream* receive_stream) OVERRIDE {
+      stream_ = send_stream;
+    }
+
+    virtual void ModifyConfigs(
+        VideoSendStream::Config* send_config,
+        VideoReceiveStream::Config* receive_config,
+        std::vector<VideoStream>* video_streams) OVERRIDE {
+      send_config->rtp.nack.rtp_history_ms = 1000;
+      send_config->pre_encode_callback = this;
+      send_config->suspend_below_min_bitrate = true;
+      int min_bitrate_bps = (*video_streams)[0].min_bitrate_bps;
+      set_low_remb_bps(min_bitrate_bps - 10000);
+      int threshold_window = std::max(min_bitrate_bps / 10, 10000);
+      ASSERT_GT((*video_streams)[0].max_bitrate_bps,
+                min_bitrate_bps + threshold_window + 5000);
+      set_high_remb_bps(min_bitrate_bps + threshold_window + 5000);
+    }
+
+    virtual void PerformTest() OVERRIDE {
+      EXPECT_EQ(kEventSignaled, Wait())
+          << "Timed out during suspend-below-min-bitrate test.";
+      transport_.StopSending();
+    }
+
     enum TestState {
       kBeforeSuspend,
       kDuringSuspend,
@@ -929,12 +933,12 @@
     virtual void SendRtcpFeedback(int remb_value)
         EXCLUSIVE_LOCKS_REQUIRED(crit_) {
       FakeReceiveStatistics receive_stats(
-          kSendSsrc, last_sequence_number_, rtp_count_, 0);
+          kSendSsrcs[0], last_sequence_number_, rtp_count_, 0);
       RTCPSender rtcp_sender(0, false, clock_, &receive_stats);
       EXPECT_EQ(0, rtcp_sender.RegisterSendTransport(&transport_adapter_));
 
       rtcp_sender.SetRTCPStatus(kRtcpNonCompound);
-      rtcp_sender.SetRemoteSSRC(kSendSsrc);
+      rtcp_sender.SetRemoteSSRC(kSendSsrcs[0]);
       if (remb_value > 0) {
         rtcp_sender.SetREMBStatus(true);
         rtcp_sender.SetREMBData(remb_value, 0, NULL);
@@ -946,7 +950,7 @@
     internal::TransportAdapter transport_adapter_;
     test::DirectTransport transport_;
     Clock* const clock_;
-    VideoSendStream** const send_stream_ptr_;
+    VideoSendStream* stream_;
 
     const scoped_ptr<CriticalSectionWrapper> crit_;
     TestState test_state_ GUARDED_BY(crit_);
@@ -955,34 +959,16 @@
     int suspended_frame_count_ GUARDED_BY(crit_);
     int low_remb_bps_ GUARDED_BY(crit_);
     int high_remb_bps_ GUARDED_BY(crit_);
-  } observer(&send_stream_);
-  // Note that |send_stream_| is created in RunSendTest(), called below. This
-  // is why a pointer to |send_stream_| must be provided here.
+  } test;
 
-  Call::Config call_config(observer.SendTransport());
-  scoped_ptr<Call> call(Call::Create(call_config));
-  observer.SetReceiver(call->Receiver());
-
-  CreateTestConfig(call.get(), 1);
-  send_config_.rtp.nack.rtp_history_ms = 1000;
-  send_config_.pre_encode_callback = &observer;
-  send_config_.suspend_below_min_bitrate = true;
-  int min_bitrate_bps = video_streams_[0].min_bitrate_bps;
-  observer.set_low_remb_bps(min_bitrate_bps - 10000);
-  int threshold_window = std::max(min_bitrate_bps / 10, 10000);
-  ASSERT_GT(video_streams_[0].max_bitrate_bps,
-            min_bitrate_bps + threshold_window + 5000);
-  observer.set_high_remb_bps(min_bitrate_bps + threshold_window + 5000);
-
-  RunSendTest(call.get(), &observer);
-  observer.Stop();
+  RunBaseTest(&test);
 }
 
 TEST_F(VideoSendStreamTest, NoPaddingWhenVideoIsMuted) {
-  class PacketObserver : public test::RtpRtcpObserver {
+  class NoPaddingWhenVideoIsMuted : public test::SendTest {
    public:
-    PacketObserver()
-        : RtpRtcpObserver(30 * 1000),  // Timeout after 30 seconds.
+    NoPaddingWhenVideoIsMuted()
+        : SendTest(kDefaultTimeoutMs),
           clock_(Clock::GetRealTimeClock()),
           transport_adapter_(ReceiveTransport()),
           crit_(CriticalSectionWrapper::CreateCriticalSection()),
@@ -991,11 +977,7 @@
       transport_adapter_.Enable();
     }
 
-    void SetCapturer(test::FrameGeneratorCapturer* capturer) {
-      CriticalSectionScoped lock(crit_.get());
-      capturer_ = capturer;
-    }
-
+   private:
     virtual Action OnSendRtp(const uint8_t* packet, size_t length) OVERRIDE {
       CriticalSectionScoped lock(crit_.get());
       last_packet_time_ms_ = clock_->TimeInMilliseconds();
@@ -1025,46 +1007,43 @@
       return SEND_PACKET;
     }
 
-   private:
+    virtual void SetReceivers(
+        PacketReceiver* send_transport_receiver,
+        PacketReceiver* receive_transport_receiver) OVERRIDE {
+      RtpRtcpObserver::SetReceivers(send_transport_receiver,
+                                    send_transport_receiver);
+    }
+
+    virtual size_t GetNumStreams() const OVERRIDE { return 3; }
+
+    virtual void OnFrameGeneratorCapturerCreated(
+        test::FrameGeneratorCapturer* frame_generator_capturer) {
+      CriticalSectionScoped lock(crit_.get());
+      capturer_ = frame_generator_capturer;
+    }
+
+    virtual void PerformTest() OVERRIDE {
+      EXPECT_EQ(kEventSignaled, Wait())
+          << "Timed out while waiting for RTP packets to stop being sent.";
+    }
+
     Clock* const clock_;
     internal::TransportAdapter transport_adapter_;
     const scoped_ptr<CriticalSectionWrapper> crit_;
     int64_t last_packet_time_ms_ GUARDED_BY(crit_);
     test::FrameGeneratorCapturer* capturer_ GUARDED_BY(crit_);
-  } observer;
+  } test;
 
-  Call::Config call_config(observer.SendTransport());
-  scoped_ptr<Call> call(Call::Create(call_config));
-  observer.SetReceivers(call->Receiver(), call->Receiver());
-
-  CreateTestConfig(call.get(), 3);
-
-  send_stream_ =
-      call->CreateVideoSendStream(send_config_, video_streams_, NULL);
-  scoped_ptr<test::FrameGeneratorCapturer> frame_generator_capturer(
-      test::FrameGeneratorCapturer::Create(
-          send_stream_->Input(), 320, 240, 30, Clock::GetRealTimeClock()));
-  observer.SetCapturer(frame_generator_capturer.get());
-  send_stream_->Start();
-  frame_generator_capturer->Start();
-
-  EXPECT_EQ(kEventSignaled, observer.Wait())
-      << "Timed out while waiting for RTP packets to stop being sent.";
-
-  observer.StopSending();
-  frame_generator_capturer->Stop();
-  send_stream_->Stop();
-  call->DestroyVideoSendStream(send_stream_);
+  RunBaseTest(&test);
 }
 
 TEST_F(VideoSendStreamTest, ProducesStats) {
   static const std::string kCName =
       "PjQatC14dGfbVwGPUOA9IH7RlsFDbWl4AhXEiDsBizo=";
-  static const uint32_t kTimeoutMs = 30 * 1000;
-  class StatsObserver : public test::RtpRtcpObserver {
+  class ProducesStats : public test::SendTest {
    public:
-    StatsObserver()
-        : RtpRtcpObserver(kTimeoutMs),
+    ProducesStats()
+        : SendTest(kDefaultTimeoutMs),
           stream_(NULL),
           event_(EventWrapper::Create()) {}
 
@@ -1074,10 +1053,11 @@
       return SEND_PACKET;
     }
 
+   private:
     bool WaitForFilledStats() {
       Clock* clock = Clock::GetRealTimeClock();
       int64_t now = clock->TimeInMilliseconds();
-      int64_t stop_time = now + kTimeoutMs;
+      int64_t stop_time = now + kDefaultTimeoutMs;
       while (now < stop_time) {
         int64_t time_left = stop_time - now;
         if (time_left > 0 && event_->Wait(time_left) == kEventSignaled &&
@@ -1113,36 +1093,30 @@
 
     void SetConfig(const VideoSendStream::Config& config) { config_ = config; }
 
-    void SetSendStream(VideoSendStream* stream) { stream_ = stream; }
+    virtual void ModifyConfigs(
+        VideoSendStream::Config* send_config,
+        VideoReceiveStream::Config* receive_config,
+        std::vector<VideoStream>* video_streams) OVERRIDE {
+      send_config->rtp.c_name = kCName;
+      SetConfig(*send_config);
+    }
+
+    virtual void OnStreamsCreated(VideoSendStream* send_stream,
+                                  VideoReceiveStream* receive_stream) OVERRIDE {
+      stream_ = send_stream;
+    }
+
+    virtual void PerformTest() OVERRIDE {
+      EXPECT_TRUE(WaitForFilledStats())
+          << "Timed out waiting for filled statistics.";
+    }
 
     VideoSendStream* stream_;
     VideoSendStream::Config config_;
     scoped_ptr<EventWrapper> event_;
-  } observer;
+  } test;
 
-  Call::Config call_config(observer.SendTransport());
-  scoped_ptr<Call> call(Call::Create(call_config));
-
-  CreateTestConfig(call.get(), 1);
-  send_config_.rtp.c_name = kCName;
-  observer.SetConfig(send_config_);
-
-  send_stream_ =
-      call->CreateVideoSendStream(send_config_, video_streams_, NULL);
-  observer.SetSendStream(send_stream_);
-  scoped_ptr<test::FrameGeneratorCapturer> frame_generator_capturer(
-      test::FrameGeneratorCapturer::Create(
-          send_stream_->Input(), 320, 240, 30, Clock::GetRealTimeClock()));
-  send_stream_->Start();
-  frame_generator_capturer->Start();
-
-  EXPECT_TRUE(observer.WaitForFilledStats())
-      << "Timed out waiting for filled statistics.";
-
-  observer.StopSending();
-  frame_generator_capturer->Stop();
-  send_stream_->Stop();
-  call->DestroyVideoSendStream(send_stream_);
+  RunBaseTest(&test);
 }
 
 // This test first observes "high" bitrate use at which point it sends a REMB to
@@ -1157,12 +1131,11 @@
   static const int kHighBitrateBps = 150000;
   static const int kRembBitrateBps = 80000;
   static const int kRembRespectedBitrateBps = 100000;
-  class BitrateObserver: public test::RtpRtcpObserver, public PacketReceiver {
+  class BitrateObserver : public test::SendTest, public PacketReceiver {
    public:
     BitrateObserver()
-        : RtpRtcpObserver(30 * 1000),
+        : SendTest(kDefaultTimeoutMs),
           feedback_transport_(ReceiveTransport()),
-          send_stream_(NULL),
           bitrate_capped_(false) {
       RtpRtcp::Configuration config;
       feedback_transport_.Enable();
@@ -1172,8 +1145,9 @@
       rtp_rtcp_->SetRTCPStatus(kRtcpNonCompound);
     }
 
-    void SetSendStream(VideoSendStream* send_stream) {
-      send_stream_ = send_stream;
+    virtual void OnStreamsCreated(VideoSendStream* send_stream,
+                                  VideoReceiveStream* receive_stream) OVERRIDE {
+      stream_ = send_stream;
     }
 
    private:
@@ -1185,8 +1159,8 @@
       RTPHeader header;
       if (!parser_->Parse(packet, static_cast<int>(length), &header))
         return DELIVERY_PACKET_ERROR;
-      assert(send_stream_ != NULL);
-      VideoSendStream::Stats stats = send_stream_->GetStats();
+      assert(stream_ != NULL);
+      VideoSendStream::Stats stats = stream_->GetStats();
       if (!stats.substreams.empty()) {
         EXPECT_EQ(1u, stats.substreams.size());
         int bitrate_bps = stats.substreams.begin()->second.bitrate_bps;
@@ -1209,35 +1183,31 @@
       return DELIVERY_OK;
     }
 
+    virtual void SetReceivers(
+        PacketReceiver* send_transport_receiver,
+        PacketReceiver* receive_transport_receiver) OVERRIDE {
+      RtpRtcpObserver::SetReceivers(this, send_transport_receiver);
+    }
+
+    virtual void ModifyConfigs(
+        VideoSendStream::Config* send_config,
+        VideoReceiveStream::Config* receive_config,
+        std::vector<VideoStream>* video_streams) OVERRIDE {
+      send_config->rtp.min_transmit_bitrate_bps = kMinTransmitBitrateBps;
+    }
+
+    virtual void PerformTest() OVERRIDE {
+      EXPECT_EQ(kEventSignaled, Wait())
+          << "Timeout while waiting for low bitrate stats after REMB.";
+    }
+
     scoped_ptr<RtpRtcp> rtp_rtcp_;
     internal::TransportAdapter feedback_transport_;
-    VideoSendStream* send_stream_;
+    VideoSendStream* stream_;
     bool bitrate_capped_;
-  } observer;
+  } test;
 
-  Call::Config call_config(observer.SendTransport());
-  scoped_ptr<Call> call(Call::Create(call_config));
-  observer.SetReceivers(&observer, call->Receiver());
-
-  CreateTestConfig(call.get(), 1);
-  send_config_.rtp.min_transmit_bitrate_bps = kMinTransmitBitrateBps;
-  send_stream_ =
-      call->CreateVideoSendStream(send_config_, video_streams_, NULL);
-  observer.SetSendStream(send_stream_);
-
-  scoped_ptr<test::FrameGeneratorCapturer> frame_generator_capturer(
-      test::FrameGeneratorCapturer::Create(
-          send_stream_->Input(), 320, 240, 30, Clock::GetRealTimeClock()));
-  send_stream_->Start();
-  frame_generator_capturer->Start();
-
-  EXPECT_EQ(kEventSignaled, observer.Wait())
-      << "Timeout while waiting for low bitrate stats after REMB.";
-
-  observer.StopSending();
-  frame_generator_capturer->Stop();
-  send_stream_->Stop();
-  call->DestroyVideoSendStream(send_stream_);
+  RunBaseTest(&test);
 }
 
 TEST_F(VideoSendStreamTest, CapturesTextureAndI420VideoFrames) {
@@ -1271,13 +1241,12 @@
 
   // Initialize send stream.
   test::NullTransport transport;
-  Call::Config call_config(&transport);
-  scoped_ptr<Call> call(Call::Create(call_config));
-  CreateTestConfig(call.get(), 1);
+  CreateSenderCall(Call::Config(&transport));
+
+  CreateSendConfig(1);
   FrameObserver observer;
   send_config_.pre_encode_callback = &observer;
-  send_stream_ =
-      call->CreateVideoSendStream(send_config_, video_streams_, NULL);
+  CreateStreams();
 
   // Prepare five input frames. Send I420VideoFrame and TextureVideoFrame
   // alternatively.
@@ -1314,7 +1283,7 @@
   // timestamp are not compared because capturer sets those values.
   ExpectEqualFramesVector(input_frames.get(), observer.output_frames());
 
-  call->DestroyVideoSendStream(send_stream_);
+  DestroyStreams();
 }
 
 void ExpectEqualFrames(const I420VideoFrame& frame1,
diff --git a/webrtc/webrtc_tests.gypi b/webrtc/webrtc_tests.gypi
index 3c1dca6..85a7e73 100644
--- a/webrtc/webrtc_tests.gypi
+++ b/webrtc/webrtc_tests.gypi
@@ -46,7 +46,7 @@
       'type': '<(gtest_target_type)',
       'sources': [
         'video/bitrate_estimator_tests.cc',
-        'video/call_tests.cc',
+        'video/end_to_end_tests.cc',
         'video/send_statistics_proxy_unittest.cc',
         'video/video_send_stream_tests.cc',
         'test/common_unittest.cc',