SimulcastEncoderAdapter: Add field trial for EncoderInfo settings.
Allowed settings:
- requested_resolution_alignment
- apply_alignment_to_all_simulcast_layers
Bug: none
Change-Id: Ic4c733fd1134b9d097a2d19963eef1b676058f49
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/201626
Commit-Queue: Åsa Persson <asapersson@webrtc.org>
Reviewed-by: Erik Språng <sprang@webrtc.org>
Reviewed-by: Sergey Silkin <ssilkin@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#33010}
diff --git a/media/BUILD.gn b/media/BUILD.gn
index b253a61..55fc59c 100644
--- a/media/BUILD.gn
+++ b/media/BUILD.gn
@@ -193,6 +193,7 @@
"../modules/video_coding:video_coding_utility",
"../rtc_base:checks",
"../rtc_base:rtc_base_approved",
+ "../rtc_base/experiments:field_trial_parser",
"../rtc_base/experiments:rate_control_settings",
"../rtc_base/synchronization:sequence_checker",
"../rtc_base/system:no_unique_address",
diff --git a/media/engine/simulcast_encoder_adapter.cc b/media/engine/simulcast_encoder_adapter.cc
index 525d818..10cf686 100644
--- a/media/engine/simulcast_encoder_adapter.cc
+++ b/media/engine/simulcast_encoder_adapter.cc
@@ -228,6 +228,11 @@
"WebRTC-Video-PreferTemporalSupportOnBaseLayer")) {
RTC_DCHECK(primary_factory);
+ ParseFieldTrial({&requested_resolution_alignment_override_,
+ &apply_alignment_to_all_simulcast_layers_override_},
+ field_trial::FindFullName(
+ "WebRTC-SimulcastEncoderAdapter-GetEncoderInfoOverride"));
+
// The adapter is typically created on the worker thread, but operated on
// the encoder task queue.
encoder_queue_.Detach();
@@ -425,6 +430,27 @@
return WEBRTC_VIDEO_CODEC_UNINITIALIZED;
}
+ if (requested_resolution_alignment_override_) {
+ const int alignment = *requested_resolution_alignment_override_;
+ if (input_image.width() % alignment != 0 ||
+ input_image.height() % alignment != 0) {
+ RTC_LOG(LS_WARNING) << "Frame " << input_image.width() << "x"
+ << input_image.height() << " not divisible by "
+ << alignment;
+ return WEBRTC_VIDEO_CODEC_ERROR;
+ }
+ if (apply_alignment_to_all_simulcast_layers_override_.Get()) {
+ for (const auto& layer : encoder_contexts_) {
+ if (layer.width() % alignment != 0 || layer.height() % alignment != 0) {
+ RTC_LOG(LS_WARNING)
+ << "Codec " << layer.width() << "x" << layer.height()
+ << " not divisible by " << alignment;
+ return WEBRTC_VIDEO_CODEC_ERROR;
+ }
+ }
+ }
+ }
+
// All active streams should generate a key frame if
// a key frame is requested by any stream.
bool send_key_frame = false;
@@ -713,10 +739,23 @@
}
}
+void SimulcastEncoderAdapter::OverrideFromFieldTrial(
+ VideoEncoder::EncoderInfo* info) const {
+ if (requested_resolution_alignment_override_) {
+ info->requested_resolution_alignment =
+ *requested_resolution_alignment_override_;
+ info->apply_alignment_to_all_simulcast_layers =
+ apply_alignment_to_all_simulcast_layers_override_.Get();
+ }
+}
+
VideoEncoder::EncoderInfo SimulcastEncoderAdapter::GetEncoderInfo() const {
if (encoder_contexts_.size() == 1) {
// Not using simulcast adapting functionality, just pass through.
- return encoder_contexts_.front().encoder().GetEncoderInfo();
+ VideoEncoder::EncoderInfo info =
+ encoder_contexts_.front().encoder().GetEncoderInfo();
+ OverrideFromFieldTrial(&info);
+ return info;
}
VideoEncoder::EncoderInfo encoder_info;
@@ -726,6 +765,7 @@
encoder_info.supports_native_handle = true;
encoder_info.scaling_settings.thresholds = absl::nullopt;
if (encoder_contexts_.empty()) {
+ OverrideFromFieldTrial(&encoder_info);
return encoder_info;
}
@@ -784,6 +824,8 @@
}
encoder_info.implementation_name += ")";
+ OverrideFromFieldTrial(&encoder_info);
+
return encoder_info;
}
diff --git a/media/engine/simulcast_encoder_adapter.h b/media/engine/simulcast_encoder_adapter.h
index 6b1b177..d3d5d17 100644
--- a/media/engine/simulcast_encoder_adapter.h
+++ b/media/engine/simulcast_encoder_adapter.h
@@ -26,6 +26,7 @@
#include "modules/video_coding/include/video_codec_interface.h"
#include "modules/video_coding/utility/framerate_controller.h"
#include "rtc_base/atomic_ops.h"
+#include "rtc_base/experiments/field_trial_parser.h"
#include "rtc_base/synchronization/sequence_checker.h"
#include "rtc_base/system/no_unique_address.h"
#include "rtc_base/system/rtc_export.h"
@@ -138,6 +139,8 @@
void OnDroppedFrame(size_t stream_idx);
+ void OverrideFromFieldTrial(VideoEncoder::EncoderInfo* info) const;
+
volatile int inited_; // Accessed atomically.
VideoEncoderFactory* const primary_encoder_factory_;
VideoEncoderFactory* const fallback_encoder_factory_;
@@ -158,6 +161,14 @@
const absl::optional<unsigned int> experimental_boosted_screenshare_qp_;
const bool boost_base_layer_quality_;
const bool prefer_temporal_support_on_base_layer_;
+
+ // Overrides from field trial.
+ // EncoderInfo::requested_resolution_alignment.
+ FieldTrialOptional<int> requested_resolution_alignment_override_{
+ "requested_resolution_alignment"};
+ // EncoderInfo::apply_alignment_to_all_simulcast_layers.
+ FieldTrialFlag apply_alignment_to_all_simulcast_layers_override_{
+ "apply_alignment_to_all_simulcast_layers"};
};
} // namespace webrtc
diff --git a/media/engine/simulcast_encoder_adapter_unittest.cc b/media/engine/simulcast_encoder_adapter_unittest.cc
index 24686e8..510db6f 100644
--- a/media/engine/simulcast_encoder_adapter_unittest.cc
+++ b/media/engine/simulcast_encoder_adapter_unittest.cc
@@ -28,6 +28,7 @@
#include "modules/video_coding/include/video_codec_interface.h"
#include "modules/video_coding/utility/simulcast_test_fixture_impl.h"
#include "rtc_base/checks.h"
+#include "test/field_trial.h"
#include "test/gmock.h"
#include "test/gtest.h"
@@ -1291,6 +1292,42 @@
adapter_->GetEncoderInfo().apply_alignment_to_all_simulcast_layers);
}
+TEST_F(TestSimulcastEncoderAdapterFake, AlignmentFromFieldTrial) {
+ test::ScopedFieldTrials field_trials(
+ "WebRTC-SimulcastEncoderAdapter-GetEncoderInfoOverride/"
+ "requested_resolution_alignment:8,"
+ "apply_alignment_to_all_simulcast_layers/");
+ SetUp();
+ SimulcastTestFixtureImpl::DefaultSettings(
+ &codec_, static_cast<const int*>(kTestTemporalLayerProfile),
+ kVideoCodecVP8);
+ codec_.numberOfSimulcastStreams = 3;
+ EXPECT_EQ(0, adapter_->InitEncode(&codec_, kSettings));
+ ASSERT_EQ(3u, helper_->factory()->encoders().size());
+
+ EXPECT_EQ(8, adapter_->GetEncoderInfo().requested_resolution_alignment);
+ EXPECT_TRUE(
+ adapter_->GetEncoderInfo().apply_alignment_to_all_simulcast_layers);
+}
+
+TEST_F(TestSimulcastEncoderAdapterFake,
+ AlignmentFromFieldTrialForSingleStream) {
+ test::ScopedFieldTrials field_trials(
+ "WebRTC-SimulcastEncoderAdapter-GetEncoderInfoOverride/"
+ "requested_resolution_alignment:9/");
+ SetUp();
+ SimulcastTestFixtureImpl::DefaultSettings(
+ &codec_, static_cast<const int*>(kTestTemporalLayerProfile),
+ kVideoCodecVP8);
+ codec_.numberOfSimulcastStreams = 1;
+ EXPECT_EQ(0, adapter_->InitEncode(&codec_, kSettings));
+ ASSERT_EQ(1u, helper_->factory()->encoders().size());
+
+ EXPECT_EQ(9, adapter_->GetEncoderInfo().requested_resolution_alignment);
+ EXPECT_FALSE(
+ adapter_->GetEncoderInfo().apply_alignment_to_all_simulcast_layers);
+}
+
TEST_F(TestSimulcastEncoderAdapterFake, ReportsInternalSource) {
SimulcastTestFixtureImpl::DefaultSettings(
&codec_, static_cast<const int*>(kTestTemporalLayerProfile),