
Updating resource file separately, once LGTM. Generates ~628k of files for current tests, highly compressable, once/if we need that. BUG= R=mflodman@webrtc.org, stefan@webrtc.org Review URL: https://webrtc-codereview.appspot.com/4639004 git-svn-id: http://webrtc.googlecode.com/svn/trunk@5204 4adac7df-926f-26a2-2b94-8c16560cd09d
280 lines
8.8 KiB
C++
280 lines
8.8 KiB
C++
/*
|
|
* Copyright (c) 2013 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/test/bwe_test.h"
|
|
|
|
#include "webrtc/modules/remote_bitrate_estimator/test/bwe_test_baselinefile.h"
|
|
#include "webrtc/modules/remote_bitrate_estimator/test/bwe_test_framework.h"
|
|
#include "webrtc/modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h"
|
|
#include "webrtc/system_wrappers/interface/clock.h"
|
|
#include "webrtc/system_wrappers/interface/scoped_ptr.h"
|
|
|
|
using std::string;
|
|
using std::vector;
|
|
|
|
namespace webrtc {
|
|
namespace testing {
|
|
namespace bwe {
|
|
|
|
namespace stl_helpers {
|
|
template<typename T> void DeleteElements(T* container) {
|
|
if (!container) return;
|
|
for (typename T::iterator it = container->begin(); it != container->end();
|
|
++it) {
|
|
delete *it;
|
|
}
|
|
container->clear();
|
|
}
|
|
} // namespace stl_helpers
|
|
|
|
class BweTest::TestedEstimator : public RemoteBitrateObserver {
|
|
public:
|
|
TestedEstimator(const string& test_name,
|
|
const BweTestConfig::EstimatorConfig& config)
|
|
: debug_name_(config.debug_name),
|
|
clock_(0),
|
|
stats_(),
|
|
relative_estimator_stats_(),
|
|
latest_estimate_bps_(-1),
|
|
estimator_(config.estimator_factory->Create(this, &clock_)),
|
|
relative_estimator_(NULL),
|
|
baseline_(BaseLineFileInterface::Create(test_name + "_" + debug_name_,
|
|
config.update_baseline)) {
|
|
assert(estimator_.get());
|
|
assert(baseline_.get());
|
|
// Default RTT in RemoteRateControl is 200 ms ; 50 ms is more realistic.
|
|
estimator_->OnRttUpdate(50);
|
|
}
|
|
|
|
void SetRelativeEstimator(TestedEstimator* relative_estimator) {
|
|
relative_estimator_ = relative_estimator;
|
|
}
|
|
|
|
void EatPacket(const Packet& packet) {
|
|
BWE_TEST_LOGGING_CONTEXT(debug_name_);
|
|
|
|
latest_estimate_bps_ = -1;
|
|
|
|
// We're treating the send time (from previous filter) as the arrival
|
|
// time once packet reaches the estimator.
|
|
int64_t packet_time_ms = (packet.send_time_us() + 500) / 1000;
|
|
BWE_TEST_LOGGING_TIME(packet_time_ms);
|
|
|
|
int64_t step_ms = estimator_->TimeUntilNextProcess();
|
|
while ((clock_.TimeInMilliseconds() + step_ms) < packet_time_ms) {
|
|
clock_.AdvanceTimeMilliseconds(step_ms);
|
|
estimator_->Process();
|
|
step_ms = estimator_->TimeUntilNextProcess();
|
|
}
|
|
|
|
estimator_->IncomingPacket(packet_time_ms, packet.payload_size(),
|
|
packet.header());
|
|
clock_.AdvanceTimeMilliseconds(packet_time_ms -
|
|
clock_.TimeInMilliseconds());
|
|
ASSERT_TRUE(packet_time_ms == clock_.TimeInMilliseconds());
|
|
}
|
|
|
|
bool CheckEstimate(PacketSender::Feedback* feedback) {
|
|
assert(feedback);
|
|
BWE_TEST_LOGGING_CONTEXT(debug_name_);
|
|
uint32_t estimated_bps = 0;
|
|
if (LatestEstimate(&estimated_bps)) {
|
|
feedback->estimated_bps = estimated_bps;
|
|
baseline_->Estimate(clock_.TimeInMilliseconds(), estimated_bps);
|
|
|
|
double estimated_kbps = static_cast<double>(estimated_bps) / 1000.0;
|
|
stats_.Push(estimated_kbps);
|
|
BWE_TEST_LOGGING_PLOT("Estimate", clock_.TimeInMilliseconds(),
|
|
estimated_kbps / 1000.0);
|
|
uint32_t relative_estimate_bps = 0;
|
|
if (relative_estimator_ &&
|
|
relative_estimator_->LatestEstimate(&relative_estimate_bps)) {
|
|
double relative_estimate_kbps =
|
|
static_cast<double>(relative_estimate_bps) / 1000.0;
|
|
relative_estimator_stats_.Push(estimated_kbps - relative_estimate_kbps);
|
|
}
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void LogStats() {
|
|
BWE_TEST_LOGGING_CONTEXT(debug_name_);
|
|
BWE_TEST_LOGGING_CONTEXT("Mean");
|
|
stats_.Log("kbps");
|
|
if (relative_estimator_) {
|
|
BWE_TEST_LOGGING_CONTEXT("Diff");
|
|
relative_estimator_stats_.Log("kbps");
|
|
}
|
|
}
|
|
|
|
void VerifyOrWriteBaseline() {
|
|
EXPECT_TRUE(baseline_->VerifyOrWrite());
|
|
}
|
|
|
|
virtual void OnReceiveBitrateChanged(const vector<unsigned int>& ssrcs,
|
|
unsigned int bitrate) {
|
|
}
|
|
|
|
private:
|
|
bool LatestEstimate(uint32_t* estimate_bps) {
|
|
if (latest_estimate_bps_ < 0) {
|
|
vector<unsigned int> ssrcs;
|
|
unsigned int bps = 0;
|
|
if (!estimator_->LatestEstimate(&ssrcs, &bps)) {
|
|
return false;
|
|
}
|
|
latest_estimate_bps_ = bps;
|
|
}
|
|
*estimate_bps = latest_estimate_bps_;
|
|
return true;
|
|
}
|
|
|
|
string debug_name_;
|
|
SimulatedClock clock_;
|
|
Stats<double> stats_;
|
|
Stats<double> relative_estimator_stats_;
|
|
int64_t latest_estimate_bps_;
|
|
scoped_ptr<RemoteBitrateEstimator> estimator_;
|
|
TestedEstimator* relative_estimator_;
|
|
scoped_ptr<BaseLineFileInterface> baseline_;
|
|
|
|
DISALLOW_IMPLICIT_CONSTRUCTORS(TestedEstimator);
|
|
};
|
|
|
|
BweTest::BweTest()
|
|
: run_time_ms_(0),
|
|
simulation_interval_ms_(-1),
|
|
previous_packets_(),
|
|
packet_senders_(),
|
|
estimators_(),
|
|
processors_() {
|
|
}
|
|
|
|
BweTest::~BweTest() {
|
|
stl_helpers::DeleteElements(&estimators_);
|
|
stl_helpers::DeleteElements(&packet_senders_);
|
|
}
|
|
|
|
void BweTest::SetUp() {
|
|
const ::testing::TestInfo* const test_info =
|
|
::testing::UnitTest::GetInstance()->current_test_info();
|
|
string test_name =
|
|
string(test_info->test_case_name()) + "_" + string(test_info->name());
|
|
BWE_TEST_LOGGING_GLOBAL_CONTEXT(test_name);
|
|
|
|
const BweTestConfig& config = GetParam();
|
|
|
|
uint32_t total_capacity = 0;
|
|
for (vector<const PacketSenderFactory*>::const_iterator it =
|
|
config.sender_factories.begin(); it != config.sender_factories.end();
|
|
++it) {
|
|
PacketSender* sender = (*it)->Create();
|
|
assert(sender);
|
|
total_capacity += sender->GetCapacityKbps();
|
|
packet_senders_.push_back(sender);
|
|
processors_.push_back(sender);
|
|
}
|
|
BWE_TEST_LOGGING_LOG1("RequiredLinkCapacity", "%d kbps", total_capacity)
|
|
|
|
// Set simulation interval from first packet sender.
|
|
if (packet_senders_.size() > 0) {
|
|
simulation_interval_ms_ = packet_senders_[0]->GetFeedbackIntervalMs();
|
|
}
|
|
|
|
for (vector<BweTestConfig::EstimatorConfig>:: const_iterator it =
|
|
config.estimator_configs.begin(); it != config.estimator_configs.end();
|
|
++it) {
|
|
estimators_.push_back(new TestedEstimator(test_name, *it));
|
|
}
|
|
if (estimators_.size() > 1) {
|
|
// Set all estimators as relative to the first one.
|
|
for (uint32_t i = 1; i < estimators_.size(); ++i) {
|
|
estimators_[i]->SetRelativeEstimator(estimators_[0]);
|
|
}
|
|
}
|
|
|
|
BWE_TEST_LOGGING_GLOBAL_ENABLE(false);
|
|
}
|
|
|
|
void BweTest::TearDown() {
|
|
BWE_TEST_LOGGING_GLOBAL_ENABLE(true);
|
|
|
|
for (vector<TestedEstimator*>::iterator eit = estimators_.begin();
|
|
eit != estimators_.end(); ++eit) {
|
|
(*eit)->VerifyOrWriteBaseline();
|
|
(*eit)->LogStats();
|
|
}
|
|
|
|
BWE_TEST_LOGGING_GLOBAL_CONTEXT("");
|
|
}
|
|
|
|
void BweTest::AddPacketProcessor(
|
|
PacketProcessor* processor) {
|
|
assert(processor);
|
|
processors_.push_back(processor);
|
|
}
|
|
|
|
void BweTest::RemovePacketProcessor(
|
|
PacketProcessor* processor) {
|
|
vector<PacketProcessor*>::iterator it =
|
|
std::find(processors_.begin(), processors_.end(), processor);
|
|
assert(it != processors_.end());
|
|
processors_.erase(it);
|
|
}
|
|
|
|
void BweTest::VerboseLogging(bool enable) {
|
|
BWE_TEST_LOGGING_GLOBAL_ENABLE(enable);
|
|
}
|
|
|
|
void BweTest::RunFor(int64_t time_ms) {
|
|
for (run_time_ms_ += time_ms; run_time_ms_ >= simulation_interval_ms_;
|
|
run_time_ms_ -= simulation_interval_ms_) {
|
|
Packets packets;
|
|
for (vector<PacketProcessor*>::const_iterator it =
|
|
processors_.begin(); it != processors_.end(); ++it) {
|
|
(*it)->RunFor(simulation_interval_ms_, &packets);
|
|
}
|
|
|
|
// Verify packets are in order between batches.
|
|
if (!packets.empty() && !previous_packets_.empty()) {
|
|
packets.splice(packets.begin(), previous_packets_,
|
|
--previous_packets_.end());
|
|
ASSERT_TRUE(IsTimeSorted(packets));
|
|
packets.erase(packets.begin());
|
|
} else {
|
|
ASSERT_TRUE(IsTimeSorted(packets));
|
|
}
|
|
|
|
for (PacketsConstIt pit = packets.begin(); pit != packets.end(); ++pit) {
|
|
for (vector<TestedEstimator*>::iterator eit = estimators_.begin();
|
|
eit != estimators_.end(); ++eit) {
|
|
(*eit)->EatPacket(*pit);
|
|
}
|
|
}
|
|
|
|
previous_packets_.swap(packets);
|
|
|
|
for (vector<TestedEstimator*>::iterator eit = estimators_.begin();
|
|
eit != estimators_.end(); ++eit) {
|
|
PacketSender::Feedback feedback = {0};
|
|
if ((*eit)->CheckEstimate(&feedback)) {
|
|
for (vector<PacketSender*>::iterator psit = packet_senders_.begin();
|
|
psit != packet_senders_.end(); ++psit) {
|
|
(*psit)->GiveFeedback(feedback);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} // namespace bwe
|
|
} // namespace testing
|
|
} // namespace webrtc
|