Add pcap support to bwe tools. Allow filtering on SSRCs.

Also switches the command line interface to gflags.

Review URL: https://codereview.webrtc.org/1235433005

Cr-Commit-Position: refs/heads/master@{#9599}
diff --git a/webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimator.gypi b/webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimator.gypi
index 3fca240..f318433 100644
--- a/webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimator.gypi
+++ b/webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimator.gypi
@@ -105,6 +105,7 @@
           'target_name': 'bwe_tools_util',
           'type': 'static_library',
           'dependencies': [
+            '<(DEPTH)/third_party/gflags/gflags.gyp:gflags',
             '<(webrtc_root)/system_wrappers/system_wrappers.gyp:system_wrappers',
             'rtp_rtcp',
           ],
diff --git a/webrtc/modules/remote_bitrate_estimator/tools/bwe_rtp.cc b/webrtc/modules/remote_bitrate_estimator/tools/bwe_rtp.cc
index d424919..7728873 100644
--- a/webrtc/modules/remote_bitrate_estimator/tools/bwe_rtp.cc
+++ b/webrtc/modules/remote_bitrate_estimator/tools/bwe_rtp.cc
@@ -10,9 +10,11 @@
 
 #include "webrtc/modules/remote_bitrate_estimator/tools/bwe_rtp.h"
 
+#include <sstream>
 #include <stdio.h>
 #include <string>
 
+#include "gflags/gflags.h"
 #include "webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimator_abs_send_time.h"
 #include "webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimator_single_stream.h"
 #include "webrtc/modules/rtp_rtcp/interface/rtp_header_parser.h"
@@ -21,6 +23,49 @@
 
 const int kMinBitrateBps = 30000;
 
+namespace flags {
+
+DEFINE_string(extension_type,
+              "abs",
+              "Extension type, either abs for absolute send time or tsoffset "
+              "for timestamp offset.");
+std::string ExtensionType() {
+  return static_cast<std::string>(FLAGS_extension_type);
+}
+
+DEFINE_int32(extension_id, 3, "Extension id.");
+int ExtensionId() {
+  return static_cast<int>(FLAGS_extension_id);
+}
+
+DEFINE_string(input_file, "", "Input file.");
+std::string InputFile() {
+  return static_cast<std::string>(FLAGS_input_file);
+}
+
+DEFINE_string(ssrc_filter,
+              "",
+              "Comma-separated list of SSRCs in hexadecimal which are to be "
+              "used as input to the BWE (only applicable to pcap files).");
+std::set<uint32_t> SsrcFilter() {
+  std::string ssrc_filter_string = static_cast<std::string>(FLAGS_ssrc_filter);
+  if (ssrc_filter_string.empty())
+    return std::set<uint32_t>();
+  std::stringstream ss;
+  std::string ssrc_filter = ssrc_filter_string;
+  std::set<uint32_t> ssrcs;
+
+  // Parse the ssrcs in hexadecimal format.
+  ss << std::hex << ssrc_filter;
+  uint32_t ssrc;
+  while (ss >> ssrc) {
+    ssrcs.insert(ssrc);
+    ss.ignore(1, ',');
+  }
+  return ssrcs;
+}
+}  // namespace flags
+
 bool ParseArgsAndSetupEstimator(int argc,
                                 char** argv,
                                 webrtc::Clock* clock,
@@ -29,26 +74,45 @@
                                 webrtc::RtpHeaderParser** parser,
                                 webrtc::RemoteBitrateEstimator** estimator,
                                 std::string* estimator_used) {
-  *rtp_reader = webrtc::test::RtpFileReader::Create(
-      webrtc::test::RtpFileReader::kRtpDump, argv[3]);
+  google::ParseCommandLineFlags(&argc, &argv, true);
+  std::string filename = flags::InputFile();
+
+  std::set<uint32_t> ssrc_filter = flags::SsrcFilter();
+  fprintf(stderr, "Filter on SSRC: ");
+  for (auto& s : ssrc_filter) {
+    fprintf(stderr, "0x%08x, ", s);
+  }
+  fprintf(stderr, "\n");
+  if (filename.substr(filename.find_last_of(".")) == ".pcap") {
+    fprintf(stderr, "Opening as pcap\n");
+    *rtp_reader = webrtc::test::RtpFileReader::Create(
+        webrtc::test::RtpFileReader::kPcap, filename.c_str(),
+        flags::SsrcFilter());
+  } else {
+    fprintf(stderr, "Opening as rtp\n");
+    *rtp_reader = webrtc::test::RtpFileReader::Create(
+        webrtc::test::RtpFileReader::kRtpDump, filename.c_str());
+  }
   if (!*rtp_reader) {
-    fprintf(stderr, "Cannot open input file %s\n", argv[3]);
+    fprintf(stderr, "Cannot open input file %s\n", filename.c_str());
     return false;
   }
-  fprintf(stderr, "Input file: %s\n\n", argv[3]);
-  webrtc::RTPExtensionType extension = webrtc::kRtpExtensionAbsoluteSendTime;
+  fprintf(stderr, "Input file: %s\n\n", filename.c_str());
 
-  if (strncmp("tsoffset", argv[1], 8) == 0) {
+  webrtc::RTPExtensionType extension = webrtc::kRtpExtensionAbsoluteSendTime;
+  if (flags::ExtensionType() == "tsoffset") {
     extension = webrtc::kRtpExtensionTransmissionTimeOffset;
     fprintf(stderr, "Extension: toffset\n");
-  } else {
+  } else if (flags::ExtensionType() == "abs") {
     fprintf(stderr, "Extension: abs\n");
+  } else {
+    fprintf(stderr, "Unknown extension type\n");
+    return false;
   }
-  int id = atoi(argv[2]);
 
   // Setup the RTP header parser and the bitrate estimator.
   *parser = webrtc::RtpHeaderParser::Create();
-  (*parser)->RegisterRtpHeaderExtension(extension, id);
+  (*parser)->RegisterRtpHeaderExtension(extension, flags::ExtensionId());
   if (estimator) {
     switch (extension) {
       case webrtc::kRtpExtensionAbsoluteSendTime: {
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 9655867..19e4a07 100644
--- a/webrtc/modules/remote_bitrate_estimator/tools/bwe_rtp_play.cc
+++ b/webrtc/modules/remote_bitrate_estimator/tools/bwe_rtp_play.cc
@@ -38,15 +38,6 @@
 };
 
 int main(int argc, char** argv) {
-  if (argc < 4) {
-    printf("Usage: bwe_rtp_play <extension type> <extension id> "
-           "<input_file.rtp>\n");
-    printf("<extension type> can either be:\n"
-           "  abs for absolute send time or\n"
-           "  tsoffset for timestamp offset.\n"
-           "<extension id> is the id associated with the extension.\n");
-    return -1;
-  }
   webrtc::test::RtpFileReader* reader;
   webrtc::RemoteBitrateEstimator* estimator;
   webrtc::RtpHeaderParser* parser;
@@ -76,22 +67,24 @@
   packet.time_ms = packet.time_ms - first_rtp_time_ms;
   while (true) {
     if (next_rtp_time_ms <= clock.TimeInMilliseconds()) {
-      webrtc::RTPHeader header;
-      parser->Parse(packet.data, packet.length, &header);
-      if (header.extension.hasAbsoluteSendTime)
-        ++abs_send_time_count;
-      if (header.extension.hasTransmissionTimeOffset)
-        ++ts_offset_count;
-      size_t packet_length = packet.length;
-      // Some RTP dumps only include the header, in which case packet.length
-      // is equal to the header length. In those cases packet.original_length
-      // usually contains the original packet length.
-      if (packet.original_length > 0) {
-        packet_length = packet.original_length;
+      if (!parser->IsRtcp(packet.data, packet.length)) {
+        webrtc::RTPHeader header;
+        parser->Parse(packet.data, packet.length, &header);
+        if (header.extension.hasAbsoluteSendTime)
+          ++abs_send_time_count;
+        if (header.extension.hasTransmissionTimeOffset)
+          ++ts_offset_count;
+        size_t packet_length = packet.length;
+        // Some RTP dumps only include the header, in which case packet.length
+        // is equal to the header length. In those cases packet.original_length
+        // usually contains the original packet length.
+        if (packet.original_length > 0) {
+          packet_length = packet.original_length;
+        }
+        rbe->IncomingPacket(clock.TimeInMilliseconds(),
+                            packet_length - header.headerLength, header, true);
+        ++packet_counter;
       }
-      rbe->IncomingPacket(clock.TimeInMilliseconds(),
-                          packet_length - header.headerLength, header, true);
-      ++packet_counter;
       if (!rtp_reader->NextPacket(&packet)) {
         break;
       }
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 f2ff7df..e277481 100644
--- a/webrtc/modules/remote_bitrate_estimator/tools/rtp_to_text.cc
+++ b/webrtc/modules/remote_bitrate_estimator/tools/rtp_to_text.cc
@@ -19,17 +19,6 @@
 #include "webrtc/test/rtp_file_reader.h"
 
 int main(int argc, char** argv) {
-  if (argc < 4) {
-    fprintf(stderr, "Usage: rtp_to_text <extension type> <extension id>"
-           " <input_file.rtp> [-t]\n");
-    fprintf(stderr, "<extension type> can either be:\n"
-           "  abs for absolute send time or\n"
-           "  tsoffset for timestamp offset.\n"
-           "<extension id> is the id associated with the extension.\n"
-           "  -t is an optional flag, if set only packet arrival time will be"
-           " output.\n");
-    return -1;
-  }
   webrtc::test::RtpFileReader* reader;
   webrtc::RtpHeaderParser* parser;
   if (!ParseArgsAndSetupEstimator(argc, argv, NULL, NULL, &reader, &parser,
diff --git a/webrtc/test/rtp_file_reader.cc b/webrtc/test/rtp_file_reader.cc
index 26151bb..c1a0bc8 100644
--- a/webrtc/test/rtp_file_reader.cc
+++ b/webrtc/test/rtp_file_reader.cc
@@ -69,7 +69,8 @@
 
 class RtpFileReaderImpl : public RtpFileReader {
  public:
-  virtual bool Init(const std::string& filename) = 0;
+  virtual bool Init(const std::string& filename,
+                    const std::set<uint32_t>& ssrc_filter) = 0;
 };
 
 class InterleavedRtpFileReader : public RtpFileReaderImpl {
@@ -81,7 +82,8 @@
     }
   }
 
-  virtual bool Init(const std::string& filename) {
+  virtual bool Init(const std::string& filename,
+                    const std::set<uint32_t>& ssrc_filter) {
     file_ = fopen(filename.c_str(), "rb");
     if (file_ == NULL) {
       printf("ERROR: Can't open file: %s\n", filename.c_str());
@@ -127,7 +129,8 @@
     }
   }
 
-  bool Init(const std::string& filename) {
+  bool Init(const std::string& filename,
+            const std::set<uint32_t>& ssrc_filter) {
     file_ = fopen(filename.c_str(), "rb");
     if (file_ == NULL) {
       printf("ERROR: Can't open file: %s\n", filename.c_str());
@@ -265,11 +268,13 @@
     }
   }
 
-  bool Init(const std::string& filename) override {
-    return Initialize(filename) == kResultSuccess;
+  bool Init(const std::string& filename,
+            const std::set<uint32_t>& ssrc_filter) override {
+    return Initialize(filename, ssrc_filter) == kResultSuccess;
   }
 
-  int Initialize(const std::string& filename) {
+  int Initialize(const std::string& filename,
+                 const std::set<uint32_t>& ssrc_filter) {
     file_ = fopen(filename.c_str(), "rb");
     if (file_ == NULL) {
       printf("ERROR: Can't open file: %s\n", filename.c_str());
@@ -286,7 +291,7 @@
     for (;;) {
       TRY_PCAP(fseek(file_, next_packet_pos, SEEK_SET));
       int result = ReadPacket(&next_packet_pos, stream_start_ms,
-                              ++total_packet_count);
+                              ++total_packet_count, ssrc_filter);
       if (result == kResultFail) {
         break;
       } else if (result == kResultSuccess && packets_.size() == 1) {
@@ -308,10 +313,10 @@
     for (SsrcMapIterator mit = packets_by_ssrc_.begin();
         mit != packets_by_ssrc_.end(); ++mit) {
       uint32_t ssrc = mit->first;
-      const std::vector<uint32_t>& packet_numbers = mit->second;
-      uint8_t pt = packets_[packet_numbers[0]].rtp_header.payloadType;
+      const std::vector<uint32_t>& packet_indices = mit->second;
+      uint8_t pt = packets_[packet_indices[0]].rtp_header.payloadType;
       printf("SSRC: %08x, %" PRIuS " packets, pt=%d\n", ssrc,
-             packet_numbers.size(), pt);
+             packet_indices.size(), pt);
     }
 
     // TODO(solenberg): Better validation of identified SSRC streams.
@@ -419,8 +424,10 @@
     return kResultSuccess;
   }
 
-  int ReadPacket(int32_t* next_packet_pos, uint32_t stream_start_ms,
-                 uint32_t number) {
+  int ReadPacket(int32_t* next_packet_pos,
+                 uint32_t stream_start_ms,
+                 uint32_t number,
+                 const std::set<uint32_t>& ssrc_filter) {
     assert(next_packet_pos);
 
     uint32_t ts_sec;    // Timestamp seconds.
@@ -457,8 +464,13 @@
       }
 
       uint32_t ssrc = marker.rtp_header.ssrc;
-      packets_by_ssrc_[ssrc].push_back(marker.packet_number);
-      packets_.push_back(marker);
+      if (ssrc_filter.empty() || ssrc_filter.find(ssrc) != ssrc_filter.end()) {
+        packets_by_ssrc_[ssrc].push_back(
+            static_cast<uint32_t>(packets_.size()));
+        packets_.push_back(marker);
+      } else {
+        return kResultSkip;
+      }
     }
 
     return kResultSuccess;
@@ -632,7 +644,8 @@
 };
 
 RtpFileReader* RtpFileReader::Create(FileFormat format,
-                                     const std::string& filename) {
+                                     const std::string& filename,
+                                     const std::set<uint32_t>& ssrc_filter) {
   RtpFileReaderImpl* reader = NULL;
   switch (format) {
     case kPcap:
@@ -645,12 +658,17 @@
       reader = new InterleavedRtpFileReader();
       break;
   }
-  if (!reader->Init(filename)) {
+  if (!reader->Init(filename, ssrc_filter)) {
     delete reader;
     return NULL;
   }
   return reader;
 }
 
+RtpFileReader* RtpFileReader::Create(FileFormat format,
+                                     const std::string& filename) {
+  return RtpFileReader::Create(format, filename, std::set<uint32_t>());
+}
+
 }  // namespace test
 }  // namespace webrtc
diff --git a/webrtc/test/rtp_file_reader.h b/webrtc/test/rtp_file_reader.h
index c302d4f..c132d31 100644
--- a/webrtc/test/rtp_file_reader.h
+++ b/webrtc/test/rtp_file_reader.h
@@ -10,6 +10,7 @@
 #ifndef WEBRTC_TEST_RTP_FILE_READER_H_
 #define WEBRTC_TEST_RTP_FILE_READER_H_
 
+#include <set>
 #include <string>
 
 #include "webrtc/common_types.h"
@@ -37,6 +38,9 @@
   virtual ~RtpFileReader() {}
   static RtpFileReader* Create(FileFormat format,
                                const std::string& filename);
+  static RtpFileReader* Create(FileFormat format,
+                               const std::string& filename,
+                               const std::set<uint32_t>& ssrc_filter);
 
   virtual bool NextPacket(RtpPacket* packet) = 0;
 };