From fd8794404280da0e5831caff5f46b6b65c7467d4 Mon Sep 17 00:00:00 2001 From: philipel Date: Fri, 12 Mar 2021 15:00:51 +0100 Subject: [PATCH] Removed WebRTC-NetworkCondition-EncoderSwitch field trial. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bug: webrtc:12474 Change-Id: I50b3219c0dc9d8a63ff097ee6a71c04fe903aea9 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/211663 Reviewed-by: Åsa Persson Commit-Queue: Philip Eliasson Cr-Commit-Position: refs/heads/master@{#33449} --- video/video_stream_encoder.cc | 144 +------------------------ video/video_stream_encoder.h | 36 ------- video/video_stream_encoder_unittest.cc | 119 -------------------- 3 files changed, 4 insertions(+), 295 deletions(-) diff --git a/video/video_stream_encoder.cc b/video/video_stream_encoder.cc index cfef876f04..31a06ca800 100644 --- a/video/video_stream_encoder.cc +++ b/video/video_stream_encoder.cc @@ -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(&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 - // ";;", and are separated by the "|" - // character. - webrtc::FieldTrialOptional codec_thresholds_string{ - "codec_thresholds"}; - webrtc::FieldTrialOptional to_codec{"to_codec"}; - webrtc::FieldTrialOptional to_param{"to_param"}; - webrtc::FieldTrialOptional to_value{"to_value"}; - webrtc::FieldTrialOptional 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 codecs_thresholds; - if (rtc::split(*codec_thresholds_string, '|', &codecs_thresholds) == 0) { - return {}; - } - - for (const std::string& codec_threshold : codecs_thresholds) { - std::vector 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("") - << " to_value:" << result.to_value.value_or("") - << " 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()) - : ""; - std::string pixels = kv.second.pixel_count - ? std::to_string(*kv.second.pixel_count) - : ""; - ss << " (" << codec_name << ":" << bitrate << ":" << pixels << ")"; - } - - RTC_LOG(LS_INFO) << ss.str(); - - return result; -} - VideoStreamEncoder::AutomaticAnimationDetectionExperiment VideoStreamEncoder::ParseAutomatincAnimationDetectionFieldTrial() const { AutomaticAnimationDetectionExperiment result; diff --git a/video/video_stream_encoder.h b/video/video_stream_encoder.h index b1c3bd8718..129311d71a 100644 --- a/video/video_stream_encoder.h +++ b/video/video_stream_encoder.h @@ -352,38 +352,6 @@ class VideoStreamEncoder : public VideoStreamEncoderInterface, // experiment group numbers incremented by 1. const std::array experiment_groups_; - struct EncoderSwitchExperiment { - struct Thresholds { - absl::optional bitrate; - absl::optional pixel_count; - }; - - // Codec --> switching thresholds - std::map 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 to_param; - absl::optional 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_; diff --git a/video/video_stream_encoder_unittest.cc b/video/video_stream_encoder_unittest.cc index 72ff98407c..7ace082665 100644 --- a/video/video_stream_encoder_unittest.cc +++ b/video/video_stream_encoder_unittest.cc @@ -7340,125 +7340,6 @@ struct MockEncoderSwitchRequestCallback : public EncoderSwitchRequestCallback { (override)); }; -TEST_F(VideoStreamEncoderTest, BitrateEncoderSwitch) { - constexpr int kDontCare = 100; - - StrictMock 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( - 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 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(_))) - .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 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( - 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 encoder_selector;