2021-10-03 10:58:10 +08:00
|
|
|
/*
|
|
|
|
|
* 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 <memory>
|
|
|
|
|
#include <string>
|
|
|
|
|
|
2022-08-19 08:16:48 +00:00
|
|
|
#include "api/units/time_delta.h"
|
2025-02-14 20:14:27 +08:00
|
|
|
#include "api/video/video_codec_type.h"
|
2021-10-03 10:58:10 +08:00
|
|
|
#include "rtc_base/checks.h"
|
|
|
|
|
#include "rtc_base/event.h"
|
|
|
|
|
#include "rtc_base/experiments/encoder_info_settings.h"
|
|
|
|
|
#include "rtc_base/task_queue_for_test.h"
|
|
|
|
|
#include "rtc_base/time_utils.h"
|
|
|
|
|
#include "test/gtest.h"
|
2024-05-03 10:55:23 +02:00
|
|
|
#include "test/time_controller/simulated_time_controller.h"
|
2021-10-03 10:58:10 +08:00
|
|
|
|
|
|
|
|
namespace webrtc {
|
|
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
constexpr int kFramerateFps = 30;
|
2022-08-19 08:16:48 +00:00
|
|
|
constexpr TimeDelta kDefaultEncodeTime = TimeDelta::Seconds(1) / kFramerateFps;
|
2024-05-03 10:55:23 +02:00
|
|
|
constexpr TimeDelta kWaitTime = TimeDelta::Millis(200);
|
2021-10-03 10:58:10 +08:00
|
|
|
|
|
|
|
|
} // namespace
|
|
|
|
|
|
|
|
|
|
class FakeBandwidthQualityScalerHandler
|
|
|
|
|
: public BandwidthQualityScalerUsageHandlerInterface {
|
|
|
|
|
public:
|
|
|
|
|
~FakeBandwidthQualityScalerHandler() override = default;
|
|
|
|
|
void OnReportUsageBandwidthHigh() override {
|
|
|
|
|
adapt_down_event_count_++;
|
|
|
|
|
event_.Set();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void OnReportUsageBandwidthLow() override {
|
|
|
|
|
adapt_up_event_count_++;
|
|
|
|
|
event_.Set();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
rtc::Event event_;
|
|
|
|
|
int adapt_up_event_count_ = 0;
|
|
|
|
|
int adapt_down_event_count_ = 0;
|
|
|
|
|
};
|
|
|
|
|
|
2024-05-03 10:55:23 +02:00
|
|
|
class BandwidthQualityScalerTest : public ::testing::Test {
|
2021-10-03 10:58:10 +08:00
|
|
|
protected:
|
|
|
|
|
enum ScaleDirection {
|
|
|
|
|
kKeepScaleNormalBandwidth,
|
|
|
|
|
kKeepScaleAboveMaxBandwidth,
|
|
|
|
|
kKeepScaleUnderMinBandwidth,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
enum FrameType {
|
|
|
|
|
kKeyFrame,
|
|
|
|
|
kNormalFrame,
|
|
|
|
|
kNormalFrame_Overuse,
|
|
|
|
|
kNormalFrame_Underuse,
|
|
|
|
|
};
|
|
|
|
|
struct FrameConfig {
|
|
|
|
|
FrameConfig(int frame_num,
|
|
|
|
|
FrameType frame_type,
|
|
|
|
|
int actual_width,
|
|
|
|
|
int actual_height)
|
|
|
|
|
: frame_num(frame_num),
|
|
|
|
|
frame_type(frame_type),
|
|
|
|
|
actual_width(actual_width),
|
|
|
|
|
actual_height(actual_height) {}
|
|
|
|
|
|
|
|
|
|
int frame_num;
|
|
|
|
|
FrameType frame_type;
|
|
|
|
|
int actual_width;
|
|
|
|
|
int actual_height;
|
|
|
|
|
};
|
|
|
|
|
|
2025-02-14 20:14:27 +08:00
|
|
|
explicit BandwidthQualityScalerTest(VideoCodecType codec_type)
|
2024-05-03 10:55:23 +02:00
|
|
|
: task_queue_(time_controller_.GetTaskQueueFactory()->CreateTaskQueue(
|
|
|
|
|
"BandwidthQualityScalerTestQueue",
|
|
|
|
|
TaskQueueFactory::Priority::NORMAL)),
|
2025-02-14 20:14:27 +08:00
|
|
|
handler_(std::make_unique<FakeBandwidthQualityScalerHandler>()),
|
|
|
|
|
codec_type_(codec_type) {
|
2021-10-03 10:58:10 +08:00
|
|
|
task_queue_.SendTask([this] {
|
|
|
|
|
bandwidth_quality_scaler_ =
|
2024-05-03 10:55:23 +02:00
|
|
|
std::make_unique<BandwidthQualityScaler>(handler_.get());
|
2021-10-03 10:58:10 +08:00
|
|
|
bandwidth_quality_scaler_->SetResolutionBitrateLimits(
|
|
|
|
|
EncoderInfoSettings::
|
2025-02-14 20:14:27 +08:00
|
|
|
GetDefaultSinglecastBitrateLimitsWhenQpIsUntrusted(codec_type_),
|
|
|
|
|
codec_type_);
|
2021-10-03 10:58:10 +08:00
|
|
|
// Only for testing. Set first_timestamp_ in RateStatistics to 0.
|
|
|
|
|
bandwidth_quality_scaler_->ReportEncodeInfo(0, 0, 0, 0);
|
2022-08-11 12:26:09 +02:00
|
|
|
});
|
2021-10-03 10:58:10 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
~BandwidthQualityScalerTest() {
|
2022-08-11 12:26:09 +02:00
|
|
|
task_queue_.SendTask([this] { bandwidth_quality_scaler_ = nullptr; });
|
2021-10-03 10:58:10 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int GetFrameSizeBytes(
|
|
|
|
|
const FrameConfig& config,
|
|
|
|
|
const VideoEncoder::ResolutionBitrateLimits& bitrate_limits) {
|
|
|
|
|
int scale = 8 * kFramerateFps;
|
|
|
|
|
switch (config.frame_type) {
|
|
|
|
|
case FrameType::kKeyFrame: {
|
|
|
|
|
// 4 is experimental value. Based on the test, the number of bytes of
|
|
|
|
|
// the key frame is about four times of the normal frame
|
|
|
|
|
return bitrate_limits.max_bitrate_bps * 4 / scale;
|
|
|
|
|
}
|
|
|
|
|
case FrameType::kNormalFrame_Overuse: {
|
|
|
|
|
return bitrate_limits.max_bitrate_bps * 3 / 2 / scale;
|
|
|
|
|
}
|
|
|
|
|
case FrameType::kNormalFrame_Underuse: {
|
|
|
|
|
return bitrate_limits.min_start_bitrate_bps * 3 / 4 / scale;
|
|
|
|
|
}
|
|
|
|
|
case FrameType::kNormalFrame: {
|
|
|
|
|
return (bitrate_limits.max_bitrate_bps +
|
|
|
|
|
bitrate_limits.min_start_bitrate_bps) /
|
|
|
|
|
2 / scale;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
2024-08-29 13:00:40 +00:00
|
|
|
std::optional<VideoEncoder::ResolutionBitrateLimits>
|
2021-10-03 10:58:10 +08:00
|
|
|
GetDefaultSuitableBitrateLimit(int frame_size_pixels) {
|
|
|
|
|
return EncoderInfoSettings::
|
|
|
|
|
GetSinglecastBitrateLimitForResolutionWhenQpIsUntrusted(
|
|
|
|
|
frame_size_pixels,
|
|
|
|
|
EncoderInfoSettings::
|
2025-02-14 20:14:27 +08:00
|
|
|
GetDefaultSinglecastBitrateLimitsWhenQpIsUntrusted(
|
|
|
|
|
codec_type_));
|
2021-10-03 10:58:10 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void TriggerBandwidthQualityScalerTest(
|
|
|
|
|
const std::vector<FrameConfig>& frame_configs) {
|
2024-05-03 10:55:23 +02:00
|
|
|
RTC_CHECK(!frame_configs.empty());
|
2023-04-19 16:24:03 -07:00
|
|
|
|
2024-05-03 10:55:23 +02:00
|
|
|
int total_frame_nums = 0;
|
|
|
|
|
for (const FrameConfig& frame_config : frame_configs) {
|
|
|
|
|
total_frame_nums += frame_config.frame_num;
|
|
|
|
|
}
|
2023-04-19 16:24:03 -07:00
|
|
|
|
2024-05-03 10:55:23 +02:00
|
|
|
EXPECT_EQ(kFramerateFps *
|
|
|
|
|
BandwidthQualityScaler::kBitrateStateUpdateInterval.seconds(),
|
|
|
|
|
total_frame_nums);
|
|
|
|
|
|
|
|
|
|
TimeDelta delay = TimeDelta::Zero();
|
|
|
|
|
int num_delayed_tasks = 0;
|
|
|
|
|
for (const FrameConfig& config : frame_configs) {
|
2024-08-29 13:00:40 +00:00
|
|
|
std::optional<VideoEncoder::ResolutionBitrateLimits> suitable_bitrate =
|
2024-05-03 10:55:23 +02:00
|
|
|
GetDefaultSuitableBitrateLimit(config.actual_width *
|
|
|
|
|
config.actual_height);
|
|
|
|
|
EXPECT_TRUE(suitable_bitrate);
|
|
|
|
|
for (int j = 0; j <= config.frame_num; ++j) {
|
|
|
|
|
delay += kDefaultEncodeTime;
|
|
|
|
|
int frame_size_bytes = GetFrameSizeBytes(config, *suitable_bitrate);
|
|
|
|
|
RTC_CHECK_GT(frame_size_bytes, 0);
|
|
|
|
|
++num_delayed_tasks;
|
|
|
|
|
task_queue_.PostDelayedTask(
|
|
|
|
|
[frame_size_bytes, config, &num_delayed_tasks, this] {
|
|
|
|
|
bandwidth_quality_scaler_->ReportEncodeInfo(
|
|
|
|
|
frame_size_bytes,
|
|
|
|
|
time_controller_.GetClock()->CurrentTime().ms(),
|
|
|
|
|
config.actual_width, config.actual_height);
|
|
|
|
|
--num_delayed_tasks;
|
|
|
|
|
},
|
|
|
|
|
delay);
|
2021-10-03 10:58:10 +08:00
|
|
|
}
|
2024-05-03 10:55:23 +02:00
|
|
|
}
|
|
|
|
|
time_controller_.AdvanceTime(delay);
|
|
|
|
|
ASSERT_TRUE(time_controller_.Wait([&] { return num_delayed_tasks == 0; }));
|
2021-10-03 10:58:10 +08:00
|
|
|
}
|
|
|
|
|
|
2024-05-03 10:55:23 +02:00
|
|
|
GlobalSimulatedTimeController time_controller_{Timestamp::Seconds(1234)};
|
2021-10-03 10:58:10 +08:00
|
|
|
TaskQueueForTest task_queue_;
|
2024-05-03 10:55:23 +02:00
|
|
|
std::unique_ptr<BandwidthQualityScaler> bandwidth_quality_scaler_;
|
2021-10-03 10:58:10 +08:00
|
|
|
std::unique_ptr<FakeBandwidthQualityScalerHandler> handler_;
|
2025-02-14 20:14:27 +08:00
|
|
|
VideoCodecType codec_type_;
|
2021-10-03 10:58:10 +08:00
|
|
|
};
|
|
|
|
|
|
2025-02-14 20:14:27 +08:00
|
|
|
class BandwidthQualityScalerTests
|
|
|
|
|
: public BandwidthQualityScalerTest,
|
|
|
|
|
public ::testing::WithParamInterface<VideoCodecType> {
|
|
|
|
|
protected:
|
|
|
|
|
BandwidthQualityScalerTests() : BandwidthQualityScalerTest(GetParam()) {}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
TEST_P(BandwidthQualityScalerTests, AllNormalFrame_640x360) {
|
2021-10-03 10:58:10 +08:00
|
|
|
const std::vector<FrameConfig> frame_configs{
|
|
|
|
|
FrameConfig(150, FrameType::kNormalFrame, 640, 360)};
|
|
|
|
|
TriggerBandwidthQualityScalerTest(frame_configs);
|
|
|
|
|
|
|
|
|
|
// When resolution is 640*360, experimental working bitrate range is
|
|
|
|
|
// [500000,800000] bps. Encoded bitrate is 654253, so it falls in the range
|
|
|
|
|
// without any operation(up/down).
|
2024-05-03 10:55:23 +02:00
|
|
|
EXPECT_FALSE(handler_->event_.Wait(kWaitTime));
|
2021-10-03 10:58:10 +08:00
|
|
|
EXPECT_EQ(0, handler_->adapt_down_event_count_);
|
|
|
|
|
EXPECT_EQ(0, handler_->adapt_up_event_count_);
|
|
|
|
|
}
|
|
|
|
|
|
2025-02-14 20:14:27 +08:00
|
|
|
TEST_P(BandwidthQualityScalerTests, AllNormalFrame_AboveMaxBandwidth_640x360) {
|
2021-10-03 10:58:10 +08:00
|
|
|
const std::vector<FrameConfig> frame_configs{
|
|
|
|
|
FrameConfig(150, FrameType::kNormalFrame_Overuse, 640, 360)};
|
|
|
|
|
TriggerBandwidthQualityScalerTest(frame_configs);
|
|
|
|
|
|
|
|
|
|
// When resolution is 640*360, experimental working bitrate range is
|
|
|
|
|
// [500000,800000] bps. Encoded bitrate is 1208000 > 800000 * 0.95, so it
|
|
|
|
|
// triggers adapt_up_event_count_.
|
2024-05-03 10:55:23 +02:00
|
|
|
EXPECT_TRUE(handler_->event_.Wait(kWaitTime));
|
2021-10-03 10:58:10 +08:00
|
|
|
EXPECT_EQ(0, handler_->adapt_down_event_count_);
|
|
|
|
|
EXPECT_EQ(1, handler_->adapt_up_event_count_);
|
|
|
|
|
}
|
|
|
|
|
|
2025-02-14 20:14:27 +08:00
|
|
|
TEST_P(BandwidthQualityScalerTests, AllNormalFrame_Underuse_640x360) {
|
2021-10-03 10:58:10 +08:00
|
|
|
const std::vector<FrameConfig> frame_configs{
|
|
|
|
|
FrameConfig(150, FrameType::kNormalFrame_Underuse, 640, 360)};
|
|
|
|
|
TriggerBandwidthQualityScalerTest(frame_configs);
|
|
|
|
|
|
|
|
|
|
// When resolution is 640*360, experimental working bitrate range is
|
|
|
|
|
// [500000,800000] bps. Encoded bitrate is 377379 < 500000 * 0.8, so it
|
|
|
|
|
// triggers adapt_down_event_count_.
|
2024-05-03 10:55:23 +02:00
|
|
|
EXPECT_TRUE(handler_->event_.Wait(kWaitTime));
|
2021-10-03 10:58:10 +08:00
|
|
|
EXPECT_EQ(1, handler_->adapt_down_event_count_);
|
|
|
|
|
EXPECT_EQ(0, handler_->adapt_up_event_count_);
|
|
|
|
|
}
|
|
|
|
|
|
2025-02-14 20:14:27 +08:00
|
|
|
TEST_P(BandwidthQualityScalerTests, FixedFrameTypeTest1_640x360) {
|
2021-10-03 10:58:10 +08:00
|
|
|
const std::vector<FrameConfig> frame_configs{
|
|
|
|
|
FrameConfig(5, FrameType::kNormalFrame_Underuse, 640, 360),
|
|
|
|
|
FrameConfig(110, FrameType::kNormalFrame, 640, 360),
|
|
|
|
|
FrameConfig(20, FrameType::kNormalFrame_Overuse, 640, 360),
|
|
|
|
|
FrameConfig(15, FrameType::kKeyFrame, 640, 360),
|
|
|
|
|
};
|
|
|
|
|
TriggerBandwidthQualityScalerTest(frame_configs);
|
|
|
|
|
|
|
|
|
|
// When resolution is 640*360, experimental working bitrate range is
|
|
|
|
|
// [500000,800000] bps. Encoded bitrate is 1059462 > 800000 * 0.95, so it
|
|
|
|
|
// triggers adapt_up_event_count_.
|
2024-05-03 10:55:23 +02:00
|
|
|
EXPECT_TRUE(handler_->event_.Wait(kWaitTime));
|
2021-10-03 10:58:10 +08:00
|
|
|
EXPECT_EQ(0, handler_->adapt_down_event_count_);
|
|
|
|
|
EXPECT_EQ(1, handler_->adapt_up_event_count_);
|
|
|
|
|
}
|
|
|
|
|
|
2025-02-14 20:14:27 +08:00
|
|
|
TEST_P(BandwidthQualityScalerTests, FixedFrameTypeTest2_640x360) {
|
2021-10-03 10:58:10 +08:00
|
|
|
const std::vector<FrameConfig> frame_configs{
|
|
|
|
|
FrameConfig(10, FrameType::kNormalFrame_Underuse, 640, 360),
|
|
|
|
|
FrameConfig(50, FrameType::kNormalFrame, 640, 360),
|
|
|
|
|
FrameConfig(5, FrameType::kKeyFrame, 640, 360),
|
|
|
|
|
FrameConfig(85, FrameType::kNormalFrame_Overuse, 640, 360),
|
|
|
|
|
};
|
|
|
|
|
TriggerBandwidthQualityScalerTest(frame_configs);
|
|
|
|
|
|
|
|
|
|
// When resolution is 640*360, experimental working bitrate range is
|
|
|
|
|
// [500000,800000] bps. Encoded bitrate is 1059462 > 800000 * 0.95, so it
|
|
|
|
|
// triggers adapt_up_event_count_.
|
2024-05-03 10:55:23 +02:00
|
|
|
EXPECT_TRUE(handler_->event_.Wait(kWaitTime));
|
2021-10-03 10:58:10 +08:00
|
|
|
EXPECT_EQ(0, handler_->adapt_down_event_count_);
|
|
|
|
|
EXPECT_EQ(1, handler_->adapt_up_event_count_);
|
|
|
|
|
}
|
|
|
|
|
|
2025-02-14 20:14:27 +08:00
|
|
|
INSTANTIATE_TEST_SUITE_P(AllCodecs,
|
|
|
|
|
BandwidthQualityScalerTests,
|
|
|
|
|
::testing::Values(kVideoCodecH264, kVideoCodecH265));
|
|
|
|
|
|
2021-10-03 10:58:10 +08:00
|
|
|
} // namespace webrtc
|