summaryrefslogtreecommitdiffstats
path: root/media
diff options
context:
space:
mode:
authorhubbe@chromium.org <hubbe@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-05-09 01:33:53 +0000
committerhubbe@chromium.org <hubbe@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-05-09 01:33:53 +0000
commit4c10bf30f3281897804c9158063495b212f537da (patch)
tree0eb8fefc358d6cdf20f744550d091ea7488b1938 /media
parentbd519e3d886c0ee43f98af66c061216c5c6b404b (diff)
downloadchromium_src-4c10bf30f3281897804c9158063495b212f537da.zip
chromium_src-4c10bf30f3281897804c9158063495b212f537da.tar.gz
chromium_src-4c10bf30f3281897804c9158063495b212f537da.tar.bz2
Add another network profile to the udp proxy.
This adds a network profile called "bad" which is somewhere in between "wifi" and "evil". Also add bandwidth monitoring to the standalone program. Review URL: https://codereview.chromium.org/261013014 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@269136 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'media')
-rw-r--r--media/cast/test/utility/udp_proxy.cc20
-rw-r--r--media/cast/test/utility/udp_proxy.h6
-rw-r--r--media/cast/test/utility/udp_proxy_main.cc116
3 files changed, 139 insertions, 3 deletions
diff --git a/media/cast/test/utility/udp_proxy.cc b/media/cast/test/utility/udp_proxy.cc
index eed3744..1132815 100644
--- a/media/cast/test/utility/udp_proxy.cc
+++ b/media/cast/test/utility/udp_proxy.cc
@@ -385,6 +385,24 @@ scoped_ptr<PacketPipe> WifiNetwork() {
return pipe.Pass();
}
+scoped_ptr<PacketPipe> BadNetwork() {
+ scoped_ptr<PacketPipe> pipe;
+ // This represents the buffer on the sender.
+ BuildPipe(&pipe, new Buffer(64 << 10, 5000000)); // 64 kb buf, 5mbit/s
+ BuildPipe(&pipe, new RandomDrop(0.05)); // 5% packet drop
+ BuildPipe(&pipe, new RandomSortedDelay(2E-3, 20E-3, 1));
+ // This represents the buffer on the router.
+ BuildPipe(&pipe, new Buffer(64 << 10, 2000000)); // 64 kb buf, 2mbit/s
+ BuildPipe(&pipe, new ConstantDelay(1E-3));
+ // Random 40ms every other second
+ // BuildPipe(&pipe, new NetworkGlitchPipe(2, 40E-1));
+ BuildPipe(&pipe, new RandomUnsortedDelay(5E-3));
+ // This represents the buffer on the receiving device.
+ BuildPipe(&pipe, new Buffer(64 << 10, 4000000)); // 64 kb buf, 4mbit/s
+ return pipe.Pass();
+}
+
+
scoped_ptr<PacketPipe> EvilNetwork() {
// This represents the buffer on the sender.
scoped_ptr<PacketPipe> pipe;
@@ -413,7 +431,7 @@ class UDPProxyImpl : public UDPProxy {
destination_(destination),
proxy_thread_("media::cast::test::UdpProxy Thread"),
to_dest_pipe_(to_dest_pipe.Pass()),
- from_dest_pipe_(to_dest_pipe.Pass()) {
+ from_dest_pipe_(from_dest_pipe.Pass()) {
proxy_thread_.StartWithOptions(
base::Thread::Options(base::MessageLoop::TYPE_IO, 0));
base::WaitableEvent start_event(false, false);
diff --git a/media/cast/test/utility/udp_proxy.h b/media/cast/test/utility/udp_proxy.h
index 41c686e..9dce0cf 100644
--- a/media/cast/test/utility/udp_proxy.h
+++ b/media/cast/test/utility/udp_proxy.h
@@ -93,8 +93,14 @@ scoped_ptr<PacketPipe> NewNetworkGlitchPipe(double average_work_time,
// good wifi network. ~5mbit, 1% packet loss, ~3ms latency.
scoped_ptr<PacketPipe> WifiNetwork();
+// This method builds a stack of PacketPipes to emulate a
+// bad wifi network. ~2mbit, 5% packet loss, ~7ms latency
+// 40ms dropouts every ~2 seconds. Can reorder packets.
+scoped_ptr<PacketPipe> BadNetwork();
+
// This method builds a stack of PacketPipes to emulate a crappy wifi network.
// ~1mbit, 20% packet loss, ~40ms latency and packets can get reordered.
+// 300ms drouputs every ~2 seconds.
scoped_ptr<PacketPipe> EvilNetwork();
} // namespace test
diff --git a/media/cast/test/utility/udp_proxy_main.cc b/media/cast/test/utility/udp_proxy_main.cc
index 68a885f..0202d8c 100644
--- a/media/cast/test/utility/udp_proxy_main.cc
+++ b/media/cast/test/utility/udp_proxy_main.cc
@@ -4,6 +4,7 @@
#include <cstdio>
#include <cstdlib>
+#include <deque>
#include <string>
#include "base/at_exit.h"
@@ -13,11 +14,112 @@
#include "base/message_loop/message_loop.h"
#include "media/cast/test/utility/udp_proxy.h"
+base::TimeTicks last_printout;
+
+class ByteCounter {
+ public:
+ ByteCounter() : bytes_(0), packets_(0) {
+ push(base::TimeTicks::Now());
+ }
+
+ base::TimeDelta time_range() {
+ return time_data_.back() - time_data_.front();
+ }
+
+ void push(base::TimeTicks now) {
+ byte_data_.push_back(bytes_);
+ packet_data_.push_back(packets_);
+ time_data_.push_back(now);
+ while (time_range().InSeconds() > 10) {
+ byte_data_.pop_front();
+ packet_data_.pop_front();
+ time_data_.pop_front();
+ }
+ }
+
+ double megabits_per_second() {
+ double megabits = (byte_data_.back() - byte_data_.front()) * 8 / 1E6;
+ return megabits / time_range().InSecondsF();
+ }
+
+ double packets_per_second() {
+ double packets = packet_data_.back()- packet_data_.front();
+ return packets / time_range().InSecondsF();
+ }
+
+ void Increment(uint64 x) {
+ bytes_ += x;
+ packets_ ++;
+ }
+
+ private:
+ uint64 bytes_;
+ uint64 packets_;
+ std::deque<uint64> byte_data_;
+ std::deque<uint64> packet_data_;
+ std::deque<base::TimeTicks> time_data_;
+};
+
+ByteCounter in_pipe_input_counter;
+ByteCounter in_pipe_output_counter;
+ByteCounter out_pipe_input_counter;
+ByteCounter out_pipe_output_counter;
+
+class ByteCounterPipe : public media::cast::test::PacketPipe {
+ public:
+ ByteCounterPipe(ByteCounter* counter) : counter_(counter) {}
+ virtual void Send(scoped_ptr<media::cast::transport::Packet> packet)
+ OVERRIDE {
+ counter_->Increment(packet->size());
+ pipe_->Send(packet.Pass());
+ }
+ private:
+ ByteCounter* counter_;
+};
+
+void SetupByteCounters(scoped_ptr<media::cast::test::PacketPipe>* pipe,
+ ByteCounter* pipe_input_counter,
+ ByteCounter* pipe_output_counter) {
+ media::cast::test::PacketPipe* new_pipe =
+ new ByteCounterPipe(pipe_input_counter);
+ new_pipe->AppendToPipe(pipe->Pass());
+ new_pipe->AppendToPipe(
+ scoped_ptr<media::cast::test::PacketPipe>(
+ new ByteCounterPipe(pipe_output_counter)).Pass());
+ pipe->reset(new_pipe);
+}
+
+void CheckByteCounters() {
+ base::TimeTicks now = base::TimeTicks::Now();
+ in_pipe_input_counter.push(now);
+ in_pipe_output_counter.push(now);
+ out_pipe_input_counter.push(now);
+ out_pipe_output_counter.push(now);
+ if ((now - last_printout).InSeconds() >= 5) {
+ fprintf(stderr, "Sending : %5.2f / %5.2f mbps %6.2f / %6.2f packets / s\n",
+ in_pipe_output_counter.megabits_per_second(),
+ in_pipe_input_counter.megabits_per_second(),
+ in_pipe_output_counter.packets_per_second(),
+ in_pipe_input_counter.packets_per_second());
+ fprintf(stderr, "Receiving: %5.2f / %5.2f mbps %6.2f / %6.2f packets / s\n",
+ out_pipe_output_counter.megabits_per_second(),
+ out_pipe_input_counter.megabits_per_second(),
+ out_pipe_output_counter.packets_per_second(),
+ out_pipe_input_counter.packets_per_second());
+
+ last_printout = now;
+ }
+ base::MessageLoopProxy::current()->PostDelayedTask(
+ FROM_HERE,
+ base::Bind(&CheckByteCounters),
+ base::TimeDelta::FromMilliseconds(100));
+}
+
int main(int argc, char** argv) {
if (argc < 5) {
fprintf(stderr,
"Usage: udp_proxy <localport> <remotehost> <remoteport> <type>\n"
- "Where type is one of: perfect, wifi, evil\n");
+ "Where type is one of: perfect, wifi, bad, evil\n");
exit(1);
}
@@ -42,6 +144,9 @@ int main(int argc, char** argv) {
} else if (network_type == "wifi") {
in_pipe = media::cast::test::WifiNetwork().Pass();
out_pipe = media::cast::test::WifiNetwork().Pass();
+ } else if (network_type == "bad") {
+ in_pipe = media::cast::test::BadNetwork().Pass();
+ out_pipe = media::cast::test::BadNetwork().Pass();
} else if (network_type == "evil") {
in_pipe = media::cast::test::EvilNetwork().Pass();
out_pipe = media::cast::test::EvilNetwork().Pass();
@@ -50,6 +155,10 @@ int main(int argc, char** argv) {
exit(1);
}
+ SetupByteCounters(&in_pipe, &in_pipe_input_counter, &in_pipe_output_counter);
+ SetupByteCounters(
+ &out_pipe, &out_pipe_input_counter, &out_pipe_output_counter);
+
printf("Press Ctrl-C when done.\n");
scoped_ptr<media::cast::test::UDPProxy> proxy(
media::cast::test::UDPProxy::Create(local_endpoint,
@@ -57,6 +166,9 @@ int main(int argc, char** argv) {
in_pipe.Pass(),
out_pipe.Pass(),
NULL));
- base::MessageLoop().Run(); // Run forever.
+ base::MessageLoop message_loop;
+ last_printout = base::TimeTicks::Now();
+ CheckByteCounters();
+ message_loop.Run();
return 1;
}