diff --git a/webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimator.gypi b/webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimator.gypi index 3fca240d4e..f318433db7 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 d424919f7a..7728873db8 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 #include #include +#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(FLAGS_extension_type); +} + +DEFINE_int32(extension_id, 3, "Extension id."); +int ExtensionId() { + return static_cast(FLAGS_extension_id); +} + +DEFINE_string(input_file, "", "Input file."); +std::string InputFile() { + return static_cast(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 SsrcFilter() { + std::string ssrc_filter_string = static_cast(FLAGS_ssrc_filter); + if (ssrc_filter_string.empty()) + return std::set(); + std::stringstream ss; + std::string ssrc_filter = ssrc_filter_string; + std::set 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 @@ bool ParseArgsAndSetupEstimator(int argc, 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 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 965586757d..19e4a07b4d 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 @@ class Observer : public webrtc::RemoteBitrateObserver { }; int main(int argc, char** argv) { - if (argc < 4) { - printf("Usage: bwe_rtp_play " - "\n"); - printf(" can either be:\n" - " abs for absolute send time or\n" - " tsoffset for timestamp offset.\n" - " is the id associated with the extension.\n"); - return -1; - } webrtc::test::RtpFileReader* reader; webrtc::RemoteBitrateEstimator* estimator; webrtc::RtpHeaderParser* parser; @@ -76,22 +67,24 @@ int main(int argc, char** argv) { 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 f2ff7dfb85..e277481886 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 " - " [-t]\n"); - fprintf(stderr, " can either be:\n" - " abs for absolute send time or\n" - " tsoffset for timestamp offset.\n" - " 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 26151bba1f..c1a0bc81a2 100644 --- a/webrtc/test/rtp_file_reader.cc +++ b/webrtc/test/rtp_file_reader.cc @@ -69,7 +69,8 @@ bool ReadUint16(uint16_t* out, FILE* file) { class RtpFileReaderImpl : public RtpFileReader { public: - virtual bool Init(const std::string& filename) = 0; + virtual bool Init(const std::string& filename, + const std::set& ssrc_filter) = 0; }; class InterleavedRtpFileReader : public RtpFileReaderImpl { @@ -81,7 +82,8 @@ class InterleavedRtpFileReader : public RtpFileReaderImpl { } } - virtual bool Init(const std::string& filename) { + virtual bool Init(const std::string& filename, + const std::set& 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 @@ class RtpDumpReader : public RtpFileReaderImpl { } } - bool Init(const std::string& filename) { + bool Init(const std::string& filename, + const std::set& 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 @@ class PcapReader : public RtpFileReaderImpl { } } - bool Init(const std::string& filename) override { - return Initialize(filename) == kResultSuccess; + bool Init(const std::string& filename, + const std::set& ssrc_filter) override { + return Initialize(filename, ssrc_filter) == kResultSuccess; } - int Initialize(const std::string& filename) { + int Initialize(const std::string& filename, + const std::set& 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 @@ class PcapReader : public RtpFileReaderImpl { 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 @@ class PcapReader : public RtpFileReaderImpl { for (SsrcMapIterator mit = packets_by_ssrc_.begin(); mit != packets_by_ssrc_.end(); ++mit) { uint32_t ssrc = mit->first; - const std::vector& packet_numbers = mit->second; - uint8_t pt = packets_[packet_numbers[0]].rtp_header.payloadType; + const std::vector& 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 @@ class PcapReader : public RtpFileReaderImpl { 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& ssrc_filter) { assert(next_packet_pos); uint32_t ts_sec; // Timestamp seconds. @@ -457,8 +464,13 @@ class PcapReader : public RtpFileReaderImpl { } 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(packets_.size())); + packets_.push_back(marker); + } else { + return kResultSkip; + } } return kResultSuccess; @@ -632,7 +644,8 @@ class PcapReader : public RtpFileReaderImpl { }; RtpFileReader* RtpFileReader::Create(FileFormat format, - const std::string& filename) { + const std::string& filename, + const std::set& ssrc_filter) { RtpFileReaderImpl* reader = NULL; switch (format) { case kPcap: @@ -645,12 +658,17 @@ RtpFileReader* RtpFileReader::Create(FileFormat format, 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()); +} + } // namespace test } // namespace webrtc diff --git a/webrtc/test/rtp_file_reader.h b/webrtc/test/rtp_file_reader.h index c302d4fbde..c132d318fd 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 #include #include "webrtc/common_types.h" @@ -37,6 +38,9 @@ class RtpFileReader { virtual ~RtpFileReader() {} static RtpFileReader* Create(FileFormat format, const std::string& filename); + static RtpFileReader* Create(FileFormat format, + const std::string& filename, + const std::set& ssrc_filter); virtual bool NextPacket(RtpPacket* packet) = 0; };