mirror of
https://github.com/mollyim/webrtc.git
synced 2025-05-13 22:00:47 +01:00

rtc::TaskQueue is a simple wrapper over TaskQueueBase and adds no extra features when task queue is used without passing ownership. Reducing usage of the internal rtc::TaskQueue wrapper gives users more flexibility how TaskQueueBase* is stored. Bug: webrtc:14169 Change-Id: If5c8827544c843502c7dfcef775ac558de79ec3a Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/268189 Reviewed-by: Ilya Nikolaevskiy <ilnik@webrtc.org> Commit-Queue: Danil Chapovalov <danilchap@webrtc.org> Cr-Commit-Position: refs/heads/main@{#37549}
148 lines
5.4 KiB
C++
148 lines
5.4 KiB
C++
/*
|
|
* Copyright (c) 2021 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 "modules/video_coding/utility/bandwidth_quality_scaler.h"
|
|
|
|
#include <algorithm>
|
|
#include <memory>
|
|
#include <utility>
|
|
#include <vector>
|
|
|
|
#include "api/video/video_adaptation_reason.h"
|
|
#include "api/video_codecs/video_encoder.h"
|
|
#include "rtc_base/checks.h"
|
|
#include "rtc_base/experiments/bandwidth_quality_scaler_settings.h"
|
|
#include "rtc_base/logging.h"
|
|
#include "rtc_base/numerics/exp_filter.h"
|
|
#include "rtc_base/time_utils.h"
|
|
#include "rtc_base/weak_ptr.h"
|
|
|
|
namespace webrtc {
|
|
|
|
namespace {
|
|
|
|
constexpr int kDefaultMaxWindowSizeMs = 5000;
|
|
constexpr float kHigherMaxBitrateTolerationFactor = 0.95;
|
|
constexpr float kLowerMinBitrateTolerationFactor = 0.8;
|
|
constexpr int kDefaultBitrateStateUpdateIntervalSeconds = 5;
|
|
} // namespace
|
|
|
|
BandwidthQualityScaler::BandwidthQualityScaler(
|
|
BandwidthQualityScalerUsageHandlerInterface* handler)
|
|
: kBitrateStateUpdateInterval(TimeDelta::Seconds(
|
|
BandwidthQualityScalerSettings::ParseFromFieldTrials()
|
|
.BitrateStateUpdateInterval()
|
|
.value_or(kDefaultBitrateStateUpdateIntervalSeconds))),
|
|
handler_(handler),
|
|
encoded_bitrate_(kDefaultMaxWindowSizeMs, RateStatistics::kBpsScale),
|
|
weak_ptr_factory_(this) {
|
|
RTC_DCHECK_RUN_ON(&task_checker_);
|
|
RTC_DCHECK(handler_ != nullptr);
|
|
|
|
StartCheckForBitrate();
|
|
}
|
|
|
|
BandwidthQualityScaler::~BandwidthQualityScaler() {
|
|
RTC_DCHECK_RUN_ON(&task_checker_);
|
|
}
|
|
|
|
void BandwidthQualityScaler::StartCheckForBitrate() {
|
|
RTC_DCHECK_RUN_ON(&task_checker_);
|
|
TaskQueueBase::Current()->PostDelayedTask(
|
|
[this_weak_ptr = weak_ptr_factory_.GetWeakPtr(), this] {
|
|
if (!this_weak_ptr) {
|
|
// The caller BandwidthQualityScaler has been deleted.
|
|
return;
|
|
}
|
|
RTC_DCHECK_RUN_ON(&task_checker_);
|
|
switch (CheckBitrate()) {
|
|
case BandwidthQualityScaler::CheckBitrateResult::kHighBitRate: {
|
|
handler_->OnReportUsageBandwidthHigh();
|
|
last_frame_size_pixels_.reset();
|
|
break;
|
|
}
|
|
case BandwidthQualityScaler::CheckBitrateResult::kLowBitRate: {
|
|
handler_->OnReportUsageBandwidthLow();
|
|
last_frame_size_pixels_.reset();
|
|
break;
|
|
}
|
|
case BandwidthQualityScaler::CheckBitrateResult::kNormalBitrate: {
|
|
break;
|
|
}
|
|
case BandwidthQualityScaler::CheckBitrateResult::
|
|
kInsufficientSamples: {
|
|
break;
|
|
}
|
|
}
|
|
StartCheckForBitrate();
|
|
},
|
|
kBitrateStateUpdateInterval);
|
|
}
|
|
|
|
void BandwidthQualityScaler::ReportEncodeInfo(int frame_size_bytes,
|
|
int64_t time_sent_in_ms,
|
|
uint32_t encoded_width,
|
|
uint32_t encoded_height) {
|
|
RTC_DCHECK_RUN_ON(&task_checker_);
|
|
last_time_sent_in_ms_ = time_sent_in_ms;
|
|
last_frame_size_pixels_ = encoded_width * encoded_height;
|
|
encoded_bitrate_.Update(frame_size_bytes, time_sent_in_ms);
|
|
}
|
|
|
|
void BandwidthQualityScaler::SetResolutionBitrateLimits(
|
|
const std::vector<VideoEncoder::ResolutionBitrateLimits>&
|
|
resolution_bitrate_limits) {
|
|
if (resolution_bitrate_limits.empty()) {
|
|
resolution_bitrate_limits_ = EncoderInfoSettings::
|
|
GetDefaultSinglecastBitrateLimitsWhenQpIsUntrusted();
|
|
} else {
|
|
resolution_bitrate_limits_ = resolution_bitrate_limits;
|
|
}
|
|
}
|
|
|
|
BandwidthQualityScaler::CheckBitrateResult
|
|
BandwidthQualityScaler::CheckBitrate() {
|
|
RTC_DCHECK_RUN_ON(&task_checker_);
|
|
if (!last_frame_size_pixels_.has_value() ||
|
|
!last_time_sent_in_ms_.has_value()) {
|
|
return BandwidthQualityScaler::CheckBitrateResult::kInsufficientSamples;
|
|
}
|
|
|
|
absl::optional<int64_t> current_bitrate_bps =
|
|
encoded_bitrate_.Rate(last_time_sent_in_ms_.value());
|
|
if (!current_bitrate_bps.has_value()) {
|
|
// We can't get a valid bitrate due to not enough data points.
|
|
return BandwidthQualityScaler::CheckBitrateResult::kInsufficientSamples;
|
|
}
|
|
absl::optional<VideoEncoder::ResolutionBitrateLimits> suitable_bitrate_limit =
|
|
EncoderInfoSettings::
|
|
GetSinglecastBitrateLimitForResolutionWhenQpIsUntrusted(
|
|
last_frame_size_pixels_, resolution_bitrate_limits_);
|
|
|
|
if (!suitable_bitrate_limit.has_value()) {
|
|
return BandwidthQualityScaler::CheckBitrateResult::kInsufficientSamples;
|
|
}
|
|
|
|
// Multiply by toleration factor to solve the frequent adaptation due to
|
|
// critical value.
|
|
if (current_bitrate_bps > suitable_bitrate_limit->max_bitrate_bps *
|
|
kHigherMaxBitrateTolerationFactor) {
|
|
return BandwidthQualityScaler::CheckBitrateResult::kLowBitRate;
|
|
} else if (current_bitrate_bps <
|
|
suitable_bitrate_limit->min_start_bitrate_bps *
|
|
kLowerMinBitrateTolerationFactor) {
|
|
return BandwidthQualityScaler::CheckBitrateResult::kHighBitRate;
|
|
}
|
|
return BandwidthQualityScaler::CheckBitrateResult::kNormalBitrate;
|
|
}
|
|
|
|
BandwidthQualityScalerUsageHandlerInterface::
|
|
~BandwidthQualityScalerUsageHandlerInterface() {}
|
|
} // namespace webrtc
|