Add QP threshold experiment for H265.
The old experiment WebRTC-Video-QualityScaling only applies for VP8,
VP9, H264 and Generic, which does not cover H265.
In order to fine tune QP thresholds for H265, a new field trial is
added, this allows us to experiment with those without affecting the
old field trial which has a bunch of existing dependencies.
Some drive-by comments are added to the existing code.
Bug: webrtc:402154973, chromium:391907171
Change-Id: I13c8b496a1c708528d7538c8d1d2ff66de4c2ae5
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/380420
Commit-Queue: Henrik Boström <hbos@webrtc.org>
Reviewed-by: Erik Språng <sprang@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#44088}
diff --git a/experiments/field_trials.py b/experiments/field_trials.py
index 1834752..d9e46f3 100755
--- a/experiments/field_trials.py
+++ b/experiments/field_trials.py
@@ -188,6 +188,9 @@
FieldTrial('WebRTC-IceHandshakeDtls',
367395350,
date(2026, 1, 1)),
+ FieldTrial('WebRTC-H265-QualityScaling',
+ 402154973,
+ date(2026, 1, 1)),
# keep-sorted end
]) # yapf: disable
diff --git a/rtc_base/experiments/BUILD.gn b/rtc_base/experiments/BUILD.gn
index c5fce04..9f5573c 100644
--- a/rtc_base/experiments/BUILD.gn
+++ b/rtc_base/experiments/BUILD.gn
@@ -66,6 +66,7 @@
"../../api:field_trials_view",
"../../api/transport:field_trial_based_config",
"../../api/video_codecs:video_codecs_api",
+ "../../rtc_base/experiments:field_trial_parser",
"//third_party/abseil-cpp/absl/strings",
]
}
diff --git a/rtc_base/experiments/quality_scaling_experiment.cc b/rtc_base/experiments/quality_scaling_experiment.cc
index 7bad026..be56363 100644
--- a/rtc_base/experiments/quality_scaling_experiment.cc
+++ b/rtc_base/experiments/quality_scaling_experiment.cc
@@ -16,10 +16,14 @@
#include "absl/strings/match.h"
#include "api/field_trials_view.h"
#include "api/transport/field_trial_based_config.h"
+#include "rtc_base/experiments/field_trial_parser.h"
#include "rtc_base/logging.h"
namespace webrtc {
namespace {
+
+// This experiment controls QP thresholds for VP8, VP9, H264 and Generic codecs.
+// Generic includes H265X but not standard H265.
constexpr char kFieldTrial[] = "WebRTC-Video-QualityScaling";
constexpr int kMinQp = 1;
constexpr int kMaxVp8Qp = 127;
@@ -28,6 +32,13 @@
constexpr int kMaxGenericQp = 255;
#if !defined(WEBRTC_IOS)
+// On non-iOS, this default string is used unless explicitly overriden.
+// TODO(https://crbug.com/400338987): For use cases that does not explicitly
+// turn the QP experiment on (e.g. Chrome), it does not make sense for this QP
+// threshold to override the QP thresholds provided by the encoder
+// implementation - we should trust that an encoder implementation that reports
+// its own QP thresholds would know best, and only use these as a fallback for
+// when the encoder does not specify any.
constexpr char kDefaultQualityScalingSetttings[] =
"Enabled-29,95,149,205,24,37,26,36,0.9995,0.9999,1";
#endif
@@ -42,14 +53,42 @@
return std::optional<VideoEncoder::QpThresholds>(
VideoEncoder::QpThresholds(low, high));
}
+
+// This experiment controls QP thresholds for standard H265 (not H265X).
+// - Only for debugging/experimentation. Once QP thresholds have been determined
+// it is up to the encoder implementation to provide
+// VideoEncoder::EncoderInfo::scaling_settings.
+//
+// Example usage:
+// --force-fieldtrials=WebRTC-H265-QualityScaling/low_qp:27,high_qp:35/
+struct WebRTCH265QualityScaling {
+ static constexpr char kFieldTrialName[] = "WebRTC-H265-QualityScaling";
+
+ WebRTCH265QualityScaling(const FieldTrialsView& field_trials)
+ : low_qp("low_qp"), high_qp("high_qp") {
+ ParseFieldTrial({&low_qp, &high_qp}, field_trials.Lookup(kFieldTrialName));
+ }
+
+ bool IsEnabled() const { return low_qp && high_qp; }
+ VideoEncoder::QpThresholds ToQpThresholds() const {
+ RTC_DCHECK(IsEnabled());
+ return VideoEncoder::QpThresholds(*low_qp, *high_qp);
+ }
+
+ FieldTrialOptional<int> low_qp;
+ FieldTrialOptional<int> high_qp;
+};
} // namespace
bool QualityScalingExperiment::Enabled(const FieldTrialsView& field_trials) {
+ WebRTCH265QualityScaling h265_quality_scaling(field_trials);
+ return
#if defined(WEBRTC_IOS)
- return absl::StartsWith(field_trials.Lookup(kFieldTrial), "Enabled");
+ absl::StartsWith(field_trials.Lookup(kFieldTrial), "Enabled") ||
#else
- return !absl::StartsWith(field_trials.Lookup(kFieldTrial), "Disabled");
+ !absl::StartsWith(field_trials.Lookup(kFieldTrial), "Disabled") ||
#endif
+ h265_quality_scaling.IsEnabled();
}
std::optional<QualityScalingExperiment::Settings>
@@ -75,6 +114,12 @@
std::optional<VideoEncoder::QpThresholds>
QualityScalingExperiment::GetQpThresholds(VideoCodecType codec_type,
const FieldTrialsView& field_trials) {
+ if (codec_type == kVideoCodecH265) {
+ WebRTCH265QualityScaling h265_quality_scaling(field_trials);
+ if (h265_quality_scaling.IsEnabled()) {
+ return h265_quality_scaling.ToQpThresholds();
+ }
+ }
const auto settings = ParseSettings(field_trials);
if (!settings)
return std::nullopt;