RTP video playback tool using Call APIs.

Plays back rtpdump files from Wireshark in realtime as well as save the
resulting raw video to file. Unlike the RTP playback tool it doesn't
support faster-than-realtime playback/rendering, but it instead utilizes
the same path as production code and also contains support for playing
back FEC.

BUG=
R=stefan@webrtc.org

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

git-svn-id: http://webrtc.googlecode.com/svn/trunk@6838 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/webrtc/modules/modules.gyp b/webrtc/modules/modules.gyp
index 10a1860..b8aa55b 100644
--- a/webrtc/modules/modules.gyp
+++ b/webrtc/modules/modules.gyp
@@ -242,10 +242,6 @@
             'video_coding/main/source/qm_select_unittest.cc',
             'video_coding/main/source/test/stream_generator.cc',
             'video_coding/main/source/test/stream_generator.h',
-            'video_coding/main/test/pcap_file_reader.cc',
-            'video_coding/main/test/pcap_file_reader_unittest.cc',
-            'video_coding/main/test/rtp_file_reader.cc',
-            'video_coding/main/test/rtp_file_reader_unittest.cc',
             'video_processing/main/test/unit_test/brightness_detection_test.cc',
             'video_processing/main/test/unit_test/color_enhancement_test.cc',
             'video_processing/main/test/unit_test/content_metrics_test.cc',
diff --git a/webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimator.gypi b/webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimator.gypi
index c2f1b3d..f290a34 100644
--- a/webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimator.gypi
+++ b/webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimator.gypi
@@ -56,8 +56,8 @@
       },
       'sources': [
         'tools/rtp_to_text.cc',
-        '<(webrtc_root)/modules/video_coding/main/test/rtp_file_reader.cc',
-        '<(webrtc_root)/modules/video_coding/main/test/rtp_file_reader.h',
+        '<(webrtc_root)/test/rtp_file_reader.cc',
+        '<(webrtc_root)/test/rtp_file_reader.h',
       ], # source
     },
     {
@@ -79,8 +79,8 @@
       },
       'sources': [
         'tools/bwe_rtp_play.cc',
-        '<(webrtc_root)/modules/video_coding/main/test/rtp_file_reader.cc',
-        '<(webrtc_root)/modules/video_coding/main/test/rtp_file_reader.h',
+        '<(webrtc_root)/test/rtp_file_reader.cc',
+        '<(webrtc_root)/test/rtp_file_reader.h',
       ], # source
     },
   ], # targets
diff --git a/webrtc/modules/remote_bitrate_estimator/tools/bwe_rtp.cc b/webrtc/modules/remote_bitrate_estimator/tools/bwe_rtp.cc
index 40fa6df..e71c75c 100644
--- a/webrtc/modules/remote_bitrate_estimator/tools/bwe_rtp.cc
+++ b/webrtc/modules/remote_bitrate_estimator/tools/bwe_rtp.cc
@@ -16,10 +16,7 @@
 #include "webrtc/modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h"
 #include "webrtc/modules/rtp_rtcp/interface/rtp_header_parser.h"
 #include "webrtc/modules/rtp_rtcp/interface/rtp_payload_registry.h"
-#include "webrtc/modules/video_coding/main/test/rtp_file_reader.h"
-#include "webrtc/modules/video_coding/main/test/rtp_player.h"
-
-using webrtc::rtpplayer::RtpPacketSourceInterface;
+#include "webrtc/test/rtp_file_reader.h"
 
 const int kMinBitrateBps = 30000;
 
@@ -27,11 +24,12 @@
                                 char** argv,
                                 webrtc::Clock* clock,
                                 webrtc::RemoteBitrateObserver* observer,
-                                RtpPacketSourceInterface** rtp_reader,
+                                webrtc::test::RtpFileReader** rtp_reader,
                                 webrtc::RtpHeaderParser** parser,
                                 webrtc::RemoteBitrateEstimator** estimator,
                                 std::string* estimator_used) {
-  *rtp_reader = webrtc::rtpplayer::CreateRtpFileReader(argv[3]);
+  *rtp_reader = webrtc::test::RtpFileReader::Create(
+      webrtc::test::RtpFileReader::kRtpDump, argv[3]);
   if (!*rtp_reader) {
     fprintf(stderr, "Cannot open input file %s\n", argv[3]);
     return false;
diff --git a/webrtc/modules/remote_bitrate_estimator/tools/bwe_rtp.h b/webrtc/modules/remote_bitrate_estimator/tools/bwe_rtp.h
index 714457d..2d12a80 100644
--- a/webrtc/modules/remote_bitrate_estimator/tools/bwe_rtp.h
+++ b/webrtc/modules/remote_bitrate_estimator/tools/bwe_rtp.h
@@ -18,8 +18,8 @@
 class RemoteBitrateEstimator;
 class RemoteBitrateObserver;
 class RtpHeaderParser;
-namespace rtpplayer {
-class RtpPacketSourceInterface;
+namespace test {
+class RtpFileReader;
 }
 }
 
@@ -28,7 +28,7 @@
     char** argv,
     webrtc::Clock* clock,
     webrtc::RemoteBitrateObserver* observer,
-    webrtc::rtpplayer::RtpPacketSourceInterface** rtp_reader,
+    webrtc::test::RtpFileReader** rtp_reader,
     webrtc::RtpHeaderParser** parser,
     webrtc::RemoteBitrateEstimator** estimator,
     std::string* estimator_used);
diff --git a/webrtc/modules/remote_bitrate_estimator/tools/bwe_rtp_play.cc b/webrtc/modules/remote_bitrate_estimator/tools/bwe_rtp_play.cc
index 9ea3f08..eb224f2 100644
--- a/webrtc/modules/remote_bitrate_estimator/tools/bwe_rtp_play.cc
+++ b/webrtc/modules/remote_bitrate_estimator/tools/bwe_rtp_play.cc
@@ -14,11 +14,8 @@
 #include "webrtc/modules/remote_bitrate_estimator/tools/bwe_rtp.h"
 #include "webrtc/modules/rtp_rtcp/interface/rtp_header_parser.h"
 #include "webrtc/modules/rtp_rtcp/interface/rtp_payload_registry.h"
-#include "webrtc/modules/video_coding/main/test/rtp_file_reader.h"
-#include "webrtc/modules/video_coding/main/test/rtp_player.h"
 #include "webrtc/system_wrappers/interface/scoped_ptr.h"
-
-using webrtc::rtpplayer::RtpPacketSourceInterface;
+#include "webrtc/test/rtp_file_reader.h"
 
 class Observer : public webrtc::RemoteBitrateObserver {
  public:
@@ -49,7 +46,7 @@
            "<extension id> is the id associated with the extension.\n");
     return -1;
   }
-  RtpPacketSourceInterface* reader;
+  webrtc::test::RtpFileReader* reader;
   webrtc::RemoteBitrateEstimator* estimator;
   webrtc::RtpHeaderParser* parser;
   std::string estimator_used;
@@ -59,7 +56,7 @@
                                   &parser, &estimator, &estimator_used)) {
     return -1;
   }
-  webrtc::scoped_ptr<RtpPacketSourceInterface> rtp_reader(reader);
+  webrtc::scoped_ptr<webrtc::test::RtpFileReader> rtp_reader(reader);
   webrtc::scoped_ptr<webrtc::RtpHeaderParser> rtp_parser(parser);
   webrtc::scoped_ptr<webrtc::RemoteBitrateEstimator> rbe(estimator);
 
@@ -68,30 +65,25 @@
   int64_t next_process_time_ms = 0;
   int64_t next_rtp_time_ms = 0;
   int64_t first_rtp_time_ms = -1;
-  const uint32_t kMaxPacketSize = 1500;
-  uint8_t packet_buffer[kMaxPacketSize];
-  uint8_t* packet = packet_buffer;
   int non_zero_abs_send_time = 0;
   int non_zero_ts_offsets = 0;
   while (true) {
-    uint32_t next_rtp_time;
     if (next_rtp_time_ms <= clock.TimeInMilliseconds()) {
-      uint32_t packet_length = kMaxPacketSize;
-      if (rtp_reader->NextPacket(packet, &packet_length,
-                                 &next_rtp_time) == -1) {
+      webrtc::test::RtpFileReader::Packet packet;
+      if (!rtp_reader->NextPacket(&packet)) {
         break;
       }
       if (first_rtp_time_ms == -1)
-        first_rtp_time_ms = next_rtp_time;
-      next_rtp_time_ms = next_rtp_time - first_rtp_time_ms;
+        first_rtp_time_ms = packet.time_ms;
+      packet.time_ms = packet.time_ms - first_rtp_time_ms;
       webrtc::RTPHeader header;
-      parser->Parse(packet, packet_length, &header);
+      parser->Parse(packet.data, packet.length, &header);
       if (header.extension.absoluteSendTime != 0)
         ++non_zero_abs_send_time;
       if (header.extension.transmissionTimeOffset != 0)
         ++non_zero_ts_offsets;
       rbe->IncomingPacket(clock.TimeInMilliseconds(),
-                          packet_length - header.headerLength,
+                          static_cast<int>(packet.length - header.headerLength),
                           header);
       ++packet_counter;
     }
diff --git a/webrtc/modules/remote_bitrate_estimator/tools/rtp_to_text.cc b/webrtc/modules/remote_bitrate_estimator/tools/rtp_to_text.cc
index af4a4d4..a85bca4 100644
--- a/webrtc/modules/remote_bitrate_estimator/tools/rtp_to_text.cc
+++ b/webrtc/modules/remote_bitrate_estimator/tools/rtp_to_text.cc
@@ -14,11 +14,8 @@
 #include "webrtc/modules/remote_bitrate_estimator/tools/bwe_rtp.h"
 #include "webrtc/modules/rtp_rtcp/interface/rtp_header_parser.h"
 #include "webrtc/modules/rtp_rtcp/interface/rtp_payload_registry.h"
-#include "webrtc/modules/video_coding/main/test/rtp_file_reader.h"
-#include "webrtc/modules/video_coding/main/test/rtp_player.h"
 #include "webrtc/system_wrappers/interface/scoped_ptr.h"
-
-using webrtc::rtpplayer::RtpPacketSourceInterface;
+#include "webrtc/test/rtp_file_reader.h"
 
 int main(int argc, char** argv) {
   if (argc < 4) {
@@ -32,43 +29,44 @@
            " output.\n");
     return -1;
   }
-  RtpPacketSourceInterface* reader;
+  webrtc::test::RtpFileReader* reader;
   webrtc::RtpHeaderParser* parser;
   if (!ParseArgsAndSetupEstimator(argc, argv, NULL, NULL, &reader, &parser,
                                   NULL, NULL)) {
     return -1;
   }
   bool arrival_time_only = (argc >= 5 && strncmp(argv[4], "-t", 2) == 0);
-  webrtc::scoped_ptr<RtpPacketSourceInterface> rtp_reader(reader);
+  webrtc::scoped_ptr<webrtc::test::RtpFileReader> rtp_reader(reader);
   webrtc::scoped_ptr<webrtc::RtpHeaderParser> rtp_parser(parser);
   fprintf(stdout, "seqnum timestamp ts_offset abs_sendtime recvtime "
           "markerbit ssrc size\n");
   int packet_counter = 0;
-  static const uint32_t kMaxPacketSize = 1500;
-  uint8_t packet_buffer[kMaxPacketSize];
-  uint8_t* packet = packet_buffer;
-  uint32_t packet_length = kMaxPacketSize;
-  uint32_t time_ms = 0;
   int non_zero_abs_send_time = 0;
   int non_zero_ts_offsets = 0;
-  while (rtp_reader->NextPacket(packet, &packet_length, &time_ms) == 0) {
+  webrtc::test::RtpFileReader::Packet packet;
+  while (rtp_reader->NextPacket(&packet)) {
     webrtc::RTPHeader header;
-    parser->Parse(packet, packet_length, &header);
+    parser->Parse(packet.data, packet.length, &header);
     if (header.extension.absoluteSendTime != 0)
       ++non_zero_abs_send_time;
     if (header.extension.transmissionTimeOffset != 0)
       ++non_zero_ts_offsets;
     if (arrival_time_only) {
       std::stringstream ss;
-      ss << static_cast<int64_t>(time_ms) * 1000000;
+      ss << static_cast<int64_t>(packet.time_ms) * 1000000;
       fprintf(stdout, "%s\n", ss.str().c_str());
     } else {
-      fprintf(stdout, "%u %u %d %u %u %d %u %u\n", header.sequenceNumber,
-              header.timestamp, header.extension.transmissionTimeOffset,
-              header.extension.absoluteSendTime, time_ms, header.markerBit,
-              header.ssrc, packet_length);
+      fprintf(stdout,
+              "%u %u %d %u %u %d %u %d\n",
+              header.sequenceNumber,
+              header.timestamp,
+              header.extension.transmissionTimeOffset,
+              header.extension.absoluteSendTime,
+              packet.time_ms,
+              header.markerBit,
+              header.ssrc,
+              static_cast<int>(packet.length));
     }
-    packet_length = kMaxPacketSize;
     ++packet_counter;
   }
   fprintf(stderr, "Parsed %d packets\n", packet_counter);
diff --git a/webrtc/modules/video_coding/main/source/video_coding_test.gypi b/webrtc/modules/video_coding/main/source/video_coding_test.gypi
index b0fe510..576524d 100644
--- a/webrtc/modules/video_coding/main/source/video_coding_test.gypi
+++ b/webrtc/modules/video_coding/main/source/video_coding_test.gypi
@@ -21,6 +21,7 @@
          '<(webrtc_root)/test/metrics.gyp:metrics',
          '<(webrtc_root)/common_video/common_video.gyp:common_video',
          '<(webrtc_root)/system_wrappers/source/system_wrappers.gyp:field_trial_default',
+         '<(webrtc_root)/test/webrtc_test_common.gyp:webrtc_test_common',
       ],
       'sources': [
         # headers
@@ -30,11 +31,9 @@
         '../test/media_opt_test.h',
         '../test/mt_test_common.h',
         '../test/normal_test.h',
-        '../test/pcap_file_reader.h',
         '../test/quality_modes_test.h',
         '../test/receiver_tests.h',
         '../test/release_test.h',
-        '../test/rtp_file_reader.h',
         '../test/rtp_player.h',
         '../test/test_callbacks.h',
         '../test/test_util.h',
@@ -48,9 +47,7 @@
         '../test/mt_test_common.cc',
         '../test/mt_rx_tx_test.cc',
         '../test/normal_test.cc',
-        '../test/pcap_file_reader.cc',
         '../test/quality_modes_test.cc',
-        '../test/rtp_file_reader.cc',
         '../test/rtp_player.cc',
         '../test/test_callbacks.cc',
         '../test/test_util.cc',
diff --git a/webrtc/modules/video_coding/main/test/pcap_file_reader.h b/webrtc/modules/video_coding/main/test/pcap_file_reader.h
deleted file mode 100644
index 6450e2d..0000000
--- a/webrtc/modules/video_coding/main/test/pcap_file_reader.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- *  Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
- *
- *  Use of this source code is governed by a BSD-style license
- *  that can be found in the LICENSE file in the root of the source
- *  tree. An additional intellectual property rights grant can be found
- *  in the file PATENTS.  All contributing project authors may
- *  be found in the AUTHORS file in the root of the source tree.
- */
-
-#ifndef WEBRTC_MODULES_VIDEO_CODING_TEST_PCAP_FILE_READER_H_
-#define WEBRTC_MODULES_VIDEO_CODING_TEST_PCAP_FILE_READER_H_
-
-#include <string>
-
-namespace webrtc {
-namespace rtpplayer {
-
-class RtpPacketSourceInterface;
-
-RtpPacketSourceInterface* CreatePcapFileReader(const std::string& filename);
-
-}  // namespace rtpplayer
-}  // namespace webrtc
-
-#endif  // WEBRTC_MODULES_VIDEO_CODING_TEST_PCAP_FILE_READER_H_
diff --git a/webrtc/modules/video_coding/main/test/rtp_file_reader.cc b/webrtc/modules/video_coding/main/test/rtp_file_reader.cc
deleted file mode 100644
index 447eb9b..0000000
--- a/webrtc/modules/video_coding/main/test/rtp_file_reader.cc
+++ /dev/null
@@ -1,166 +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 "webrtc/modules/video_coding/main/test/rtp_file_reader.h"
-
-#ifdef WIN32
-#include <windows.h>
-#include <Winsock2.h>
-#else
-#include <arpa/inet.h>
-#endif
-#include <assert.h>
-#include <stdio.h>
-
-#include "webrtc/modules/video_coding/main/test/rtp_player.h"
-#include "webrtc/system_wrappers/interface/scoped_ptr.h"
-
-namespace webrtc {
-namespace rtpplayer {
-
-enum {
-  kResultFail = -1,
-  kResultSuccess = 0,
-
-  kFirstLineLength = 40,    // More than needed to read the ID line.
-  kPacketHeaderSize = 8     // Rtpplay packet header size in bytes.
-};
-
-#if 1
-# define DEBUG_LOG(text)
-# define DEBUG_LOG1(text, arg)
-#else
-# define DEBUG_LOG(text) (printf(text "\n"))
-# define DEBUG_LOG1(text, arg) (printf(text "\n", arg))
-#endif
-
-#define TRY(expr)                                      \
-  do {                                                 \
-    if ((expr) < 0) {                                  \
-      DEBUG_LOG1("FAIL at " __FILE__ ":%d", __LINE__);       \
-      return kResultFail;                                       \
-    }                                                  \
-  } while (0)
-
-// Read RTP packets from file in rtpdump format, as documented at:
-// http://www.cs.columbia.edu/irt/software/rtptools/
-class RtpFileReaderImpl : public RtpPacketSourceInterface {
- public:
-  RtpFileReaderImpl() : file_(NULL) {}
-  virtual ~RtpFileReaderImpl() {
-    if (file_ != NULL) {
-      fclose(file_);
-      file_ = NULL;
-    }
-  }
-
-  int Initialize(const std::string& filename) {
-    file_ = fopen(filename.c_str(), "rb");
-    if (file_ == NULL) {
-      printf("ERROR: Can't open file: %s\n", filename.c_str());
-      return kResultFail;
-    }
-
-    char firstline[kFirstLineLength + 1] = {0};
-    if (fgets(firstline, kFirstLineLength, file_) == NULL) {
-      DEBUG_LOG("ERROR: Can't read from file\n");
-      return kResultFail;
-    }
-    if (strncmp(firstline, "#!rtpplay", 9) == 0) {
-      if (strncmp(firstline, "#!rtpplay1.0", 12) != 0) {
-        DEBUG_LOG("ERROR: wrong rtpplay version, must be 1.0\n");
-        return kResultFail;
-      }
-    } else if (strncmp(firstline, "#!RTPencode", 11) == 0) {
-      if (strncmp(firstline, "#!RTPencode1.0", 14) != 0) {
-        DEBUG_LOG("ERROR: wrong RTPencode version, must be 1.0\n");
-        return kResultFail;
-      }
-    } else {
-      DEBUG_LOG("ERROR: wrong file format of input file\n");
-      return kResultFail;
-    }
-
-    uint32_t start_sec;
-    uint32_t start_usec;
-    uint32_t source;
-    uint16_t port;
-    uint16_t padding;
-    TRY(Read(&start_sec));
-    TRY(Read(&start_usec));
-    TRY(Read(&source));
-    TRY(Read(&port));
-    TRY(Read(&padding));
-
-    return kResultSuccess;
-  }
-
-  virtual int NextPacket(uint8_t* rtp_data, uint32_t* length,
-                         uint32_t* time_ms) {
-    assert(rtp_data);
-    assert(length);
-    assert(time_ms);
-
-    uint16_t len;
-    uint16_t plen;
-    uint32_t offset;
-    TRY(Read(&len));
-    TRY(Read(&plen));
-    TRY(Read(&offset));
-
-    // Use 'len' here because a 'plen' of 0 specifies rtcp.
-    len -= kPacketHeaderSize;
-    if (*length < len) {
-      return kResultFail;
-    }
-    if (fread(rtp_data, 1, len, file_) != len) {
-      return kResultFail;
-    }
-
-    *length = len;
-    *time_ms = offset;
-    return kResultSuccess;
-  }
-
- private:
-  int Read(uint32_t* out) {
-    assert(out);
-    uint32_t tmp = 0;
-    if (fread(&tmp, 1, sizeof(uint32_t), file_) != sizeof(uint32_t)) {
-      return kResultFail;
-    }
-    *out = ntohl(tmp);
-    return kResultSuccess;
-  }
-
-  int Read(uint16_t* out) {
-    assert(out);
-    uint16_t tmp = 0;
-    if (fread(&tmp, 1, sizeof(uint16_t), file_) != sizeof(uint16_t)) {
-      return kResultFail;
-    }
-    *out = ntohs(tmp);
-    return kResultSuccess;
-  }
-
-  FILE* file_;
-
-  DISALLOW_COPY_AND_ASSIGN(RtpFileReaderImpl);
-};
-
-RtpPacketSourceInterface* CreateRtpFileReader(const std::string& filename) {
-  scoped_ptr<RtpFileReaderImpl> impl(new RtpFileReaderImpl());
-  if (impl->Initialize(filename) != 0) {
-    return NULL;
-  }
-  return impl.release();
-}
-}  // namespace rtpplayer
-}  // namespace webrtc
diff --git a/webrtc/modules/video_coding/main/test/rtp_file_reader.h b/webrtc/modules/video_coding/main/test/rtp_file_reader.h
deleted file mode 100644
index b763ee7..0000000
--- a/webrtc/modules/video_coding/main/test/rtp_file_reader.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- *  Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
- *
- *  Use of this source code is governed by a BSD-style license
- *  that can be found in the LICENSE file in the root of the source
- *  tree. An additional intellectual property rights grant can be found
- *  in the file PATENTS.  All contributing project authors may
- *  be found in the AUTHORS file in the root of the source tree.
- */
-
-#ifndef WEBRTC_MODULES_VIDEO_CODING_MAIN_TEST_RTP_FILE_READER_H_
-#define WEBRTC_MODULES_VIDEO_CODING_MAIN_TEST_RTP_FILE_READER_H_
-
-#include <string>
-
-namespace webrtc {
-namespace rtpplayer {
-
-class RtpPacketSourceInterface;
-
-RtpPacketSourceInterface* CreateRtpFileReader(const std::string& filename);
-
-}  // namespace rtpplayer
-}  // namespace webrtc
-
-#endif  // WEBRTC_MODULES_VIDEO_CODING_MAIN_TEST_RTP_FILE_READER_H_
diff --git a/webrtc/modules/video_coding/main/test/rtp_file_reader_unittest.cc b/webrtc/modules/video_coding/main/test/rtp_file_reader_unittest.cc
deleted file mode 100644
index 7e0e607..0000000
--- a/webrtc/modules/video_coding/main/test/rtp_file_reader_unittest.cc
+++ /dev/null
@@ -1,54 +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 "testing/gtest/include/gtest/gtest.h"
-#include "webrtc/modules/rtp_rtcp/source/rtp_utility.h"
-#include "webrtc/modules/video_coding/main/test/rtp_file_reader.h"
-#include "webrtc/modules/video_coding/main/test/rtp_player.h"
-#include "webrtc/system_wrappers/interface/scoped_ptr.h"
-#include "webrtc/test/testsupport/fileutils.h"
-
-namespace webrtc {
-namespace rtpplayer {
-
-class TestRtpFileReader : public ::testing::Test {
- public:
-  void Init(const std::string& filename) {
-    std::string filepath =
-        test::ResourcePath("video_coding/" + filename, "rtp");
-    rtp_packet_source_.reset(CreateRtpFileReader(filepath));
-    ASSERT_TRUE(rtp_packet_source_.get() != NULL);
-  }
-
-  int CountRtpPackets() {
-    const uint32_t kBufferSize = 4096;
-    uint8_t data[kBufferSize];
-    uint32_t length = kBufferSize;
-    uint32_t dummy_time_ms = 0;
-    int c = 0;
-    while (rtp_packet_source_->NextPacket(data, &length, &dummy_time_ms) == 0) {
-      EXPECT_GE(kBufferSize, length);
-      length = kBufferSize;
-      c++;
-    }
-    return c;
-  }
-
- private:
-  scoped_ptr<RtpPacketSourceInterface> rtp_packet_source_;
-};
-
-TEST_F(TestRtpFileReader, Test60Packets) {
-  Init("pltype103");
-  EXPECT_EQ(60, CountRtpPackets());
-}
-
-}  // namespace rtpplayer
-}  // namespace webrtc
diff --git a/webrtc/modules/video_coding/main/test/rtp_player.cc b/webrtc/modules/video_coding/main/test/rtp_player.cc
index f02aebb..8c8c56e 100644
--- a/webrtc/modules/video_coding/main/test/rtp_player.cc
+++ b/webrtc/modules/video_coding/main/test/rtp_player.cc
@@ -19,12 +19,11 @@
 #include "webrtc/modules/rtp_rtcp/interface/rtp_receiver.h"
 #include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp.h"
 #include "webrtc/modules/video_coding/main/source/internal_defines.h"
-#include "webrtc/modules/video_coding/main/test/pcap_file_reader.h"
-#include "webrtc/modules/video_coding/main/test/rtp_file_reader.h"
 #include "webrtc/modules/video_coding/main/test/test_util.h"
 #include "webrtc/system_wrappers/interface/clock.h"
 #include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
 #include "webrtc/system_wrappers/interface/scoped_ptr.h"
+#include "webrtc/test/rtp_file_reader.h"
 
 #if 1
 # define DEBUG_LOG1(text, arg)
@@ -323,7 +322,7 @@
  public:
   RtpPlayerImpl(PayloadSinkFactoryInterface* payload_sink_factory,
       const PayloadTypes& payload_types, Clock* clock,
-      scoped_ptr<RtpPacketSourceInterface>* packet_source,
+      scoped_ptr<test::RtpFileReader>* packet_source,
       float loss_rate, uint32_t rtt_ms, bool reordering)
     : ssrc_handlers_(payload_sink_factory, payload_types),
       clock_(clock),
@@ -337,9 +336,7 @@
       no_loss_startup_(100),
       end_of_file_(false),
       reordering_(false),
-      reorder_buffer_(),
-      next_packet_(),
-      next_packet_length_(0) {
+      reorder_buffer_() {
     assert(clock);
     assert(packet_source);
     assert(packet_source->get());
@@ -368,22 +365,23 @@
     // Send any packets from packet source.
     if (!end_of_file_ && (TimeUntilNextPacket() == 0 || first_packet_)) {
       if (first_packet_) {
-        next_packet_length_ = sizeof(next_packet_);
-        if (packet_source_->NextPacket(next_packet_, &next_packet_length_,
-                                      &next_rtp_time_) != 0) {
+        if (!packet_source_->NextPacket(&next_packet_))
           return 0;
-        }
-        first_packet_rtp_time_ = next_rtp_time_;
+        first_packet_rtp_time_ = next_packet_.time_ms;
         first_packet_time_ms_ = clock_->TimeInMilliseconds();
         first_packet_ = false;
       }
 
       if (reordering_ && reorder_buffer_.get() == NULL) {
-        reorder_buffer_.reset(new RawRtpPacket(next_packet_,
-                                               next_packet_length_, 0, 0));
+        reorder_buffer_.reset(
+            new RawRtpPacket(next_packet_.data,
+                             static_cast<uint32_t>(next_packet_.length),
+                             0,
+                             0));
         return 0;
       }
-      int ret = SendPacket(next_packet_, next_packet_length_);
+      int ret = SendPacket(next_packet_.data,
+                           static_cast<uint32_t>(next_packet_.length));
       if (reorder_buffer_.get()) {
         SendPacket(reorder_buffer_->data(), reorder_buffer_->length());
         reorder_buffer_.reset(NULL);
@@ -392,13 +390,11 @@
         return ret;
       }
 
-      next_packet_length_ = sizeof(next_packet_);
-      if (packet_source_->NextPacket(next_packet_, &next_packet_length_,
-                                    &next_rtp_time_) != 0) {
+      if (!packet_source_->NextPacket(&next_packet_)) {
         end_of_file_ = true;
         return 0;
       }
-      else if (next_packet_length_ == 0) {
+      else if (next_packet_.length == 0) {
         return 0;
       }
     }
@@ -456,7 +452,8 @@
 
   SsrcHandlers ssrc_handlers_;
   Clock* clock_;
-  scoped_ptr<RtpPacketSourceInterface> packet_source_;
+  scoped_ptr<test::RtpFileReader> packet_source_;
+  test::RtpFileReader::Packet next_packet_;
   uint32_t next_rtp_time_;
   bool first_packet_;
   int64_t first_packet_rtp_time_;
@@ -468,8 +465,6 @@
   bool end_of_file_;
   bool reordering_;
   scoped_ptr<RawRtpPacket> reorder_buffer_;
-  uint8_t next_packet_[kMaxPacketBufferSize];
-  uint32_t next_packet_length_;
 
   DISALLOW_IMPLICIT_CONSTRUCTORS(RtpPlayerImpl);
 };
@@ -478,10 +473,11 @@
     PayloadSinkFactoryInterface* payload_sink_factory, Clock* clock,
     const PayloadTypes& payload_types, float loss_rate, uint32_t rtt_ms,
     bool reordering) {
-  scoped_ptr<RtpPacketSourceInterface> packet_source(
-      CreateRtpFileReader(input_filename));
+  scoped_ptr<test::RtpFileReader> packet_source(test::RtpFileReader::Create(
+      test::RtpFileReader::kRtpDump, input_filename));
   if (packet_source.get() == NULL) {
-    packet_source.reset(CreatePcapFileReader(input_filename));
+    packet_source.reset(test::RtpFileReader::Create(test::RtpFileReader::kPcap,
+                                                    input_filename));
     if (packet_source.get() == NULL) {
       return NULL;
     }
diff --git a/webrtc/modules/video_coding/main/test/rtp_player.h b/webrtc/modules/video_coding/main/test/rtp_player.h
index 24e62b6..1703618 100644
--- a/webrtc/modules/video_coding/main/test/rtp_player.h
+++ b/webrtc/modules/video_coding/main/test/rtp_player.h
@@ -44,20 +44,6 @@
 typedef std::vector<PayloadCodecTuple> PayloadTypes;
 typedef std::vector<PayloadCodecTuple>::const_iterator PayloadTypesIterator;
 
-// Implemented by something that can provide RTP packets, for instance a file
-// format parser such as the rtp_file_reader or the pcap_file_reader.
-class RtpPacketSourceInterface {
- public:
-  virtual ~RtpPacketSourceInterface() {}
-
-  // Read next RTP packet into buffer pointed to by rtp_data. On call, 'length'
-  // field must be filled in with the size of the buffer. The actual size of
-  // the packet is available in 'length' upon returning. Time in milliseconds
-  // from start of stream is returned in 'time_ms'.
-  virtual int NextPacket(uint8_t* rtp_data, uint32_t* length,
-                         uint32_t* time_ms) = 0;
-};
-
 // Implemented by RtpPlayer and given to client as a means to retrieve
 // information about a specific RTP stream.
 class RtpStreamInterface {
diff --git a/webrtc/modules/video_coding/main/test/pcap_file_reader.cc b/webrtc/test/rtp_file_reader.cc
similarity index 64%
rename from webrtc/modules/video_coding/main/test/pcap_file_reader.cc
rename to webrtc/test/rtp_file_reader.cc
index 68c8566..be8dc2b 100644
--- a/webrtc/modules/video_coding/main/test/pcap_file_reader.cc
+++ b/webrtc/test/rtp_file_reader.cc
@@ -1,5 +1,5 @@
 /*
- *  Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
+ *  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
@@ -8,15 +8,8 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#include "webrtc/modules/video_coding/main/test/pcap_file_reader.h"
+#include "webrtc/test/rtp_file_reader.h"
 
-#ifdef WIN32
-#include <windows.h>
-#include <Winsock2.h>
-#else
-#include <arpa/inet.h>
-#endif
-#include <assert.h>
 #include <stdio.h>
 
 #include <map>
@@ -24,11 +17,142 @@
 #include <vector>
 
 #include "webrtc/modules/rtp_rtcp/source/rtp_utility.h"
-#include "webrtc/modules/video_coding/main/test/rtp_player.h"
 #include "webrtc/system_wrappers/interface/scoped_ptr.h"
 
 namespace webrtc {
-namespace rtpplayer {
+namespace test {
+
+static const size_t kFirstLineLength = 40;
+static uint16_t kPacketHeaderSize = 8;
+
+#if 1
+# define DEBUG_LOG(text)
+# define DEBUG_LOG1(text, arg)
+#else
+# define DEBUG_LOG(text) (printf(text "\n"))
+# define DEBUG_LOG1(text, arg) (printf(text "\n", arg))
+#endif
+
+#define TRY(expr)                                      \
+  do {                                                 \
+    if (!(expr)) {                                     \
+      DEBUG_LOG1("FAIL at " __FILE__ ":%d", __LINE__); \
+      return false;                                    \
+    }                                                  \
+  } while (0)
+
+class RtpFileReaderImpl : public RtpFileReader {
+ public:
+  virtual bool Init(const std::string& filename) = 0;
+};
+
+// Read RTP packets from file in rtpdump format, as documented at:
+// http://www.cs.columbia.edu/irt/software/rtptools/
+class RtpDumpReader : public RtpFileReaderImpl {
+ public:
+  RtpDumpReader() : file_(NULL) {}
+  virtual ~RtpDumpReader() {
+    if (file_ != NULL) {
+      fclose(file_);
+      file_ = NULL;
+    }
+  }
+
+  bool Init(const std::string& filename) {
+    file_ = fopen(filename.c_str(), "rb");
+    if (file_ == NULL) {
+      printf("ERROR: Can't open file: %s\n", filename.c_str());
+      return false;
+    }
+
+    char firstline[kFirstLineLength + 1] = {0};
+    if (fgets(firstline, kFirstLineLength, file_) == NULL) {
+      DEBUG_LOG("ERROR: Can't read from file\n");
+      return false;
+    }
+    if (strncmp(firstline, "#!rtpplay", 9) == 0) {
+      if (strncmp(firstline, "#!rtpplay1.0", 12) != 0) {
+        DEBUG_LOG("ERROR: wrong rtpplay version, must be 1.0\n");
+        return false;
+      }
+    } else if (strncmp(firstline, "#!RTPencode", 11) == 0) {
+      if (strncmp(firstline, "#!RTPencode1.0", 14) != 0) {
+        DEBUG_LOG("ERROR: wrong RTPencode version, must be 1.0\n");
+        return false;
+      }
+    } else {
+      DEBUG_LOG("ERROR: wrong file format of input file\n");
+      return false;
+    }
+
+    uint32_t start_sec;
+    uint32_t start_usec;
+    uint32_t source;
+    uint16_t port;
+    uint16_t padding;
+    TRY(Read(&start_sec));
+    TRY(Read(&start_usec));
+    TRY(Read(&source));
+    TRY(Read(&port));
+    TRY(Read(&padding));
+
+    return true;
+  }
+
+  virtual bool NextPacket(Packet* packet) OVERRIDE {
+    uint8_t* rtp_data = packet->data;
+    packet->length = Packet::kMaxPacketBufferSize;
+
+    uint16_t len;
+    uint16_t plen;
+    uint32_t offset;
+    TRY(Read(&len));
+    TRY(Read(&plen));
+    TRY(Read(&offset));
+
+    // Use 'len' here because a 'plen' of 0 specifies rtcp.
+    len -= kPacketHeaderSize;
+    if (packet->length < len) {
+      return false;
+    }
+    if (fread(rtp_data, 1, len, file_) != len) {
+      return false;
+    }
+
+    packet->length = len;
+    packet->time_ms = offset;
+    return true;
+  }
+
+ private:
+  bool Read(uint32_t* out) {
+    *out = 0;
+    for (size_t i = 0; i < 4; ++i) {
+      *out <<= 8;
+      uint8_t tmp;
+      if (fread(&tmp, 1, sizeof(uint8_t), file_) != sizeof(uint8_t))
+        return false;
+      *out |= tmp;
+    }
+    return true;
+  }
+
+  bool Read(uint16_t* out) {
+    *out = 0;
+    for (size_t i = 0; i < 2; ++i) {
+      *out <<= 8;
+      uint8_t tmp;
+      if (fread(&tmp, 1, sizeof(uint8_t), file_) != sizeof(uint8_t))
+        return false;
+      *out |= tmp;
+    }
+    return true;
+  }
+
+  FILE* file_;
+
+  DISALLOW_COPY_AND_ASSIGN(RtpDumpReader);
+};
 
 enum {
   kResultFail = -1,
@@ -56,50 +180,46 @@
 const uint32_t kPcapBOMSwapOrder = 0xd4c3b2a1UL;
 const uint32_t kPcapBOMNoSwapOrder = 0xa1b2c3d4UL;
 
-#if 1
-# define DEBUG_LOG(text)
-# define DEBUG_LOG1(text, arg)
-#else
-# define DEBUG_LOG(text) (printf(text "\n"))
-# define DEBUG_LOG1(text, arg) (printf(text "\n", arg))
-#endif
-
-#define TRY(expr)                                       \
-  do {                                                  \
-    int r = (expr);                                     \
-    if (r == kResultFail) {                             \
-      DEBUG_LOG1("FAIL at " __FILE__ ":%d", __LINE__);  \
-      return kResultFail;                               \
-    } else if (r == kResultSkip) {                      \
-      return kResultSkip;                               \
-    }                                                   \
+#define TRY_PCAP(expr)                                 \
+  do {                                                 \
+    int r = (expr);                                    \
+    if (r == kResultFail) {                            \
+      DEBUG_LOG1("FAIL at " __FILE__ ":%d", __LINE__); \
+      return kResultFail;                              \
+    } else if (r == kResultSkip) {                     \
+      return kResultSkip;                              \
+    }                                                  \
   } while (0)
 
 // Read RTP packets from file in tcpdump/libpcap format, as documented at:
 // http://wiki.wireshark.org/Development/LibpcapFileFormat
-class PcapFileReaderImpl : public RtpPacketSourceInterface {
+class PcapReader : public RtpFileReaderImpl {
  public:
-  PcapFileReaderImpl()
+  PcapReader()
     : file_(NULL),
       swap_pcap_byte_order_(false),
+#ifdef WEBRTC_ARCH_BIG_ENDIAN
       swap_network_byte_order_(false),
+#else
+      swap_network_byte_order_(true),
+#endif
       read_buffer_(),
       packets_by_ssrc_(),
       packets_(),
       next_packet_it_() {
-    int16_t test = 0x7f00;
-    if (test != htons(test)) {
-      swap_network_byte_order_ = true;
-    }
   }
 
-  virtual ~PcapFileReaderImpl() {
+  virtual ~PcapReader() {
     if (file_ != NULL) {
       fclose(file_);
       file_ = NULL;
     }
   }
 
+  bool Init(const std::string& filename) OVERRIDE {
+    return Initialize(filename) == kResultSuccess;
+  }
+
   int Initialize(const std::string& filename) {
     file_ = fopen(filename.c_str(), "rb");
     if (file_ == NULL) {
@@ -115,7 +235,7 @@
     uint32_t stream_start_ms = 0;
     int32_t next_packet_pos = ftell(file_);
     for (;;) {
-      TRY(fseek(file_, next_packet_pos, SEEK_SET));
+      TRY_PCAP(fseek(file_, next_packet_pos, SEEK_SET));
       int result = ReadPacket(&next_packet_pos, stream_start_ms,
                               ++total_packet_count);
       if (result == kResultFail) {
@@ -165,7 +285,15 @@
     return kResultSuccess;
   }
 
-  virtual int NextPacket(uint8_t* data, uint32_t* length, uint32_t* time_ms) {
+  virtual bool NextPacket(Packet* packet) OVERRIDE {
+    uint32_t length = Packet::kMaxPacketBufferSize;
+    if (NextPcap(packet->data, &length, &packet->time_ms) != kResultSuccess)
+      return false;
+    packet->length = static_cast<size_t>(length);
+    return true;
+  }
+
+  virtual int NextPcap(uint8_t* data, uint32_t* length, uint32_t* time_ms) {
     assert(data);
     assert(length);
     assert(time_ms);
@@ -176,8 +304,8 @@
     if (*length < next_packet_it_->payload_length) {
       return -1;
     }
-    TRY(fseek(file_, next_packet_it_->pos_in_file, SEEK_SET));
-    TRY(Read(data, next_packet_it_->payload_length));
+    TRY_PCAP(fseek(file_, next_packet_it_->pos_in_file, SEEK_SET));
+    TRY_PCAP(Read(data, next_packet_it_->payload_length));
     *length = next_packet_it_->payload_length;
     *time_ms = next_packet_it_->time_offset_ms;
     next_packet_it_++;
@@ -205,7 +333,7 @@
 
   int ReadGlobalHeader() {
     uint32_t magic;
-    TRY(Read(&magic, false));
+    TRY_PCAP(Read(&magic, false));
     if (magic == kPcapBOMSwapOrder) {
       swap_pcap_byte_order_ = true;
     } else if (magic == kPcapBOMNoSwapOrder) {
@@ -216,8 +344,8 @@
 
     uint16_t version_major;
     uint16_t version_minor;
-    TRY(Read(&version_major, false));
-    TRY(Read(&version_minor, false));
+    TRY_PCAP(Read(&version_major, false));
+    TRY_PCAP(Read(&version_minor, false));
     if (version_major != kPcapVersionMajor ||
         version_minor != kPcapVersionMinor) {
       return kResultFail;
@@ -227,10 +355,10 @@
     uint32_t sigfigs;   // Accuracy of timestamps.
     uint32_t snaplen;   // Max length of captured packets, in octets.
     uint32_t network;   // Data link type.
-    TRY(Read(&this_zone, false));
-    TRY(Read(&sigfigs, false));
-    TRY(Read(&snaplen, false));
-    TRY(Read(&network, false));
+    TRY_PCAP(Read(&this_zone, false));
+    TRY_PCAP(Read(&sigfigs, false));
+    TRY_PCAP(Read(&snaplen, false));
+    TRY_PCAP(Read(&network, false));
 
     // Accept only LINKTYPE_NULL and LINKTYPE_ETHERNET.
     // See: http://www.tcpdump.org/linktypes.html
@@ -249,24 +377,24 @@
     uint32_t ts_usec;   // Timestamp microseconds.
     uint32_t incl_len;  // Number of octets of packet saved in file.
     uint32_t orig_len;  // Actual length of packet.
-    TRY(Read(&ts_sec, false));
-    TRY(Read(&ts_usec, false));
-    TRY(Read(&incl_len, false));
-    TRY(Read(&orig_len, false));
+    TRY_PCAP(Read(&ts_sec, false));
+    TRY_PCAP(Read(&ts_usec, false));
+    TRY_PCAP(Read(&incl_len, false));
+    TRY_PCAP(Read(&orig_len, false));
 
     *next_packet_pos = ftell(file_) + incl_len;
 
     RtpPacketMarker marker = {0};
     marker.packet_number = number;
     marker.time_offset_ms = CalcTimeDelta(ts_sec, ts_usec, stream_start_ms);
-    TRY(ReadPacketHeader(&marker));
+    TRY_PCAP(ReadPacketHeader(&marker));
     marker.pos_in_file = ftell(file_);
 
     if (marker.payload_length > sizeof(read_buffer_)) {
       printf("Packet too large!\n");
       return kResultFail;
     }
-    TRY(Read(read_buffer_, marker.payload_length));
+    TRY_PCAP(Read(read_buffer_, marker.payload_length));
 
     RtpUtility::RtpHeaderParser rtp_parser(read_buffer_, marker.payload_length);
     if (rtp_parser.RTCP()) {
@@ -294,7 +422,7 @@
     // the header as such and will likely fail reading the IP header if this is
     // something else than null/loopback.
     uint32_t protocol;
-    TRY(Read(&protocol, true));
+    TRY_PCAP(Read(&protocol, true));
     if (protocol == kBsdNullLoopback1 || protocol == kBsdNullLoopback2) {
       int result = ReadXxpIpHeader(marker);
       DEBUG_LOG("Recognized loopback frame");
@@ -303,12 +431,12 @@
       }
     }
 
-    TRY(fseek(file_, file_pos, SEEK_SET));
+    TRY_PCAP(fseek(file_, file_pos, SEEK_SET));
 
     // Check for Ethernet II, IP frame header.
     uint16_t type;
-    TRY(Skip(kEthernetIIHeaderMacSkip));  // Source+destination MAC.
-    TRY(Read(&type, true));
+    TRY_PCAP(Skip(kEthernetIIHeaderMacSkip));  // Source+destination MAC.
+    TRY_PCAP(Read(&type, true));
     if (type == kEthertypeIp) {
       int result = ReadXxpIpHeader(marker);
       DEBUG_LOG("Recognized ethernet 2 frame");
@@ -341,14 +469,14 @@
     uint16_t fragment;
     uint16_t protocol;
     uint16_t checksum;
-    TRY(Read(&version, true));
-    TRY(Read(&length, true));
-    TRY(Read(&id, true));
-    TRY(Read(&fragment, true));
-    TRY(Read(&protocol, true));
-    TRY(Read(&checksum, true));
-    TRY(Read(&marker->source_ip, true));
-    TRY(Read(&marker->dest_ip, true));
+    TRY_PCAP(Read(&version, true));
+    TRY_PCAP(Read(&length, true));
+    TRY_PCAP(Read(&id, true));
+    TRY_PCAP(Read(&fragment, true));
+    TRY_PCAP(Read(&protocol, true));
+    TRY_PCAP(Read(&checksum, true));
+    TRY_PCAP(Read(&marker->source_ip, true));
+    TRY_PCAP(Read(&marker->dest_ip, true));
 
     if (((version >> 12) & 0x000f) != kIpVersion4) {
       DEBUG_LOG("IP header is not IPv4");
@@ -364,7 +492,7 @@
     // Skip remaining fields of IP header.
     uint16_t header_length = (version & 0x0f00) >> (8 - 2);
     assert(header_length >= kMinIpHeaderLength);
-    TRY(Skip(header_length - kMinIpHeaderLength));
+    TRY_PCAP(Skip(header_length - kMinIpHeaderLength));
 
     protocol = protocol & 0x00ff;
     if (protocol == kProtocolTcp) {
@@ -373,10 +501,10 @@
     } else if (protocol == kProtocolUdp) {
       uint16_t length;
       uint16_t checksum;
-      TRY(Read(&marker->source_port, true));
-      TRY(Read(&marker->dest_port, true));
-      TRY(Read(&length, true));
-      TRY(Read(&checksum, true));
+      TRY_PCAP(Read(&marker->source_port, true));
+      TRY_PCAP(Read(&marker->dest_port, true));
+      TRY_PCAP(Read(&length, true));
+      TRY_PCAP(Read(&checksum, true));
       marker->payload_length = length - kUdpHeaderLength;
     } else {
       DEBUG_LOG("Unknown transport (expected UDP or TCP)");
@@ -443,22 +571,33 @@
 
   FILE* file_;
   bool swap_pcap_byte_order_;
-  bool swap_network_byte_order_;
+  const bool swap_network_byte_order_;
   uint8_t read_buffer_[kMaxReadBufferSize];
 
   SsrcMap packets_by_ssrc_;
   std::vector<RtpPacketMarker> packets_;
   PacketIterator next_packet_it_;
 
-  DISALLOW_COPY_AND_ASSIGN(PcapFileReaderImpl);
+  DISALLOW_COPY_AND_ASSIGN(PcapReader);
 };
 
-RtpPacketSourceInterface* CreatePcapFileReader(const std::string& filename) {
-  scoped_ptr<PcapFileReaderImpl> impl(new PcapFileReaderImpl());
-  if (impl->Initialize(filename) != 0) {
+RtpFileReader* RtpFileReader::Create(FileFormat format,
+                                     const std::string& filename) {
+  RtpFileReaderImpl* reader = NULL;
+  switch (format) {
+    case kPcap:
+      reader = new PcapReader();
+      break;
+    case kRtpDump:
+      reader = new RtpDumpReader();
+      break;
+  }
+  if (!reader->Init(filename)) {
+    delete reader;
     return NULL;
   }
-  return impl.release();
+  return reader;
 }
-}  // namespace rtpplayer
+
+}  // namespace test
 }  // namespace webrtc
diff --git a/webrtc/test/rtp_file_reader.h b/webrtc/test/rtp_file_reader.h
new file mode 100644
index 0000000..379bf2d
--- /dev/null
+++ b/webrtc/test/rtp_file_reader.h
@@ -0,0 +1,42 @@
+/*
+ *  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_RTP_FILE_READER_H_
+#define WEBRTC_TEST_RTP_FILE_READER_H_
+
+#include <string>
+
+#include "webrtc/common_types.h"
+
+namespace webrtc {
+namespace test {
+class RtpFileReader {
+ public:
+  enum FileFormat {
+    kPcap,
+    kRtpDump,
+  };
+
+  struct Packet {
+    static const size_t kMaxPacketBufferSize = 1500;
+    uint8_t data[kMaxPacketBufferSize];
+    size_t length;
+
+    uint32_t time_ms;
+  };
+
+  virtual ~RtpFileReader() {}
+  static RtpFileReader* Create(FileFormat format,
+                               const std::string& filename);
+
+  virtual bool NextPacket(Packet* packet) = 0;
+};
+}  // namespace test
+}  // namespace webrtc
+#endif  // WEBRTC_TEST_RTP_FILE_READER_H_
diff --git a/webrtc/modules/video_coding/main/test/pcap_file_reader_unittest.cc b/webrtc/test/rtp_file_reader_unittest.cc
similarity index 63%
rename from webrtc/modules/video_coding/main/test/pcap_file_reader_unittest.cc
rename to webrtc/test/rtp_file_reader_unittest.cc
index c6f1d51..b5fa260 100644
--- a/webrtc/modules/video_coding/main/test/pcap_file_reader_unittest.cc
+++ b/webrtc/test/rtp_file_reader_unittest.cc
@@ -12,13 +12,38 @@
 
 #include "testing/gtest/include/gtest/gtest.h"
 #include "webrtc/modules/rtp_rtcp/source/rtp_utility.h"
-#include "webrtc/modules/video_coding/main/test/pcap_file_reader.h"
-#include "webrtc/modules/video_coding/main/test/rtp_player.h"
 #include "webrtc/system_wrappers/interface/scoped_ptr.h"
+#include "webrtc/test/rtp_file_reader.h"
 #include "webrtc/test/testsupport/fileutils.h"
 
 namespace webrtc {
-namespace rtpplayer {
+
+class TestRtpFileReader : public ::testing::Test {
+ public:
+  void Init(const std::string& filename) {
+    std::string filepath =
+        test::ResourcePath("video_coding/" + filename, "rtp");
+    rtp_packet_source_.reset(
+        test::RtpFileReader::Create(test::RtpFileReader::kRtpDump, filepath));
+    ASSERT_TRUE(rtp_packet_source_.get() != NULL);
+  }
+
+  int CountRtpPackets() {
+    test::RtpFileReader::Packet packet;
+    int c = 0;
+    while (rtp_packet_source_->NextPacket(&packet))
+      c++;
+    return c;
+  }
+
+ private:
+  scoped_ptr<test::RtpFileReader> rtp_packet_source_;
+};
+
+TEST_F(TestRtpFileReader, Test60Packets) {
+  Init("pltype103");
+  EXPECT_EQ(60, CountRtpPackets());
+}
 
 typedef std::map<uint32_t, int> PacketsPerSsrc;
 
@@ -27,35 +52,24 @@
   void Init(const std::string& filename) {
     std::string filepath =
         test::ResourcePath("video_coding/" + filename, "pcap");
-    rtp_packet_source_.reset(CreatePcapFileReader(filepath));
+    rtp_packet_source_.reset(
+        test::RtpFileReader::Create(test::RtpFileReader::kPcap, filepath));
     ASSERT_TRUE(rtp_packet_source_.get() != NULL);
   }
 
   int CountRtpPackets() {
-    const uint32_t kBufferSize = 4096;
-    uint8_t data[kBufferSize];
-    uint32_t length = kBufferSize;
-    uint32_t dummy_time_ms = 0;
     int c = 0;
-    while (rtp_packet_source_->NextPacket(data, &length, &dummy_time_ms) == 0) {
-      EXPECT_GE(kBufferSize, length);
-      length = kBufferSize;
+    test::RtpFileReader::Packet packet;
+    while (rtp_packet_source_->NextPacket(&packet))
       c++;
-    }
     return c;
   }
 
   PacketsPerSsrc CountRtpPacketsPerSsrc() {
-    const uint32_t kBufferSize = 4096;
-    uint8_t data[kBufferSize];
-    uint32_t length = kBufferSize;
-    uint32_t dummy_time_ms = 0;
     PacketsPerSsrc pps;
-    while (rtp_packet_source_->NextPacket(data, &length, &dummy_time_ms) == 0) {
-      EXPECT_GE(kBufferSize, length);
-      length = kBufferSize;
-
-      RtpUtility::RtpHeaderParser rtp_header_parser(data, length);
+    test::RtpFileReader::Packet packet;
+    while (rtp_packet_source_->NextPacket(&packet)) {
+      RtpUtility::RtpHeaderParser rtp_header_parser(packet.data, packet.length);
       webrtc::RTPHeader header;
       if (!rtp_header_parser.RTCP() && rtp_header_parser.Parse(header, NULL)) {
         pps[header.ssrc]++;
@@ -65,7 +79,7 @@
   }
 
  private:
-  scoped_ptr<RtpPacketSourceInterface> rtp_packet_source_;
+  scoped_ptr<test::RtpFileReader> rtp_packet_source_;
 };
 
 TEST_F(TestPcapFileReader, TestEthernetIIFrame) {
@@ -94,6 +108,4 @@
   EXPECT_EQ(113, pps[0x59fe6ef0]);
   EXPECT_EQ(61, pps[0xed2bd2ac]);
 }
-
-}  // namespace rtpplayer
 }  // namespace webrtc
diff --git a/webrtc/test/webrtc_test_common.gyp b/webrtc/test/webrtc_test_common.gyp
index 8c8774f..be6b303 100644
--- a/webrtc/test/webrtc_test_common.gyp
+++ b/webrtc/test/webrtc_test_common.gyp
@@ -35,6 +35,8 @@
         'mock_transport.h',
         'null_transport.cc',
         'null_transport.h',
+        'rtp_file_reader.cc',
+        'rtp_file_reader.h',
         'rtp_rtcp_observer.h',
         'run_loop.cc',
         'run_loop.h',
@@ -184,6 +186,7 @@
           ],
           'sources': [
             'fake_network_pipe_unittest.cc',
+            'rtp_file_reader_unittest.cc',
           ],
         },
       ],  #targets
diff --git a/webrtc/video/replay.cc b/webrtc/video/replay.cc
new file mode 100644
index 0000000..7539025
--- /dev/null
+++ b/webrtc/video/replay.cc
@@ -0,0 +1,266 @@
+/*
+ *  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 <stdio.h>
+
+#include <map>
+#include <sstream>
+
+#include "gflags/gflags.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+#include "webrtc/call.h"
+#include "webrtc/common_video/libyuv/include/webrtc_libyuv.h"
+#include "webrtc/modules/rtp_rtcp/interface/rtp_header_parser.h"
+#include "webrtc/system_wrappers/interface/clock.h"
+#include "webrtc/system_wrappers/interface/scoped_ptr.h"
+#include "webrtc/system_wrappers/interface/sleep.h"
+#include "webrtc/test/encoder_settings.h"
+#include "webrtc/test/null_transport.h"
+#include "webrtc/test/rtp_file_reader.h"
+#include "webrtc/test/run_loop.h"
+#include "webrtc/test/run_test.h"
+#include "webrtc/test/video_capturer.h"
+#include "webrtc/test/video_renderer.h"
+#include "webrtc/typedefs.h"
+
+namespace webrtc {
+namespace flags {
+
+// TODO(pbos): Multiple receivers.
+
+// Flag for payload type.
+static bool ValidatePayloadType(const char* flagname, int32_t payload_type) {
+  return payload_type > 0 && payload_type <= 127;
+}
+DEFINE_int32(payload_type, 0, "Payload type.");
+static int PayloadType() { return static_cast<int>(FLAGS_payload_type); }
+static const bool payload_dummy =
+    google::RegisterFlagValidator(&FLAGS_payload_type, &ValidatePayloadType);
+
+// Flag for SSRC.
+static bool ValidateSsrc(const char* flagname, uint64_t ssrc) {
+  return ssrc > 0 && ssrc <= 0xFFFFFFFFu;
+}
+
+DEFINE_uint64(ssrc, 0, "Incoming SSRC.");
+static uint32_t Ssrc() { return static_cast<uint32_t>(FLAGS_ssrc); }
+static const bool ssrc_dummy =
+    google::RegisterFlagValidator(&FLAGS_ssrc, &ValidateSsrc);
+
+static bool ValidateOptionalPayloadType(const char* flagname,
+                                        int32_t payload_type) {
+  return payload_type == -1 || ValidatePayloadType(flagname, payload_type);
+}
+
+// Flag for RED payload type.
+DEFINE_int32(red_payload_type, -1, "RED payload type.");
+static int RedPayloadType() {
+  return static_cast<int>(FLAGS_red_payload_type);
+}
+static const bool red_dummy =
+    google::RegisterFlagValidator(&FLAGS_red_payload_type,
+                                  &ValidateOptionalPayloadType);
+
+// Flag for ULPFEC payload type.
+DEFINE_int32(fec_payload_type, -1, "ULPFEC payload type.");
+static int FecPayloadType() {
+  return static_cast<int>(FLAGS_fec_payload_type);
+}
+static const bool fec_dummy =
+    google::RegisterFlagValidator(&FLAGS_fec_payload_type,
+                                  &ValidateOptionalPayloadType);
+
+// Flag for abs-send-time id.
+static bool ValidateRtpHeaderExtensionId(const char* flagname,
+                                         int32_t extension_id) {
+  return extension_id >= -1 || extension_id < 15;
+}
+DEFINE_int32(abs_send_time_id, -1, "RTP extension ID for abs-send-time.");
+static int AbsSendTimeId() { return static_cast<int>(FLAGS_abs_send_time_id); }
+static const bool abs_send_time_dummy =
+    google::RegisterFlagValidator(&FLAGS_abs_send_time_id,
+                                  &ValidateRtpHeaderExtensionId);
+
+// Flag for transmission-offset id.
+DEFINE_int32(transmission_offset_id,
+             -1,
+             "RTP extension ID for transmission-offset.");
+static int TransmissionOffsetId() {
+  return static_cast<int>(FLAGS_transmission_offset_id);
+}
+static const bool timestamp_offset_dummy =
+    google::RegisterFlagValidator(&FLAGS_transmission_offset_id,
+                                  &ValidateRtpHeaderExtensionId);
+
+// Flag for rtpdump input file.
+DEFINE_string(input_file, "", "rtpdump input file.");
+static std::string InputFile() {
+  return static_cast<std::string>(FLAGS_input_file);
+}
+
+// Flag for raw output files.
+DEFINE_string(out_base, "", "Basename (excluding .yuv) for raw output.");
+static std::string OutBase() {
+  return static_cast<std::string>(FLAGS_out_base);
+}
+
+// Flag for video codec.
+DEFINE_string(codec, "VP8", "Video codec.");
+static std::string Codec() { return static_cast<std::string>(FLAGS_codec); }
+
+}  // namespace flags
+
+static const uint32_t kReceiverLocalSsrc = 0x123456;
+
+class FileRenderPassthrough : public VideoRenderer {
+ public:
+  FileRenderPassthrough(const std::string& basename, VideoRenderer* renderer)
+      : basename_(basename),
+        renderer_(renderer),
+        file_(NULL),
+        count_(0),
+        last_width_(0),
+        last_height_(0) {}
+
+  ~FileRenderPassthrough() {
+    if (file_ != NULL)
+      fclose(file_);
+  }
+
+ private:
+  virtual void RenderFrame(const I420VideoFrame& video_frame,
+                           int time_to_render_ms) OVERRIDE {
+    if (renderer_ != NULL)
+      renderer_->RenderFrame(video_frame, time_to_render_ms);
+    if (basename_ == "")
+      return;
+    if (last_width_ != video_frame.width() ||
+        last_height_ != video_frame.height()) {
+      if (file_ != NULL)
+        fclose(file_);
+      std::stringstream filename;
+      filename << basename_;
+      if (++count_ > 1)
+        filename << '-' << count_;
+      filename << '_' << video_frame.width() << 'x' << video_frame.height()
+               << ".yuv";
+      file_ = fopen(filename.str().c_str(), "wb");
+      if (file_ == NULL) {
+        fprintf(stderr,
+                "Couldn't open file for writing: %s\n",
+                filename.str().c_str());
+      }
+    }
+    last_width_ = video_frame.width();
+    last_height_ = video_frame.height();
+    if (file_ == NULL)
+      return;
+    PrintI420VideoFrame(video_frame, file_);
+  }
+
+  const std::string basename_;
+  VideoRenderer* const renderer_;
+  FILE* file_;
+  size_t count_;
+  int last_width_;
+  int last_height_;
+};
+
+void RtpReplay() {
+  scoped_ptr<test::VideoRenderer> playback_video(test::VideoRenderer::Create(
+      "Playback Video", 640, 480));
+  FileRenderPassthrough file_passthrough(flags::OutBase(),
+                                         playback_video.get());
+
+  // TODO(pbos): Might be good to have a transport that prints keyframe requests
+  //             etc.
+  test::NullTransport transport;
+  Call::Config call_config(&transport);
+  scoped_ptr<Call> call(Call::Create(call_config));
+
+  VideoReceiveStream::Config receive_config;
+  receive_config.rtp.remote_ssrc = flags::Ssrc();
+  receive_config.rtp.local_ssrc = kReceiverLocalSsrc;
+  receive_config.rtp.fec.ulpfec_payload_type = flags::FecPayloadType();
+  receive_config.rtp.fec.red_payload_type = flags::RedPayloadType();
+  receive_config.rtp.nack.rtp_history_ms = 1000;
+  if (flags::TransmissionOffsetId() != -1) {
+    receive_config.rtp.extensions.push_back(
+        RtpExtension(RtpExtension::kTOffset, flags::TransmissionOffsetId()));
+  }
+  if (flags::AbsSendTimeId() != -1) {
+    receive_config.rtp.extensions.push_back(
+        RtpExtension(RtpExtension::kAbsSendTime, flags::AbsSendTimeId()));
+  }
+  receive_config.renderer = &file_passthrough;
+
+  VideoSendStream::Config::EncoderSettings encoder_settings;
+  encoder_settings.payload_name = flags::Codec();
+  encoder_settings.payload_type = flags::PayloadType();
+  VideoCodec codec = test::CreateDecoderVideoCodec(encoder_settings);
+  receive_config.codecs.push_back(codec);
+
+  VideoReceiveStream* receive_stream =
+      call->CreateVideoReceiveStream(receive_config);
+
+  scoped_ptr<test::RtpFileReader> rtp_reader(test::RtpFileReader::Create(
+      test::RtpFileReader::kRtpDump, flags::InputFile()));
+  if (rtp_reader.get() == NULL) {
+    rtp_reader.reset(test::RtpFileReader::Create(test::RtpFileReader::kPcap,
+                                                 flags::InputFile()));
+    if (rtp_reader.get() == NULL) {
+      fprintf(stderr,
+              "Couldn't open input file as either a rtpdump or .pcap. Note "
+              "that .pcapng is not supported.\n");
+      return;
+    }
+  }
+  receive_stream->Start();
+
+  uint32_t last_time_ms = 0;
+  int num_packets = 0;
+  while (true) {
+    test::RtpFileReader::Packet packet;
+    if (!rtp_reader->NextPacket(&packet))
+      break;
+    ++num_packets;
+    switch (call->Receiver()->DeliverPacket(packet.data, packet.length)) {
+      case PacketReceiver::DELIVERY_OK:
+        break;
+      case PacketReceiver::DELIVERY_UNKNOWN_SSRC: {
+        RTPHeader header;
+        scoped_ptr<RtpHeaderParser> parser(RtpHeaderParser::Create());
+        parser->Parse(packet.data, packet.length, &header);
+        fprintf(stderr, "Unknown SSRC: %u!\n", header.ssrc);
+        break;
+      }
+      case PacketReceiver::DELIVERY_PACKET_ERROR:
+        fprintf(stderr, "Packet error, corrupt packets or incorrect setup?\n");
+        break;
+    }
+    if (last_time_ms != 0 && last_time_ms != packet.time_ms) {
+      SleepMs(packet.time_ms - last_time_ms);
+    }
+    last_time_ms = packet.time_ms;
+  }
+  fprintf(stderr, "num_packets: %d\n", num_packets);
+
+  call->DestroyVideoReceiveStream(receive_stream);
+}
+}  // namespace webrtc
+
+int main(int argc, char* argv[]) {
+  ::testing::InitGoogleTest(&argc, argv);
+  google::ParseCommandLineFlags(&argc, &argv, true);
+
+  webrtc::test::RunTest(webrtc::RtpReplay);
+  return 0;
+}
diff --git a/webrtc/webrtc_tests.gypi b/webrtc/webrtc_tests.gypi
index 78b199f..ace6684 100644
--- a/webrtc/webrtc_tests.gypi
+++ b/webrtc/webrtc_tests.gypi
@@ -13,6 +13,7 @@
       'dependencies': [
         'video_engine_tests',
         'video_loopback',
+        'video_replay',
         'webrtc_perf_tests',
       ],
     },
@@ -42,6 +43,31 @@
       ],
     },
     {
+      'target_name': 'video_replay',
+      'type': 'executable',
+      'sources': [
+        'test/mac/run_test.mm',
+        'test/run_test.cc',
+        'test/run_test.h',
+        'video/replay.cc',
+      ],
+      'conditions': [
+        ['OS=="mac"', {
+          'sources!': [
+            'test/run_test.cc',
+          ],
+        }],
+      ],
+      'dependencies': [
+        '<(DEPTH)/testing/gtest.gyp:gtest',
+        '<(DEPTH)/third_party/gflags/gflags.gyp:gflags',
+        'system_wrappers/source/system_wrappers.gyp:field_trial_default',
+        'test/webrtc_test_common.gyp:webrtc_test_common',
+        'test/webrtc_test_common.gyp:webrtc_test_renderer',
+        'webrtc',
+      ],
+    },
+    {
       'target_name': 'video_engine_tests',
       'type': '<(gtest_target_type)',
       'sources': [