webrtc_m130/test/fake_network_pipe.cc

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

256 lines
8.9 KiB
C++
Raw Normal View History

/*
* Copyright (c) 2012 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 "test/fake_network_pipe.h"
#include <assert.h>
#include <math.h>
#include <string.h>
#include <algorithm>
#include <cmath>
#include "call/call.h"
#include "modules/rtp_rtcp/include/rtp_header_parser.h"
#include "rtc_base/logging.h"
#include "system_wrappers/include/clock.h"
namespace webrtc {
namespace {
constexpr int64_t kDefaultProcessIntervalMs = 5;
}
DemuxerImpl::DemuxerImpl(const std::map<uint8_t, MediaType>& payload_type_map)
: packet_receiver_(nullptr), payload_type_map_(payload_type_map) {}
void DemuxerImpl::SetReceiver(PacketReceiver* receiver) {
packet_receiver_ = receiver;
}
void DemuxerImpl::DeliverPacket(const NetworkPacket* packet,
const PacketTime& packet_time) {
// No packet receiver means that this demuxer will terminate the flow of
// packets.
if (!packet_receiver_)
return;
const uint8_t* const packet_data = packet->data();
const size_t packet_length = packet->data_length();
MediaType media_type = MediaType::ANY;
if (!RtpHeaderParser::IsRtcp(packet_data, packet_length)) {
RTC_CHECK_GE(packet_length, 2);
const uint8_t payload_type = packet_data[1] & 0x7f;
std::map<uint8_t, MediaType>::const_iterator it =
payload_type_map_.find(payload_type);
RTC_CHECK(it != payload_type_map_.end())
<< "payload type " << static_cast<int>(payload_type) << " unknown.";
media_type = it->second;
}
packet_receiver_->DeliverPacket(media_type, packet_data, packet_length,
packet_time);
}
FakeNetworkPipe::FakeNetworkPipe(Clock* clock,
Reland of Don't hardcode MediaType::ANY in FakeNetworkPipe. (patchset #1 id:1 of https://codereview.webrtc.org/2784543002/ ) Reason for revert: Intend to fix perf failures and reland. Original issue's description: > Revert of Don't hardcode MediaType::ANY in FakeNetworkPipe. (patchset #4 id:60001 of https://codereview.webrtc.org/2774463003/ ) > > Reason for revert: > Reverting since this seems to break multiple WebRTC Perf buildbots > > Original issue's description: > > Don't hardcode MediaType::ANY in FakeNetworkPipe. > > > > Instead let each test set the appropriate media type. This simplifies > > demuxing in Call and later in RtpTransportController. > > > > BUG=webrtc:7135 > > > > Review-Url: https://codereview.webrtc.org/2774463003 > > Cr-Commit-Position: refs/heads/master@{#17418} > > Committed: https://chromium.googlesource.com/external/webrtc/+/9c47b00e24da2941eb095df5a4459c6d98a8a88d > > TBR=stefan@webrtc.org,deadbeef@webrtc.org,solenberg@webrtc.org,pbos@webrtc.org,sprang@webrtc.org,nisse@webrtc.org > # Skipping CQ checks because original CL landed less than 1 days ago. > NOPRESUBMIT=true > NOTREECHECKS=true > NOTRY=true > BUG=webrtc:7135 > > Review-Url: https://codereview.webrtc.org/2784543002 > Cr-Commit-Position: refs/heads/master@{#17427} > Committed: https://chromium.googlesource.com/external/webrtc/+/3a3bd5061089da5327fc549337a8430054d66057 TBR=stefan@webrtc.org,deadbeef@webrtc.org,solenberg@webrtc.org,pbos@webrtc.org,sprang@webrtc.org,lliuu@webrtc.org # Skipping CQ checks because original CL landed less than 1 days ago. NOPRESUBMIT=true NOTREECHECKS=true NOTRY=true BUG=webrtc:7135 Review-Url: https://codereview.webrtc.org/2783853002 Cr-Commit-Position: refs/heads/master@{#17459}
2017-03-29 23:57:43 -07:00
const FakeNetworkPipe::Config& config,
std::unique_ptr<Demuxer> demuxer)
: FakeNetworkPipe(clock, config, std::move(demuxer), 1) {}
FakeNetworkPipe::FakeNetworkPipe(Clock* clock,
const FakeNetworkPipe::Config& config,
std::unique_ptr<Demuxer> demuxer,
uint64_t seed)
: clock_(clock),
demuxer_(std::move(demuxer)),
random_(seed),
Reland of Fixes a bug where a video stream can get stuck in the suspended state. (patchset #1 id:1 of https://codereview.chromium.org/2703393002/ ) Reason for revert: Downstream fixed Original issue's description: > Revert of Fixes a bug where a video stream can get stuck in the suspended state. (patchset #8 id:120001 of https://codereview.webrtc.org/2705603002/ ) > > Reason for revert: > Breaks downstream > > Original issue's description: > > Fixes a bug where a video stream can get stuck in the suspended state. > > > > This happens if a lot of FEC is allocated when the stream becomes suspended. The required bitrate to unsuspend can then be too high so that the padding bitrate we are allowed to generate is not enough. > > > > This CL also switches the tests from using ISAC to OPUS as RampUpTest.UpDownUpAudioVideoTransportSequenceNumberRtx relies on audio BWE to work (which is only compatible with OPUS). I don't know why it didn't fail before. > > > > BUG=webrtc:7178 > > > > Review-Url: https://codereview.webrtc.org/2705603002 > > Cr-Commit-Position: refs/heads/master@{#16739} > > Committed: https://chromium.googlesource.com/external/webrtc/+/a518a39963d34616d8f0e94991c7f5fbb5affb38 > > TBR=mflodman@webrtc.org,terelius@webrtc.org,stefan@webrtc.org > # Skipping CQ checks because original CL landed less than 1 days ago. > NOPRESUBMIT=true > NOTREECHECKS=true > NOTRY=true > BUG=webrtc:7178 > > Review-Url: https://codereview.webrtc.org/2703393002 > Cr-Commit-Position: refs/heads/master@{#16751} > Committed: https://chromium.googlesource.com/external/webrtc/+/b80bdcafed6c529be140da7d9f3e95a00b94219e TBR=mflodman@webrtc.org,terelius@webrtc.org,stefan@webrtc.org # Skipping CQ checks because original CL landed less than 1 days ago. NOPRESUBMIT=true NOTREECHECKS=true NOTRY=true BUG=webrtc:7178 Review-Url: https://codereview.webrtc.org/2704323003 Cr-Commit-Position: refs/heads/master@{#16753}
2017-02-21 07:28:31 -08:00
config_(),
dropped_packets_(0),
sent_packets_(0),
total_packet_delay_(0),
bursting_(false),
next_process_time_(clock_->TimeInMilliseconds()),
last_log_time_(clock_->TimeInMilliseconds()) {
Reland of Fixes a bug where a video stream can get stuck in the suspended state. (patchset #1 id:1 of https://codereview.chromium.org/2703393002/ ) Reason for revert: Downstream fixed Original issue's description: > Revert of Fixes a bug where a video stream can get stuck in the suspended state. (patchset #8 id:120001 of https://codereview.webrtc.org/2705603002/ ) > > Reason for revert: > Breaks downstream > > Original issue's description: > > Fixes a bug where a video stream can get stuck in the suspended state. > > > > This happens if a lot of FEC is allocated when the stream becomes suspended. The required bitrate to unsuspend can then be too high so that the padding bitrate we are allowed to generate is not enough. > > > > This CL also switches the tests from using ISAC to OPUS as RampUpTest.UpDownUpAudioVideoTransportSequenceNumberRtx relies on audio BWE to work (which is only compatible with OPUS). I don't know why it didn't fail before. > > > > BUG=webrtc:7178 > > > > Review-Url: https://codereview.webrtc.org/2705603002 > > Cr-Commit-Position: refs/heads/master@{#16739} > > Committed: https://chromium.googlesource.com/external/webrtc/+/a518a39963d34616d8f0e94991c7f5fbb5affb38 > > TBR=mflodman@webrtc.org,terelius@webrtc.org,stefan@webrtc.org > # Skipping CQ checks because original CL landed less than 1 days ago. > NOPRESUBMIT=true > NOTREECHECKS=true > NOTRY=true > BUG=webrtc:7178 > > Review-Url: https://codereview.webrtc.org/2703393002 > Cr-Commit-Position: refs/heads/master@{#16751} > Committed: https://chromium.googlesource.com/external/webrtc/+/b80bdcafed6c529be140da7d9f3e95a00b94219e TBR=mflodman@webrtc.org,terelius@webrtc.org,stefan@webrtc.org # Skipping CQ checks because original CL landed less than 1 days ago. NOPRESUBMIT=true NOTREECHECKS=true NOTRY=true BUG=webrtc:7178 Review-Url: https://codereview.webrtc.org/2704323003 Cr-Commit-Position: refs/heads/master@{#16753}
2017-02-21 07:28:31 -08:00
SetConfig(config);
}
FakeNetworkPipe::~FakeNetworkPipe() {
while (!capacity_link_.empty()) {
delete capacity_link_.front();
capacity_link_.pop();
}
while (!delay_link_.empty()) {
delete *delay_link_.begin();
delay_link_.erase(delay_link_.begin());
}
}
void FakeNetworkPipe::SetReceiver(PacketReceiver* receiver) {
RTC_CHECK(demuxer_);
demuxer_->SetReceiver(receiver);
}
void FakeNetworkPipe::SetConfig(const FakeNetworkPipe::Config& config) {
rtc::CritScope crit(&lock_);
config_ = config; // Shallow copy of the struct.
Reland of Fixes a bug where a video stream can get stuck in the suspended state. (patchset #1 id:1 of https://codereview.chromium.org/2703393002/ ) Reason for revert: Downstream fixed Original issue's description: > Revert of Fixes a bug where a video stream can get stuck in the suspended state. (patchset #8 id:120001 of https://codereview.webrtc.org/2705603002/ ) > > Reason for revert: > Breaks downstream > > Original issue's description: > > Fixes a bug where a video stream can get stuck in the suspended state. > > > > This happens if a lot of FEC is allocated when the stream becomes suspended. The required bitrate to unsuspend can then be too high so that the padding bitrate we are allowed to generate is not enough. > > > > This CL also switches the tests from using ISAC to OPUS as RampUpTest.UpDownUpAudioVideoTransportSequenceNumberRtx relies on audio BWE to work (which is only compatible with OPUS). I don't know why it didn't fail before. > > > > BUG=webrtc:7178 > > > > Review-Url: https://codereview.webrtc.org/2705603002 > > Cr-Commit-Position: refs/heads/master@{#16739} > > Committed: https://chromium.googlesource.com/external/webrtc/+/a518a39963d34616d8f0e94991c7f5fbb5affb38 > > TBR=mflodman@webrtc.org,terelius@webrtc.org,stefan@webrtc.org > # Skipping CQ checks because original CL landed less than 1 days ago. > NOPRESUBMIT=true > NOTREECHECKS=true > NOTRY=true > BUG=webrtc:7178 > > Review-Url: https://codereview.webrtc.org/2703393002 > Cr-Commit-Position: refs/heads/master@{#16751} > Committed: https://chromium.googlesource.com/external/webrtc/+/b80bdcafed6c529be140da7d9f3e95a00b94219e TBR=mflodman@webrtc.org,terelius@webrtc.org,stefan@webrtc.org # Skipping CQ checks because original CL landed less than 1 days ago. NOPRESUBMIT=true NOTREECHECKS=true NOTRY=true BUG=webrtc:7178 Review-Url: https://codereview.webrtc.org/2704323003 Cr-Commit-Position: refs/heads/master@{#16753}
2017-02-21 07:28:31 -08:00
double prob_loss = config.loss_percent / 100.0;
if (config_.avg_burst_loss_length == -1) {
// Uniform loss
prob_loss_bursting_ = prob_loss;
prob_start_bursting_ = prob_loss;
} else {
// Lose packets according to a gilbert-elliot model.
int avg_burst_loss_length = config.avg_burst_loss_length;
int min_avg_burst_loss_length = std::ceil(prob_loss / (1 - prob_loss));
RTC_CHECK_GT(avg_burst_loss_length, min_avg_burst_loss_length)
<< "For a total packet loss of " << config.loss_percent << "%% then"
<< " avg_burst_loss_length must be " << min_avg_burst_loss_length + 1
<< " or higher.";
prob_loss_bursting_ = (1.0 - 1.0 / avg_burst_loss_length);
prob_start_bursting_ = prob_loss / (1 - prob_loss) / avg_burst_loss_length;
}
}
void FakeNetworkPipe::SendPacket(const uint8_t* data, size_t data_length) {
RTC_CHECK(demuxer_);
rtc::CritScope crit(&lock_);
if (config_.queue_length_packets > 0 &&
capacity_link_.size() >= config_.queue_length_packets) {
// Too many packet on the link, drop this one.
++dropped_packets_;
return;
}
int64_t time_now = clock_->TimeInMilliseconds();
// Delay introduced by the link capacity.
int64_t capacity_delay_ms = 0;
if (config_.link_capacity_kbps > 0) {
const int bytes_per_millisecond = config_.link_capacity_kbps / 8;
// To round to the closest millisecond we add half a milliseconds worth of
// bytes to the delay calculation.
capacity_delay_ms = (data_length + capacity_delay_error_bytes_ +
bytes_per_millisecond / 2) /
bytes_per_millisecond;
capacity_delay_error_bytes_ +=
data_length - capacity_delay_ms * bytes_per_millisecond;
}
int64_t network_start_time = time_now;
// Check if there already are packets on the link and change network start
// time forward if there is.
if (!capacity_link_.empty() &&
network_start_time < capacity_link_.back()->arrival_time())
network_start_time = capacity_link_.back()->arrival_time();
int64_t arrival_time = network_start_time + capacity_delay_ms;
NetworkPacket* packet = new NetworkPacket(data, data_length, time_now,
arrival_time);
capacity_link_.push(packet);
}
float FakeNetworkPipe::PercentageLoss() {
rtc::CritScope crit(&lock_);
if (sent_packets_ == 0)
return 0;
return static_cast<float>(dropped_packets_) /
(sent_packets_ + dropped_packets_);
}
int FakeNetworkPipe::AverageDelay() {
rtc::CritScope crit(&lock_);
if (sent_packets_ == 0)
return 0;
return static_cast<int>(total_packet_delay_ /
static_cast<int64_t>(sent_packets_));
}
void FakeNetworkPipe::Process() {
int64_t time_now = clock_->TimeInMilliseconds();
std::queue<NetworkPacket*> packets_to_deliver;
{
rtc::CritScope crit(&lock_);
if (time_now - last_log_time_ > 5000) {
int64_t queueing_delay_ms = 0;
if (!capacity_link_.empty()) {
queueing_delay_ms = time_now - capacity_link_.front()->send_time();
}
RTC_LOG(LS_INFO) << "Network queue: " << queueing_delay_ms << " ms.";
last_log_time_ = time_now;
}
// Check the capacity link first.
while (!capacity_link_.empty() &&
time_now >= capacity_link_.front()->arrival_time()) {
// Time to get this packet.
NetworkPacket* packet = capacity_link_.front();
capacity_link_.pop();
// Drop packets at an average rate of |config_.loss_percent| with
// and average loss burst length of |config_.avg_burst_loss_length|.
if ((bursting_ && random_.Rand<double>() < prob_loss_bursting_) ||
(!bursting_ && random_.Rand<double>() < prob_start_bursting_)) {
bursting_ = true;
delete packet;
continue;
} else {
bursting_ = false;
}
int arrival_time_jitter = random_.Gaussian(
config_.queue_delay_ms, config_.delay_standard_deviation_ms);
// If reordering is not allowed then adjust arrival_time_jitter
// to make sure all packets are sent in order.
if (!config_.allow_reordering && !delay_link_.empty() &&
packet->arrival_time() + arrival_time_jitter <
(*delay_link_.rbegin())->arrival_time()) {
arrival_time_jitter =
(*delay_link_.rbegin())->arrival_time() - packet->arrival_time();
}
packet->IncrementArrivalTime(arrival_time_jitter);
delay_link_.insert(packet);
}
// Check the extra delay queue.
while (!delay_link_.empty() &&
time_now >= (*delay_link_.begin())->arrival_time()) {
// Deliver this packet.
NetworkPacket* packet = *delay_link_.begin();
packets_to_deliver.push(packet);
delay_link_.erase(delay_link_.begin());
// |time_now| might be later than when the packet should have arrived, due
// to NetworkProcess being called too late. For stats, use the time it
// should have been on the link.
total_packet_delay_ += packet->arrival_time() - packet->send_time();
}
sent_packets_ += packets_to_deliver.size();
}
while (!packets_to_deliver.empty()) {
NetworkPacket* packet = packets_to_deliver.front();
packets_to_deliver.pop();
demuxer_->DeliverPacket(packet, PacketTime());
delete packet;
}
next_process_time_ = !delay_link_.empty()
? (*delay_link_.begin())->arrival_time()
: time_now + kDefaultProcessIntervalMs;
}
int64_t FakeNetworkPipe::TimeUntilNextProcess() const {
rtc::CritScope crit(&lock_);
return std::max<int64_t>(next_process_time_ - clock_->TimeInMilliseconds(),
0);
}
} // namespace webrtc