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
This commit is contained in:
parent
ccd7c7c45d
commit
db8e605c16
@ -231,6 +231,12 @@
|
|||||||
'remote_bitrate_estimator/test/packet_sender.cc',
|
'remote_bitrate_estimator/test/packet_sender.cc',
|
||||||
'remote_bitrate_estimator/test/packet_sender.h',
|
'remote_bitrate_estimator/test/packet_sender.h',
|
||||||
'remote_bitrate_estimator/test/packets.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/mock/mock_rtp_payload_strategy.h',
|
||||||
'rtp_rtcp/source/byte_io_unittest.cc',
|
'rtp_rtcp/source/byte_io_unittest.cc',
|
||||||
'rtp_rtcp/source/fec_receiver_unittest.cc',
|
'rtp_rtcp/source/fec_receiver_unittest.cc',
|
||||||
|
@ -10,171 +10,33 @@
|
|||||||
|
|
||||||
#include "webrtc/modules/remote_bitrate_estimator/test/bwe.h"
|
#include "webrtc/modules/remote_bitrate_estimator/test/bwe.h"
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
#include <limits>
|
#include <limits>
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#include "testing/gtest/include/gtest/gtest.h"
|
|
||||||
#include "webrtc/base/common.h"
|
#include "webrtc/base/common.h"
|
||||||
#include "webrtc/modules/remote_bitrate_estimator/rate_statistics.h"
|
#include "webrtc/modules/remote_bitrate_estimator/test/estimators/nada.h"
|
||||||
#include "webrtc/modules/remote_bitrate_estimator/test/bwe_test_logging.h"
|
#include "webrtc/modules/remote_bitrate_estimator/test/estimators/remb.h"
|
||||||
#include "webrtc/modules/rtp_rtcp/interface/receive_statistics.h"
|
#include "webrtc/modules/remote_bitrate_estimator/test/estimators/send_side.h"
|
||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
namespace testing {
|
namespace testing {
|
||||||
namespace bwe {
|
namespace bwe {
|
||||||
|
|
||||||
const int kMinBitrateKbps = 150;
|
|
||||||
const int kMaxBitrateKbps = 2000;
|
|
||||||
|
|
||||||
class NullBweSender : public BweSender {
|
class NullBweSender : public BweSender {
|
||||||
public:
|
public:
|
||||||
NullBweSender() {}
|
NullBweSender() {}
|
||||||
virtual ~NullBweSender() {}
|
virtual ~NullBweSender() {}
|
||||||
|
|
||||||
virtual int GetFeedbackIntervalMs() const OVERRIDE { return 1000; }
|
virtual int GetFeedbackIntervalMs() const override { return 1000; }
|
||||||
virtual void GiveFeedback(const FeedbackPacket& feedback) OVERRIDE {}
|
virtual void GiveFeedback(const FeedbackPacket& feedback) override {}
|
||||||
virtual int64_t TimeUntilNextProcess() OVERRIDE {
|
virtual int64_t TimeUntilNextProcess() override {
|
||||||
return std::numeric_limits<int64_t>::max();
|
return std::numeric_limits<int64_t>::max();
|
||||||
}
|
}
|
||||||
virtual int Process() OVERRIDE { return 0; }
|
virtual int Process() override { return 0; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
DISALLOW_COPY_AND_ASSIGN(NullBweSender);
|
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) {
|
int64_t GetAbsSendTimeInMs(uint32_t abs_send_time) {
|
||||||
const int kInterArrivalShift = 26;
|
const int kInterArrivalShift = 26;
|
||||||
const int kAbsSendTimeInterArrivalUpshift = 8;
|
const int kAbsSendTimeInterArrivalUpshift = 8;
|
||||||
@ -184,254 +46,6 @@ int64_t GetAbsSendTimeInMs(uint32_t abs_send_time) {
|
|||||||
return static_cast<int64_t>(timestamp) * kTimestampToMs;
|
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,
|
BweSender* CreateBweSender(BandwidthEstimatorType estimator,
|
||||||
int kbps,
|
int kbps,
|
||||||
BitrateObserver* observer,
|
BitrateObserver* observer,
|
||||||
|
@ -20,6 +20,9 @@ namespace webrtc {
|
|||||||
namespace testing {
|
namespace testing {
|
||||||
namespace bwe {
|
namespace bwe {
|
||||||
|
|
||||||
|
const int kMinBitrateKbps = 150;
|
||||||
|
const int kMaxBitrateKbps = 2000;
|
||||||
|
|
||||||
class BweSender : public Module {
|
class BweSender : public Module {
|
||||||
public:
|
public:
|
||||||
BweSender() {}
|
BweSender() {}
|
||||||
@ -52,6 +55,8 @@ enum BandwidthEstimatorType {
|
|||||||
kFullSendSideEstimator
|
kFullSendSideEstimator
|
||||||
};
|
};
|
||||||
|
|
||||||
|
int64_t GetAbsSendTimeInMs(uint32_t abs_send_time);
|
||||||
|
|
||||||
BweSender* CreateBweSender(BandwidthEstimatorType estimator,
|
BweSender* CreateBweSender(BandwidthEstimatorType estimator,
|
||||||
int kbps,
|
int kbps,
|
||||||
BitrateObserver* observer,
|
BitrateObserver* observer,
|
||||||
|
128
webrtc/modules/remote_bitrate_estimator/test/estimators/nada.cc
Normal file
128
webrtc/modules/remote_bitrate_estimator/test/estimators/nada.cc
Normal file
@ -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
|
@ -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_
|
159
webrtc/modules/remote_bitrate_estimator/test/estimators/remb.cc
Normal file
159
webrtc/modules/remote_bitrate_estimator/test/estimators/remb.cc
Normal file
@ -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
|
@ -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_
|
@ -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
|
@ -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_
|
Loading…
x
Reference in New Issue
Block a user