Let RtpFileSource use RtpFileReader

RtpFileSource used to implement it's own RTP dump file reader, but
with this change it simply uses RtpFileReader. One benefit is that
pcap files are now also supported.

All NetEq test tools that use RtpFileSource are updated.

BUG=2692
R=kwiberg@webrtc.org

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

git-svn-id: http://webrtc.googlecode.com/svn/trunk@7367 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/webrtc/modules/audio_coding/neteq/neteq.gypi b/webrtc/modules/audio_coding/neteq/neteq.gypi
index 01143bc..34d64a1 100644
--- a/webrtc/modules/audio_coding/neteq/neteq.gypi
+++ b/webrtc/modules/audio_coding/neteq/neteq.gypi
@@ -170,6 +170,7 @@
           'type': 'static_library',
           'dependencies': [
             'rtp_rtcp',
+            '<(webrtc_root)/test/webrtc_test_common.gyp:webrtc_test_common',
           ],
           'direct_dependent_settings': {
             'include_dirs': [
diff --git a/webrtc/modules/audio_coding/neteq/tools/neteq_rtpplay.cc b/webrtc/modules/audio_coding/neteq/tools/neteq_rtpplay.cc
index e144ba7..3d5bd60 100644
--- a/webrtc/modules/audio_coding/neteq/tools/neteq_rtpplay.cc
+++ b/webrtc/modules/audio_coding/neteq/tools/neteq_rtpplay.cc
@@ -172,12 +172,12 @@
   RegisterPayloadTypes(neteq);
 
   // Read first packet.
-  if (file_source->EndOfFile()) {
+  webrtc::scoped_ptr<webrtc::test::Packet> packet(file_source->NextPacket());
+  if (!packet) {
     printf("Warning: RTP file is empty");
     webrtc::Trace::ReturnTrace();
     return 0;
   }
-  webrtc::scoped_ptr<webrtc::test::Packet> packet(file_source->NextPacket());
   bool packet_available = true;
 
   // Set up variables for audio replacement if needed.
@@ -195,8 +195,8 @@
     replacement_audio.reset(new int16_t[input_frame_size_timestamps]);
     payload_mem_size_bytes = 2 * input_frame_size_timestamps;
     payload.reset(new uint8_t[payload_mem_size_bytes]);
-    assert(!file_source->EndOfFile());
     next_packet.reset(file_source->NextPacket());
+    assert(next_packet);
     next_packet_available = true;
   }
 
@@ -241,8 +241,9 @@
       }
 
       // Get next packet from file.
-      if (!file_source->EndOfFile()) {
-        packet.reset(file_source->NextPacket());
+      webrtc::test::Packet* temp_packet = file_source->NextPacket();
+      if (temp_packet) {
+        packet.reset(temp_packet);
       } else {
         packet_available = false;
       }
diff --git a/webrtc/modules/audio_coding/neteq/tools/packet_source.h b/webrtc/modules/audio_coding/neteq/tools/packet_source.h
index ab9ef83..0b724b1 100644
--- a/webrtc/modules/audio_coding/neteq/tools/packet_source.h
+++ b/webrtc/modules/audio_coding/neteq/tools/packet_source.h
@@ -24,7 +24,7 @@
 // Interface class for an object delivering RTP packets to test applications.
 class PacketSource {
  public:
-  PacketSource() {}
+  PacketSource() : use_ssrc_filter_(false), ssrc_(0) {}
   virtual ~PacketSource() {}
 
   // Returns a pointer to the next packet. Returns NULL if the source is
@@ -35,8 +35,16 @@
     filter_.set(payload_type, true);
   }
 
+  virtual void SelectSsrc(uint32_t ssrc) {
+    use_ssrc_filter_ = true;
+    ssrc_ = ssrc;
+  }
+
  protected:
   std::bitset<128> filter_;  // Payload type is 7 bits in the RFC.
+  // If SSRC filtering discards all packet that do not match the SSRC.
+  bool use_ssrc_filter_;  // True when SSRC filtering is active.
+  uint32_t ssrc_;  // The selected SSRC. All other SSRCs will be discarded.
 
  private:
   DISALLOW_COPY_AND_ASSIGN(PacketSource);
diff --git a/webrtc/modules/audio_coding/neteq/tools/rtp_analyze.cc b/webrtc/modules/audio_coding/neteq/tools/rtp_analyze.cc
index b07de0b..ec604d2 100644
--- a/webrtc/modules/audio_coding/neteq/tools/rtp_analyze.cc
+++ b/webrtc/modules/audio_coding/neteq/tools/rtp_analyze.cc
@@ -91,13 +91,12 @@
   fprintf(out_file, "\n");
 
   webrtc::scoped_ptr<webrtc::test::Packet> packet;
-  while (!file_source->EndOfFile()) {
+  while (true) {
     packet.reset(file_source->NextPacket());
     if (!packet.get()) {
-      // This is probably an RTCP packet. Move on to the next one.
-      continue;
+      // End of file reached.
+      break;
     }
-    assert(packet.get());
     // Write packet data to file.
     fprintf(out_file,
             "%5u %10u %10u %5i %5i %2i %#08X",
diff --git a/webrtc/modules/audio_coding/neteq/tools/rtp_file_source.cc b/webrtc/modules/audio_coding/neteq/tools/rtp_file_source.cc
index 6924a7f..6667afc 100644
--- a/webrtc/modules/audio_coding/neteq/tools/rtp_file_source.cc
+++ b/webrtc/modules/audio_coding/neteq/tools/rtp_file_source.cc
@@ -18,26 +18,21 @@
 #include <netinet/in.h>
 #endif
 
+#include "webrtc/base/checks.h"
 #include "webrtc/modules/audio_coding/neteq/tools/packet.h"
 #include "webrtc/modules/rtp_rtcp/interface/rtp_header_parser.h"
+#include "webrtc/test/rtp_file_reader.h"
 
 namespace webrtc {
 namespace test {
 
 RtpFileSource* RtpFileSource::Create(const std::string& file_name) {
-  RtpFileSource* source = new RtpFileSource;
-  assert(source);
-  if (!source->OpenFile(file_name) || !source->SkipFileHeader()) {
-    assert(false);
-    delete source;
-    return NULL;
-  }
+  RtpFileSource* source = new RtpFileSource();
+  CHECK(source->OpenFile(file_name));
   return source;
 }
 
 RtpFileSource::~RtpFileSource() {
-  if (in_file_)
-    fclose(in_file_);
 }
 
 bool RtpFileSource::RegisterRtpHeaderExtension(RTPExtensionType type,
@@ -47,102 +42,48 @@
 }
 
 Packet* RtpFileSource::NextPacket() {
-  while (!EndOfFile()) {
-    uint16_t length;
-    if (fread(&length, sizeof(length), 1, in_file_) == 0) {
-      assert(false);
+  while (true) {
+    RtpFileReader::Packet temp_packet;
+    if (!rtp_reader_->NextPacket(&temp_packet)) {
       return NULL;
     }
-    length = ntohs(length);
-
-    uint16_t plen;
-    if (fread(&plen, sizeof(plen), 1, in_file_) == 0) {
-      assert(false);
-      return NULL;
-    }
-    plen = ntohs(plen);
-
-    uint32_t offset;
-    if (fread(&offset, sizeof(offset), 1, in_file_) == 0) {
-      assert(false);
-      return NULL;
-    }
-    offset = ntohl(offset);
-
-    // Use length here because a plen of 0 specifies RTCP.
-    assert(length >= kPacketHeaderSize);
-    size_t packet_size_bytes = length - kPacketHeaderSize;
-    if (packet_size_bytes == 0) {
+    if (temp_packet.length == 0) {
       // May be an RTCP packet.
       // Read the next one.
       continue;
     }
-    scoped_ptr<uint8_t> packet_memory(new uint8_t[packet_size_bytes]);
-    if (fread(packet_memory.get(), 1, packet_size_bytes, in_file_) !=
-        packet_size_bytes) {
-      assert(false);
-      return NULL;
-    }
+    scoped_ptr<uint8_t[]> packet_memory(new uint8_t[temp_packet.length]);
+    memcpy(packet_memory.get(), temp_packet.data, temp_packet.length);
     scoped_ptr<Packet> packet(new Packet(packet_memory.release(),
-                                         packet_size_bytes,
-                                         plen,
-                                         offset,
+                                         temp_packet.length,
+                                         temp_packet.original_length,
+                                         temp_packet.time_ms,
                                          *parser_.get()));
     if (!packet->valid_header()) {
       assert(false);
       return NULL;
     }
-    if (filter_.test(packet->header().payloadType)) {
+    if (filter_.test(packet->header().payloadType) ||
+        (use_ssrc_filter_ && packet->header().ssrc != ssrc_)) {
       // This payload type should be filtered out. Continue to the next packet.
       continue;
     }
     return packet.release();
   }
-  return NULL;
-}
-
-bool RtpFileSource::EndOfFile() const {
-  assert(in_file_);
-  return ftell(in_file_) >= file_end_;
 }
 
 RtpFileSource::RtpFileSource()
     : PacketSource(),
-      in_file_(NULL),
-      file_end_(-1),
       parser_(RtpHeaderParser::Create()) {}
 
 bool RtpFileSource::OpenFile(const std::string& file_name) {
-  in_file_ = fopen(file_name.c_str(), "rb");
-  assert(in_file_);
-  if (in_file_ == NULL) {
-    return false;
-  }
-
-  // Find out how long the file is.
-  fseek(in_file_, 0, SEEK_END);
-  file_end_ = ftell(in_file_);
-  rewind(in_file_);
-  return true;
-}
-
-bool RtpFileSource::SkipFileHeader() {
-  char firstline[kFirstLineLength];
-  assert(in_file_);
-  if (fgets(firstline, kFirstLineLength, in_file_) == NULL) {
-    assert(false);
-    return false;
-  }
-  // Check that the first line is ok.
-  if ((strncmp(firstline, "#!rtpplay1.0", 12) != 0) &&
-      (strncmp(firstline, "#!RTPencode1.0", 14) != 0)) {
-    assert(false);
-    return false;
-  }
-  // Skip the file header.
-  if (fseek(in_file_, kRtpFileHeaderSize, SEEK_CUR) != 0) {
-    assert(false);
-    return false;
+  rtp_reader_.reset(RtpFileReader::Create(RtpFileReader::kRtpDump, file_name));
+  if (rtp_reader_)
+    return true;
+  rtp_reader_.reset(RtpFileReader::Create(RtpFileReader::kPcap, file_name));
+  if (!rtp_reader_) {
+    FATAL() << "Couldn't open input file as either a rtpdump or .pcap. Note "
+               "that .pcapng is not supported.";
   }
   return true;
 }
diff --git a/webrtc/modules/audio_coding/neteq/tools/rtp_file_source.h b/webrtc/modules/audio_coding/neteq/tools/rtp_file_source.h
index 6b92a88..d309280 100644
--- a/webrtc/modules/audio_coding/neteq/tools/rtp_file_source.h
+++ b/webrtc/modules/audio_coding/neteq/tools/rtp_file_source.h
@@ -26,6 +26,8 @@
 
 namespace test {
 
+class RtpFileReader;
+
 class RtpFileSource : public PacketSource {
  public:
   // Creates an RtpFileSource reading from |file_name|. If the file cannot be
@@ -39,10 +41,7 @@
 
   // Returns a pointer to the next packet. Returns NULL if end of file was
   // reached, or if a the data was corrupt.
-  virtual Packet* NextPacket();
-
-  // Returns true if the end of file has been reached.
-  virtual bool EndOfFile() const;
+  virtual Packet* NextPacket() OVERRIDE;
 
  private:
   static const int kFirstLineLength = 40;
@@ -53,10 +52,7 @@
 
   bool OpenFile(const std::string& file_name);
 
-  bool SkipFileHeader();
-
-  FILE* in_file_;
-  int64_t file_end_;
+  scoped_ptr<RtpFileReader> rtp_reader_;
   scoped_ptr<RtpHeaderParser> parser_;
 
   DISALLOW_COPY_AND_ASSIGN(RtpFileSource);