Extend WebRTC-Video-MinVideoBitrate to experiment per-codec

The experiment was extended to support per-codec minimum bitrates
for the following codecs:
 * VP8
 * VP9
 * H.264

The old semantic meaning for the field trial is retained, in that
specifying "br:" applies a minimum bitrate to all codecs. If "br:"
is not specified, the per-codec minimum config is consulted.

Bug: webrtc:11024
Change-Id: I89630262c7710771d5e25d039fe35f0bd217b58a
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/156171
Commit-Queue: Elad Alon <eladalon@webrtc.org>
Reviewed-by: Åsa Persson <asapersson@webrtc.org>
Reviewed-by: Ying Wang <yinwa@webrtc.org>
Reviewed-by: Ilya Nikolaevskiy <ilnik@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#29450}
This commit is contained in:
Elad Alon 2019-10-11 16:19:43 +02:00 committed by Commit Bot
parent e62a588314
commit 80f53b785b
13 changed files with 363 additions and 126 deletions

View File

@ -274,6 +274,7 @@ rtc_static_library("rtc_audio_video") {
"../api/transport:datagram_transport_interface",
"../api/transport/media:media_transport_interface",
"../api/transport/rtp:rtp_source",
"../api/units:data_rate",
"../api/video:video_bitrate_allocation",
"../api/video:video_bitrate_allocator_factory",
"../api/video:video_codec_constants",
@ -302,6 +303,7 @@ rtc_static_library("rtc_audio_video") {
"../rtc_base:stringutils",
"../rtc_base/experiments:experimental_screenshare_settings",
"../rtc_base/experiments:field_trial_parser",
"../rtc_base/experiments:min_video_bitrate_experiment",
"../rtc_base/experiments:normalize_simulcast_size_experiment",
"../rtc_base/system:rtc_export",
"../rtc_base/third_party/base64",
@ -565,6 +567,7 @@ if (rtc_include_tests) {
"../rtc_base:rtc_base_tests_utils",
"../rtc_base:rtc_task_queue",
"../rtc_base:stringutils",
"../rtc_base/experiments:min_video_bitrate_experiment",
"../rtc_base/third_party/sigslot",
"../test:audio_codec_mocks",
"../test:field_trial",

View File

@ -12,9 +12,8 @@
namespace cricket {
const int kMinVideoBitrateBps = 30000;
const int kVideoMtu = 1200;
const int kVideoRtpSendBufferSize = 65536;
const int kVideoRtpRecvBufferSize = 262144;
const char kMinVideoBitrateExperiment[] = "WebRTC-Video-MinVideoBitrate";
} // namespace cricket

View File

@ -19,9 +19,6 @@ extern const int kVideoRtpRecvBufferSize;
extern const char kH264CodecName[];
extern const int kMinVideoBitrateBps;
extern const char kMinVideoBitrateExperiment[];
} // namespace cricket
#endif // MEDIA_ENGINE_CONSTANTS_H_

View File

@ -19,11 +19,11 @@
#include "absl/types/optional.h"
#include "api/video/video_codec_constants.h"
#include "media/base/media_constants.h"
#include "media/engine/constants.h"
#include "modules/video_coding/utility/simulcast_rate_allocator.h"
#include "rtc_base/arraysize.h"
#include "rtc_base/checks.h"
#include "rtc_base/experiments/experimental_screenshare_settings.h"
#include "rtc_base/experiments/min_video_bitrate_experiment.h"
#include "rtc_base/experiments/normalize_simulcast_size_experiment.h"
#include "rtc_base/logging.h"
#include "system_wrappers/include/field_trial.h"
@ -335,7 +335,7 @@ std::vector<webrtc::VideoStream> GetScreenshareLayers(
layers[0].height = height;
layers[0].max_qp = max_qp;
layers[0].max_framerate = 5;
layers[0].min_bitrate_bps = kMinVideoBitrateBps;
layers[0].min_bitrate_bps = webrtc::kDefaultMinVideoBitrateBps;
layers[0].target_bitrate_bps = kScreenshareDefaultTl0BitrateKbps * 1000;
layers[0].max_bitrate_bps = kScreenshareDefaultTl1BitrateKbps * 1000;
layers[0].num_temporal_layers = temporal_layers_supported ? 2 : 0;

View File

@ -20,6 +20,7 @@
#include "absl/algorithm/container.h"
#include "absl/strings/match.h"
#include "api/transport/datagram_transport_interface.h"
#include "api/units/data_rate.h"
#include "api/video/video_codec_constants.h"
#include "api/video/video_codec_type.h"
#include "api/video_codecs/sdp_video_format.h"
@ -33,7 +34,9 @@
#include "rtc_base/copy_on_write_buffer.h"
#include "rtc_base/experiments/field_trial_parser.h"
#include "rtc_base/experiments/field_trial_units.h"
#include "rtc_base/experiments/min_video_bitrate_experiment.h"
#include "rtc_base/logging.h"
#include "rtc_base/numerics/safe_conversions.h"
#include "rtc_base/strings/string_builder.h"
#include "rtc_base/time_utils.h"
#include "rtc_base/trace_event.h"
@ -298,46 +301,6 @@ absl::optional<size_t> GetVp9TemporalLayersFromFieldTrial() {
return absl::nullopt;
}
const char kForcedFallbackFieldTrial[] =
"WebRTC-VP8-Forced-Fallback-Encoder-v2";
absl::optional<int> GetFallbackMinBpsFromFieldTrial(
webrtc::VideoCodecType type) {
if (type != webrtc::kVideoCodecVP8)
return absl::nullopt;
if (!webrtc::field_trial::IsEnabled(kForcedFallbackFieldTrial))
return absl::nullopt;
std::string group =
webrtc::field_trial::FindFullName(kForcedFallbackFieldTrial);
if (group.empty())
return absl::nullopt;
int min_pixels;
int max_pixels;
int min_bps;
if (sscanf(group.c_str(), "Enabled-%d,%d,%d", &min_pixels, &max_pixels,
&min_bps) != 3) {
return absl::nullopt;
}
if (min_bps <= 0)
return absl::nullopt;
return min_bps;
}
int GetMinVideoBitrateBps(webrtc::VideoCodecType type) {
if (GetFallbackMinBpsFromFieldTrial(type).has_value()) {
return GetFallbackMinBpsFromFieldTrial(type).value();
}
if (webrtc::field_trial::IsEnabled(kMinVideoBitrateExperiment)) {
return MinVideoBitrateConfig().min_video_bitrate->bps();
}
return kMinVideoBitrateBps;
}
// Returns its smallest positive argument. If neither argument is positive,
// returns an arbitrary nonpositive value.
int MinPositive(int a, int b) {
@ -3069,6 +3032,9 @@ std::vector<webrtc::VideoStream> EncoderStreamFactory::CreateEncoderStreams(
encoder_config.number_of_streams);
std::vector<webrtc::VideoStream> layers;
const absl::optional<webrtc::DataRate> experimental_min_bitrate =
GetExperimentalMinVideoBitrate(encoder_config.codec_type);
if (encoder_config.number_of_streams > 1 ||
((absl::EqualsIgnoreCase(codec_name_, kVp8CodecName) ||
absl::EqualsIgnoreCase(codec_name_, kH264CodecName)) &&
@ -3082,6 +3048,12 @@ std::vector<webrtc::VideoStream> EncoderStreamFactory::CreateEncoderStreams(
encoder_config.bitrate_priority, max_qp_,
is_screenshare_ && conference_mode_,
temporal_layers_supported);
// Allow an experiment to override the minimum bitrate for the lowest
// spatial layer. The experiment's configuration has the lowest priority.
if (experimental_min_bitrate) {
layers[0].min_bitrate_bps =
rtc::saturated_cast<int>(experimental_min_bitrate->bps());
}
// The maximum |max_framerate| is currently used for video.
const int max_framerate = GetMaxFramerate(encoder_config, layers.size());
// Update the active simulcast layers and configured bitrates.
@ -3170,7 +3142,10 @@ std::vector<webrtc::VideoStream> EncoderStreamFactory::CreateEncoderStreams(
: GetMaxDefaultVideoBitrateKbps(width, height, is_screenshare_) *
1000;
int min_bitrate_bps = GetMinVideoBitrateBps(encoder_config.codec_type);
int min_bitrate_bps =
experimental_min_bitrate
? rtc::saturated_cast<int>(experimental_min_bitrate->bps())
: webrtc::kDefaultMinVideoBitrateBps;
if (encoder_config.simulcast_layers[0].min_bitrate_bps > 0) {
// Use set min bitrate.
min_bitrate_bps = encoder_config.simulcast_layers[0].min_bitrate_bps;

View File

@ -33,11 +33,9 @@
#include "media/engine/unhandled_packets_buffer.h"
#include "rtc_base/async_invoker.h"
#include "rtc_base/critical_section.h"
#include "rtc_base/experiments/field_trial_parser.h"
#include "rtc_base/network_route.h"
#include "rtc_base/thread_annotations.h"
#include "rtc_base/thread_checker.h"
#include "system_wrappers/include/field_trial.h"
namespace webrtc {
class VideoDecoderFactory;
@ -51,17 +49,6 @@ class Thread;
namespace cricket {
struct MinVideoBitrateConfig {
webrtc::FieldTrialParameter<webrtc::DataRate> min_video_bitrate;
MinVideoBitrateConfig()
: min_video_bitrate("br", webrtc::DataRate::bps(kMinVideoBitrateBps)) {
webrtc::ParseFieldTrial(
{&min_video_bitrate},
webrtc::field_trial::FindFullName(kMinVideoBitrateExperiment));
}
};
class WebRtcVideoChannel;
class UnsignalledSsrcHandler {

View File

@ -52,6 +52,7 @@
#include "media/engine/simulcast.h"
#include "media/engine/webrtc_voice_engine.h"
#include "rtc_base/arraysize.h"
#include "rtc_base/experiments/min_video_bitrate_experiment.h"
#include "rtc_base/fake_clock.h"
#include "rtc_base/gunit.h"
#include "rtc_base/numerics/safe_conversions.h"
@ -3489,7 +3490,7 @@ INSTANTIATE_TEST_SUITE_P(
TEST_F(WebRtcVideoChannelTest, VerifyMinBitrate) {
std::vector<webrtc::VideoStream> streams = AddSendStream()->GetVideoStreams();
ASSERT_EQ(1u, streams.size());
EXPECT_EQ(cricket::kMinVideoBitrateBps, streams[0].min_bitrate_bps);
EXPECT_EQ(webrtc::kDefaultMinVideoBitrateBps, streams[0].min_bitrate_bps);
}
TEST_F(WebRtcVideoChannelTest, VerifyMinBitrateWithForcedFallbackFieldTrial) {
@ -5862,12 +5863,13 @@ TEST_F(WebRtcVideoChannelTest,
// we are just testing the behavior of
// EncoderStreamFactory::CreateEncoderStreams.
ASSERT_EQ(1UL, stream->GetVideoStreams().size());
EXPECT_EQ(kMinVideoBitrateBps, stream->GetVideoStreams()[0].min_bitrate_bps);
EXPECT_EQ(webrtc::kDefaultMinVideoBitrateBps,
stream->GetVideoStreams()[0].min_bitrate_bps);
// Set a low max bitrate & check that VideoStream.min_bitrate_bps is limited
// by this amount.
parameters = channel_->GetRtpSendParameters(last_ssrc_);
int low_max_bitrate_bps = kMinVideoBitrateBps - 1000;
int low_max_bitrate_bps = webrtc::kDefaultMinVideoBitrateBps - 1000;
parameters.encodings[0].max_bitrate_bps = low_max_bitrate_bps;
EXPECT_TRUE(channel_->SetRtpSendParameters(last_ssrc_, parameters).ok());
@ -5905,7 +5907,8 @@ TEST_F(WebRtcVideoChannelTest,
ExpectSetMaxBitrate(send_parameters_.max_bandwidth_bps);
ASSERT_TRUE(channel_->SetSendParameters(send_parameters_));
ASSERT_EQ(1UL, stream->GetVideoStreams().size());
EXPECT_EQ(kMinVideoBitrateBps, stream->GetVideoStreams()[0].min_bitrate_bps);
EXPECT_EQ(webrtc::kDefaultMinVideoBitrateBps,
stream->GetVideoStreams()[0].min_bitrate_bps);
EXPECT_EQ(send_parameters_.max_bandwidth_bps,
stream->GetVideoStreams()[0].max_bitrate_bps);
@ -7070,7 +7073,7 @@ TEST_F(WebRtcVideoChannelTest, DefaultMinAndMaxBitratePropagatedToEncoder) {
// FakeVideoSendStream calls CreateEncoderStreams, test that the vector of
// VideoStreams are created appropriately.
EXPECT_EQ(1u, stream->GetVideoStreams().size());
EXPECT_EQ(cricket::kMinVideoBitrateBps,
EXPECT_EQ(webrtc::kDefaultMinVideoBitrateBps,
stream->GetVideoStreams()[0].min_bitrate_bps);
EXPECT_GT(stream->GetVideoStreams()[0].max_bitrate_bps,
stream->GetVideoStreams()[0].min_bitrate_bps);
@ -7565,7 +7568,7 @@ class WebRtcVideoChannelSimulcastTest : public ::testing::Test {
stream.width = capture_width;
stream.height = capture_height;
stream.max_framerate = kDefaultVideoMaxFramerate;
stream.min_bitrate_bps = cricket::kMinVideoBitrateBps;
stream.min_bitrate_bps = webrtc::kDefaultMinVideoBitrateBps;
stream.target_bitrate_bps = stream.max_bitrate_bps =
GetMaxDefaultBitrateBps(capture_width, capture_height);
stream.max_qp = kDefaultQpMax;

View File

@ -192,6 +192,22 @@ rtc_static_library("stable_target_rate_experiment") {
]
}
rtc_static_library("min_video_bitrate_experiment") {
sources = [
"min_video_bitrate_experiment.cc",
"min_video_bitrate_experiment.h",
]
deps = [
":field_trial_parser",
"../../api/units:data_rate",
"../../api/video:video_frame",
"../../rtc_base:checks",
"../../rtc_base:logging",
"../../system_wrappers:field_trial",
"//third_party/abseil-cpp/absl/types:optional",
]
}
if (rtc_include_tests) {
rtc_source_set("experiments_unittests") {
testonly = true
@ -203,6 +219,7 @@ if (rtc_include_tests) {
"field_trial_parser_unittest.cc",
"field_trial_units_unittest.cc",
"keyframe_interval_settings_unittest.cc",
"min_video_bitrate_experiment_unittest.cc",
"normalize_simulcast_size_experiment_unittest.cc",
"quality_scaler_settings_unittest.cc",
"quality_scaling_experiment_unittest.cc",
@ -216,6 +233,7 @@ if (rtc_include_tests) {
":cpu_speed_experiment",
":field_trial_parser",
":keyframe_interval_settings_experiment",
":min_video_bitrate_experiment",
":normalize_simulcast_size_experiment",
":quality_scaler_settings",
":quality_scaling_experiment",
@ -224,6 +242,8 @@ if (rtc_include_tests) {
":stable_target_rate_experiment",
"..:gunit_helpers",
"../:rtc_base_tests_utils",
"../../api/units:data_rate",
"../../api/video:video_frame",
"../../api/video_codecs:video_codecs_api",
"../../system_wrappers:field_trial",
"../../test:field_trial",

View File

@ -0,0 +1,110 @@
/*
* Copyright 2019 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 "rtc_base/experiments/min_video_bitrate_experiment.h"
#include <string>
#include "rtc_base/checks.h"
#include "rtc_base/experiments/field_trial_parser.h"
#include "rtc_base/logging.h"
#include "system_wrappers/include/field_trial.h"
namespace webrtc {
const int kDefaultMinVideoBitrateBps = 30000;
namespace {
const char kForcedFallbackFieldTrial[] =
"WebRTC-VP8-Forced-Fallback-Encoder-v2";
const char kMinVideoBitrateExperiment[] = "WebRTC-Video-MinVideoBitrate";
absl::optional<int> GetFallbackMinBpsFromFieldTrial(VideoCodecType type) {
if (type != kVideoCodecVP8) {
return absl::nullopt;
}
if (!webrtc::field_trial::IsEnabled(kForcedFallbackFieldTrial)) {
return absl::nullopt;
}
const std::string group =
webrtc::field_trial::FindFullName(kForcedFallbackFieldTrial);
if (group.empty()) {
return absl::nullopt;
}
int min_pixels; // Ignored.
int max_pixels; // Ignored.
int min_bps;
if (sscanf(group.c_str(), "Enabled-%d,%d,%d", &min_pixels, &max_pixels,
&min_bps) != 3) {
return absl::nullopt;
}
if (min_bps <= 0) {
return absl::nullopt;
}
return min_bps;
}
} // namespace
absl::optional<DataRate> GetExperimentalMinVideoBitrate(VideoCodecType type) {
const absl::optional<int> fallback_min_bitrate_bps =
GetFallbackMinBpsFromFieldTrial(type);
if (fallback_min_bitrate_bps) {
return DataRate::bps(*fallback_min_bitrate_bps);
}
if (webrtc::field_trial::IsEnabled(kMinVideoBitrateExperiment)) {
webrtc::FieldTrialFlag enabled("Enabled");
// Backwards-compatibility with an old experiment - a generic minimum which,
// if set, applies to all codecs.
webrtc::FieldTrialOptional<webrtc::DataRate> min_video_bitrate("br");
// New experiment - per-codec minimum bitrate.
webrtc::FieldTrialOptional<webrtc::DataRate> min_bitrate_vp8("vp8_br");
webrtc::FieldTrialOptional<webrtc::DataRate> min_bitrate_vp9("vp9_br");
webrtc::FieldTrialOptional<webrtc::DataRate> min_bitrate_h264("h264_br");
webrtc::ParseFieldTrial(
{&enabled, &min_video_bitrate, &min_bitrate_vp8, &min_bitrate_vp9,
&min_bitrate_h264},
webrtc::field_trial::FindFullName(kMinVideoBitrateExperiment));
if (min_video_bitrate) {
if (min_bitrate_vp8 || min_bitrate_vp9 || min_bitrate_h264) {
// "br" is mutually-exclusive with the other configuration possibilites.
RTC_LOG(LS_WARNING) << "Self-contradictory experiment config.";
}
return *min_video_bitrate;
}
switch (type) {
case kVideoCodecVP8:
return min_bitrate_vp8.GetOptional();
case kVideoCodecVP9:
return min_bitrate_vp9.GetOptional();
case kVideoCodecH264:
return min_bitrate_h264.GetOptional();
case kVideoCodecGeneric:
case kVideoCodecMultiplex:
return absl::nullopt;
}
RTC_NOTREACHED();
}
return absl::nullopt;
}
} // namespace webrtc

View File

@ -0,0 +1,28 @@
/*
* Copyright 2019 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.
*/
#ifndef RTC_BASE_EXPERIMENTS_MIN_VIDEO_BITRATE_EXPERIMENT_H_
#define RTC_BASE_EXPERIMENTS_MIN_VIDEO_BITRATE_EXPERIMENT_H_
#include "absl/types/optional.h"
#include "api/units/data_rate.h"
#include "api/video/video_codec_type.h"
namespace webrtc {
extern const int kDefaultMinVideoBitrateBps;
// Return the experiment-driven minimum video bitrate.
// If no experiment is effective, returns nullopt.
absl::optional<DataRate> GetExperimentalMinVideoBitrate(VideoCodecType type);
} // namespace webrtc
#endif // RTC_BASE_EXPERIMENTS_MIN_VIDEO_BITRATE_EXPERIMENT_H_

View File

@ -0,0 +1,161 @@
/*
* Copyright 2019 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 "rtc_base/experiments/min_video_bitrate_experiment.h"
#include "absl/types/optional.h"
#include "api/units/data_rate.h"
#include "api/video/video_codec_type.h"
#include "test/field_trial.h"
#include "test/gtest.h"
namespace webrtc {
namespace {
TEST(GetExperimentalMinVideoBitrateTest,
NulloptForAllCodecsIfFieldTrialUndefined) {
test::ScopedFieldTrials field_trials("");
EXPECT_EQ(GetExperimentalMinVideoBitrate(VideoCodecType::kVideoCodecGeneric),
absl::nullopt);
EXPECT_EQ(GetExperimentalMinVideoBitrate(VideoCodecType::kVideoCodecVP8),
absl::nullopt);
EXPECT_EQ(GetExperimentalMinVideoBitrate(VideoCodecType::kVideoCodecVP9),
absl::nullopt);
EXPECT_EQ(GetExperimentalMinVideoBitrate(VideoCodecType::kVideoCodecH264),
absl::nullopt);
EXPECT_EQ(
GetExperimentalMinVideoBitrate(VideoCodecType::kVideoCodecMultiplex),
absl::nullopt);
}
TEST(GetExperimentalMinVideoBitrateTest,
NulloptForAllCodecsIfFieldTrialDisabled) {
test::ScopedFieldTrials field_trials(
"WebRTC-Video-MinVideoBitrate/Disabled,br:123kbps/");
EXPECT_EQ(GetExperimentalMinVideoBitrate(VideoCodecType::kVideoCodecGeneric),
absl::nullopt);
EXPECT_EQ(GetExperimentalMinVideoBitrate(VideoCodecType::kVideoCodecVP8),
absl::nullopt);
EXPECT_EQ(GetExperimentalMinVideoBitrate(VideoCodecType::kVideoCodecVP9),
absl::nullopt);
EXPECT_EQ(GetExperimentalMinVideoBitrate(VideoCodecType::kVideoCodecH264),
absl::nullopt);
EXPECT_EQ(
GetExperimentalMinVideoBitrate(VideoCodecType::kVideoCodecMultiplex),
absl::nullopt);
}
TEST(GetExperimentalMinVideoBitrateTest, BrForAllCodecsIfDefined) {
test::ScopedFieldTrials field_trials(
"WebRTC-Video-MinVideoBitrate/Enabled,br:123kbps/");
EXPECT_EQ(GetExperimentalMinVideoBitrate(VideoCodecType::kVideoCodecGeneric),
absl::make_optional(DataRate::kbps(123)));
EXPECT_EQ(GetExperimentalMinVideoBitrate(VideoCodecType::kVideoCodecVP8),
absl::make_optional(DataRate::kbps(123)));
EXPECT_EQ(GetExperimentalMinVideoBitrate(VideoCodecType::kVideoCodecVP9),
absl::make_optional(DataRate::kbps(123)));
EXPECT_EQ(GetExperimentalMinVideoBitrate(VideoCodecType::kVideoCodecH264),
absl::make_optional(DataRate::kbps(123)));
EXPECT_EQ(
GetExperimentalMinVideoBitrate(VideoCodecType::kVideoCodecMultiplex),
absl::make_optional(DataRate::kbps(123)));
}
TEST(GetExperimentalMinVideoBitrateTest, BrTrumpsSpecificCodecConfigs) {
test::ScopedFieldTrials field_trials(
"WebRTC-Video-MinVideoBitrate/"
"Enabled,br:123kbps,vp8_br:100kbps,vp9_br:200kbps,h264_br:300kbps/");
EXPECT_EQ(GetExperimentalMinVideoBitrate(VideoCodecType::kVideoCodecGeneric),
absl::make_optional(DataRate::kbps(123)));
EXPECT_EQ(GetExperimentalMinVideoBitrate(VideoCodecType::kVideoCodecVP8),
absl::make_optional(DataRate::kbps(123)));
EXPECT_EQ(GetExperimentalMinVideoBitrate(VideoCodecType::kVideoCodecVP9),
absl::make_optional(DataRate::kbps(123)));
EXPECT_EQ(GetExperimentalMinVideoBitrate(VideoCodecType::kVideoCodecH264),
absl::make_optional(DataRate::kbps(123)));
EXPECT_EQ(
GetExperimentalMinVideoBitrate(VideoCodecType::kVideoCodecMultiplex),
absl::make_optional(DataRate::kbps(123)));
}
TEST(GetExperimentalMinVideoBitrateTest,
SpecificCodecConfigsIgnoredIfExpDisabled) {
test::ScopedFieldTrials field_trials(
"WebRTC-Video-MinVideoBitrate/"
"Disabled,vp8_br:100kbps,vp9_br:200kbps,h264_br:300kbps/");
EXPECT_EQ(GetExperimentalMinVideoBitrate(VideoCodecType::kVideoCodecGeneric),
absl::nullopt);
EXPECT_EQ(GetExperimentalMinVideoBitrate(VideoCodecType::kVideoCodecVP8),
absl::nullopt);
EXPECT_EQ(GetExperimentalMinVideoBitrate(VideoCodecType::kVideoCodecVP9),
absl::nullopt);
EXPECT_EQ(GetExperimentalMinVideoBitrate(VideoCodecType::kVideoCodecH264),
absl::nullopt);
EXPECT_EQ(
GetExperimentalMinVideoBitrate(VideoCodecType::kVideoCodecMultiplex),
absl::nullopt);
}
TEST(GetExperimentalMinVideoBitrateTest, SpecificCodecConfigsUsedIfExpEnabled) {
test::ScopedFieldTrials field_trials(
"WebRTC-Video-MinVideoBitrate/"
"Enabled,vp8_br:100kbps,vp9_br:200kbps,h264_br:300kbps/");
EXPECT_EQ(GetExperimentalMinVideoBitrate(VideoCodecType::kVideoCodecGeneric),
absl::nullopt);
EXPECT_EQ(GetExperimentalMinVideoBitrate(VideoCodecType::kVideoCodecVP8),
absl::make_optional(DataRate::kbps(100)));
EXPECT_EQ(GetExperimentalMinVideoBitrate(VideoCodecType::kVideoCodecVP9),
absl::make_optional(DataRate::kbps(200)));
EXPECT_EQ(GetExperimentalMinVideoBitrate(VideoCodecType::kVideoCodecH264),
absl::make_optional(DataRate::kbps(300)));
EXPECT_EQ(
GetExperimentalMinVideoBitrate(VideoCodecType::kVideoCodecMultiplex),
absl::nullopt);
}
TEST(GetExperimentalMinVideoBitrateTest,
Vp8BitrateValueTakenFromFallbackIfAvailable) {
test::ScopedFieldTrials field_trials(
"WebRTC-Video-MinVideoBitrate/"
"Enabled,vp8_br:100kbps,vp9_br:200kbps,h264_br:300kbps/"
"WebRTC-VP8-Forced-Fallback-Encoder-v2/"
"Enabled-444444,555555,666666/");
EXPECT_EQ(GetExperimentalMinVideoBitrate(VideoCodecType::kVideoCodecVP8),
absl::make_optional(DataRate::bps(666666)));
}
TEST(GetExperimentalMinVideoBitrateTest,
NonVp8BitrateValuesTakenFromMinVideoBitrate) {
test::ScopedFieldTrials field_trials(
"WebRTC-Video-MinVideoBitrate/"
"Enabled,vp8_br:100kbps,vp9_br:200kbps,h264_br:300kbps/"
"WebRTC-VP8-Forced-Fallback-Encoder-v2/"
"Enabled-444444,555555,666666/");
EXPECT_EQ(GetExperimentalMinVideoBitrate(VideoCodecType::kVideoCodecGeneric),
absl::nullopt);
EXPECT_EQ(GetExperimentalMinVideoBitrate(VideoCodecType::kVideoCodecVP9),
absl::make_optional(DataRate::kbps(200)));
EXPECT_EQ(GetExperimentalMinVideoBitrate(VideoCodecType::kVideoCodecH264),
absl::make_optional(DataRate::kbps(300)));
EXPECT_EQ(
GetExperimentalMinVideoBitrate(VideoCodecType::kVideoCodecMultiplex),
absl::nullopt);
}
} // namespace
} // namespace webrtc

View File

@ -106,6 +106,7 @@ rtc_static_library("video") {
"../rtc_base/experiments:alr_experiment",
"../rtc_base/experiments:field_trial_parser",
"../rtc_base/experiments:keyframe_interval_settings_experiment",
"../rtc_base/experiments:min_video_bitrate_experiment",
"../rtc_base/experiments:quality_scaling_experiment",
"../rtc_base/experiments:rate_control_settings",
"../rtc_base/synchronization:sequence_checker",

View File

@ -28,6 +28,7 @@
#include "rtc_base/checks.h"
#include "rtc_base/experiments/alr_experiment.h"
#include "rtc_base/experiments/field_trial_parser.h"
#include "rtc_base/experiments/min_video_bitrate_experiment.h"
#include "rtc_base/experiments/rate_control_settings.h"
#include "rtc_base/logging.h"
#include "rtc_base/numerics/safe_conversions.h"
@ -55,60 +56,6 @@ bool TransportSeqNumExtensionConfigured(const VideoSendStream::Config& config) {
});
}
const char kForcedFallbackFieldTrial[] =
"WebRTC-VP8-Forced-Fallback-Encoder-v2";
const int kDefaultEncoderMinBitrateBps = 30000;
const char kMinVideoBitrateExperiment[] = "WebRTC-Video-MinVideoBitrate";
struct MinVideoBitrateConfig {
webrtc::FieldTrialParameter<webrtc::DataRate> min_video_bitrate;
MinVideoBitrateConfig()
: min_video_bitrate("br",
webrtc::DataRate::bps(kDefaultEncoderMinBitrateBps)) {
webrtc::ParseFieldTrial(
{&min_video_bitrate},
webrtc::field_trial::FindFullName(kMinVideoBitrateExperiment));
}
};
absl::optional<int> GetFallbackMinBpsFromFieldTrial(VideoCodecType type) {
if (type != kVideoCodecVP8)
return absl::nullopt;
if (!webrtc::field_trial::IsEnabled(kForcedFallbackFieldTrial))
return absl::nullopt;
std::string group =
webrtc::field_trial::FindFullName(kForcedFallbackFieldTrial);
if (group.empty())
return absl::nullopt;
int min_pixels;
int max_pixels;
int min_bps;
if (sscanf(group.c_str(), "Enabled-%d,%d,%d", &min_pixels, &max_pixels,
&min_bps) != 3) {
return absl::nullopt;
}
if (min_bps <= 0)
return absl::nullopt;
return min_bps;
}
int GetEncoderMinBitrateBps(VideoCodecType type) {
if (GetFallbackMinBpsFromFieldTrial(type).has_value()) {
return GetFallbackMinBpsFromFieldTrial(type).value();
}
if (webrtc::field_trial::IsEnabled(kMinVideoBitrateExperiment)) {
return MinVideoBitrateConfig().min_video_bitrate->bps();
}
return kDefaultEncoderMinBitrateBps;
}
// Calculate max padding bitrate for a multi layer codec.
int CalculateMaxPadBitrateBps(const std::vector<VideoStream>& streams,
VideoEncoderConfig::ContentType content_type,
@ -554,10 +501,18 @@ void VideoSendStreamImpl::OnEncoderConfigurationChanged(
RTC_DCHECK_GE(config_->rtp.ssrcs.size(), streams.size());
RTC_DCHECK_RUN_ON(worker_queue_);
const VideoCodecType codec_type =
PayloadStringToCodecType(config_->rtp.payload_name);
const absl::optional<DataRate> experimental_min_bitrate =
GetExperimentalMinVideoBitrate(codec_type);
const int min_bitrate_bps =
experimental_min_bitrate
? rtc::saturated_cast<int>(experimental_min_bitrate->bps())
: kDefaultMinVideoBitrateBps;
encoder_min_bitrate_bps_ =
std::max(streams[0].min_bitrate_bps,
GetEncoderMinBitrateBps(
PayloadStringToCodecType(config_->rtp.payload_name)));
std::max(streams[0].min_bitrate_bps, min_bitrate_bps);
encoder_max_bitrate_bps_ = 0;
double stream_bitrate_priority_sum = 0;
for (const auto& stream : streams) {
@ -575,8 +530,6 @@ void VideoSendStreamImpl::OnEncoderConfigurationChanged(
encoder_max_bitrate_bps_);
// TODO(bugs.webrtc.org/10266): Query the VideoBitrateAllocator instead.
const VideoCodecType codec_type =
PayloadStringToCodecType(config_->rtp.payload_name);
if (codec_type == kVideoCodecVP9) {
max_padding_bitrate_ = has_alr_probing_ ? streams[0].min_bitrate_bps
: streams[0].target_bitrate_bps;