diff --git a/webrtc/modules/modules.gyp b/webrtc/modules/modules.gyp index d9f071e99e..61d00ebf42 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 fe6c011386..3221d2b7af 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 #include -#include -#include -#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::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 bitrate_controller_; - scoped_ptr 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& ssrcs, - unsigned int bitrate) OVERRIDE; - virtual int64_t TimeUntilNextProcess() OVERRIDE; - virtual int Process() OVERRIDE; - - protected: - scoped_ptr bitrate_controller_; - scoped_ptr rbe_; - scoped_ptr 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(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(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& 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 @@ int64_t GetAbsSendTimeInMs(uint32_t abs_send_time) { return static_cast(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 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(estimator_->TimeUntilNextProcess(), 0); - while ((clock_.TimeInMilliseconds() + step_ms) < arrival_time_ms) { - clock_.AdvanceTimeMilliseconds(step_ms); - estimator_->Process(); - step_ms = std::max(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(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& 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 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 recv_stats_; - int64_t latest_estimate_bps_; - scoped_ptr 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(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(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 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(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 1bbabd1a55..a0515db8cd 100644 --- a/webrtc/modules/remote_bitrate_estimator/test/bwe.h +++ b/webrtc/modules/remote_bitrate_estimator/test/bwe.h @@ -20,6 +20,9 @@ namespace webrtc { namespace testing { namespace bwe { +const int kMinBitrateKbps = 150; +const int kMaxBitrateKbps = 2000; + class BweSender : public Module { public: BweSender() {} @@ -52,6 +55,8 @@ enum BandwidthEstimatorType { 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 0000000000..32f772c02f --- /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 + +#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(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(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(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 0000000000..5d7671257e --- /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 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 0000000000..b28a7b8dc9 --- /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 + +#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(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(estimator_->TimeUntilNextProcess(), 0); + while ((clock_.TimeInMilliseconds() + step_ms) < arrival_time_ms) { + clock_.AdvanceTimeMilliseconds(step_ms); + estimator_->Process(); + step_ms = std::max(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(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& 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 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 0000000000..a8cbf89be2 --- /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 +#include + +#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 bitrate_controller_; + scoped_ptr 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& 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 recv_stats_; + int64_t latest_estimate_bps_; + scoped_ptr 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 0000000000..8f7c784c2c --- /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(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& 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 0000000000..e31e31118f --- /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 + +#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& ssrcs, + unsigned int bitrate) override; + int64_t TimeUntilNextProcess() override; + int Process() override; + + protected: + scoped_ptr bitrate_controller_; + scoped_ptr rbe_; + scoped_ptr 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 packet_feedback_vector_; +}; + +} // namespace bwe +} // namespace testing +} // namespace webrtc + +#endif // WEBRTC_MODULES_REMOTE_BITRATE_ESTIMATOR_TEST_ESTIMATORS_SEND_SIDE_H_