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

Bug: b/235812579 Change-Id: I9fa3dc4a65044df8b44fff4e9bfeac7233fa381c Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/266080 Reviewed-by: Harald Alvestrand <hta@webrtc.org> Commit-Queue: Artem Titov <titovartem@webrtc.org> Cr-Commit-Position: refs/heads/main@{#37248}
150 lines
5.5 KiB
C++
150 lines
5.5 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/task_queue/to_queued_task.h"
|
|
#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/task_queue.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(
|
|
ToQueuedTask([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.ms());
|
|
}
|
|
|
|
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
|