Removed WebRTC-NetworkCondition-EncoderSwitch field trial.
Bug: webrtc:12474 Change-Id: I50b3219c0dc9d8a63ff097ee6a71c04fe903aea9 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/211663 Reviewed-by: Åsa Persson <asapersson@webrtc.org> Commit-Queue: Philip Eliasson <philipel@webrtc.org> Cr-Commit-Position: refs/heads/master@{#33449}
This commit is contained in:
parent
7c7885c016
commit
fd87944042
@ -633,10 +633,8 @@ VideoStreamEncoder::VideoStreamEncoder(
|
||||
next_frame_types_(1, VideoFrameType::kVideoFrameDelta),
|
||||
frame_encode_metadata_writer_(this),
|
||||
experiment_groups_(GetExperimentGroups()),
|
||||
encoder_switch_experiment_(ParseEncoderSwitchFieldTrial()),
|
||||
automatic_animation_detection_experiment_(
|
||||
ParseAutomatincAnimationDetectionFieldTrial()),
|
||||
encoder_switch_requested_(false),
|
||||
input_state_provider_(encoder_stats_observer),
|
||||
video_stream_adapter_(
|
||||
std::make_unique<VideoStreamAdapter>(&input_state_provider_,
|
||||
@ -847,19 +845,6 @@ void VideoStreamEncoder::ReconfigureEncoder() {
|
||||
// Running on the encoder queue.
|
||||
RTC_DCHECK(pending_encoder_reconfiguration_);
|
||||
|
||||
if (!encoder_selector_ &&
|
||||
encoder_switch_experiment_.IsPixelCountBelowThreshold(
|
||||
last_frame_info_->width * last_frame_info_->height) &&
|
||||
!encoder_switch_requested_ && settings_.encoder_switch_request_callback) {
|
||||
EncoderSwitchRequestCallback::Config conf;
|
||||
conf.codec_name = encoder_switch_experiment_.to_codec;
|
||||
conf.param = encoder_switch_experiment_.to_param;
|
||||
conf.value = encoder_switch_experiment_.to_value;
|
||||
QueueRequestEncoderSwitch(conf);
|
||||
|
||||
encoder_switch_requested_ = true;
|
||||
}
|
||||
|
||||
bool encoder_reset_required = false;
|
||||
if (pending_encoder_creation_) {
|
||||
// Destroy existing encoder instance before creating a new one. Otherwise
|
||||
@ -1101,8 +1086,6 @@ void VideoStreamEncoder::ReconfigureEncoder() {
|
||||
}
|
||||
send_codec_ = codec;
|
||||
|
||||
encoder_switch_experiment_.SetCodec(send_codec_.codecType);
|
||||
|
||||
// Keep the same encoder, as long as the video_format is unchanged.
|
||||
// Encoder creation block is split in two since EncoderInfo needed to start
|
||||
// CPU adaptation with the correct settings should be polled after
|
||||
@ -2045,22 +2028,10 @@ void VideoStreamEncoder::OnBitrateUpdated(DataRate target_bitrate,
|
||||
const bool video_is_suspended = target_bitrate == DataRate::Zero();
|
||||
const bool video_suspension_changed = video_is_suspended != EncoderPaused();
|
||||
|
||||
if (!video_is_suspended && settings_.encoder_switch_request_callback) {
|
||||
if (encoder_selector_) {
|
||||
if (auto encoder =
|
||||
encoder_selector_->OnAvailableBitrate(link_allocation)) {
|
||||
QueueRequestEncoderSwitch(*encoder);
|
||||
}
|
||||
} else if (encoder_switch_experiment_.IsBitrateBelowThreshold(
|
||||
target_bitrate) &&
|
||||
!encoder_switch_requested_) {
|
||||
EncoderSwitchRequestCallback::Config conf;
|
||||
conf.codec_name = encoder_switch_experiment_.to_codec;
|
||||
conf.param = encoder_switch_experiment_.to_param;
|
||||
conf.value = encoder_switch_experiment_.to_value;
|
||||
QueueRequestEncoderSwitch(conf);
|
||||
|
||||
encoder_switch_requested_ = true;
|
||||
if (!video_is_suspended && settings_.encoder_switch_request_callback &&
|
||||
encoder_selector_) {
|
||||
if (auto encoder = encoder_selector_->OnAvailableBitrate(link_allocation)) {
|
||||
QueueRequestEncoderSwitch(*encoder);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2229,113 +2200,6 @@ void VideoStreamEncoder::ReleaseEncoder() {
|
||||
TRACE_EVENT0("webrtc", "VCMGenericEncoder::Release");
|
||||
}
|
||||
|
||||
bool VideoStreamEncoder::EncoderSwitchExperiment::IsBitrateBelowThreshold(
|
||||
const DataRate& target_bitrate) {
|
||||
DataRate rate = DataRate::KilobitsPerSec(
|
||||
bitrate_filter.Apply(1.0, target_bitrate.kbps()));
|
||||
return current_thresholds.bitrate && rate < *current_thresholds.bitrate;
|
||||
}
|
||||
|
||||
bool VideoStreamEncoder::EncoderSwitchExperiment::IsPixelCountBelowThreshold(
|
||||
int pixel_count) const {
|
||||
return current_thresholds.pixel_count &&
|
||||
pixel_count < *current_thresholds.pixel_count;
|
||||
}
|
||||
|
||||
void VideoStreamEncoder::EncoderSwitchExperiment::SetCodec(
|
||||
VideoCodecType codec) {
|
||||
auto it = codec_thresholds.find(codec);
|
||||
if (it == codec_thresholds.end()) {
|
||||
current_thresholds = {};
|
||||
} else {
|
||||
current_thresholds = it->second;
|
||||
}
|
||||
}
|
||||
|
||||
VideoStreamEncoder::EncoderSwitchExperiment
|
||||
VideoStreamEncoder::ParseEncoderSwitchFieldTrial() const {
|
||||
EncoderSwitchExperiment result;
|
||||
|
||||
// Each "codec threshold" have the format
|
||||
// "<codec name>;<bitrate kbps>;<pixel count>", and are separated by the "|"
|
||||
// character.
|
||||
webrtc::FieldTrialOptional<std::string> codec_thresholds_string{
|
||||
"codec_thresholds"};
|
||||
webrtc::FieldTrialOptional<std::string> to_codec{"to_codec"};
|
||||
webrtc::FieldTrialOptional<std::string> to_param{"to_param"};
|
||||
webrtc::FieldTrialOptional<std::string> to_value{"to_value"};
|
||||
webrtc::FieldTrialOptional<double> window{"window"};
|
||||
|
||||
webrtc::ParseFieldTrial(
|
||||
{&codec_thresholds_string, &to_codec, &to_param, &to_value, &window},
|
||||
webrtc::field_trial::FindFullName(
|
||||
"WebRTC-NetworkCondition-EncoderSwitch"));
|
||||
|
||||
if (!codec_thresholds_string || !to_codec || !window) {
|
||||
return {};
|
||||
}
|
||||
|
||||
result.bitrate_filter.Reset(1.0 - 1.0 / *window);
|
||||
result.to_codec = *to_codec;
|
||||
result.to_param = to_param.GetOptional();
|
||||
result.to_value = to_value.GetOptional();
|
||||
|
||||
std::vector<std::string> codecs_thresholds;
|
||||
if (rtc::split(*codec_thresholds_string, '|', &codecs_thresholds) == 0) {
|
||||
return {};
|
||||
}
|
||||
|
||||
for (const std::string& codec_threshold : codecs_thresholds) {
|
||||
std::vector<std::string> thresholds_split;
|
||||
if (rtc::split(codec_threshold, ';', &thresholds_split) != 3) {
|
||||
return {};
|
||||
}
|
||||
|
||||
VideoCodecType codec = PayloadStringToCodecType(thresholds_split[0]);
|
||||
int bitrate_kbps;
|
||||
rtc::FromString(thresholds_split[1], &bitrate_kbps);
|
||||
int pixel_count;
|
||||
rtc::FromString(thresholds_split[2], &pixel_count);
|
||||
|
||||
if (bitrate_kbps > 0) {
|
||||
result.codec_thresholds[codec].bitrate =
|
||||
DataRate::KilobitsPerSec(bitrate_kbps);
|
||||
}
|
||||
|
||||
if (pixel_count > 0) {
|
||||
result.codec_thresholds[codec].pixel_count = pixel_count;
|
||||
}
|
||||
|
||||
if (!result.codec_thresholds[codec].bitrate &&
|
||||
!result.codec_thresholds[codec].pixel_count) {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
rtc::StringBuilder ss;
|
||||
ss << "Successfully parsed WebRTC-NetworkCondition-EncoderSwitch field "
|
||||
"trial."
|
||||
" to_codec:"
|
||||
<< result.to_codec << " to_param:" << result.to_param.value_or("<none>")
|
||||
<< " to_value:" << result.to_value.value_or("<none>")
|
||||
<< " codec_thresholds:";
|
||||
|
||||
for (auto kv : result.codec_thresholds) {
|
||||
std::string codec_name = CodecTypeToPayloadString(kv.first);
|
||||
std::string bitrate = kv.second.bitrate
|
||||
? std::to_string(kv.second.bitrate->kbps())
|
||||
: "<none>";
|
||||
std::string pixels = kv.second.pixel_count
|
||||
? std::to_string(*kv.second.pixel_count)
|
||||
: "<none>";
|
||||
ss << " (" << codec_name << ":" << bitrate << ":" << pixels << ")";
|
||||
}
|
||||
|
||||
RTC_LOG(LS_INFO) << ss.str();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
VideoStreamEncoder::AutomaticAnimationDetectionExperiment
|
||||
VideoStreamEncoder::ParseAutomatincAnimationDetectionFieldTrial() const {
|
||||
AutomaticAnimationDetectionExperiment result;
|
||||
|
||||
@ -352,38 +352,6 @@ class VideoStreamEncoder : public VideoStreamEncoderInterface,
|
||||
// experiment group numbers incremented by 1.
|
||||
const std::array<uint8_t, 2> experiment_groups_;
|
||||
|
||||
struct EncoderSwitchExperiment {
|
||||
struct Thresholds {
|
||||
absl::optional<DataRate> bitrate;
|
||||
absl::optional<int> pixel_count;
|
||||
};
|
||||
|
||||
// Codec --> switching thresholds
|
||||
std::map<VideoCodecType, Thresholds> codec_thresholds;
|
||||
|
||||
// To smooth out the target bitrate so that we don't trigger a switch
|
||||
// too easily.
|
||||
rtc::ExpFilter bitrate_filter{1.0};
|
||||
|
||||
// Codec/implementation to switch to
|
||||
std::string to_codec;
|
||||
absl::optional<std::string> to_param;
|
||||
absl::optional<std::string> to_value;
|
||||
|
||||
// Thresholds for the currently used codecs.
|
||||
Thresholds current_thresholds;
|
||||
|
||||
// Updates the |bitrate_filter|, so not const.
|
||||
bool IsBitrateBelowThreshold(const DataRate& target_bitrate);
|
||||
bool IsPixelCountBelowThreshold(int pixel_count) const;
|
||||
void SetCodec(VideoCodecType codec);
|
||||
};
|
||||
|
||||
EncoderSwitchExperiment ParseEncoderSwitchFieldTrial() const;
|
||||
|
||||
EncoderSwitchExperiment encoder_switch_experiment_
|
||||
RTC_GUARDED_BY(&encoder_queue_);
|
||||
|
||||
struct AutomaticAnimationDetectionExperiment {
|
||||
bool enabled = false;
|
||||
int min_duration_ms = 2000;
|
||||
@ -404,10 +372,6 @@ class VideoStreamEncoder : public VideoStreamEncoderInterface,
|
||||
AutomaticAnimationDetectionExperiment
|
||||
automatic_animation_detection_experiment_ RTC_GUARDED_BY(&encoder_queue_);
|
||||
|
||||
// An encoder switch is only requested once, this variable is used to keep
|
||||
// track of whether a request has been made or not.
|
||||
bool encoder_switch_requested_ RTC_GUARDED_BY(&encoder_queue_);
|
||||
|
||||
// Provies video stream input states: current resolution and frame rate.
|
||||
VideoStreamInputStateProvider input_state_provider_;
|
||||
|
||||
|
||||
@ -7340,125 +7340,6 @@ struct MockEncoderSwitchRequestCallback : public EncoderSwitchRequestCallback {
|
||||
(override));
|
||||
};
|
||||
|
||||
TEST_F(VideoStreamEncoderTest, BitrateEncoderSwitch) {
|
||||
constexpr int kDontCare = 100;
|
||||
|
||||
StrictMock<MockEncoderSwitchRequestCallback> switch_callback;
|
||||
video_send_config_.encoder_settings.encoder_switch_request_callback =
|
||||
&switch_callback;
|
||||
VideoEncoderConfig encoder_config = video_encoder_config_.Copy();
|
||||
encoder_config.codec_type = kVideoCodecVP8;
|
||||
webrtc::test::ScopedFieldTrials field_trial(
|
||||
"WebRTC-NetworkCondition-EncoderSwitch/"
|
||||
"codec_thresholds:VP8;100;-1|H264;-1;30000,"
|
||||
"to_codec:AV1,to_param:ping,to_value:pong,window:2.0/");
|
||||
|
||||
// Reset encoder for new configuration to take effect.
|
||||
ConfigureEncoder(std::move(encoder_config));
|
||||
|
||||
// Send one frame to trigger ReconfigureEncoder.
|
||||
video_source_.IncomingCapturedFrame(
|
||||
CreateFrame(kDontCare, kDontCare, kDontCare));
|
||||
|
||||
using Config = EncoderSwitchRequestCallback::Config;
|
||||
EXPECT_CALL(switch_callback, RequestEncoderSwitch(Matcher<const Config&>(
|
||||
AllOf(Field(&Config::codec_name, "AV1"),
|
||||
Field(&Config::param, "ping"),
|
||||
Field(&Config::value, "pong")))));
|
||||
|
||||
video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
|
||||
/*target_bitrate=*/DataRate::KilobitsPerSec(50),
|
||||
/*stable_target_bitrate=*/DataRate::KilobitsPerSec(kDontCare),
|
||||
/*link_allocation=*/DataRate::KilobitsPerSec(kDontCare),
|
||||
/*fraction_lost=*/0,
|
||||
/*rtt_ms=*/0,
|
||||
/*cwnd_reduce_ratio=*/0);
|
||||
AdvanceTime(TimeDelta::Millis(0));
|
||||
|
||||
video_stream_encoder_->Stop();
|
||||
}
|
||||
|
||||
TEST_F(VideoStreamEncoderTest, VideoSuspendedNoEncoderSwitch) {
|
||||
constexpr int kDontCare = 100;
|
||||
|
||||
StrictMock<MockEncoderSwitchRequestCallback> switch_callback;
|
||||
video_send_config_.encoder_settings.encoder_switch_request_callback =
|
||||
&switch_callback;
|
||||
VideoEncoderConfig encoder_config = video_encoder_config_.Copy();
|
||||
encoder_config.codec_type = kVideoCodecVP8;
|
||||
webrtc::test::ScopedFieldTrials field_trial(
|
||||
"WebRTC-NetworkCondition-EncoderSwitch/"
|
||||
"codec_thresholds:VP8;100;-1|H264;-1;30000,"
|
||||
"to_codec:AV1,to_param:ping,to_value:pong,window:2.0/");
|
||||
|
||||
// Reset encoder for new configuration to take effect.
|
||||
ConfigureEncoder(std::move(encoder_config));
|
||||
|
||||
// Send one frame to trigger ReconfigureEncoder.
|
||||
video_source_.IncomingCapturedFrame(
|
||||
CreateFrame(kDontCare, kDontCare, kDontCare));
|
||||
|
||||
using Config = EncoderSwitchRequestCallback::Config;
|
||||
EXPECT_CALL(switch_callback, RequestEncoderSwitch(Matcher<const Config&>(_)))
|
||||
.Times(0);
|
||||
|
||||
video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
|
||||
/*target_bitrate=*/DataRate::KilobitsPerSec(0),
|
||||
/*stable_target_bitrate=*/DataRate::KilobitsPerSec(0),
|
||||
/*link_allocation=*/DataRate::KilobitsPerSec(kDontCare),
|
||||
/*fraction_lost=*/0,
|
||||
/*rtt_ms=*/0,
|
||||
/*cwnd_reduce_ratio=*/0);
|
||||
|
||||
video_stream_encoder_->Stop();
|
||||
}
|
||||
|
||||
TEST_F(VideoStreamEncoderTest, ResolutionEncoderSwitch) {
|
||||
constexpr int kSufficientBitrateToNotDrop = 1000;
|
||||
constexpr int kHighRes = 500;
|
||||
constexpr int kLowRes = 100;
|
||||
|
||||
StrictMock<MockEncoderSwitchRequestCallback> switch_callback;
|
||||
video_send_config_.encoder_settings.encoder_switch_request_callback =
|
||||
&switch_callback;
|
||||
webrtc::test::ScopedFieldTrials field_trial(
|
||||
"WebRTC-NetworkCondition-EncoderSwitch/"
|
||||
"codec_thresholds:VP8;120;-1|H264;-1;30000,"
|
||||
"to_codec:AV1,to_param:ping,to_value:pong,window:2.0/");
|
||||
VideoEncoderConfig encoder_config = video_encoder_config_.Copy();
|
||||
encoder_config.codec_type = kVideoCodecH264;
|
||||
|
||||
// Reset encoder for new configuration to take effect.
|
||||
ConfigureEncoder(std::move(encoder_config));
|
||||
|
||||
// The VideoStreamEncoder needs some bitrate before it can start encoding,
|
||||
// setting some bitrate so that subsequent calls to WaitForEncodedFrame does
|
||||
// not fail.
|
||||
video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
|
||||
/*target_bitrate=*/DataRate::KilobitsPerSec(kSufficientBitrateToNotDrop),
|
||||
/*stable_target_bitrate=*/
|
||||
DataRate::KilobitsPerSec(kSufficientBitrateToNotDrop),
|
||||
/*link_allocation=*/DataRate::KilobitsPerSec(kSufficientBitrateToNotDrop),
|
||||
/*fraction_lost=*/0,
|
||||
/*rtt_ms=*/0,
|
||||
/*cwnd_reduce_ratio=*/0);
|
||||
|
||||
// Send one frame to trigger ReconfigureEncoder.
|
||||
video_source_.IncomingCapturedFrame(CreateFrame(1, kHighRes, kHighRes));
|
||||
WaitForEncodedFrame(1);
|
||||
|
||||
using Config = EncoderSwitchRequestCallback::Config;
|
||||
EXPECT_CALL(switch_callback, RequestEncoderSwitch(Matcher<const Config&>(
|
||||
AllOf(Field(&Config::codec_name, "AV1"),
|
||||
Field(&Config::param, "ping"),
|
||||
Field(&Config::value, "pong")))));
|
||||
|
||||
video_source_.IncomingCapturedFrame(CreateFrame(2, kLowRes, kLowRes));
|
||||
WaitForEncodedFrame(2);
|
||||
|
||||
video_stream_encoder_->Stop();
|
||||
}
|
||||
|
||||
TEST_F(VideoStreamEncoderTest, EncoderSelectorCurrentEncoderIsSignaled) {
|
||||
constexpr int kDontCare = 100;
|
||||
StrictMock<MockEncoderSelector> encoder_selector;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user