| /* | |
| * Copyright (c) 2018 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 <algorithm> | |
| #include <cstddef> | |
| #include <cstdint> | |
| #include <limits> | |
| #include <memory> | |
| #include <optional> | |
| #include <span> | |
| #include <string> | |
| #include <vector> | |
| #include "api/environment/environment.h" | |
| #include "api/make_ref_counted.h" | |
| #include "api/rtp_parameters.h" | |
| #include "api/test/video/function_video_encoder_factory.h" | |
| #include "api/transport/bitrate_settings.h" | |
| #include "api/units/time_delta.h" | |
| #include "api/video/video_codec_type.h" | |
| #include "api/video/video_frame.h" | |
| #include "api/video/video_sink_interface.h" | |
| #include "api/video/video_source_interface.h" | |
| #include "api/video_codecs/scalability_mode.h" | |
| #include "api/video_codecs/sdp_video_format.h" | |
| #include "api/video_codecs/video_codec.h" | |
| #include "api/video_codecs/video_encoder.h" | |
| #include "call/video_receive_stream.h" | |
| #include "call/video_send_stream.h" | |
| #include "modules/video_coding/codecs/h264/include/h264.h" | |
| #include "modules/video_coding/codecs/vp8/include/vp8.h" | |
| #include "modules/video_coding/codecs/vp9/include/vp9.h" | |
| #include "rtc_base/checks.h" | |
| #include "rtc_base/experiments/encoder_info_settings.h" | |
| #include "rtc_base/strings/string_builder.h" | |
| #include "test/call_test.h" | |
| #include "test/frame_generator_capturer.h" | |
| #include "test/gtest.h" | |
| #include "test/rtp_rtcp_observer.h" | |
| #include "test/video_test_constants.h" | |
| #include "video/config/video_encoder_config.h" | |
| namespace webrtc { | |
| namespace { | |
| constexpr int kInitialWidth = 1280; | |
| constexpr int kInitialHeight = 720; | |
| constexpr int kLowStartBps = 100000; | |
| constexpr int kHighStartBps = 1000000; | |
| constexpr int kDefaultVgaMinStartBps = 500000; // From video_stream_encoder.cc | |
| constexpr TimeDelta kTimeout = | |
| TimeDelta::Seconds(10); // Some tests are expected to time out. | |
| void SetEncoderSpecific(VideoEncoderConfig* encoder_config, | |
| VideoCodecType type, | |
| bool automatic_resize, | |
| size_t num_spatial_layers) { | |
| if (type == kVideoCodecVP8) { | |
| VideoCodecVP8 vp8 = VideoEncoder::GetDefaultVp8Settings(); | |
| vp8.automaticResizeOn = automatic_resize; | |
| encoder_config->encoder_specific_settings = | |
| make_ref_counted<VideoEncoderConfig::Vp8EncoderSpecificSettings>(vp8); | |
| } else if (type == kVideoCodecVP9) { | |
| VideoCodecVP9 vp9 = VideoEncoder::GetDefaultVp9Settings(); | |
| vp9.automaticResizeOn = automatic_resize; | |
| vp9.numberOfSpatialLayers = num_spatial_layers; | |
| encoder_config->encoder_specific_settings = | |
| make_ref_counted<VideoEncoderConfig::Vp9EncoderSpecificSettings>(vp9); | |
| } | |
| } | |
| } // namespace | |
| class QualityScalingTest : public test::CallTest { | |
| protected: | |
| struct QualityScalingParams { | |
| int vp8_low = 0; | |
| int vp8_high = 0; | |
| int vp9_low = 0; | |
| int vp9_high = 0; | |
| int h264_low = 0; | |
| int h264_high = 0; | |
| }; | |
| void SetQualityScalingTrialQP(QualityScalingParams p) { | |
| StringBuilder sb; | |
| sb << "Enabled-" << p.vp8_low << "," << p.vp8_high // | |
| << "," << p.vp9_low << "," << p.vp9_high // | |
| << "," << p.h264_low << "," << p.h264_high // | |
| << ",0,0,0.9995,0.9999,1"; | |
| field_trials().Set("WebRTC-Video-QualityScaling", sb.str()); | |
| } | |
| const std::optional<VideoEncoder::ResolutionBitrateLimits> | |
| kSinglecastLimits720pVp8 = | |
| EncoderInfoSettings::GetDefaultSinglecastBitrateLimitsForResolution( | |
| kVideoCodecVP8, | |
| 1280 * 720); | |
| const std::optional<VideoEncoder::ResolutionBitrateLimits> | |
| kSinglecastLimits360pVp9 = | |
| EncoderInfoSettings::GetDefaultSinglecastBitrateLimitsForResolution( | |
| kVideoCodecVP9, | |
| 640 * 360); | |
| const std::optional<VideoEncoder::ResolutionBitrateLimits> | |
| kSinglecastLimits720pVp9 = | |
| EncoderInfoSettings::GetDefaultSinglecastBitrateLimitsForResolution( | |
| kVideoCodecVP9, | |
| 1280 * 720); | |
| }; | |
| class ScalingObserver : public test::SendTest { | |
| protected: | |
| struct TestParams { | |
| bool active; | |
| std::optional<ScalabilityMode> scalability_mode; | |
| }; | |
| ScalingObserver(const std::string& payload_name, | |
| const std::vector<TestParams>& test_params, | |
| int start_bps, | |
| bool automatic_resize, | |
| bool expect_scaling) | |
| : SendTest(expect_scaling ? kTimeout * 4 : kTimeout), | |
| encoder_factory_( | |
| [](const Environment& env, | |
| const SdpVideoFormat& format) -> std::unique_ptr<VideoEncoder> { | |
| if (format.name == "VP8") | |
| return CreateVp8Encoder(env); | |
| if (format.name == "VP9") | |
| return CreateVp9Encoder(env); | |
| if (format.name == "H264") | |
| return CreateH264Encoder(env); | |
| RTC_DCHECK_NOTREACHED() << format.name; | |
| return nullptr; | |
| }), | |
| payload_name_(payload_name), | |
| test_params_(test_params), | |
| start_bps_(start_bps), | |
| automatic_resize_(automatic_resize), | |
| expect_scaling_(expect_scaling) {} | |
| DegradationPreference degradation_preference_ = | |
| DegradationPreference::MAINTAIN_FRAMERATE; | |
| private: | |
| void ModifySenderBitrateConfig(BitrateConstraints* bitrate_config) override { | |
| bitrate_config->start_bitrate_bps = start_bps_; | |
| } | |
| void ModifyVideoDegradationPreference( | |
| DegradationPreference* degradation_preference) override { | |
| *degradation_preference = degradation_preference_; | |
| } | |
| size_t GetNumVideoStreams() const override { | |
| return (payload_name_ == "VP9") ? 1 : test_params_.size(); | |
| } | |
| void ModifyVideoConfigs( | |
| VideoSendStream::Config* send_config, | |
| std::vector<VideoReceiveStreamInterface::Config>* receive_configs, | |
| VideoEncoderConfig* encoder_config) override { | |
| send_config->encoder_settings.encoder_factory = &encoder_factory_; | |
| send_config->rtp.payload_name = payload_name_; | |
| send_config->rtp.payload_type = | |
| test::VideoTestConstants::kVideoSendPayloadType; | |
| encoder_config->video_format.name = payload_name_; | |
| const VideoCodecType codec_type = PayloadStringToCodecType(payload_name_); | |
| encoder_config->codec_type = codec_type; | |
| encoder_config->max_bitrate_bps = | |
| std::max(start_bps_, encoder_config->max_bitrate_bps); | |
| if (payload_name_ == "VP9") { | |
| // Simulcast layers indicates which spatial layers are active. | |
| encoder_config->simulcast_layers.resize(test_params_.size()); | |
| encoder_config->simulcast_layers[0].max_bitrate_bps = | |
| encoder_config->max_bitrate_bps; | |
| } | |
| double scale_factor = 1.0; | |
| for (int i = test_params_.size() - 1; i >= 0; --i) { | |
| VideoStream& stream = encoder_config->simulcast_layers[i]; | |
| stream.active = test_params_[i].active; | |
| stream.scalability_mode = test_params_[i].scalability_mode; | |
| stream.scale_resolution_down_by = scale_factor; | |
| scale_factor *= (payload_name_ == "VP9") ? 1.0 : 2.0; | |
| } | |
| encoder_config->frame_drop_enabled = true; | |
| SetEncoderSpecific(encoder_config, codec_type, automatic_resize_, | |
| test_params_.size()); | |
| } | |
| Action OnSendRtp(std::span<const uint8_t> packet) override { | |
| // The tests are expected to send at the configured start bitrate. Do not | |
| // send any packets to avoid receiving REMB and possibly go down in target | |
| // bitrate. A low bitrate estimate could result in downgrading due to other | |
| // reasons than low/high QP-value (e.g. high frame drop percent) or not | |
| // upgrading due to bitrate constraint. | |
| return DROP_PACKET; | |
| } | |
| void PerformTest() override { EXPECT_EQ(expect_scaling_, Wait()); } | |
| test::FunctionVideoEncoderFactory encoder_factory_; | |
| const std::string payload_name_; | |
| const std::vector<TestParams> test_params_; | |
| const int start_bps_; | |
| const bool automatic_resize_; | |
| const bool expect_scaling_; | |
| }; | |
| class DownscalingObserver | |
| : public ScalingObserver, | |
| public test::FrameGeneratorCapturer::SinkWantsObserver { | |
| public: | |
| DownscalingObserver(const std::string& payload_name, | |
| const std::vector<TestParams>& test_params, | |
| int start_bps, | |
| bool automatic_resize, | |
| bool expect_downscale) | |
| : ScalingObserver(payload_name, | |
| test_params, | |
| start_bps, | |
| automatic_resize, | |
| expect_downscale) {} | |
| private: | |
| void OnFrameGeneratorCapturerCreated( | |
| test::FrameGeneratorCapturer* frame_generator_capturer) override { | |
| frame_generator_capturer->SetSinkWantsObserver(this); | |
| frame_generator_capturer->ChangeResolution(kInitialWidth, kInitialHeight); | |
| } | |
| void OnSinkWantsChanged(VideoSinkInterface<VideoFrame>* sink, | |
| const VideoSinkWants& wants) override { | |
| if (wants.max_pixel_count < kInitialWidth * kInitialHeight) | |
| observation_complete_.Set(); | |
| } | |
| }; | |
| class UpscalingObserver | |
| : public ScalingObserver, | |
| public test::FrameGeneratorCapturer::SinkWantsObserver { | |
| public: | |
| UpscalingObserver(const std::string& payload_name, | |
| const std::vector<TestParams>& test_params, | |
| int start_bps, | |
| bool automatic_resize, | |
| bool expect_upscale) | |
| : ScalingObserver(payload_name, | |
| test_params, | |
| start_bps, | |
| automatic_resize, | |
| expect_upscale) {} | |
| void SetDegradationPreference(DegradationPreference preference) { | |
| degradation_preference_ = preference; | |
| } | |
| private: | |
| void OnFrameGeneratorCapturerCreated( | |
| test::FrameGeneratorCapturer* frame_generator_capturer) override { | |
| frame_generator_capturer->SetSinkWantsObserver(this); | |
| frame_generator_capturer->ChangeResolution(kInitialWidth, kInitialHeight); | |
| } | |
| void OnSinkWantsChanged(VideoSinkInterface<VideoFrame>* sink, | |
| const VideoSinkWants& wants) override { | |
| if (wants.max_pixel_count > last_wants_.max_pixel_count) { | |
| if (wants.max_pixel_count == std::numeric_limits<int>::max()) | |
| observation_complete_.Set(); | |
| } | |
| last_wants_ = wants; | |
| } | |
| VideoSinkWants last_wants_; | |
| }; | |
| TEST_F(QualityScalingTest, AdaptsDownForHighQp_Vp8) { | |
| // qp_low:1, qp_high:1 -> kHighQp | |
| SetQualityScalingTrialQP({.vp8_low = 1, .vp8_high = 1}); | |
| DownscalingObserver test("VP8", {{.active = true}}, kHighStartBps, | |
| /*automatic_resize=*/true, | |
| /*expect_downscale=*/true); | |
| RunBaseTest(&test); | |
| } | |
| TEST_F(QualityScalingTest, NoAdaptDownForHighQpIfScalingOff_Vp8) { | |
| // qp_low:1, qp_high:1 -> kHighQp | |
| SetQualityScalingTrialQP({.vp8_low = 1, .vp8_high = 1}); | |
| DownscalingObserver test("VP8", {{.active = true}}, kHighStartBps, | |
| /*automatic_resize=*/false, | |
| /*expect_downscale=*/false); | |
| RunBaseTest(&test); | |
| } | |
| TEST_F(QualityScalingTest, NoAdaptDownForNormalQp_Vp8) { | |
| // qp_low:1, qp_high:127 -> kNormalQp | |
| SetQualityScalingTrialQP({.vp8_low = 1, .vp8_high = 127}); | |
| DownscalingObserver test("VP8", {{.active = true}}, kHighStartBps, | |
| /*automatic_resize=*/true, | |
| /*expect_downscale=*/false); | |
| RunBaseTest(&test); | |
| } | |
| TEST_F(QualityScalingTest, AdaptsDownForLowStartBitrate_Vp8) { | |
| // qp_low:1, qp_high:127 -> kNormalQp | |
| SetQualityScalingTrialQP({.vp8_low = 1, .vp8_high = 127}); | |
| DownscalingObserver test("VP8", {{.active = true}}, kLowStartBps, | |
| /*automatic_resize=*/true, | |
| /*expect_downscale=*/true); | |
| RunBaseTest(&test); | |
| } | |
| TEST_F(QualityScalingTest, AdaptsDownForLowStartBitrateAndThenUp) { | |
| // qp_low:127, qp_high:127 -> kLowQp | |
| SetQualityScalingTrialQP({.vp8_low = 127, .vp8_high = 127}); | |
| field_trials().Set( | |
| "WebRTC-Video-BalancedDegradationSettings", | |
| "pixels:230400|921600,fps:20|30,kbps:300|500"); // should not affect | |
| UpscalingObserver test("VP8", {{.active = true}}, kDefaultVgaMinStartBps - 1, | |
| /*automatic_resize=*/true, /*expect_upscale=*/true); | |
| RunBaseTest(&test); | |
| } | |
| TEST_F(QualityScalingTest, AdaptsDownAndThenUpWithBalanced) { | |
| // qp_low:127, qp_high:127 -> kLowQp | |
| SetQualityScalingTrialQP({.vp8_low = 127, .vp8_high = 127}); | |
| field_trials().Set("WebRTC-Video-BalancedDegradationSettings", | |
| "pixels:230400|921600,fps:20|30,kbps:300|499"); | |
| UpscalingObserver test("VP8", {{.active = true}}, kDefaultVgaMinStartBps - 1, | |
| /*automatic_resize=*/true, /*expect_upscale=*/true); | |
| test.SetDegradationPreference(DegradationPreference::BALANCED); | |
| RunBaseTest(&test); | |
| } | |
| TEST_F(QualityScalingTest, AdaptsDownButNotUpWithBalancedIfBitrateNotEnough) { | |
| // qp_low:127, qp_high:127 -> kLowQp | |
| SetQualityScalingTrialQP({.vp8_low = 127, .vp8_high = 127}); | |
| field_trials().Set("WebRTC-Video-BalancedDegradationSettings", | |
| "pixels:230400|921600,fps:20|30,kbps:300|500"); | |
| UpscalingObserver test("VP8", {{.active = true}}, kDefaultVgaMinStartBps - 1, | |
| /*automatic_resize=*/true, /*expect_upscale=*/false); | |
| test.SetDegradationPreference(DegradationPreference::BALANCED); | |
| RunBaseTest(&test); | |
| } | |
| TEST_F(QualityScalingTest, NoAdaptDownForLowStartBitrate_Simulcast) { | |
| // qp_low:1, qp_high:127 -> kNormalQp | |
| SetQualityScalingTrialQP({.vp8_low = 1, .vp8_high = 127}); | |
| DownscalingObserver test("VP8", {{.active = true}, {.active = true}}, | |
| kLowStartBps, | |
| /*automatic_resize=*/false, | |
| /*expect_downscale=*/false); | |
| RunBaseTest(&test); | |
| } | |
| TEST_F(QualityScalingTest, AdaptsDownForHighQp_HighestStreamActive_Vp8) { | |
| // qp_low:1, qp_high:1 -> kHighQp | |
| SetQualityScalingTrialQP({.vp8_low = 1, .vp8_high = 1}); | |
| DownscalingObserver test( | |
| "VP8", {{.active = false}, {.active = false}, {.active = true}}, | |
| kHighStartBps, | |
| /*automatic_resize=*/true, | |
| /*expect_downscale=*/true); | |
| RunBaseTest(&test); | |
| } | |
| TEST_F(QualityScalingTest, | |
| AdaptsDownForLowStartBitrate_HighestStreamActive_Vp8) { | |
| // qp_low:1, qp_high:127 -> kNormalQp | |
| SetQualityScalingTrialQP({.vp8_low = 1, .vp8_high = 127}); | |
| DownscalingObserver test( | |
| "VP8", {{.active = false}, {.active = false}, {.active = true}}, | |
| kSinglecastLimits720pVp8->min_start_bitrate_bps - 1, | |
| /*automatic_resize=*/true, | |
| /*expect_downscale=*/true); | |
| RunBaseTest(&test); | |
| } | |
| TEST_F(QualityScalingTest, AdaptsDownButNotUpWithMinStartBitrateLimit) { | |
| // qp_low:127, qp_high:127 -> kLowQp | |
| SetQualityScalingTrialQP({.vp8_low = 127, .vp8_high = 127}); | |
| UpscalingObserver test("VP8", {{.active = false}, {.active = true}}, | |
| kSinglecastLimits720pVp8->min_start_bitrate_bps - 1, | |
| /*automatic_resize=*/true, /*expect_upscale=*/false); | |
| RunBaseTest(&test); | |
| } | |
| TEST_F(QualityScalingTest, NoAdaptDownForLowStartBitrateIfBitrateEnough_Vp8) { | |
| // qp_low:1, qp_high:127 -> kNormalQp | |
| SetQualityScalingTrialQP({.vp8_low = 1, .vp8_high = 127}); | |
| DownscalingObserver test( | |
| "VP8", {{.active = false}, {.active = false}, {.active = true}}, | |
| kSinglecastLimits720pVp8->min_start_bitrate_bps, | |
| /*automatic_resize=*/true, | |
| /*expect_downscale=*/false); | |
| RunBaseTest(&test); | |
| } | |
| TEST_F(QualityScalingTest, | |
| NoAdaptDownForLowStartBitrateIfDefaultLimitsDisabled_Vp8) { | |
| // qp_low:1, qp_high:127 -> kNormalQp | |
| SetQualityScalingTrialQP({.vp8_low = 1, .vp8_high = 127}); | |
| field_trials().Set("WebRTC-DefaultBitrateLimitsKillSwitch", "Enabled"); | |
| DownscalingObserver test( | |
| "VP8", {{.active = false}, {.active = false}, {.active = true}}, | |
| kSinglecastLimits720pVp8->min_start_bitrate_bps - 1, | |
| /*automatic_resize=*/true, | |
| /*expect_downscale=*/false); | |
| RunBaseTest(&test); | |
| } | |
| TEST_F(QualityScalingTest, | |
| NoAdaptDownForLowStartBitrate_OneStreamSinglecastLimitsNotUsed_Vp8) { | |
| // qp_low:1, qp_high:127 -> kNormalQp | |
| SetQualityScalingTrialQP({.vp8_low = 1, .vp8_high = 127}); | |
| DownscalingObserver test("VP8", {{.active = true}}, | |
| kSinglecastLimits720pVp8->min_start_bitrate_bps - 1, | |
| /*automatic_resize=*/true, | |
| /*expect_downscale=*/false); | |
| RunBaseTest(&test); | |
| } | |
| TEST_F(QualityScalingTest, NoAdaptDownForHighQp_LowestStreamActive_Vp8) { | |
| // qp_low:1, qp_high:1 -> kHighQp | |
| SetQualityScalingTrialQP({.vp8_low = 1, .vp8_high = 1}); | |
| DownscalingObserver test( | |
| "VP8", {{.active = true}, {.active = false}, {.active = false}}, | |
| kHighStartBps, | |
| /*automatic_resize=*/true, | |
| /*expect_downscale=*/false); | |
| RunBaseTest(&test); | |
| } | |
| TEST_F(QualityScalingTest, | |
| NoAdaptDownForLowStartBitrate_LowestStreamActive_Vp8) { | |
| // qp_low:1, qp_high:127 -> kNormalQp | |
| SetQualityScalingTrialQP({.vp8_low = 1, .vp8_high = 127}); | |
| DownscalingObserver test( | |
| "VP8", {{.active = true}, {.active = false}, {.active = false}}, | |
| kLowStartBps, | |
| /*automatic_resize=*/true, | |
| /*expect_downscale=*/false); | |
| RunBaseTest(&test); | |
| } | |
| TEST_F(QualityScalingTest, NoAdaptDownForLowStartBitrateIfScalingOff_Vp8) { | |
| // qp_low:1, qp_high:127 -> kNormalQp | |
| SetQualityScalingTrialQP({.vp8_low = 1, .vp8_high = 127}); | |
| DownscalingObserver test("VP8", {{.active = true}}, kLowStartBps, | |
| /*automatic_resize=*/false, | |
| /*expect_downscale=*/false); | |
| RunBaseTest(&test); | |
| } | |
| TEST_F(QualityScalingTest, AdaptsDownForHighQp_Vp9) { | |
| // qp_low:1, qp_high:1 -> kHighQp | |
| SetQualityScalingTrialQP({.vp9_low = 1, .vp9_high = 1}); | |
| DownscalingObserver test("VP9", {{.active = true}}, kHighStartBps, | |
| /*automatic_resize=*/true, | |
| /*expect_downscale=*/true); | |
| RunBaseTest(&test); | |
| } | |
| TEST_F(QualityScalingTest, NoAdaptDownForHighQpIfScalingOff_Vp9) { | |
| // qp_low:1, qp_high:1 -> kHighQp | |
| SetQualityScalingTrialQP({.vp9_low = 1, .vp9_high = 1}); | |
| field_trials().Set("WebRTC-VP9QualityScaler", "Disabled"); | |
| DownscalingObserver test("VP9", {{.active = true}}, kHighStartBps, | |
| /*automatic_resize=*/true, | |
| /*expect_downscale=*/false); | |
| RunBaseTest(&test); | |
| } | |
| TEST_F(QualityScalingTest, AdaptsDownForLowStartBitrate_Vp9) { | |
| // qp_low:1, qp_high:255 -> kNormalQp | |
| SetQualityScalingTrialQP({.vp9_low = 1, .vp9_high = 255}); | |
| DownscalingObserver test("VP9", {{.active = true}}, kLowStartBps, | |
| /*automatic_resize=*/true, | |
| /*expect_downscale=*/true); | |
| RunBaseTest(&test); | |
| } | |
| TEST_F(QualityScalingTest, NoAdaptDownForHighStartBitrate_Vp9) { | |
| DownscalingObserver test( | |
| "VP9", {{.active = false}, {.active = false}, {.active = true}}, | |
| kHighStartBps, | |
| /*automatic_resize=*/true, | |
| /*expect_downscale=*/false); | |
| RunBaseTest(&test); | |
| } | |
| TEST_F(QualityScalingTest, NoAdaptDownForHighQp_LowestStreamActive_Vp9) { | |
| // qp_low:1, qp_high:1 -> kHighQp | |
| SetQualityScalingTrialQP({.vp9_low = 1, .vp9_high = 1}); | |
| DownscalingObserver test( | |
| "VP9", {{.active = true}, {.active = false}, {.active = false}}, | |
| kHighStartBps, | |
| /*automatic_resize=*/true, | |
| /*expect_downscale=*/false); | |
| RunBaseTest(&test); | |
| } | |
| TEST_F(QualityScalingTest, | |
| NoAdaptDownForLowStartBitrate_LowestStreamActive_Vp9) { | |
| // qp_low:1, qp_high:255 -> kNormalQp | |
| SetQualityScalingTrialQP({.vp9_low = 1, .vp9_high = 255}); | |
| DownscalingObserver test( | |
| "VP9", {{.active = true}, {.active = false}, {.active = false}}, | |
| kLowStartBps, | |
| /*automatic_resize=*/true, | |
| /*expect_downscale=*/false); | |
| RunBaseTest(&test); | |
| } | |
| TEST_F(QualityScalingTest, AdaptsDownForHighQp_MiddleStreamActive_Vp9) { | |
| // qp_low:1, qp_high:1 -> kHighQp | |
| SetQualityScalingTrialQP({.vp9_low = 1, .vp9_high = 1}); | |
| DownscalingObserver test( | |
| "VP9", {{.active = false}, {.active = true}, {.active = false}}, | |
| kHighStartBps, | |
| /*automatic_resize=*/true, | |
| /*expect_downscale=*/true); | |
| RunBaseTest(&test); | |
| } | |
| TEST_F(QualityScalingTest, | |
| AdaptsDownForLowStartBitrate_MiddleStreamActive_Vp9) { | |
| // qp_low:1, qp_high:255 -> kNormalQp | |
| SetQualityScalingTrialQP({.vp9_low = 1, .vp9_high = 255}); | |
| DownscalingObserver test( | |
| "VP9", {{.active = false}, {.active = true}, {.active = false}}, | |
| kSinglecastLimits360pVp9->min_start_bitrate_bps - 1, | |
| /*automatic_resize=*/true, | |
| /*expect_downscale=*/true); | |
| RunBaseTest(&test); | |
| } | |
| TEST_F(QualityScalingTest, NoAdaptDownForLowStartBitrateIfBitrateEnough_Vp9) { | |
| // qp_low:1, qp_high:255 -> kNormalQp | |
| SetQualityScalingTrialQP({.vp9_low = 1, .vp9_high = 255}); | |
| DownscalingObserver test( | |
| "VP9", {{.active = false}, {.active = true}, {.active = false}}, | |
| kSinglecastLimits360pVp9->min_start_bitrate_bps, | |
| /*automatic_resize=*/true, | |
| /*expect_downscale=*/false); | |
| RunBaseTest(&test); | |
| } | |
| TEST_F(QualityScalingTest, | |
| AdaptsDownButNotUpWithMinStartBitrateLimitWithScalabilityMode_VP9) { | |
| // qp_low:255, qp_high:255 -> kLowQp | |
| SetQualityScalingTrialQP({.vp9_low = 255, .vp9_high = 255}); | |
| UpscalingObserver test( | |
| "VP9", | |
| {{.active = true, .scalability_mode = ScalabilityMode::kL1T3}, | |
| {.active = false}}, | |
| kSinglecastLimits720pVp9->min_start_bitrate_bps - 1, | |
| /*automatic_resize=*/true, /*expect_upscale=*/false); | |
| RunBaseTest(&test); | |
| } | |
| TEST_F(QualityScalingTest, | |
| NoAdaptDownForLowStartBitrateIfBitrateEnoughWithScalabilityMode_Vp9) { | |
| // qp_low:1, qp_high:255 -> kNormalQp | |
| SetQualityScalingTrialQP({.vp9_low = 1, .vp9_high = 255}); | |
| DownscalingObserver test( | |
| "VP9", | |
| {{.active = true, .scalability_mode = ScalabilityMode::kL1T3}, | |
| {.active = false}, | |
| {.active = false}}, | |
| kSinglecastLimits720pVp9->min_start_bitrate_bps, | |
| /*automatic_resize=*/true, | |
| /*expect_downscale=*/false); | |
| RunBaseTest(&test); | |
| } | |
| #if defined(WEBRTC_USE_H264) | |
| TEST_F(QualityScalingTest, AdaptsDownForHighQp_H264) { | |
| // qp_low:1, qp_high:1 -> kHighQp | |
| SetQualityScalingTrialQP({.h264_low = 1, .h264_high = 1}); | |
| DownscalingObserver test("H264", {{.active = true}}, kHighStartBps, | |
| /*automatic_resize=*/true, | |
| /*expect_downscale=*/true); | |
| RunBaseTest(&test); | |
| } | |
| TEST_F(QualityScalingTest, AdaptsDownForLowStartBitrate_H264) { | |
| // qp_low:1, qp_high:51 -> kNormalQp | |
| SetQualityScalingTrialQP({.h264_low = 1, .h264_high = 51}); | |
| DownscalingObserver test("H264", {{.active = true}}, kLowStartBps, | |
| /*automatic_resize=*/true, | |
| /*expect_downscale=*/true); | |
| RunBaseTest(&test); | |
| } | |
| #endif // defined(WEBRTC_USE_H264) | |
| } // namespace webrtc |