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
This commit is contained in:
stefan@webrtc.org 2014-01-31 09:15:48 +00:00
parent 668a23b402
commit 1dd9b4d98e
6 changed files with 359 additions and 2 deletions

View File

@ -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
}

View File

@ -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 <stdio.h>
#include <string>
#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;
}

View File

@ -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 <string>
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_

View File

@ -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 <stdio.h>
#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<unsigned int>& ssrcs,
unsigned int bitrate) {
printf("[%u] Num SSRCs: %d, bitrate: %u\n",
static_cast<uint32_t>(clock_->TimeInMilliseconds()),
static_cast<int>(ssrcs.size()), bitrate);
}
virtual ~Observer() {}
private:
webrtc::Clock* clock_;
};
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;
}
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<RtpPacketSourceInterface> rtp_reader(reader);
webrtc::scoped_ptr<webrtc::RtpHeaderParser> rtp_parser(parser);
webrtc::scoped_ptr<webrtc::RemoteBitrateEstimator> 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<uint32_t>(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;
}

View File

@ -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 <stdio.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;
int main(int argc, char** argv) {
if (argc < 5) {
printf("Usage: rtp_to_text <extension type> <extension id> <input_file.rtp>"
" <output_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;
}
RtpPacketSourceInterface* reader;
webrtc::RtpHeaderParser* parser;
if (!ParseArgsAndSetupEstimator(argc, argv, NULL, NULL, &reader, &parser,
NULL, NULL)) {
return -1;
}
webrtc::scoped_ptr<RtpPacketSourceInterface> rtp_reader(reader);
webrtc::scoped_ptr<webrtc::RtpHeaderParser> 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;
}

View File

@ -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;
}