webrtc_m130/call/rtp_transport_controller_send.cc
Sebastian Jansson 35fa280229 Adds allocated rate without feedback to new congestion controller.
When bitrate is allocated to streams that does not have packet feedback,
the allocated bitrate should be included in the estimate. This was
previously only implemented for the old congestion controller and not
for the new task queue based version.

To make the behavior more robust, the responsibility for tracking this
is moved to BitrateAllocator where it's handled consistently for
multiple streams without feedback.

Bug: webrtc:9586, webrtc:8243
Change-Id: I8af7fec23e1bdc08cc61cf1b4ff10461c3711fb0
Reviewed-on: https://webrtc-review.googlesource.com/102681
Commit-Queue: Sebastian Jansson <srte@webrtc.org>
Reviewed-by: Christoffer Rodbro <crodbro@webrtc.org>
Reviewed-by: Karl Wiberg <kwiberg@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#24905}
2018-10-01 07:48:02 +00:00

319 lines
12 KiB
C++

/*
* Copyright (c) 2017 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 <utility>
#include <vector>
#include "absl/memory/memory.h"
#include "call/rtp_transport_controller_send.h"
#include "modules/congestion_controller/include/send_side_congestion_controller.h"
#include "modules/congestion_controller/rtp/include/send_side_congestion_controller.h"
#include "rtc_base/location.h"
#include "rtc_base/logging.h"
#include "rtc_base/rate_limiter.h"
#include "system_wrappers/include/field_trial.h"
namespace webrtc {
namespace {
static const int64_t kRetransmitWindowSizeMs = 500;
const char kTaskQueueExperiment[] = "WebRTC-TaskQueueCongestionControl";
using TaskQueueController = webrtc::webrtc_cc::SendSideCongestionController;
bool TaskQueueExperimentEnabled() {
std::string trial = webrtc::field_trial::FindFullName(kTaskQueueExperiment);
return trial.find("Enable") == 0;
}
std::unique_ptr<SendSideCongestionControllerInterface> CreateController(
Clock* clock,
rtc::TaskQueue* task_queue,
webrtc::RtcEventLog* event_log,
PacedSender* pacer,
const BitrateConstraints& bitrate_config,
bool task_queue_controller,
NetworkControllerFactoryInterface* controller_factory) {
if (task_queue_controller) {
RTC_LOG(LS_INFO) << "Using TaskQueue based SSCC";
return absl::make_unique<webrtc::webrtc_cc::SendSideCongestionController>(
clock, task_queue, event_log, pacer, bitrate_config.start_bitrate_bps,
bitrate_config.min_bitrate_bps, bitrate_config.max_bitrate_bps,
controller_factory);
}
RTC_LOG(LS_INFO) << "Using Legacy SSCC";
auto cc = absl::make_unique<webrtc::SendSideCongestionController>(
clock, nullptr /* observer */, event_log, pacer);
cc->SignalNetworkState(kNetworkDown);
cc->SetBweBitrates(bitrate_config.min_bitrate_bps,
bitrate_config.start_bitrate_bps,
bitrate_config.max_bitrate_bps);
return std::move(cc);
}
} // namespace
RtpTransportControllerSend::RtpTransportControllerSend(
Clock* clock,
webrtc::RtcEventLog* event_log,
NetworkControllerFactoryInterface* controller_factory,
const BitrateConstraints& bitrate_config)
: clock_(clock),
pacer_(clock, &packet_router_, event_log),
bitrate_configurator_(bitrate_config),
process_thread_(ProcessThread::Create("SendControllerThread")),
observer_(nullptr),
retransmission_rate_limiter_(clock, kRetransmitWindowSizeMs),
task_queue_("rtp_send_controller") {
// Created after task_queue to be able to post to the task queue internally.
send_side_cc_ =
CreateController(clock, &task_queue_, event_log, &pacer_, bitrate_config,
TaskQueueExperimentEnabled(), controller_factory);
process_thread_->RegisterModule(&pacer_, RTC_FROM_HERE);
process_thread_->RegisterModule(send_side_cc_.get(), RTC_FROM_HERE);
process_thread_->Start();
}
RtpTransportControllerSend::~RtpTransportControllerSend() {
process_thread_->Stop();
process_thread_->DeRegisterModule(send_side_cc_.get());
process_thread_->DeRegisterModule(&pacer_);
}
RtpVideoSenderInterface* RtpTransportControllerSend::CreateRtpVideoSender(
const std::vector<uint32_t>& ssrcs,
std::map<uint32_t, RtpState> suspended_ssrcs,
const std::map<uint32_t, RtpPayloadState>& states,
const RtpConfig& rtp_config,
const RtcpConfig& rtcp_config,
Transport* send_transport,
const RtpSenderObservers& observers,
RtcEventLog* event_log) {
video_rtp_senders_.push_back(absl::make_unique<RtpVideoSender>(
ssrcs, suspended_ssrcs, states, rtp_config, rtcp_config, send_transport,
observers,
// TODO(holmer): Remove this circular dependency by injecting
// the parts of RtpTransportControllerSendInterface that are really used.
this, event_log, &retransmission_rate_limiter_));
return video_rtp_senders_.back().get();
}
void RtpTransportControllerSend::DestroyRtpVideoSender(
RtpVideoSenderInterface* rtp_video_sender) {
std::vector<std::unique_ptr<RtpVideoSenderInterface>>::iterator it =
video_rtp_senders_.end();
for (it = video_rtp_senders_.begin(); it != video_rtp_senders_.end(); ++it) {
if (it->get() == rtp_video_sender) {
break;
}
}
RTC_DCHECK(it != video_rtp_senders_.end());
video_rtp_senders_.erase(it);
}
void RtpTransportControllerSend::OnNetworkChanged(uint32_t bitrate_bps,
uint8_t fraction_loss,
int64_t rtt_ms,
int64_t probing_interval_ms) {
// TODO(srte): Skip this step when old SendSideCongestionController is
// deprecated.
TargetTransferRate msg;
msg.at_time = Timestamp::ms(clock_->TimeInMilliseconds());
msg.target_rate = DataRate::bps(bitrate_bps);
msg.network_estimate.at_time = msg.at_time;
msg.network_estimate.bwe_period = TimeDelta::ms(probing_interval_ms);
uint32_t bandwidth_bps;
if (send_side_cc_->AvailableBandwidth(&bandwidth_bps))
msg.network_estimate.bandwidth = DataRate::bps(bandwidth_bps);
msg.network_estimate.loss_rate_ratio = fraction_loss / 255.0;
msg.network_estimate.round_trip_time = TimeDelta::ms(rtt_ms);
retransmission_rate_limiter_.SetMaxRate(bandwidth_bps);
if (!task_queue_.IsCurrent()) {
task_queue_.PostTask([this, msg] {
rtc::CritScope cs(&observer_crit_);
// We won't register as observer until we have an observers.
RTC_DCHECK(observer_ != nullptr);
observer_->OnTargetTransferRate(msg);
});
} else {
rtc::CritScope cs(&observer_crit_);
// We won't register as observer until we have an observers.
RTC_DCHECK(observer_ != nullptr);
observer_->OnTargetTransferRate(msg);
}
}
rtc::TaskQueue* RtpTransportControllerSend::GetWorkerQueue() {
return &task_queue_;
}
PacketRouter* RtpTransportControllerSend::packet_router() {
return &packet_router_;
}
TransportFeedbackObserver*
RtpTransportControllerSend::transport_feedback_observer() {
return send_side_cc_.get();
}
RtpPacketSender* RtpTransportControllerSend::packet_sender() {
return &pacer_;
}
const RtpKeepAliveConfig& RtpTransportControllerSend::keepalive_config() const {
return keepalive_;
}
void RtpTransportControllerSend::SetAllocatedSendBitrateLimits(
int min_send_bitrate_bps,
int max_padding_bitrate_bps,
int max_total_bitrate_bps) {
send_side_cc_->SetAllocatedSendBitrateLimits(
min_send_bitrate_bps, max_padding_bitrate_bps, max_total_bitrate_bps);
}
void RtpTransportControllerSend::SetKeepAliveConfig(
const RtpKeepAliveConfig& config) {
keepalive_ = config;
}
void RtpTransportControllerSend::SetPacingFactor(float pacing_factor) {
send_side_cc_->SetPacingFactor(pacing_factor);
}
void RtpTransportControllerSend::SetQueueTimeLimit(int limit_ms) {
pacer_.SetQueueTimeLimit(limit_ms);
}
CallStatsObserver* RtpTransportControllerSend::GetCallStatsObserver() {
return send_side_cc_.get();
}
void RtpTransportControllerSend::RegisterPacketFeedbackObserver(
PacketFeedbackObserver* observer) {
send_side_cc_->RegisterPacketFeedbackObserver(observer);
}
void RtpTransportControllerSend::DeRegisterPacketFeedbackObserver(
PacketFeedbackObserver* observer) {
send_side_cc_->DeRegisterPacketFeedbackObserver(observer);
}
void RtpTransportControllerSend::RegisterTargetTransferRateObserver(
TargetTransferRateObserver* observer) {
{
rtc::CritScope cs(&observer_crit_);
RTC_DCHECK(observer_ == nullptr);
observer_ = observer;
}
send_side_cc_->RegisterNetworkObserver(this);
}
void RtpTransportControllerSend::OnNetworkRouteChanged(
const std::string& transport_name,
const rtc::NetworkRoute& network_route) {
// Check if the network route is connected.
if (!network_route.connected) {
RTC_LOG(LS_INFO) << "Transport " << transport_name << " is disconnected";
// TODO(honghaiz): Perhaps handle this in SignalChannelNetworkState and
// consider merging these two methods.
return;
}
// Check whether the network route has changed on each transport.
auto result =
network_routes_.insert(std::make_pair(transport_name, network_route));
auto kv = result.first;
bool inserted = result.second;
if (inserted) {
// No need to reset BWE if this is the first time the network connects.
return;
}
if (kv->second != network_route) {
kv->second = network_route;
BitrateConstraints bitrate_config = bitrate_configurator_.GetConfig();
RTC_LOG(LS_INFO) << "Network route changed on transport " << transport_name
<< ": new local network id "
<< network_route.local_network_id
<< " new remote network id "
<< network_route.remote_network_id
<< " Reset bitrates to min: "
<< bitrate_config.min_bitrate_bps
<< " bps, start: " << bitrate_config.start_bitrate_bps
<< " bps, max: " << bitrate_config.max_bitrate_bps
<< " bps.";
RTC_DCHECK_GT(bitrate_config.start_bitrate_bps, 0);
send_side_cc_->OnNetworkRouteChanged(
network_route, bitrate_config.start_bitrate_bps,
bitrate_config.min_bitrate_bps, bitrate_config.max_bitrate_bps);
}
}
void RtpTransportControllerSend::OnNetworkAvailability(bool network_available) {
send_side_cc_->SignalNetworkState(network_available ? kNetworkUp
: kNetworkDown);
for (auto& rtp_sender : video_rtp_senders_) {
rtp_sender->OnNetworkAvailability(network_available);
}
}
RtcpBandwidthObserver* RtpTransportControllerSend::GetBandwidthObserver() {
return send_side_cc_->GetBandwidthObserver();
}
int64_t RtpTransportControllerSend::GetPacerQueuingDelayMs() const {
return pacer_.QueueInMs();
}
int64_t RtpTransportControllerSend::GetFirstPacketTimeMs() const {
return pacer_.FirstSentPacketTimeMs();
}
void RtpTransportControllerSend::SetPerPacketFeedbackAvailable(bool available) {
send_side_cc_->SetPerPacketFeedbackAvailable(available);
}
void RtpTransportControllerSend::EnablePeriodicAlrProbing(bool enable) {
send_side_cc_->EnablePeriodicAlrProbing(enable);
}
void RtpTransportControllerSend::OnSentPacket(
const rtc::SentPacket& sent_packet) {
send_side_cc_->OnSentPacket(sent_packet);
}
void RtpTransportControllerSend::SetSdpBitrateParameters(
const BitrateConstraints& constraints) {
absl::optional<BitrateConstraints> updated =
bitrate_configurator_.UpdateWithSdpParameters(constraints);
if (updated.has_value()) {
send_side_cc_->SetBweBitrates(updated->min_bitrate_bps,
updated->start_bitrate_bps,
updated->max_bitrate_bps);
} else {
RTC_LOG(LS_VERBOSE)
<< "WebRTC.RtpTransportControllerSend.SetSdpBitrateParameters: "
<< "nothing to update";
}
}
void RtpTransportControllerSend::SetClientBitratePreferences(
const BitrateSettings& preferences) {
absl::optional<BitrateConstraints> updated =
bitrate_configurator_.UpdateWithClientPreferences(preferences);
if (updated.has_value()) {
send_side_cc_->SetBweBitrates(updated->min_bitrate_bps,
updated->start_bitrate_bps,
updated->max_bitrate_bps);
} else {
RTC_LOG(LS_VERBOSE)
<< "WebRTC.RtpTransportControllerSend.SetClientBitratePreferences: "
<< "nothing to update";
}
}
void RtpTransportControllerSend::SetAllocatedBitrateWithoutFeedback(
uint32_t bitrate_bps) {
// Audio transport feedback will not be reported in this mode, instead update
// acknowledged bitrate estimator with the bitrate allocated for audio.
if (field_trial::IsEnabled("WebRTC-Audio-ABWENoTWCC")) {
// TODO(srte): Make sure it's safe to always report this and remove the
// field trial check.
send_side_cc_->SetAllocatedBitrateWithoutFeedback(bitrate_bps);
}
}
} // namespace webrtc