Skip to content

Commit

Permalink
Bug 1924098 - Vendor libwebrtc from 31350c7119
Browse files Browse the repository at this point in the history
Upstream commit: https://webrtc.googlesource.com/src/+/31350c7119fb0e100336e3f22d869e7bd9a0126f
    [M130] Increase AV1 QP threshold for quality convergence from 40 to 60

    Merge approval: https://g-issues.chromium.org/issues/367752722#comment5

    (cherry picked from commit e81ba3089755e88292c135733ea187fdd278d858)

    Bug: chromium:328598314, chromium:367752722
    Change-Id: I132b4c30f132ace2bbef6359edd994c1ad75c9ad
    Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/362620
    Reviewed-by: Johannes Kron <[email protected]>
    Commit-Queue: Sergey Silkin <[email protected]>
    Cr-Original-Commit-Position: refs/heads/main@{#43035}
    Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/362981
    Commit-Queue: Johannes Kron <[email protected]>
    Cr-Commit-Position: refs/branch-heads/6723@{#1}
    Cr-Branched-From: 13e377b804f68aa9c20ea5e449666ea5248e3286-refs/heads/main@{#43019}
  • Loading branch information
mfromanmoz committed Oct 16, 2024
1 parent 726c300 commit 2ec5275
Show file tree
Hide file tree
Showing 6 changed files with 138 additions and 90 deletions.
3 changes: 3 additions & 0 deletions third_party/libwebrtc/README.moz-ff-commit
Original file line number Diff line number Diff line change
Expand Up @@ -32847,3 +32847,6 @@ ec38238af7
# MOZ_LIBWEBRTC_SRC=/home/mfroman/mozilla/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
# base of lastest vendoring
13e377b804
# MOZ_LIBWEBRTC_SRC=/home/mfroman/mozilla/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh
# base of lastest vendoring
31350c7119
2 changes: 2 additions & 0 deletions third_party/libwebrtc/README.mozilla
Original file line number Diff line number Diff line change
Expand Up @@ -21922,3 +21922,5 @@ libwebrtc updated from /home/mfroman/mozilla/elm/.moz-fast-forward/moz-libwebrtc
libwebrtc updated from /home/mfroman/mozilla/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-10-16T00:09:04.476456.
# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /home/mfroman/mozilla/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
libwebrtc updated from /home/mfroman/mozilla/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-10-16T00:10:00.641479.
# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /home/mfroman/mozilla/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
libwebrtc updated from /home/mfroman/mozilla/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-10-16T00:10:54.604765.
60 changes: 48 additions & 12 deletions third_party/libwebrtc/video/quality_convergence_controller.cc
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,11 @@

#include "video/quality_convergence_controller.h"

#include <algorithm>

#include "rtc_base/checks.h"
#include "rtc_base/experiments/struct_parameters_parser.h"
#include "rtc_base/logging.h"

namespace webrtc {
namespace {
Expand All @@ -19,38 +23,70 @@ namespace {
// default configurations used for the software encoders.
constexpr int kVp8DefaultStaticQpThreshold = 15;
constexpr int kVp9DefaultStaticQpThreshold = 32;
constexpr int kAv1DefaultStaticQpThreshold = 40;
constexpr int kAv1DefaultStaticQpThreshold = 60;

struct StaticDetectionConfig {
// Overrides the static QP threshold if set to a higher value than what is
// reported by the encoder.
std::optional<int> static_qp_threshold_override;
std::unique_ptr<StructParametersParser> Parser();
};

int GetDefaultStaticQpThreshold(VideoCodecType codec) {
std::unique_ptr<StructParametersParser> StaticDetectionConfig::Parser() {
// The empty comments ensures that each pair is on a separate line.
return StructParametersParser::Create("static_qp_threshold",
&static_qp_threshold_override);
}

int GetDefaultStaticQpThreshold(VideoCodecType codec,
const FieldTrialsView& trials) {
StaticDetectionConfig static_config;
int default_static_qp_threhsold = 0;
switch (codec) {
case kVideoCodecVP8:
return kVp8DefaultStaticQpThreshold;
default_static_qp_threhsold = kVp8DefaultStaticQpThreshold;
static_config.Parser()->Parse(trials.Lookup("WebRTC-QCM-Static-VP8"));
break;
case kVideoCodecVP9:
return kVp9DefaultStaticQpThreshold;
default_static_qp_threhsold = kVp9DefaultStaticQpThreshold;
static_config.Parser()->Parse(trials.Lookup("WebRTC-QCM-Static-VP9"));
break;
case kVideoCodecAV1:
return kAv1DefaultStaticQpThreshold;
default_static_qp_threhsold = kAv1DefaultStaticQpThreshold;
static_config.Parser()->Parse(trials.Lookup("WebRTC-QCM-Static-AV1"));
break;
case kVideoCodecGeneric:
case kVideoCodecH264:
case kVideoCodecH265:
// -1 will effectively disable the static QP threshold since QP values are
// always >= 0.
return -1;
}

if (static_config.static_qp_threshold_override.has_value()) {
RTC_LOG(LS_INFO) << "static_qp_threshold_override: "
<< *static_config.static_qp_threshold_override;
return *static_config.static_qp_threshold_override;
}

return default_static_qp_threhsold;
}
} // namespace

void QualityConvergenceController::Initialize(
int number_of_layers,
std::optional<int> static_qp_threshold,
VideoCodecType codec,
const FieldTrialsView& trials) {
void QualityConvergenceController::Initialize(int number_of_layers,
std::optional<int> encoder_min_qp,
VideoCodecType codec,
const FieldTrialsView& trials) {
RTC_DCHECK(sequence_checker_.IsCurrent());
RTC_CHECK(number_of_layers > 0);
number_of_layers_ = number_of_layers;
convergence_monitors_.clear();

int qp_threshold =
static_qp_threshold.value_or(GetDefaultStaticQpThreshold(codec));
int qp_threshold = GetDefaultStaticQpThreshold(codec, trials);
if (encoder_min_qp.has_value()) {
qp_threshold = std::max(qp_threshold, *encoder_min_qp);
}

for (int i = 0; i < number_of_layers_; ++i) {
convergence_monitors_.push_back(
QualityConvergenceMonitor::Create(qp_threshold, codec, trials));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,56 +10,124 @@
*/
#include "video/quality_convergence_controller.h"

#include <optional>

#include "test/gtest.h"
#include "test/scoped_key_value_config.h"

namespace webrtc {
namespace {
constexpr int kStaticQpThreshold = 15;
constexpr int kVp8DefaultStaticQpThreshold = 15;

TEST(QualityConvergenceController, Singlecast) {
test::ScopedKeyValueConfig field_trials;
QualityConvergenceController controller;
controller.Initialize(1, kStaticQpThreshold, kVideoCodecVP8, field_trials);
controller.Initialize(1, /*encoder_min_qp=*/std::nullopt, kVideoCodecVP8,
field_trials);

EXPECT_FALSE(controller.AddSampleAndCheckTargetQuality(
/*layer_index=*/0, kStaticQpThreshold + 1, /*is_refresh_frame=*/false));
/*layer_index=*/0, kVp8DefaultStaticQpThreshold + 1,
/*is_refresh_frame=*/false));
EXPECT_TRUE(controller.AddSampleAndCheckTargetQuality(
/*layer_index=*/0, kStaticQpThreshold, /*is_refresh_frame=*/false));
/*layer_index=*/0, kVp8DefaultStaticQpThreshold,
/*is_refresh_frame=*/false));
}

TEST(QualityConvergenceController, Simulcast) {
test::ScopedKeyValueConfig field_trials;
QualityConvergenceController controller;
controller.Initialize(2, kStaticQpThreshold, kVideoCodecVP8, field_trials);
controller.Initialize(2, /*encoder_min_qp=*/std::nullopt, kVideoCodecVP8,
field_trials);

EXPECT_FALSE(controller.AddSampleAndCheckTargetQuality(
/*layer_index=*/0, kStaticQpThreshold + 1, /*is_refresh_frame=*/false));
/*layer_index=*/0, kVp8DefaultStaticQpThreshold + 1,
/*is_refresh_frame=*/false));
EXPECT_FALSE(controller.AddSampleAndCheckTargetQuality(
/*layer_index=*/1, kStaticQpThreshold + 1, /*is_refresh_frame=*/false));
/*layer_index=*/1, kVp8DefaultStaticQpThreshold + 1,
/*is_refresh_frame=*/false));

// Layer 0 reaches target quality.
EXPECT_TRUE(controller.AddSampleAndCheckTargetQuality(
/*layer_index=*/0, kStaticQpThreshold, /*is_refresh_frame=*/false));
/*layer_index=*/0, kVp8DefaultStaticQpThreshold,
/*is_refresh_frame=*/false));
EXPECT_FALSE(controller.AddSampleAndCheckTargetQuality(
/*layer_index=*/1, kStaticQpThreshold + 1, /*is_refresh_frame=*/false));
/*layer_index=*/1, kVp8DefaultStaticQpThreshold + 1,
/*is_refresh_frame=*/false));

// Frames are repeated for both layers. Layer 0 still at target quality.
EXPECT_TRUE(controller.AddSampleAndCheckTargetQuality(
/*layer_index=*/0, kStaticQpThreshold, /*is_refresh_frame=*/true));
/*layer_index=*/0, kVp8DefaultStaticQpThreshold,
/*is_refresh_frame=*/true));
EXPECT_FALSE(controller.AddSampleAndCheckTargetQuality(
/*layer_index=*/1, kStaticQpThreshold + 1, /*is_refresh_frame=*/true));
/*layer_index=*/1, kVp8DefaultStaticQpThreshold + 1,
/*is_refresh_frame=*/true));
}

TEST(QualityConvergenceController, InvalidLayerIndex) {
test::ScopedKeyValueConfig field_trials;
QualityConvergenceController controller;
controller.Initialize(2, kStaticQpThreshold, kVideoCodecVP8, field_trials);
controller.Initialize(2, /*encoder_min_qp=*/std::nullopt, kVideoCodecVP8,
field_trials);

EXPECT_FALSE(controller.AddSampleAndCheckTargetQuality(
/*layer_index=*/-1, kVp8DefaultStaticQpThreshold,
/*is_refresh_frame=*/false));
EXPECT_FALSE(controller.AddSampleAndCheckTargetQuality(
/*layer_index=*/3, kVp8DefaultStaticQpThreshold,
/*is_refresh_frame=*/false));
}

TEST(QualityConvergenceController, UseMaxOfEncoderMinAndDefaultQpThresholds) {
test::ScopedKeyValueConfig field_trials;
QualityConvergenceController controller;
controller.Initialize(1, kVp8DefaultStaticQpThreshold + 1, kVideoCodecVP8,
field_trials);

EXPECT_FALSE(controller.AddSampleAndCheckTargetQuality(
/*layer_index=*/0, kVp8DefaultStaticQpThreshold + 2,
/*is_refresh_frame=*/false));
EXPECT_TRUE(controller.AddSampleAndCheckTargetQuality(
/*layer_index=*/0, kVp8DefaultStaticQpThreshold + 1,
/*is_refresh_frame=*/false));
}

TEST(QualityConvergenceController, OverrideVp8StaticThreshold) {
test::ScopedKeyValueConfig field_trials(
"WebRTC-QCM-Static-VP8/static_qp_threshold:22/");
QualityConvergenceController controller;
controller.Initialize(1, /*encoder_min_qp=*/std::nullopt, kVideoCodecVP8,
field_trials);

EXPECT_FALSE(controller.AddSampleAndCheckTargetQuality(
/*layer_index=*/-1, kStaticQpThreshold, /*is_refresh_frame=*/false));
/*layer_index=*/0, /*qp=*/23, /*is_refresh_frame=*/false));
EXPECT_TRUE(controller.AddSampleAndCheckTargetQuality(
/*layer_index=*/0, /*qp=*/22, /*is_refresh_frame=*/false));
}

TEST(QualityConvergenceMonitorSetup, OverrideVp9StaticThreshold) {
test::ScopedKeyValueConfig field_trials(
"WebRTC-QCM-Static-VP9/static_qp_threshold:44/");
QualityConvergenceController controller;
controller.Initialize(1, /*encoder_min_qp=*/std::nullopt, kVideoCodecVP9,
field_trials);

EXPECT_FALSE(controller.AddSampleAndCheckTargetQuality(
/*layer_index=*/3, kStaticQpThreshold, /*is_refresh_frame=*/false));
/*layer_index=*/0, /*qp=*/45, /*is_refresh_frame=*/false));
EXPECT_TRUE(controller.AddSampleAndCheckTargetQuality(
/*layer_index=*/0, /*qp=*/44, /*is_refresh_frame=*/false));
}

TEST(QualityConvergenceMonitorSetup, OverrideAv1StaticThreshold) {
test::ScopedKeyValueConfig field_trials(
"WebRTC-QCM-Static-AV1/static_qp_threshold:46/");
QualityConvergenceController controller;
controller.Initialize(1, /*encoder_min_qp=*/std::nullopt, kVideoCodecAV1,
field_trials);

EXPECT_FALSE(controller.AddSampleAndCheckTargetQuality(
/*layer_index=*/0, /*qp=*/47, /*is_refresh_frame=*/false));
EXPECT_TRUE(controller.AddSampleAndCheckTargetQuality(
/*layer_index=*/0, /*qp=*/46, /*is_refresh_frame=*/false));
}

} // namespace
Expand Down
25 changes: 3 additions & 22 deletions third_party/libwebrtc/video/quality_convergence_monitor.cc
Original file line number Diff line number Diff line change
Expand Up @@ -22,19 +22,6 @@ constexpr size_t kDefaultRecentWindowLength = 6;
constexpr size_t kDefaultPastWindowLength = 6;
constexpr float kDefaultAlpha = 0.06;

struct StaticDetectionConfig {
// Overrides the static QP threshold if set to a higher value than what is
// reported by the encoder.
int static_qp_threshold_override = 0;
std::unique_ptr<StructParametersParser> Parser();
};

std::unique_ptr<StructParametersParser> StaticDetectionConfig::Parser() {
// The empty comments ensures that each pair is on a separate line.
return StructParametersParser::Create("static_qp_threshold",
&static_qp_threshold_override);
}

struct DynamicDetectionConfig {
bool enabled = false;
// alpha is a percentage of the codec-specific max QP value that is used to
Expand All @@ -58,30 +45,27 @@ std::unique_ptr<StructParametersParser> DynamicDetectionConfig::Parser() {
}

QualityConvergenceMonitor::Parameters GetParameters(
int static_min_qp_threshold,
int static_qp_threshold,
VideoCodecType codec,
const FieldTrialsView& trials) {
QualityConvergenceMonitor::Parameters params;
params.static_qp_threshold = static_qp_threshold;

StaticDetectionConfig static_config;
DynamicDetectionConfig dynamic_config;
// Apply codec specific settings.
int max_qp = 0;
switch (codec) {
case kVideoCodecVP8:
static_config.Parser()->Parse(trials.Lookup("WebRTC-QCM-Static-VP8"));
dynamic_config.Parser()->Parse(trials.Lookup("WebRTC-QCM-Dynamic-VP8"));
max_qp = 127;
break;
case kVideoCodecVP9:
static_config.Parser()->Parse(trials.Lookup("WebRTC-QCM-Static-VP9"));
// Change to enabled by default for VP9.
dynamic_config.enabled = true;
dynamic_config.Parser()->Parse(trials.Lookup("WebRTC-QCM-Dynamic-VP9"));
max_qp = 255;
break;
case kVideoCodecAV1:
static_config.Parser()->Parse(trials.Lookup("WebRTC-QCM-Static-AV1"));
// Change to enabled by default for AV1.
dynamic_config.enabled = true;
dynamic_config.Parser()->Parse(trials.Lookup("WebRTC-QCM-Dynamic-AV1"));
Expand All @@ -93,13 +77,10 @@ QualityConvergenceMonitor::Parameters GetParameters(
break;
}

params.static_qp_threshold = std::max(
static_min_qp_threshold, static_config.static_qp_threshold_override);

if (dynamic_config.enabled) {
params.dynamic_detection_enabled = dynamic_config.enabled;
params.dynamic_qp_threshold =
static_min_qp_threshold + max_qp * dynamic_config.alpha;
static_qp_threshold + max_qp * dynamic_config.alpha;
params.recent_window_length = dynamic_config.recent_length;
params.past_window_length = dynamic_config.past_length;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
namespace webrtc {
namespace {
constexpr int kStaticQpThreshold = 13;
constexpr int kDefaultDynamicThreshold = 28; // 13 + 0.06 * 255.

constexpr QualityConvergenceMonitor::Parameters kParametersOnlyStaticThreshold =
{.static_qp_threshold = kStaticQpThreshold,
Expand Down Expand Up @@ -300,46 +299,5 @@ TEST(QualityConvergenceMonitorSetup, DisableAv1Dynamic) {
EXPECT_FALSE(p.dynamic_detection_enabled);
}

TEST(QualityConvergenceMonitorSetup, OverrideVp8StaticThreshold) {
test::ScopedKeyValueConfig field_trials(
"WebRTC-QCM-Static-VP8/static_qp_threshold:22/");

auto monitor = QualityConvergenceMonitor::Create(
kStaticQpThreshold, kVideoCodecVP8, field_trials);
ASSERT_TRUE(monitor);
QualityConvergenceMonitor::Parameters p = monitor->GetParametersForTesting();
EXPECT_EQ(p.static_qp_threshold, 22);
EXPECT_NE(p.static_qp_threshold, kStaticQpThreshold);
// Dynamic threshold is not tested since it's not enabled by default for VP8.
}

TEST(QualityConvergenceMonitorSetup, OverrideVp9StaticThreshold) {
test::ScopedKeyValueConfig field_trials(
"WebRTC-QCM-Static-VP9/static_qp_threshold:44/");

auto monitor = QualityConvergenceMonitor::Create(
kStaticQpThreshold, kVideoCodecVP9, field_trials);
ASSERT_TRUE(monitor);
QualityConvergenceMonitor::Parameters p = monitor->GetParametersForTesting();
EXPECT_EQ(p.static_qp_threshold, 44);
EXPECT_NE(p.static_qp_threshold, kStaticQpThreshold);
// Dynamic QP threshold is unchanged.
EXPECT_EQ(p.dynamic_qp_threshold, kDefaultDynamicThreshold);
}

TEST(QualityConvergenceMonitorSetup, OverrideAv1StaticThreshold) {
test::ScopedKeyValueConfig field_trials(
"WebRTC-QCM-Static-AV1/static_qp_threshold:46/");

auto monitor = QualityConvergenceMonitor::Create(
kStaticQpThreshold, kVideoCodecAV1, field_trials);
ASSERT_TRUE(monitor);
QualityConvergenceMonitor::Parameters p = monitor->GetParametersForTesting();
EXPECT_EQ(p.static_qp_threshold, 46);
EXPECT_NE(p.static_qp_threshold, kStaticQpThreshold);
// Dynamic QP threshold is unchanged.
EXPECT_EQ(p.dynamic_qp_threshold, kDefaultDynamicThreshold);
}

} // namespace
} // namespace webrtc

0 comments on commit 2ec5275

Please sign in to comment.