/* * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ #include "webrtc/modules/congestion_controller/include/congestion_controller.h" #include #include #include #include "webrtc/base/checks.h" #include "webrtc/base/constructormagic.h" #include "webrtc/base/logging.h" #include "webrtc/base/socket.h" #include "webrtc/base/thread_annotations.h" #include "webrtc/modules/bitrate_controller/include/bitrate_controller.h" #include "webrtc/modules/remote_bitrate_estimator/include/send_time_history.h" #include "webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimator_abs_send_time.h" #include "webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimator_single_stream.h" #include "webrtc/modules/utility/include/process_thread.h" #include "webrtc/system_wrappers/include/critical_section_wrapper.h" #include "webrtc/video/payload_router.h" namespace webrtc { namespace { static const uint32_t kTimeOffsetSwitchThreshold = 30; class WrappingBitrateEstimator : public RemoteBitrateEstimator { public: WrappingBitrateEstimator(RemoteBitrateObserver* observer, Clock* clock) : observer_(observer), clock_(clock), crit_sect_(CriticalSectionWrapper::CreateCriticalSection()), rbe_(new RemoteBitrateEstimatorSingleStream(observer_, clock_)), using_absolute_send_time_(false), packets_since_absolute_send_time_(0), min_bitrate_bps_(RemoteBitrateEstimator::kDefaultMinBitrateBps) {} virtual ~WrappingBitrateEstimator() {} void IncomingPacket(int64_t arrival_time_ms, size_t payload_size, const RTPHeader& header, bool was_paced) override { CriticalSectionScoped cs(crit_sect_.get()); PickEstimatorFromHeader(header); rbe_->IncomingPacket(arrival_time_ms, payload_size, header, was_paced); } void Process() override { CriticalSectionScoped cs(crit_sect_.get()); rbe_->Process(); } int64_t TimeUntilNextProcess() override { CriticalSectionScoped cs(crit_sect_.get()); return rbe_->TimeUntilNextProcess(); } void OnRttUpdate(int64_t avg_rtt_ms, int64_t max_rtt_ms) override { CriticalSectionScoped cs(crit_sect_.get()); rbe_->OnRttUpdate(avg_rtt_ms, max_rtt_ms); } void RemoveStream(unsigned int ssrc) override { CriticalSectionScoped cs(crit_sect_.get()); rbe_->RemoveStream(ssrc); } bool LatestEstimate(std::vector* ssrcs, unsigned int* bitrate_bps) const override { CriticalSectionScoped cs(crit_sect_.get()); return rbe_->LatestEstimate(ssrcs, bitrate_bps); } void SetMinBitrate(int min_bitrate_bps) override { CriticalSectionScoped cs(crit_sect_.get()); rbe_->SetMinBitrate(min_bitrate_bps); min_bitrate_bps_ = min_bitrate_bps; } private: void PickEstimatorFromHeader(const RTPHeader& header) EXCLUSIVE_LOCKS_REQUIRED(crit_sect_.get()) { if (header.extension.hasAbsoluteSendTime) { // If we see AST in header, switch RBE strategy immediately. if (!using_absolute_send_time_) { LOG(LS_INFO) << "WrappingBitrateEstimator: Switching to absolute send time RBE."; using_absolute_send_time_ = true; PickEstimator(); } packets_since_absolute_send_time_ = 0; } else { // When we don't see AST, wait for a few packets before going back to TOF. if (using_absolute_send_time_) { ++packets_since_absolute_send_time_; if (packets_since_absolute_send_time_ >= kTimeOffsetSwitchThreshold) { LOG(LS_INFO) << "WrappingBitrateEstimator: Switching to transmission " << "time offset RBE."; using_absolute_send_time_ = false; PickEstimator(); } } } } // Instantiate RBE for Time Offset or Absolute Send Time extensions. void PickEstimator() EXCLUSIVE_LOCKS_REQUIRED(crit_sect_.get()) { if (using_absolute_send_time_) { rbe_.reset(new RemoteBitrateEstimatorAbsSendTime(observer_)); } else { rbe_.reset(new RemoteBitrateEstimatorSingleStream(observer_, clock_)); } rbe_->SetMinBitrate(min_bitrate_bps_); } RemoteBitrateObserver* observer_; Clock* const clock_; std::unique_ptr crit_sect_; std::unique_ptr rbe_; bool using_absolute_send_time_; uint32_t packets_since_absolute_send_time_; int min_bitrate_bps_; RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(WrappingBitrateEstimator); }; } // namespace CongestionController::CongestionController( Clock* clock, BitrateObserver* bitrate_observer, RemoteBitrateObserver* remote_bitrate_observer) : clock_(clock), observer_(nullptr), packet_router_(new PacketRouter()), pacer_(new PacedSender(clock_, packet_router_.get(), BitrateController::kDefaultStartBitratebps)), remote_bitrate_estimator_( new WrappingBitrateEstimator(remote_bitrate_observer, clock_)), bitrate_controller_( BitrateController::CreateBitrateController(clock_, bitrate_observer)), remote_estimator_proxy_(clock_, packet_router_.get()), transport_feedback_adapter_(bitrate_controller_.get(), clock_), min_bitrate_bps_(RemoteBitrateEstimator::kDefaultMinBitrateBps), send_queue_is_full_(false) { Init(); } CongestionController::CongestionController( Clock* clock, Observer* observer, RemoteBitrateObserver* remote_bitrate_observer) : clock_(clock), observer_(observer), packet_router_(new PacketRouter()), pacer_(new PacedSender(clock_, packet_router_.get(), BitrateController::kDefaultStartBitratebps)), remote_bitrate_estimator_( new WrappingBitrateEstimator(remote_bitrate_observer, clock_)), bitrate_controller_(BitrateController::CreateBitrateController(clock_)), remote_estimator_proxy_(clock_, packet_router_.get()), transport_feedback_adapter_(bitrate_controller_.get(), clock_), min_bitrate_bps_(RemoteBitrateEstimator::kDefaultMinBitrateBps), send_queue_is_full_(false) { Init(); } CongestionController::CongestionController( Clock* clock, Observer* observer, RemoteBitrateObserver* remote_bitrate_observer, std::unique_ptr packet_router, std::unique_ptr pacer) : clock_(clock), observer_(observer), packet_router_(std::move(packet_router)), pacer_(std::move(pacer)), remote_bitrate_estimator_( new WrappingBitrateEstimator(remote_bitrate_observer, clock_)), // Constructed last as this object calls the provided callback on // construction. bitrate_controller_(BitrateController::CreateBitrateController(clock_)), remote_estimator_proxy_(clock_, packet_router_.get()), transport_feedback_adapter_(bitrate_controller_.get(), clock_), min_bitrate_bps_(RemoteBitrateEstimator::kDefaultMinBitrateBps), send_queue_is_full_(false) { Init(); } CongestionController::~CongestionController() {} void CongestionController::Init() { transport_feedback_adapter_.SetBitrateEstimator( new RemoteBitrateEstimatorAbsSendTime(&transport_feedback_adapter_)); transport_feedback_adapter_.GetBitrateEstimator()->SetMinBitrate( min_bitrate_bps_); // This calls the observer_, which means that the observer provided by the // user must be ready to accept a bitrate update when it constructs the // controller. We do this to avoid having to keep synchronized initial values // in both the controller and the allocator. MaybeTriggerOnNetworkChanged(); } void CongestionController::SetBweBitrates(int min_bitrate_bps, int start_bitrate_bps, int max_bitrate_bps) { // TODO(holmer): We should make sure the default bitrates are set to 10 kbps, // and that we don't try to set the min bitrate to 0 from any applications. // The congestion controller should allow a min bitrate of 0. const int kMinBitrateBps = 10000; if (min_bitrate_bps < kMinBitrateBps) min_bitrate_bps = kMinBitrateBps; if (max_bitrate_bps > 0) max_bitrate_bps = std::max(min_bitrate_bps, max_bitrate_bps); if (start_bitrate_bps > 0) start_bitrate_bps = std::max(min_bitrate_bps, start_bitrate_bps); bitrate_controller_->SetBitrates(start_bitrate_bps, min_bitrate_bps, max_bitrate_bps); if (remote_bitrate_estimator_) remote_bitrate_estimator_->SetMinBitrate(min_bitrate_bps); min_bitrate_bps_ = min_bitrate_bps; transport_feedback_adapter_.GetBitrateEstimator()->SetMinBitrate( min_bitrate_bps_); MaybeTriggerOnNetworkChanged(); } BitrateController* CongestionController::GetBitrateController() const { return bitrate_controller_.get(); } RemoteBitrateEstimator* CongestionController::GetRemoteBitrateEstimator( bool send_side_bwe) { if (send_side_bwe) { return &remote_estimator_proxy_; } else { return remote_bitrate_estimator_.get(); } } TransportFeedbackObserver* CongestionController::GetTransportFeedbackObserver() { return &transport_feedback_adapter_; } void CongestionController::SetAllocatedSendBitrate(int allocated_bitrate_bps, int padding_bitrate_bps) { pacer_->SetAllocatedSendBitrate(allocated_bitrate_bps, padding_bitrate_bps); } int64_t CongestionController::GetPacerQueuingDelayMs() const { return pacer_->QueueInMs(); } void CongestionController::SignalNetworkState(NetworkState state) { if (state == kNetworkUp) { pacer_->Resume(); } else { pacer_->Pause(); } } void CongestionController::OnSentPacket(const rtc::SentPacket& sent_packet) { transport_feedback_adapter_.OnSentPacket(sent_packet.packet_id, sent_packet.send_time_ms); } void CongestionController::OnRttUpdate(int64_t avg_rtt_ms, int64_t max_rtt_ms) { remote_bitrate_estimator_->OnRttUpdate(avg_rtt_ms, max_rtt_ms); transport_feedback_adapter_.OnRttUpdate(avg_rtt_ms, max_rtt_ms); } int64_t CongestionController::TimeUntilNextProcess() { return std::min(bitrate_controller_->TimeUntilNextProcess(), remote_bitrate_estimator_->TimeUntilNextProcess()); } void CongestionController::Process() { bitrate_controller_->Process(); remote_bitrate_estimator_->Process(); MaybeTriggerOnNetworkChanged(); } void CongestionController::MaybeTriggerOnNetworkChanged() { // TODO(perkj): |observer_| can be nullptr if the ctor that accepts a // BitrateObserver is used. Remove this check once the ctor is removed. if (!observer_) return; uint32_t bitrate_bps; uint8_t fraction_loss; int64_t rtt; bool network_changed = bitrate_controller_->GetNetworkParameters( &bitrate_bps, &fraction_loss, &rtt); if (network_changed) pacer_->SetEstimatedBitrate(bitrate_bps); bool send_queue_is_full = pacer_->ExpectedQueueTimeMs() > PacedSender::kMaxQueueLengthMs; bitrate_bps = send_queue_is_full ? 0 : bitrate_bps; if ((network_changed && !send_queue_is_full) || UpdateSendQueueStatus(send_queue_is_full)) { observer_->OnNetworkChanged(bitrate_bps, fraction_loss, rtt); } } bool CongestionController::UpdateSendQueueStatus(bool send_queue_is_full) { rtc::CritScope cs(&critsect_); bool result = send_queue_is_full_ != send_queue_is_full; send_queue_is_full_ = send_queue_is_full; return result; } } // namespace webrtc