Break out BWE test models to separate files
BUG=
R=stefan@webrtc.org
Review URL: https://webrtc-codereview.appspot.com/36299004
Cr-Commit-Position: refs/heads/master@{#8471}
git-svn-id: http://webrtc.googlecode.com/svn/trunk@8471 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/webrtc/modules/modules.gyp b/webrtc/modules/modules.gyp
index d9f071e..61d00eb 100644
--- a/webrtc/modules/modules.gyp
+++ b/webrtc/modules/modules.gyp
@@ -231,6 +231,12 @@
'remote_bitrate_estimator/test/packet_sender.cc',
'remote_bitrate_estimator/test/packet_sender.h',
'remote_bitrate_estimator/test/packets.h',
+ 'remote_bitrate_estimator/test/estimators/nada.cc',
+ 'remote_bitrate_estimator/test/estimators/nada.h',
+ 'remote_bitrate_estimator/test/estimators/remb.cc',
+ 'remote_bitrate_estimator/test/estimators/remb.h',
+ 'remote_bitrate_estimator/test/estimators/send_side.cc',
+ 'remote_bitrate_estimator/test/estimators/send_side.h',
'rtp_rtcp/source/mock/mock_rtp_payload_strategy.h',
'rtp_rtcp/source/byte_io_unittest.cc',
'rtp_rtcp/source/fec_receiver_unittest.cc',
diff --git a/webrtc/modules/remote_bitrate_estimator/test/bwe.cc b/webrtc/modules/remote_bitrate_estimator/test/bwe.cc
index fe6c011..3221d2b 100644
--- a/webrtc/modules/remote_bitrate_estimator/test/bwe.cc
+++ b/webrtc/modules/remote_bitrate_estimator/test/bwe.cc
@@ -10,171 +10,33 @@
#include "webrtc/modules/remote_bitrate_estimator/test/bwe.h"
-#include <algorithm>
#include <limits>
-#include <string>
-#include <vector>
-#include "testing/gtest/include/gtest/gtest.h"
#include "webrtc/base/common.h"
-#include "webrtc/modules/remote_bitrate_estimator/rate_statistics.h"
-#include "webrtc/modules/remote_bitrate_estimator/test/bwe_test_logging.h"
-#include "webrtc/modules/rtp_rtcp/interface/receive_statistics.h"
+#include "webrtc/modules/remote_bitrate_estimator/test/estimators/nada.h"
+#include "webrtc/modules/remote_bitrate_estimator/test/estimators/remb.h"
+#include "webrtc/modules/remote_bitrate_estimator/test/estimators/send_side.h"
namespace webrtc {
namespace testing {
namespace bwe {
-const int kMinBitrateKbps = 150;
-const int kMaxBitrateKbps = 2000;
-
class NullBweSender : public BweSender {
public:
NullBweSender() {}
virtual ~NullBweSender() {}
- virtual int GetFeedbackIntervalMs() const OVERRIDE { return 1000; }
- virtual void GiveFeedback(const FeedbackPacket& feedback) OVERRIDE {}
- virtual int64_t TimeUntilNextProcess() OVERRIDE {
+ virtual int GetFeedbackIntervalMs() const override { return 1000; }
+ virtual void GiveFeedback(const FeedbackPacket& feedback) override {}
+ virtual int64_t TimeUntilNextProcess() override {
return std::numeric_limits<int64_t>::max();
}
- virtual int Process() OVERRIDE { return 0; }
+ virtual int Process() override { return 0; }
private:
DISALLOW_COPY_AND_ASSIGN(NullBweSender);
};
-class RembBweSender : public BweSender {
- public:
- RembBweSender(int kbps, BitrateObserver* observer, Clock* clock);
- virtual ~RembBweSender();
-
- virtual int GetFeedbackIntervalMs() const OVERRIDE { return 100; }
- virtual void GiveFeedback(const FeedbackPacket& feedback) OVERRIDE;
- virtual int64_t TimeUntilNextProcess() OVERRIDE;
- virtual int Process() OVERRIDE;
-
- protected:
- scoped_ptr<BitrateController> bitrate_controller_;
- scoped_ptr<RtcpBandwidthObserver> feedback_observer_;
-
- private:
- Clock* clock_;
-
- DISALLOW_IMPLICIT_CONSTRUCTORS(RembBweSender);
-};
-
-class FullBweSender : public BweSender, public RemoteBitrateObserver {
- public:
- FullBweSender(int kbps, BitrateObserver* observer, Clock* clock);
- virtual ~FullBweSender();
-
- virtual int GetFeedbackIntervalMs() const OVERRIDE { return 100; }
- virtual void GiveFeedback(const FeedbackPacket& feedback) OVERRIDE;
- virtual void OnReceiveBitrateChanged(const std::vector<unsigned int>& ssrcs,
- unsigned int bitrate) OVERRIDE;
- virtual int64_t TimeUntilNextProcess() OVERRIDE;
- virtual int Process() OVERRIDE;
-
- protected:
- scoped_ptr<BitrateController> bitrate_controller_;
- scoped_ptr<RemoteBitrateEstimator> rbe_;
- scoped_ptr<RtcpBandwidthObserver> feedback_observer_;
-
- private:
- Clock* const clock_;
- RTCPReportBlock report_block_;
-
- DISALLOW_IMPLICIT_CONSTRUCTORS(FullBweSender);
-};
-
-RembBweSender::RembBweSender(int kbps, BitrateObserver* observer, Clock* clock)
- : bitrate_controller_(
- BitrateController::CreateBitrateController(clock, false)),
- feedback_observer_(bitrate_controller_->CreateRtcpBandwidthObserver()),
- clock_(clock) {
- assert(kbps >= kMinBitrateKbps);
- assert(kbps <= kMaxBitrateKbps);
- bitrate_controller_->SetBitrateObserver(
- observer, 1000 * kbps, 1000 * kMinBitrateKbps, 1000 * kMaxBitrateKbps);
-}
-
-RembBweSender::~RembBweSender() {
-}
-
-void RembBweSender::GiveFeedback(const FeedbackPacket& feedback) {
- const RembFeedback& remb_feedback =
- static_cast<const RembFeedback&>(feedback);
- feedback_observer_->OnReceivedEstimatedBitrate(remb_feedback.estimated_bps());
- ReportBlockList report_blocks;
- report_blocks.push_back(remb_feedback.report_block());
- feedback_observer_->OnReceivedRtcpReceiverReport(
- report_blocks, 0, clock_->TimeInMilliseconds());
- bitrate_controller_->Process();
-}
-
-int64_t RembBweSender::TimeUntilNextProcess() {
- return bitrate_controller_->TimeUntilNextProcess();
-}
-
-int RembBweSender::Process() {
- return bitrate_controller_->Process();
-}
-
-FullBweSender::FullBweSender(int kbps, BitrateObserver* observer, Clock* clock)
- : bitrate_controller_(
- BitrateController::CreateBitrateController(clock, false)),
- rbe_(AbsoluteSendTimeRemoteBitrateEstimatorFactory()
- .Create(this, clock, kAimdControl, 1000 * kMinBitrateKbps)),
- feedback_observer_(bitrate_controller_->CreateRtcpBandwidthObserver()),
- clock_(clock) {
- assert(kbps >= kMinBitrateKbps);
- assert(kbps <= kMaxBitrateKbps);
- bitrate_controller_->SetBitrateObserver(
- observer, 1000 * kbps, 1000 * kMinBitrateKbps, 1000 * kMaxBitrateKbps);
-}
-
-FullBweSender::~FullBweSender() {
-}
-
-void FullBweSender::GiveFeedback(const FeedbackPacket& feedback) {
- const SendSideBweFeedback& fb =
- static_cast<const SendSideBweFeedback&>(feedback);
- if (fb.packet_feedback_vector().empty())
- return;
- rbe_->IncomingPacketFeedbackVector(fb.packet_feedback_vector());
- // TODO(holmer): Handle losses in between feedback packets.
- int expected_packets = fb.packet_feedback_vector().back().sequence_number -
- fb.packet_feedback_vector().front().sequence_number +
- 1;
- // Assuming no reordering for now.
- if (expected_packets <= 0)
- return;
- int lost_packets = expected_packets - fb.packet_feedback_vector().size();
- report_block_.fractionLost = (lost_packets << 8) / expected_packets;
- report_block_.cumulativeLost += lost_packets;
- ReportBlockList report_blocks;
- report_blocks.push_back(report_block_);
- feedback_observer_->OnReceivedRtcpReceiverReport(
- report_blocks, 0, clock_->TimeInMilliseconds());
- bitrate_controller_->Process();
-}
-
-void FullBweSender::OnReceiveBitrateChanged(
- const std::vector<unsigned int>& ssrcs,
- unsigned int bitrate) {
- feedback_observer_->OnReceivedEstimatedBitrate(bitrate);
-}
-
-int64_t FullBweSender::TimeUntilNextProcess() {
- return bitrate_controller_->TimeUntilNextProcess();
-}
-
-int FullBweSender::Process() {
- rbe_->Process();
- return bitrate_controller_->Process();
-}
-
int64_t GetAbsSendTimeInMs(uint32_t abs_send_time) {
const int kInterArrivalShift = 26;
const int kAbsSendTimeInterArrivalUpshift = 8;
@@ -184,254 +46,6 @@
return static_cast<int64_t>(timestamp) * kTimestampToMs;
}
-class SendSideBweReceiver : public BweReceiver {
- public:
- explicit SendSideBweReceiver(int flow_id)
- : BweReceiver(flow_id), last_feedback_ms_(0) {}
- virtual void ReceivePacket(int64_t arrival_time_ms,
- const MediaPacket& media_packet) OVERRIDE {
- packet_feedback_vector_.push_back(PacketInfo(
- arrival_time_ms,
- GetAbsSendTimeInMs(media_packet.header().extension.absoluteSendTime),
- media_packet.header().sequenceNumber, media_packet.payload_size()));
- }
-
- virtual FeedbackPacket* GetFeedback(int64_t now_ms) OVERRIDE {
- if (now_ms - last_feedback_ms_ < 100)
- return NULL;
- last_feedback_ms_ = now_ms;
- FeedbackPacket* fb = new SendSideBweFeedback(flow_id_, now_ms * 1000,
- packet_feedback_vector_);
- packet_feedback_vector_.clear();
- return fb;
- }
-
- private:
- int64_t last_feedback_ms_;
- std::vector<PacketInfo> packet_feedback_vector_;
-};
-
-class RembReceiver : public BweReceiver, public RemoteBitrateObserver {
- public:
- static const uint32_t kRemoteBitrateEstimatorMinBitrateBps = 30000;
-
- RembReceiver(int flow_id, bool plot)
- : BweReceiver(flow_id),
- estimate_log_prefix_(),
- plot_estimate_(plot),
- clock_(0),
- recv_stats_(ReceiveStatistics::Create(&clock_)),
- latest_estimate_bps_(-1),
- estimator_(AbsoluteSendTimeRemoteBitrateEstimatorFactory().Create(
- this,
- &clock_,
- kAimdControl,
- kRemoteBitrateEstimatorMinBitrateBps)) {
- std::stringstream ss;
- ss << "Estimate_" << flow_id_ << "#1";
- estimate_log_prefix_ = ss.str();
- // Default RTT in RemoteRateControl is 200 ms ; 50 ms is more realistic.
- estimator_->OnRttUpdate(50);
- }
-
- virtual void ReceivePacket(int64_t arrival_time_ms,
- const MediaPacket& media_packet) {
- recv_stats_->IncomingPacket(media_packet.header(),
- media_packet.payload_size(), false);
-
- latest_estimate_bps_ = -1;
-
- int64_t step_ms = std::max<int64_t>(estimator_->TimeUntilNextProcess(), 0);
- while ((clock_.TimeInMilliseconds() + step_ms) < arrival_time_ms) {
- clock_.AdvanceTimeMilliseconds(step_ms);
- estimator_->Process();
- step_ms = std::max<int64_t>(estimator_->TimeUntilNextProcess(), 0);
- }
- estimator_->IncomingPacket(arrival_time_ms, media_packet.payload_size(),
- media_packet.header());
- clock_.AdvanceTimeMilliseconds(arrival_time_ms -
- clock_.TimeInMilliseconds());
- ASSERT_TRUE(arrival_time_ms == clock_.TimeInMilliseconds());
- }
-
- virtual FeedbackPacket* GetFeedback(int64_t now_ms) OVERRIDE {
- BWE_TEST_LOGGING_CONTEXT("Remb");
- uint32_t estimated_bps = 0;
- RembFeedback* feedback = NULL;
- if (LatestEstimate(&estimated_bps)) {
- StatisticianMap statisticians = recv_stats_->GetActiveStatisticians();
- RTCPReportBlock report_block;
- if (!statisticians.empty()) {
- report_block = BuildReportBlock(statisticians.begin()->second);
- }
- feedback = new RembFeedback(flow_id_, now_ms * 1000, estimated_bps,
- report_block);
-
- double estimated_kbps = static_cast<double>(estimated_bps) / 1000.0;
- RTC_UNUSED(estimated_kbps);
- if (plot_estimate_) {
- BWE_TEST_LOGGING_PLOT(estimate_log_prefix_, clock_.TimeInMilliseconds(),
- estimated_kbps);
- }
- }
- return feedback;
- }
-
- // Implements RemoteBitrateObserver.
- virtual void OnReceiveBitrateChanged(const std::vector<unsigned int>& ssrcs,
- unsigned int bitrate) OVERRIDE {}
-
- private:
- static RTCPReportBlock BuildReportBlock(StreamStatistician* statistician) {
- RTCPReportBlock report_block;
- RtcpStatistics stats;
- if (!statistician->GetStatistics(&stats, true))
- return report_block;
- report_block.fractionLost = stats.fraction_lost;
- report_block.cumulativeLost = stats.cumulative_lost;
- report_block.extendedHighSeqNum = stats.extended_max_sequence_number;
- report_block.jitter = stats.jitter;
- return report_block;
- }
-
- bool LatestEstimate(uint32_t* estimate_bps) {
- if (latest_estimate_bps_ < 0) {
- std::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;
- }
-
- std::string estimate_log_prefix_;
- bool plot_estimate_;
- SimulatedClock clock_;
- scoped_ptr<ReceiveStatistics> recv_stats_;
- int64_t latest_estimate_bps_;
- scoped_ptr<RemoteBitrateEstimator> estimator_;
-
- DISALLOW_IMPLICIT_CONSTRUCTORS(RembReceiver);
-};
-
-class NadaBweReceiver : public BweReceiver {
- public:
- explicit NadaBweReceiver(int flow_id)
- : BweReceiver(flow_id),
- clock_(0),
- last_feedback_ms_(0),
- recv_stats_(ReceiveStatistics::Create(&clock_)),
- baseline_delay_ms_(0),
- delay_signal_ms_(0),
- last_congestion_signal_ms_(0) {}
-
- virtual void ReceivePacket(int64_t arrival_time_ms,
- const MediaPacket& media_packet) OVERRIDE {
- clock_.AdvanceTimeMilliseconds(arrival_time_ms -
- clock_.TimeInMilliseconds());
- recv_stats_->IncomingPacket(media_packet.header(),
- media_packet.payload_size(), false);
- int64_t delay_ms = arrival_time_ms - media_packet.creation_time_us() / 1000;
- // TODO(holmer): The min should time out after 10 minutes.
- if (delay_ms < baseline_delay_ms_) {
- baseline_delay_ms_ = delay_ms;
- }
- delay_signal_ms_ = delay_ms - baseline_delay_ms_;
- }
-
- virtual FeedbackPacket* GetFeedback(int64_t now_ms) OVERRIDE {
- if (now_ms - last_feedback_ms_ < 100)
- return NULL;
-
- StatisticianMap statisticians = recv_stats_->GetActiveStatisticians();
- int64_t loss_signal_ms = 0.0f;
- if (!statisticians.empty()) {
- RtcpStatistics stats;
- if (!statisticians.begin()->second->GetStatistics(&stats, true)) {
- const float kLossSignalWeight = 1000.0f;
- loss_signal_ms =
- (kLossSignalWeight * static_cast<float>(stats.fraction_lost) +
- 127) /
- 255;
- }
- }
-
- int64_t congestion_signal_ms = delay_signal_ms_ + loss_signal_ms;
-
- float derivative = 0.0f;
- if (last_feedback_ms_ > 0) {
- derivative = (congestion_signal_ms - last_congestion_signal_ms_) /
- static_cast<float>(now_ms - last_feedback_ms_);
- }
- last_feedback_ms_ = now_ms;
- last_congestion_signal_ms_ = congestion_signal_ms;
- return new NadaFeedback(flow_id_, now_ms, congestion_signal_ms, derivative);
- }
-
- private:
- SimulatedClock clock_;
- int64_t last_feedback_ms_;
- scoped_ptr<ReceiveStatistics> recv_stats_;
- int64_t baseline_delay_ms_;
- int64_t delay_signal_ms_;
- int64_t last_congestion_signal_ms_;
-};
-
-class NadaBweSender : public BweSender {
- public:
- NadaBweSender(int kbps, BitrateObserver* observer, Clock* clock)
- : clock_(clock),
- observer_(observer),
- bitrate_kbps_(kbps),
- last_feedback_ms_(0) {}
- virtual ~NadaBweSender() {}
-
- virtual int GetFeedbackIntervalMs() const OVERRIDE { return 100; }
-
- virtual void GiveFeedback(const FeedbackPacket& feedback) {
- const NadaFeedback& fb = static_cast<const NadaFeedback&>(feedback);
-
- // TODO(holmer): Implement special start-up behavior.
-
- const float kEta = 2.0f;
- const float kTaoO = 500.0f;
- float x_hat = fb.congestion_signal() + kEta * kTaoO * fb.derivative();
-
- int64_t now_ms = clock_->TimeInMilliseconds();
- float delta_s = now_ms - last_feedback_ms_;
- last_feedback_ms_ = now_ms;
-
- const float kPriorityWeight = 1.0f;
- const float kReferenceDelayS = 10.0f;
- float kTheta = kPriorityWeight * (kMaxBitrateKbps - kMinBitrateKbps) *
- kReferenceDelayS;
-
- const float kKappa = 1.0f;
- bitrate_kbps_ = bitrate_kbps_ +
- kKappa * delta_s / (kTaoO * kTaoO) *
- (kTheta - (bitrate_kbps_ - kMinBitrateKbps) * x_hat) +
- 0.5f;
- bitrate_kbps_ = std::min(bitrate_kbps_, kMaxBitrateKbps);
- bitrate_kbps_ = std::max(bitrate_kbps_, kMinBitrateKbps);
-
- observer_->OnNetworkChanged(1000 * bitrate_kbps_, 0, 0);
- }
-
- virtual int64_t TimeUntilNextProcess() OVERRIDE { return 100; }
- virtual int Process() OVERRIDE { return 0; }
-
- private:
- Clock* const clock_;
- BitrateObserver* const observer_;
- int bitrate_kbps_;
- int64_t last_feedback_ms_;
-
- DISALLOW_IMPLICIT_CONSTRUCTORS(NadaBweSender);
-};
-
BweSender* CreateBweSender(BandwidthEstimatorType estimator,
int kbps,
BitrateObserver* observer,
diff --git a/webrtc/modules/remote_bitrate_estimator/test/bwe.h b/webrtc/modules/remote_bitrate_estimator/test/bwe.h
index 1bbabd1..a0515db 100644
--- a/webrtc/modules/remote_bitrate_estimator/test/bwe.h
+++ b/webrtc/modules/remote_bitrate_estimator/test/bwe.h
@@ -20,6 +20,9 @@
namespace testing {
namespace bwe {
+const int kMinBitrateKbps = 150;
+const int kMaxBitrateKbps = 2000;
+
class BweSender : public Module {
public:
BweSender() {}
@@ -52,6 +55,8 @@
kFullSendSideEstimator
};
+int64_t GetAbsSendTimeInMs(uint32_t abs_send_time);
+
BweSender* CreateBweSender(BandwidthEstimatorType estimator,
int kbps,
BitrateObserver* observer,
diff --git a/webrtc/modules/remote_bitrate_estimator/test/estimators/nada.cc b/webrtc/modules/remote_bitrate_estimator/test/estimators/nada.cc
new file mode 100644
index 0000000..32f772c
--- /dev/null
+++ b/webrtc/modules/remote_bitrate_estimator/test/estimators/nada.cc
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2015 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 <algorithm>
+
+#include "webrtc/modules/remote_bitrate_estimator/test/estimators/nada.h"
+
+#include "webrtc/modules/rtp_rtcp/interface/receive_statistics.h"
+
+namespace webrtc {
+namespace testing {
+namespace bwe {
+
+NadaBweReceiver::NadaBweReceiver(int flow_id)
+ : BweReceiver(flow_id),
+ clock_(0),
+ last_feedback_ms_(0),
+ recv_stats_(ReceiveStatistics::Create(&clock_)),
+ baseline_delay_ms_(0),
+ delay_signal_ms_(0),
+ last_congestion_signal_ms_(0) {
+}
+
+NadaBweReceiver::~NadaBweReceiver() {
+}
+
+void NadaBweReceiver::ReceivePacket(int64_t arrival_time_ms,
+ const MediaPacket& media_packet) {
+ clock_.AdvanceTimeMilliseconds(arrival_time_ms - clock_.TimeInMilliseconds());
+ recv_stats_->IncomingPacket(media_packet.header(),
+ media_packet.payload_size(), false);
+ int64_t delay_ms = arrival_time_ms - media_packet.creation_time_us() / 1000;
+ // TODO(holmer): The min should time out after 10 minutes.
+ if (delay_ms < baseline_delay_ms_) {
+ baseline_delay_ms_ = delay_ms;
+ }
+ delay_signal_ms_ = delay_ms - baseline_delay_ms_;
+}
+
+FeedbackPacket* NadaBweReceiver::GetFeedback(int64_t now_ms) {
+ if (now_ms - last_feedback_ms_ < 100)
+ return NULL;
+
+ StatisticianMap statisticians = recv_stats_->GetActiveStatisticians();
+ int64_t loss_signal_ms = 0.0f;
+ if (!statisticians.empty()) {
+ RtcpStatistics stats;
+ if (!statisticians.begin()->second->GetStatistics(&stats, true)) {
+ const float kLossSignalWeight = 1000.0f;
+ loss_signal_ms =
+ (kLossSignalWeight * static_cast<float>(stats.fraction_lost) + 127) /
+ 255;
+ }
+ }
+
+ int64_t congestion_signal_ms = delay_signal_ms_ + loss_signal_ms;
+
+ float derivative = 0.0f;
+ if (last_feedback_ms_ > 0) {
+ derivative = (congestion_signal_ms - last_congestion_signal_ms_) /
+ static_cast<float>(now_ms - last_feedback_ms_);
+ }
+ last_feedback_ms_ = now_ms;
+ last_congestion_signal_ms_ = congestion_signal_ms;
+ return new NadaFeedback(flow_id_, now_ms, congestion_signal_ms, derivative);
+}
+
+NadaBweSender::NadaBweSender(int kbps, BitrateObserver* observer, Clock* clock)
+ : clock_(clock),
+ observer_(observer),
+ bitrate_kbps_(kbps),
+ last_feedback_ms_(0) {
+}
+
+NadaBweSender::~NadaBweSender() {
+}
+
+int NadaBweSender::GetFeedbackIntervalMs() const {
+ return 100;
+}
+
+void NadaBweSender::GiveFeedback(const FeedbackPacket& feedback) {
+ const NadaFeedback& fb = static_cast<const NadaFeedback&>(feedback);
+
+ // TODO(holmer): Implement special start-up behavior.
+
+ const float kEta = 2.0f;
+ const float kTaoO = 500.0f;
+ float x_hat = fb.congestion_signal() + kEta * kTaoO * fb.derivative();
+
+ int64_t now_ms = clock_->TimeInMilliseconds();
+ float delta_s = now_ms - last_feedback_ms_;
+ last_feedback_ms_ = now_ms;
+
+ const float kPriorityWeight = 1.0f;
+ const float kReferenceDelayS = 10.0f;
+ float kTheta =
+ kPriorityWeight * (kMaxBitrateKbps - kMinBitrateKbps) * kReferenceDelayS;
+
+ const float kKappa = 1.0f;
+ bitrate_kbps_ = bitrate_kbps_ +
+ kKappa * delta_s / (kTaoO * kTaoO) *
+ (kTheta - (bitrate_kbps_ - kMinBitrateKbps) * x_hat) +
+ 0.5f;
+ bitrate_kbps_ = std::min(bitrate_kbps_, kMaxBitrateKbps);
+ bitrate_kbps_ = std::max(bitrate_kbps_, kMinBitrateKbps);
+
+ observer_->OnNetworkChanged(1000 * bitrate_kbps_, 0, 0);
+}
+
+int64_t NadaBweSender::TimeUntilNextProcess() {
+ return 100;
+}
+
+int NadaBweSender::Process() {
+ return 0;
+}
+
+} // namespace bwe
+} // namespace testing
+} // namespace webrtc
diff --git a/webrtc/modules/remote_bitrate_estimator/test/estimators/nada.h b/webrtc/modules/remote_bitrate_estimator/test/estimators/nada.h
new file mode 100644
index 0000000..5d76712
--- /dev/null
+++ b/webrtc/modules/remote_bitrate_estimator/test/estimators/nada.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2015 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_TEST_ESTIMATORS_NADA_H_
+#define WEBRTC_MODULES_REMOTE_BITRATE_ESTIMATOR_TEST_ESTIMATORS_NADA_H_
+
+#include "webrtc/modules/remote_bitrate_estimator/test/bwe.h"
+
+namespace webrtc {
+
+class ReceiveStatistics;
+
+namespace testing {
+namespace bwe {
+
+class NadaBweReceiver : public BweReceiver {
+ public:
+ explicit NadaBweReceiver(int flow_id);
+ virtual ~NadaBweReceiver();
+
+ void ReceivePacket(int64_t arrival_time_ms,
+ const MediaPacket& media_packet) override;
+ FeedbackPacket* GetFeedback(int64_t now_ms) override;
+
+ private:
+ SimulatedClock clock_;
+ int64_t last_feedback_ms_;
+ scoped_ptr<ReceiveStatistics> recv_stats_;
+ int64_t baseline_delay_ms_;
+ int64_t delay_signal_ms_;
+ int64_t last_congestion_signal_ms_;
+};
+
+class NadaBweSender : public BweSender {
+ public:
+ NadaBweSender(int kbps, BitrateObserver* observer, Clock* clock);
+ virtual ~NadaBweSender();
+
+ int GetFeedbackIntervalMs() const override;
+ void GiveFeedback(const FeedbackPacket& feedback) override;
+ int64_t TimeUntilNextProcess() override;
+ int Process() override;
+
+ private:
+ Clock* const clock_;
+ BitrateObserver* const observer_;
+ int bitrate_kbps_;
+ int64_t last_feedback_ms_;
+
+ DISALLOW_IMPLICIT_CONSTRUCTORS(NadaBweSender);
+};
+
+} // namespace bwe
+} // namespace testing
+} // namespace webrtc
+
+#endif // WEBRTC_MODULES_REMOTE_BITRATE_ESTIMATOR_TEST_ESTIMATORS_NADA_H_
diff --git a/webrtc/modules/remote_bitrate_estimator/test/estimators/remb.cc b/webrtc/modules/remote_bitrate_estimator/test/estimators/remb.cc
new file mode 100644
index 0000000..b28a7b8
--- /dev/null
+++ b/webrtc/modules/remote_bitrate_estimator/test/estimators/remb.cc
@@ -0,0 +1,159 @@
+/*
+ * Copyright (c) 2015 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 <algorithm>
+
+#include "webrtc/modules/remote_bitrate_estimator/test/estimators/remb.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+#include "webrtc/base/common.h"
+#include "webrtc/modules/bitrate_controller/include/bitrate_controller.h"
+#include "webrtc/modules/remote_bitrate_estimator/test/bwe_test_logging.h"
+#include "webrtc/modules/rtp_rtcp/interface/receive_statistics.h"
+
+namespace webrtc {
+namespace testing {
+namespace bwe {
+
+RembBweSender::RembBweSender(int kbps, BitrateObserver* observer, Clock* clock)
+ : bitrate_controller_(
+ BitrateController::CreateBitrateController(clock, false)),
+ feedback_observer_(bitrate_controller_->CreateRtcpBandwidthObserver()),
+ clock_(clock) {
+ assert(kbps >= kMinBitrateKbps);
+ assert(kbps <= kMaxBitrateKbps);
+ bitrate_controller_->SetBitrateObserver(
+ observer, 1000 * kbps, 1000 * kMinBitrateKbps, 1000 * kMaxBitrateKbps);
+}
+
+RembBweSender::~RembBweSender() {
+}
+
+void RembBweSender::GiveFeedback(const FeedbackPacket& feedback) {
+ const RembFeedback& remb_feedback =
+ static_cast<const RembFeedback&>(feedback);
+ feedback_observer_->OnReceivedEstimatedBitrate(remb_feedback.estimated_bps());
+ ReportBlockList report_blocks;
+ report_blocks.push_back(remb_feedback.report_block());
+ feedback_observer_->OnReceivedRtcpReceiverReport(
+ report_blocks, 0, clock_->TimeInMilliseconds());
+ bitrate_controller_->Process();
+}
+
+int64_t RembBweSender::TimeUntilNextProcess() {
+ return bitrate_controller_->TimeUntilNextProcess();
+}
+
+int RembBweSender::Process() {
+ return bitrate_controller_->Process();
+}
+
+int RembBweSender::GetFeedbackIntervalMs() const {
+ return 100;
+}
+
+RembReceiver::RembReceiver(int flow_id, bool plot)
+ : BweReceiver(flow_id),
+ estimate_log_prefix_(),
+ plot_estimate_(plot),
+ clock_(0),
+ recv_stats_(ReceiveStatistics::Create(&clock_)),
+ latest_estimate_bps_(-1),
+ estimator_(AbsoluteSendTimeRemoteBitrateEstimatorFactory().Create(
+ this,
+ &clock_,
+ kAimdControl,
+ kRemoteBitrateEstimatorMinBitrateBps)) {
+ std::stringstream ss;
+ ss << "Estimate_" << flow_id_ << "#1";
+ estimate_log_prefix_ = ss.str();
+ // Default RTT in RemoteRateControl is 200 ms ; 50 ms is more realistic.
+ estimator_->OnRttUpdate(50);
+}
+
+RembReceiver::~RembReceiver() {
+}
+
+void RembReceiver::ReceivePacket(int64_t arrival_time_ms,
+ const MediaPacket& media_packet) {
+ recv_stats_->IncomingPacket(media_packet.header(),
+ media_packet.payload_size(), false);
+
+ latest_estimate_bps_ = -1;
+
+ int64_t step_ms = std::max<int64_t>(estimator_->TimeUntilNextProcess(), 0);
+ while ((clock_.TimeInMilliseconds() + step_ms) < arrival_time_ms) {
+ clock_.AdvanceTimeMilliseconds(step_ms);
+ estimator_->Process();
+ step_ms = std::max<int64_t>(estimator_->TimeUntilNextProcess(), 0);
+ }
+ estimator_->IncomingPacket(arrival_time_ms, media_packet.payload_size(),
+ media_packet.header());
+ clock_.AdvanceTimeMilliseconds(arrival_time_ms - clock_.TimeInMilliseconds());
+ ASSERT_TRUE(arrival_time_ms == clock_.TimeInMilliseconds());
+}
+
+FeedbackPacket* RembReceiver::GetFeedback(int64_t now_ms) {
+ BWE_TEST_LOGGING_CONTEXT("Remb");
+ uint32_t estimated_bps = 0;
+ RembFeedback* feedback = NULL;
+ if (LatestEstimate(&estimated_bps)) {
+ StatisticianMap statisticians = recv_stats_->GetActiveStatisticians();
+ RTCPReportBlock report_block;
+ if (!statisticians.empty()) {
+ report_block = BuildReportBlock(statisticians.begin()->second);
+ }
+ feedback =
+ new RembFeedback(flow_id_, now_ms * 1000, estimated_bps, report_block);
+
+ double estimated_kbps = static_cast<double>(estimated_bps) / 1000.0;
+ RTC_UNUSED(estimated_kbps);
+ if (plot_estimate_) {
+ BWE_TEST_LOGGING_PLOT(estimate_log_prefix_, clock_.TimeInMilliseconds(),
+ estimated_kbps);
+ }
+ }
+ return feedback;
+}
+
+void RembReceiver::OnReceiveBitrateChanged(
+ const std::vector<unsigned int>& ssrcs,
+ unsigned int bitrate) {
+}
+
+RTCPReportBlock RembReceiver::BuildReportBlock(
+ StreamStatistician* statistician) {
+ RTCPReportBlock report_block;
+ RtcpStatistics stats;
+ if (!statistician->GetStatistics(&stats, true))
+ return report_block;
+ report_block.fractionLost = stats.fraction_lost;
+ report_block.cumulativeLost = stats.cumulative_lost;
+ report_block.extendedHighSeqNum = stats.extended_max_sequence_number;
+ report_block.jitter = stats.jitter;
+ return report_block;
+}
+
+bool RembReceiver::LatestEstimate(uint32_t* estimate_bps) {
+ if (latest_estimate_bps_ < 0) {
+ std::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;
+}
+
+} // namespace bwe
+} // namespace testing
+} // namespace webrtc
diff --git a/webrtc/modules/remote_bitrate_estimator/test/estimators/remb.h b/webrtc/modules/remote_bitrate_estimator/test/estimators/remb.h
new file mode 100644
index 0000000..a8cbf89
--- /dev/null
+++ b/webrtc/modules/remote_bitrate_estimator/test/estimators/remb.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2015 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_TEST_ESTIMATORS_REMB_H_
+#define WEBRTC_MODULES_REMOTE_BITRATE_ESTIMATOR_TEST_ESTIMATORS_REMB_H_
+
+#include <string>
+#include <vector>
+
+#include "webrtc/modules/remote_bitrate_estimator/test/bwe.h"
+
+namespace webrtc {
+
+class BitrateObserver;
+class BitrateController;
+class ReceiveStatistics;
+class StreamStatistician;
+
+namespace testing {
+namespace bwe {
+
+class RembBweSender : public BweSender {
+ public:
+ RembBweSender(int kbps, BitrateObserver* observer, Clock* clock);
+ virtual ~RembBweSender();
+
+ int GetFeedbackIntervalMs() const override;
+ void GiveFeedback(const FeedbackPacket& feedback) override;
+ int64_t TimeUntilNextProcess() override;
+ int Process() override;
+
+ protected:
+ scoped_ptr<BitrateController> bitrate_controller_;
+ scoped_ptr<RtcpBandwidthObserver> feedback_observer_;
+
+ private:
+ Clock* clock_;
+
+ DISALLOW_IMPLICIT_CONSTRUCTORS(RembBweSender);
+};
+
+class RembReceiver : public BweReceiver, public RemoteBitrateObserver {
+ public:
+ static const uint32_t kRemoteBitrateEstimatorMinBitrateBps = 30000;
+
+ RembReceiver(int flow_id, bool plot);
+ virtual ~RembReceiver();
+
+ void ReceivePacket(int64_t arrival_time_ms,
+ const MediaPacket& media_packet) override;
+ FeedbackPacket* GetFeedback(int64_t now_ms) override;
+ // Implements RemoteBitrateObserver.
+ void OnReceiveBitrateChanged(const std::vector<unsigned int>& ssrcs,
+ unsigned int bitrate) override;
+
+ private:
+ static RTCPReportBlock BuildReportBlock(StreamStatistician* statistician);
+ bool LatestEstimate(uint32_t* estimate_bps);
+
+ std::string estimate_log_prefix_;
+ bool plot_estimate_;
+ SimulatedClock clock_;
+ scoped_ptr<ReceiveStatistics> recv_stats_;
+ int64_t latest_estimate_bps_;
+ scoped_ptr<RemoteBitrateEstimator> estimator_;
+
+ DISALLOW_IMPLICIT_CONSTRUCTORS(RembReceiver);
+};
+
+} // namespace bwe
+} // namespace testing
+} // namespace webrtc
+
+#endif // WEBRTC_MODULES_REMOTE_BITRATE_ESTIMATOR_TEST_ESTIMATORS_REMB_H_
diff --git a/webrtc/modules/remote_bitrate_estimator/test/estimators/send_side.cc b/webrtc/modules/remote_bitrate_estimator/test/estimators/send_side.cc
new file mode 100644
index 0000000..8f7c784
--- /dev/null
+++ b/webrtc/modules/remote_bitrate_estimator/test/estimators/send_side.cc
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2015 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/estimators/send_side.h"
+
+namespace webrtc {
+namespace testing {
+namespace bwe {
+
+FullBweSender::FullBweSender(int kbps, BitrateObserver* observer, Clock* clock)
+ : bitrate_controller_(
+ BitrateController::CreateBitrateController(clock, false)),
+ rbe_(AbsoluteSendTimeRemoteBitrateEstimatorFactory()
+ .Create(this, clock, kAimdControl, 1000 * kMinBitrateKbps)),
+ feedback_observer_(bitrate_controller_->CreateRtcpBandwidthObserver()),
+ clock_(clock) {
+ assert(kbps >= kMinBitrateKbps);
+ assert(kbps <= kMaxBitrateKbps);
+ bitrate_controller_->SetBitrateObserver(
+ observer, 1000 * kbps, 1000 * kMinBitrateKbps, 1000 * kMaxBitrateKbps);
+}
+
+FullBweSender::~FullBweSender() {
+}
+
+int FullBweSender::GetFeedbackIntervalMs() const {
+ return 100;
+}
+
+void FullBweSender::GiveFeedback(const FeedbackPacket& feedback) {
+ const SendSideBweFeedback& fb =
+ static_cast<const SendSideBweFeedback&>(feedback);
+ if (fb.packet_feedback_vector().empty())
+ return;
+ rbe_->IncomingPacketFeedbackVector(fb.packet_feedback_vector());
+ // TODO(holmer): Handle losses in between feedback packets.
+ int expected_packets = fb.packet_feedback_vector().back().sequence_number -
+ fb.packet_feedback_vector().front().sequence_number +
+ 1;
+ // Assuming no reordering for now.
+ if (expected_packets <= 0)
+ return;
+ int lost_packets = expected_packets - fb.packet_feedback_vector().size();
+ report_block_.fractionLost = (lost_packets << 8) / expected_packets;
+ report_block_.cumulativeLost += lost_packets;
+ ReportBlockList report_blocks;
+ report_blocks.push_back(report_block_);
+ feedback_observer_->OnReceivedRtcpReceiverReport(
+ report_blocks, 0, clock_->TimeInMilliseconds());
+ bitrate_controller_->Process();
+}
+
+void FullBweSender::OnReceiveBitrateChanged(
+ const std::vector<unsigned int>& ssrcs,
+ unsigned int bitrate) {
+ feedback_observer_->OnReceivedEstimatedBitrate(bitrate);
+}
+
+int64_t FullBweSender::TimeUntilNextProcess() {
+ return bitrate_controller_->TimeUntilNextProcess();
+}
+
+int FullBweSender::Process() {
+ rbe_->Process();
+ return bitrate_controller_->Process();
+}
+
+SendSideBweReceiver::SendSideBweReceiver(int flow_id)
+ : BweReceiver(flow_id), last_feedback_ms_(0) {
+}
+
+SendSideBweReceiver::~SendSideBweReceiver() {
+}
+
+void SendSideBweReceiver::ReceivePacket(int64_t arrival_time_ms,
+ const MediaPacket& media_packet) {
+ packet_feedback_vector_.push_back(PacketInfo(
+ arrival_time_ms,
+ GetAbsSendTimeInMs(media_packet.header().extension.absoluteSendTime),
+ media_packet.header().sequenceNumber, media_packet.payload_size()));
+}
+
+FeedbackPacket* SendSideBweReceiver::GetFeedback(int64_t now_ms) {
+ if (now_ms - last_feedback_ms_ < 100)
+ return NULL;
+ last_feedback_ms_ = now_ms;
+ FeedbackPacket* fb =
+ new SendSideBweFeedback(flow_id_, now_ms * 1000, packet_feedback_vector_);
+ packet_feedback_vector_.clear();
+ return fb;
+}
+
+} // namespace bwe
+} // namespace testing
+} // namespace webrtc
diff --git a/webrtc/modules/remote_bitrate_estimator/test/estimators/send_side.h b/webrtc/modules/remote_bitrate_estimator/test/estimators/send_side.h
new file mode 100644
index 0000000..e31e311
--- /dev/null
+++ b/webrtc/modules/remote_bitrate_estimator/test/estimators/send_side.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2015 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_TEST_ESTIMATORS_SEND_SIDE_H_
+#define WEBRTC_MODULES_REMOTE_BITRATE_ESTIMATOR_TEST_ESTIMATORS_SEND_SIDE_H_
+
+#include <vector>
+
+#include "webrtc/modules/remote_bitrate_estimator/test/bwe.h"
+
+namespace webrtc {
+namespace testing {
+namespace bwe {
+
+class FullBweSender : public BweSender, public RemoteBitrateObserver {
+ public:
+ FullBweSender(int kbps, BitrateObserver* observer, Clock* clock);
+ virtual ~FullBweSender();
+
+ int GetFeedbackIntervalMs() const override;
+ void GiveFeedback(const FeedbackPacket& feedback) override;
+ void OnReceiveBitrateChanged(const std::vector<unsigned int>& ssrcs,
+ unsigned int bitrate) override;
+ int64_t TimeUntilNextProcess() override;
+ int Process() override;
+
+ protected:
+ scoped_ptr<BitrateController> bitrate_controller_;
+ scoped_ptr<RemoteBitrateEstimator> rbe_;
+ scoped_ptr<RtcpBandwidthObserver> feedback_observer_;
+
+ private:
+ Clock* const clock_;
+ RTCPReportBlock report_block_;
+
+ DISALLOW_IMPLICIT_CONSTRUCTORS(FullBweSender);
+};
+
+class SendSideBweReceiver : public BweReceiver {
+ public:
+ explicit SendSideBweReceiver(int flow_id);
+ virtual ~SendSideBweReceiver();
+
+ void ReceivePacket(int64_t arrival_time_ms,
+ const MediaPacket& media_packet) override;
+ FeedbackPacket* GetFeedback(int64_t now_ms) override;
+
+ private:
+ int64_t last_feedback_ms_;
+ std::vector<PacketInfo> packet_feedback_vector_;
+};
+
+} // namespace bwe
+} // namespace testing
+} // namespace webrtc
+
+#endif // WEBRTC_MODULES_REMOTE_BITRATE_ESTIMATOR_TEST_ESTIMATORS_SEND_SIDE_H_