From bfe6e081952540bd74b62627a3b910208e33c490 Mon Sep 17 00:00:00 2001 From: "stefan@webrtc.org" Date: Thu, 31 Jul 2014 12:30:18 +0000 Subject: [PATCH] Add simulation of network effects to video_loopback tool. Also add support for uniform random packet loss to the fake network pipe. R=pbos@webrtc.org Review URL: https://webrtc-codereview.appspot.com/14039004 git-svn-id: http://webrtc.googlecode.com/svn/trunk@6803 4adac7df-926f-26a2-2b94-8c16560cd09d --- webrtc/test/fake_network_pipe.cc | 11 ++++++++ webrtc/test/fake_network_pipe.h | 2 +- webrtc/video/loopback.cc | 48 +++++++++++++++++++++++++++++++- 3 files changed, 59 insertions(+), 2 deletions(-) diff --git a/webrtc/test/fake_network_pipe.cc b/webrtc/test/fake_network_pipe.cc index 06bf062bf4..c88205b8d6 100644 --- a/webrtc/test/fake_network_pipe.cc +++ b/webrtc/test/fake_network_pipe.cc @@ -33,6 +33,11 @@ static int GaussianRandom(int mean_delay_ms, int standard_deviation_ms) { sqrt(-2 * log(uniform1)) * cos(2 * kPi * uniform2)); } +static bool UniformLoss(int loss_percent) { + int outcome = rand() % 100; + return outcome < loss_percent; +} + class NetworkPacket { public: NetworkPacket(const uint8_t* data, size_t length, int64_t send_time, @@ -159,6 +164,12 @@ void FakeNetworkPipe::Process() { NetworkPacket* packet = capacity_link_.front(); capacity_link_.pop(); + // Packets are randomly dropped after being affected by the bottleneck. + if (UniformLoss(config_.loss_percent)) { + delete packet; + continue; + } + // Add extra delay and jitter, but make sure the arrival time is not // earlier than the last packet in the queue. int extra_delay = GaussianRandom(config_.queue_delay_ms, diff --git a/webrtc/test/fake_network_pipe.h b/webrtc/test/fake_network_pipe.h index c741501e8d..a9ca7604ed 100644 --- a/webrtc/test/fake_network_pipe.h +++ b/webrtc/test/fake_network_pipe.h @@ -47,7 +47,7 @@ class FakeNetworkPipe { int delay_standard_deviation_ms; // Link capacity in kbps. int link_capacity_kbps; - // Random packet loss. Not implemented. + // Random packet loss. int loss_percent; }; diff --git a/webrtc/video/loopback.cc b/webrtc/video/loopback.cc index 614ef47a78..4ec738824f 100644 --- a/webrtc/video/loopback.cc +++ b/webrtc/video/loopback.cc @@ -51,18 +51,58 @@ size_t MaxBitrate() { return static_cast(FLAGS_max_bitrate); } DEFINE_string(codec, "VP8", "Video codec to use."); std::string Codec() { return static_cast(FLAGS_codec); } + +DEFINE_int32(loss_percent, 0, "Percentage of packets randomly lost."); +int LossPercent() { + return static_cast(FLAGS_loss_percent); +} + +DEFINE_int32(link_capacity, + 0, + "Capacity (kbps) of the fake link. 0 means infinite."); +int LinkCapacity() { + return static_cast(FLAGS_link_capacity); +} + +DEFINE_int32(queue_size, 0, "Size of the bottleneck link queue in packets."); +int QueueSize() { + return static_cast(FLAGS_queue_size); +} + +DEFINE_int32(avg_propagation_delay_ms, + 0, + "Average link propagation delay in ms."); +int AvgPropagationDelayMs() { + return static_cast(FLAGS_avg_propagation_delay_ms); +} + +DEFINE_int32(std_propagation_delay_ms, + 0, + "Link propagation delay standard deviation in ms."); +int StdPropagationDelayMs() { + return static_cast(FLAGS_std_propagation_delay_ms); +} } // namespace flags static const uint32_t kSendSsrc = 0x654321; +static const uint32_t kSendRtxSsrc = 0x654322; static const uint32_t kReceiverLocalSsrc = 0x123456; +static const uint8_t kRtxPayloadType = 96; + void Loopback() { scoped_ptr local_preview(test::VideoRenderer::Create( "Local Preview", flags::Width(), flags::Height())); scoped_ptr loopback_video(test::VideoRenderer::Create( "Loopback Video", flags::Width(), flags::Height())); - test::DirectTransport transport; + FakeNetworkPipe::Config pipe_config; + pipe_config.loss_percent = flags::LossPercent(); + pipe_config.link_capacity_kbps = flags::LinkCapacity(); + pipe_config.queue_length_packets = flags::QueueSize(); + pipe_config.queue_delay_ms = flags::AvgPropagationDelayMs(); + pipe_config.delay_standard_deviation_ms = flags::StdPropagationDelayMs(); + test::DirectTransport transport(pipe_config); Call::Config call_config(&transport); call_config.start_bitrate_bps = static_cast(flags::StartBitrate()) * 1000; @@ -73,6 +113,9 @@ void Loopback() { VideoSendStream::Config send_config; send_config.rtp.ssrcs.push_back(kSendSsrc); + send_config.rtp.rtx.ssrcs.push_back(kSendRtxSsrc); + send_config.rtp.rtx.payload_type = kRtxPayloadType; + send_config.rtp.nack.rtp_history_ms = 1000; send_config.local_renderer = local_preview.get(); scoped_ptr encoder; @@ -111,6 +154,9 @@ void Loopback() { VideoReceiveStream::Config receive_config; receive_config.rtp.remote_ssrc = send_config.rtp.ssrcs[0]; receive_config.rtp.local_ssrc = kReceiverLocalSsrc; + receive_config.rtp.nack.rtp_history_ms = 1000; + receive_config.rtp.rtx[kRtxPayloadType].ssrc = kSendRtxSsrc; + receive_config.rtp.rtx[kRtxPayloadType].payload_type = kRtxPayloadType; receive_config.renderer = loopback_video.get(); VideoCodec codec = test::CreateDecoderVideoCodec(send_config.encoder_settings);