From 1dd9b4d98e2f281d63f1f76a9b144699aca169b3 Mon Sep 17 00:00:00 2001 From: "stefan@webrtc.org" Date: Fri, 31 Jan 2014 09:15:48 +0000 Subject: [PATCH] Add BWE tools for parsing RTP files. bwe_rtp_play feeds packets from an RTP file into the BWE and prints the estimates. bwe_rtp_to_text parses an RTP file and outputs the result to a text file. R=henrik.lundin@webrtc.org Review URL: https://webrtc-codereview.appspot.com/7689006 git-svn-id: http://webrtc.googlecode.com/svn/trunk@5466 4adac7df-926f-26a2-2b94-8c16560cd09d --- .../remote_bitrate_estimator.gypi | 56 +++++++++ .../remote_bitrate_estimator/tools/bwe_rtp.cc | 72 +++++++++++ .../remote_bitrate_estimator/tools/bwe_rtp.h | 36 ++++++ .../tools/bwe_rtp_play.cc | 116 ++++++++++++++++++ .../tools/rtp_to_text.cc | 76 ++++++++++++ .../video_coding/main/test/rtp_player.cc | 5 +- 6 files changed, 359 insertions(+), 2 deletions(-) create mode 100644 webrtc/modules/remote_bitrate_estimator/tools/bwe_rtp.cc create mode 100644 webrtc/modules/remote_bitrate_estimator/tools/bwe_rtp.h create mode 100644 webrtc/modules/remote_bitrate_estimator/tools/bwe_rtp_play.cc create mode 100644 webrtc/modules/remote_bitrate_estimator/tools/rtp_to_text.cc diff --git a/webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimator.gypi b/webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimator.gypi index bbd353fcdd..810da4622b 100644 --- a/webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimator.gypi +++ b/webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimator.gypi @@ -27,5 +27,61 @@ 'rtp_to_ntp.cc', ], # source }, + { + 'target_name': 'bwe_tools_util', + 'type': 'static_library', + 'dependencies': [ + '<(webrtc_root)/system_wrappers/source/system_wrappers.gyp:system_wrappers', + 'rtp_rtcp', + ], + 'sources': [ + 'tools/bwe_rtp.cc', + 'tools/bwe_rtp.h', + ], + }, + { + 'target_name': 'bwe_rtp_to_text', + 'type': 'executable', + 'includes': [ + '../rtp_rtcp/source/rtp_rtcp.gypi', + ], + 'dependencies': [ + '<(webrtc_root)/system_wrappers/source/system_wrappers.gyp:system_wrappers', + 'bwe_tools_util', + 'rtp_rtcp', + ], + 'direct_dependent_settings': { + 'include_dirs': [ + 'include', + ], + }, + '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', + ], # source + }, + { + 'target_name': 'bwe_rtp_play', + 'type': 'executable', + 'includes': [ + '../rtp_rtcp/source/rtp_rtcp.gypi', + ], + 'dependencies': [ + '<(webrtc_root)/system_wrappers/source/system_wrappers.gyp:system_wrappers', + 'bwe_tools_util', + 'rtp_rtcp', + ], + 'direct_dependent_settings': { + 'include_dirs': [ + 'include', + ], + }, + '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', + ], # source + }, ], # targets } diff --git a/webrtc/modules/remote_bitrate_estimator/tools/bwe_rtp.cc b/webrtc/modules/remote_bitrate_estimator/tools/bwe_rtp.cc new file mode 100644 index 0000000000..688d9d46c5 --- /dev/null +++ b/webrtc/modules/remote_bitrate_estimator/tools/bwe_rtp.cc @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#include "webrtc/modules/remote_bitrate_estimator/tools/bwe_rtp.h" + +#include +#include + +#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; + +const int kMinBitrateBps = 30000; + +bool ParseArgsAndSetupEstimator(int argc, + char** argv, + webrtc::Clock* clock, + webrtc::RemoteBitrateObserver* observer, + RtpPacketSourceInterface** rtp_reader, + webrtc::RtpHeaderParser** parser, + webrtc::RemoteBitrateEstimator** estimator, + std::string* estimator_used) { + *rtp_reader = webrtc::rtpplayer::CreateRtpFileReader(argv[3]); + if (!*rtp_reader) { + printf("Cannot open input file %s\n", argv[3]); + return false; + } + printf("Input file: %s\n\n", argv[3]); + webrtc::RTPExtensionType extension = webrtc::kRtpExtensionAbsoluteSendTime; + + if (strncmp("tsoffset", argv[1], 8) == 0) { + extension = webrtc::kRtpExtensionTransmissionTimeOffset; + printf("Extension: toffset\n"); + } else { + printf("Extension: abs\n"); + } + int id = atoi(argv[2]); + + // Setup the RTP header parser and the bitrate estimator. + *parser = webrtc::RtpHeaderParser::Create(); + (*parser)->RegisterRtpHeaderExtension(extension, id); + if (estimator) { + switch (extension) { + case webrtc::kRtpExtensionAbsoluteSendTime: { + webrtc::AbsoluteSendTimeRemoteBitrateEstimatorFactory factory; + *estimator = factory.Create(observer, clock, kMinBitrateBps); + *estimator_used = "AbsoluteSendTimeRemoteBitrateEstimator"; + break; + } + case webrtc::kRtpExtensionTransmissionTimeOffset: { + webrtc::RemoteBitrateEstimatorFactory factory; + *estimator = factory.Create(observer, clock, kMinBitrateBps); + *estimator_used = "RemoteBitrateEstimator"; + break; + } + default: + assert(false); + } + } + return true; +} diff --git a/webrtc/modules/remote_bitrate_estimator/tools/bwe_rtp.h b/webrtc/modules/remote_bitrate_estimator/tools/bwe_rtp.h new file mode 100644 index 0000000000..714457d566 --- /dev/null +++ b/webrtc/modules/remote_bitrate_estimator/tools/bwe_rtp.h @@ -0,0 +1,36 @@ +/* + * 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_MODULES_REMOTE_BITRATE_ESTIMATOR_TOOLS_BWE_RTP_H_ +#define WEBRTC_MODULES_REMOTE_BITRATE_ESTIMATOR_TOOLS_BWE_RTP_H_ + +#include + +namespace webrtc { +class Clock; +class RemoteBitrateEstimator; +class RemoteBitrateObserver; +class RtpHeaderParser; +namespace rtpplayer { +class RtpPacketSourceInterface; +} +} + +bool ParseArgsAndSetupEstimator( + int argc, + char** argv, + webrtc::Clock* clock, + webrtc::RemoteBitrateObserver* observer, + webrtc::rtpplayer::RtpPacketSourceInterface** rtp_reader, + webrtc::RtpHeaderParser** parser, + webrtc::RemoteBitrateEstimator** estimator, + std::string* estimator_used); + +#endif // WEBRTC_MODULES_REMOTE_BITRATE_ESTIMATOR_TOOLS_BWE_RTP_H_ diff --git a/webrtc/modules/remote_bitrate_estimator/tools/bwe_rtp_play.cc b/webrtc/modules/remote_bitrate_estimator/tools/bwe_rtp_play.cc new file mode 100644 index 0000000000..9ea3f08eab --- /dev/null +++ b/webrtc/modules/remote_bitrate_estimator/tools/bwe_rtp_play.cc @@ -0,0 +1,116 @@ +/* + * 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 + +#include "webrtc/modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h" +#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; + +class Observer : public webrtc::RemoteBitrateObserver { + public: + explicit Observer(webrtc::Clock* clock) : clock_(clock) {} + + // Called when a receive channel group has a new bitrate estimate for the + // incoming streams. + virtual void OnReceiveBitrateChanged(const std::vector& ssrcs, + unsigned int bitrate) { + printf("[%u] Num SSRCs: %d, bitrate: %u\n", + static_cast(clock_->TimeInMilliseconds()), + static_cast(ssrcs.size()), bitrate); + } + + virtual ~Observer() {} + + private: + webrtc::Clock* clock_; +}; + +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; + } + RtpPacketSourceInterface* reader; + webrtc::RemoteBitrateEstimator* estimator; + webrtc::RtpHeaderParser* parser; + std::string estimator_used; + webrtc::SimulatedClock clock(0); + Observer observer(&clock); + if (!ParseArgsAndSetupEstimator(argc, argv, &clock, &observer, &reader, + &parser, &estimator, &estimator_used)) { + return -1; + } + webrtc::scoped_ptr rtp_reader(reader); + webrtc::scoped_ptr rtp_parser(parser); + webrtc::scoped_ptr rbe(estimator); + + // Process the file. + int packet_counter = 0; + 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) { + 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; + webrtc::RTPHeader header; + parser->Parse(packet, 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, + header); + ++packet_counter; + } + next_process_time_ms = rbe->TimeUntilNextProcess() + + clock.TimeInMilliseconds(); + if (next_process_time_ms <= clock.TimeInMilliseconds()) { + rbe->Process(); + } + int time_until_next_event = + std::min(next_process_time_ms, next_rtp_time_ms) - + clock.TimeInMilliseconds(); + clock.AdvanceTimeMilliseconds(std::max(time_until_next_event, 0)); + } + printf("Parsed %d packets\nTime passed: %u ms\n", packet_counter, + static_cast(clock.TimeInMilliseconds())); + printf("Estimator used: %s\n", estimator_used.c_str()); + printf("Packets with non-zero absolute send time: %d\n", + non_zero_abs_send_time); + printf("Packets with non-zero timestamp offset: %d\n", + non_zero_ts_offsets); + return 0; +} diff --git a/webrtc/modules/remote_bitrate_estimator/tools/rtp_to_text.cc b/webrtc/modules/remote_bitrate_estimator/tools/rtp_to_text.cc new file mode 100644 index 0000000000..2c69f25a1f --- /dev/null +++ b/webrtc/modules/remote_bitrate_estimator/tools/rtp_to_text.cc @@ -0,0 +1,76 @@ +/* + * 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 + +#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; + +int main(int argc, char** argv) { + if (argc < 5) { + printf("Usage: rtp_to_text " + " \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; + } + RtpPacketSourceInterface* reader; + webrtc::RtpHeaderParser* parser; + if (!ParseArgsAndSetupEstimator(argc, argv, NULL, NULL, &reader, &parser, + NULL, NULL)) { + return -1; + } + webrtc::scoped_ptr rtp_reader(reader); + webrtc::scoped_ptr rtp_parser(parser); + + FILE* out_file = fopen(argv[4], "wt"); + if (!out_file) + printf("Cannot open output file %s\n", argv[4]); + + printf("Output file: %s\n\n", argv[4]); + fprintf(out_file, "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::RTPHeader header = {}; + parser->Parse(packet, packet_length, &header); + if (header.extension.absoluteSendTime != 0) + ++non_zero_abs_send_time; + if (header.extension.transmissionTimeOffset != 0) + ++non_zero_ts_offsets; + fprintf(out_file, "%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); + packet_length = kMaxPacketSize; + ++packet_counter; + } + printf("Parsed %d packets\n", packet_counter); + printf("Packets with non-zero absolute send time: %d\n", + non_zero_abs_send_time); + printf("Packets with non-zero timestamp offset: %d\n", + non_zero_ts_offsets); + return 0; +} diff --git a/webrtc/modules/video_coding/main/test/rtp_player.cc b/webrtc/modules/video_coding/main/test/rtp_player.cc index 99651431b8..4c157a7168 100644 --- a/webrtc/modules/video_coding/main/test/rtp_player.cc +++ b/webrtc/modules/video_coding/main/test/rtp_player.cc @@ -203,7 +203,7 @@ class SsrcHandlers { } } - int RegisterSsrc(uint32_t ssrc, LostPackets* lost_packets) { + int RegisterSsrc(uint32_t ssrc, LostPackets* lost_packets, Clock* clock) { if (handlers_.count(ssrc) > 0) { return 0; } @@ -217,6 +217,7 @@ class SsrcHandlers { } RtpRtcp::Configuration configuration; + configuration.clock = clock; configuration.id = 1; configuration.audio = false; handler->rtp_module_.reset(RtpReceiver::CreateVideoReceiver( @@ -434,7 +435,7 @@ class RtpPlayerImpl : public RtpPlayerInterface { return -1; } uint32_t ssrc = header.ssrc; - if (ssrc_handlers_.RegisterSsrc(ssrc, &lost_packets_) < 0) { + if (ssrc_handlers_.RegisterSsrc(ssrc, &lost_packets_, clock_) < 0) { DEBUG_LOG1("Unable to register ssrc: %d", ssrc); return -1; }