Replace EncoderSwitchRequestCallback with absl::AnyInvocable This refactoring replaces the EncoderSwitchRequestCallback interface with absl::AnyInvocable in VideoStreamEncoderSettings. To ensure the callback survives stream recreation, the callback binding has been moved to RecreateWebRtcStream, relying on a new `send_channel_` back-pointer within WebRtcVideoSendStream. Bug: b/478050997 Change-Id: I1f587d563553c4f2f3d8fd02c4d9ed4473829dc4 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/454480 Commit-Queue: Tomas Gunnarsson <tommi@webrtc.org> Reviewed-by: Harald Alvestrand <hta@webrtc.org> Cr-Commit-Position: refs/heads/main@{#47087}
diff --git a/api/video/BUILD.gn b/api/video/BUILD.gn index 14cf360..d618604 100644 --- a/api/video/BUILD.gn +++ b/api/video/BUILD.gn
@@ -349,6 +349,7 @@ "../adaptation:resource_adaptation_api", "../units:data_rate", "../video_codecs:video_codecs_api", + "//third_party/abseil-cpp/absl/functional:any_invocable", ] }
diff --git a/api/video/video_stream_encoder_settings.h b/api/video/video_stream_encoder_settings.h index d02bcbe..5936dc7 100644 --- a/api/video/video_stream_encoder_settings.h +++ b/api/video/video_stream_encoder_settings.h
@@ -11,6 +11,9 @@ #ifndef API_VIDEO_VIDEO_STREAM_ENCODER_SETTINGS_H_ #define API_VIDEO_VIDEO_STREAM_ENCODER_SETTINGS_H_ +#include <optional> + +#include "absl/functional/any_invocable.h" #include "api/video/video_bitrate_allocator_factory.h" #include "api/video_codecs/sdp_video_format.h" #include "api/video_codecs/video_encoder.h" @@ -18,18 +21,13 @@ namespace webrtc { -class EncoderSwitchRequestCallback { - public: - virtual ~EncoderSwitchRequestCallback() {} - - // Requests switch to next negotiated encoder. - virtual void RequestEncoderFallback() = 0; - - // Requests switch to a specific encoder. If the encoder is not available and - // `allow_default_fallback` is `true` the default fallback is invoked. - virtual void RequestEncoderSwitch(const SdpVideoFormat& format, - bool allow_default_fallback) = 0; -}; +// Requests switch to a specific encoder. If `format` is nullopt, a fallback +// to the next negotiated encoder is requested. If the requested encoder is +// not available and `allow_default_fallback` is `true`, the default fallback +// is invoked. +using EncoderSwitchRequestCallback = + absl::AnyInvocable<void(std::optional<SdpVideoFormat> format, + bool allow_default_fallback)>; struct VideoStreamEncoderSettings { explicit VideoStreamEncoderSettings( @@ -43,9 +41,6 @@ // Ownership stays with WebrtcVideoEngine (delegated from PeerConnection). VideoEncoderFactory* encoder_factory = nullptr; - // Requests the WebRtcVideoChannel to perform a codec switch. - EncoderSwitchRequestCallback* encoder_switch_request_callback = nullptr; - // Ownership stays with WebrtcVideoEngine (delegated from PeerConnection). VideoBitrateAllocatorFactory* bitrate_allocator_factory = nullptr;
diff --git a/call/BUILD.gn b/call/BUILD.gn index dd7cbac..232c66a 100644 --- a/call/BUILD.gn +++ b/call/BUILD.gn
@@ -68,6 +68,7 @@ "../api/transport:network_control", "../api/units:time_delta", "../api/units:timestamp", + "../api/video:video_stream_encoder", "../modules/async_audio_processing", "../modules/congestion_controller/rtp:congestion_controller_feedback_stats", "../modules/rtp_rtcp", @@ -323,6 +324,7 @@ "../api/units:data_size", "../api/units:time_delta", "../api/units:timestamp", + "../api/video:video_stream_encoder", "../audio", "../logging:rtc_event_audio", "../logging:rtc_event_rtp_rtcp",
diff --git a/call/call.cc b/call/call.cc index 052c8a7..40a35c9 100644 --- a/call/call.cc +++ b/call/call.cc
@@ -43,6 +43,7 @@ #include "api/units/data_size.h" #include "api/units/time_delta.h" #include "api/units/timestamp.h" +#include "api/video/video_stream_encoder_settings.h" #include "audio/audio_receive_stream.h" #include "audio/audio_send_stream.h" #include "audio/audio_state.h" @@ -225,10 +226,13 @@ webrtc::VideoSendStream* CreateVideoSendStream( webrtc::VideoSendStream::Config config, - VideoEncoderConfig encoder_config) override; + VideoEncoderConfig encoder_config, + EncoderSwitchRequestCallback encoder_switch_request_callback = + nullptr) override; webrtc::VideoSendStream* CreateVideoSendStream( webrtc::VideoSendStream::Config config, VideoEncoderConfig encoder_config, + EncoderSwitchRequestCallback encoder_switch_request_callback, std::unique_ptr<FecController> fec_controller) override; void DestroyVideoSendStream(webrtc::VideoSendStream* send_stream) override; @@ -499,6 +503,7 @@ VideoSendStream* Call::CreateVideoSendStream( VideoSendStream::Config /* config */, VideoEncoderConfig /* encoder_config */, + EncoderSwitchRequestCallback /* encoder_switch_request_callback */, std::unique_ptr<FecController> /* fec_controller */) { return nullptr; } @@ -879,6 +884,7 @@ webrtc::VideoSendStream* Call::CreateVideoSendStream( webrtc::VideoSendStream::Config config, VideoEncoderConfig encoder_config, + EncoderSwitchRequestCallback encoder_switch_request_callback, std::unique_ptr<FecController> fec_controller) { TRACE_EVENT0("webrtc", "Call::CreateVideoSendStream"); RTC_DCHECK_RUN_ON(worker_thread_); @@ -902,7 +908,8 @@ transport_send_.get(), config_.encode_metronome, bitrate_allocator_.get(), video_send_delay_stats_.get(), std::move(config), std::move(encoder_config), suspended_video_send_ssrcs_, - suspended_video_payload_states_, std::move(fec_controller)); + suspended_video_payload_states_, std::move(fec_controller), + std::move(encoder_switch_request_callback)); for (uint32_t ssrc : ssrcs) { RTC_DCHECK(video_send_ssrcs_.find(ssrc) == video_send_ssrcs_.end()); @@ -923,7 +930,8 @@ webrtc::VideoSendStream* Call::CreateVideoSendStream( webrtc::VideoSendStream::Config config, - VideoEncoderConfig encoder_config) { + VideoEncoderConfig encoder_config, + EncoderSwitchRequestCallback encoder_switch_request_callback) { RTC_DCHECK_RUN_ON(worker_thread_); if (config_.fec_controller_factory) { RTC_LOG(LS_INFO) << "External FEC Controller will be used."; @@ -933,6 +941,7 @@ ? config_.fec_controller_factory->CreateFecController(env_) : std::make_unique<FecControllerDefault>(env_); return CreateVideoSendStream(std::move(config), std::move(encoder_config), + std::move(encoder_switch_request_callback), std::move(fec_controller)); }
diff --git a/call/call.h b/call/call.h index 8f58370..636c0f9 100644 --- a/call/call.h +++ b/call/call.h
@@ -24,6 +24,7 @@ #include "api/scoped_refptr.h" #include "api/task_queue/task_queue_base.h" #include "api/transport/bitrate_settings.h" +#include "api/video/video_stream_encoder_settings.h" #include "call/audio_receive_stream.h" #include "call/audio_send_stream.h" #include "call/call_config.h" @@ -80,11 +81,14 @@ virtual VideoSendStream* CreateVideoSendStream( VideoSendStream::Config config, - VideoEncoderConfig encoder_config) = 0; + VideoEncoderConfig encoder_config, + EncoderSwitchRequestCallback encoder_switch_request_callback = + nullptr) = 0; virtual VideoSendStream* CreateVideoSendStream( VideoSendStream::Config config, VideoEncoderConfig encoder_config, - std::unique_ptr<FecController> fec_controller); + EncoderSwitchRequestCallback encoder_switch_request_callback, + std::unique_ptr<FecController> fec_controller) = 0; virtual void DestroyVideoSendStream(VideoSendStream* send_stream) = 0; virtual VideoReceiveStreamInterface* CreateVideoReceiveStream(
diff --git a/media/BUILD.gn b/media/BUILD.gn index 47e6d7b..fbe70c9 100644 --- a/media/BUILD.gn +++ b/media/BUILD.gn
@@ -857,6 +857,7 @@ "../api/video:video_frame", "../api/video:video_frame_type", "../api/video:video_rtp_headers", + "../api/video:video_stream_encoder", "../api/video_codecs:scalability_mode", "../api/video_codecs:video_codecs_api", "../call:call_interfaces",
diff --git a/media/engine/fake_webrtc_call.cc b/media/engine/fake_webrtc_call.cc index cc537a4..20ed986 100644 --- a/media/engine/fake_webrtc_call.cc +++ b/media/engine/fake_webrtc_call.cc
@@ -12,6 +12,7 @@ #include <cstdint> #include <map> +#include <memory> #include <string> #include <utility> #include <vector> @@ -24,6 +25,7 @@ #include "api/call/audio_sink.h" #include "api/crypto/frame_decryptor_interface.h" #include "api/environment/environment.h" +#include "api/fec_controller.h" #include "api/frame_transformer_interface.h" #include "api/make_ref_counted.h" #include "api/media_types.h" @@ -35,6 +37,7 @@ #include "api/task_queue/task_queue_base.h" #include "api/units/timestamp.h" #include "api/video/video_source_interface.h" +#include "api/video/video_stream_encoder_settings.h" #include "api/video_codecs/video_codec.h" #include "api/video_codecs/video_encoder.h" #include "call/audio_receive_stream.h" @@ -586,7 +589,20 @@ VideoSendStream* FakeCall::CreateVideoSendStream( VideoSendStream::Config config, - VideoEncoderConfig encoder_config) { + VideoEncoderConfig encoder_config, + EncoderSwitchRequestCallback encoder_switch_request_callback) { + FakeVideoSendStream* fake_stream = new FakeVideoSendStream( + env_, std::move(config), std::move(encoder_config)); + video_send_streams_.push_back(fake_stream); + ++num_created_send_streams_; + return fake_stream; +} + +VideoSendStream* FakeCall::CreateVideoSendStream( + VideoSendStream::Config config, + VideoEncoderConfig encoder_config, + EncoderSwitchRequestCallback encoder_switch_request_callback, + std::unique_ptr<FecController> fec_controller) { FakeVideoSendStream* fake_stream = new FakeVideoSendStream( env_, std::move(config), std::move(encoder_config)); video_send_streams_.push_back(fake_stream);
diff --git a/media/engine/fake_webrtc_call.h b/media/engine/fake_webrtc_call.h index ac12bd5..e4dff9a 100644 --- a/media/engine/fake_webrtc_call.h +++ b/media/engine/fake_webrtc_call.h
@@ -37,6 +37,7 @@ #include "api/audio_codecs/audio_format.h" #include "api/crypto/frame_decryptor_interface.h" #include "api/environment/environment.h" +#include "api/fec_controller.h" #include "api/frame_transformer_interface.h" #include "api/media_types.h" #include "api/rtp_headers.h" @@ -51,6 +52,7 @@ #include "api/video/video_frame.h" #include "api/video/video_sink_interface.h" #include "api/video/video_source_interface.h" +#include "api/video/video_stream_encoder_settings.h" #include "api/video_codecs/video_codec.h" #include "call/audio_receive_stream.h" #include "call/audio_send_stream.h" @@ -441,7 +443,15 @@ VideoSendStream* CreateVideoSendStream( VideoSendStream::Config config, - VideoEncoderConfig encoder_config) override; + VideoEncoderConfig encoder_config, + EncoderSwitchRequestCallback encoder_switch_request_callback = + nullptr) override; + + VideoSendStream* CreateVideoSendStream( + VideoSendStream::Config config, + VideoEncoderConfig encoder_config, + EncoderSwitchRequestCallback encoder_switch_request_callback, + std::unique_ptr<FecController> fec_controller) override; void DestroyVideoSendStream(VideoSendStream* send_stream) override; VideoReceiveStreamInterface* CreateVideoReceiveStream(
diff --git a/media/engine/webrtc_video_engine.cc b/media/engine/webrtc_video_engine.cc index f1cd60d..8bfffdc 100644 --- a/media/engine/webrtc_video_engine.cc +++ b/media/engine/webrtc_video_engine.cc
@@ -1239,68 +1239,63 @@ return ApplyChangedParams(changed_params); } -void WebRtcVideoSendChannel::RequestEncoderFallback() { - if (!worker_thread_->IsCurrent()) { - worker_thread_->PostTask( - SafeTask(task_safety_.flag(), [this] { RequestEncoderFallback(); })); - return; - } - - RTC_DCHECK_RUN_ON(&thread_checker_); - if (negotiated_codecs_.size() <= 1) { - RTC_LOG(LS_WARNING) << "Encoder failed but no fallback codec is available"; - return; - } - - ChangedSenderParameters params; - params.negotiated_codecs = negotiated_codecs_; - params.negotiated_codecs->erase(params.negotiated_codecs->begin()); - params.send_codec = params.negotiated_codecs->front(); - if (ApplyChangedParams(params) && parameters_changed_callback_) { - parameters_changed_callback_(); - } -} - -void WebRtcVideoSendChannel::RequestEncoderSwitch(const SdpVideoFormat& format, - bool allow_default_fallback) { +void WebRtcVideoSendChannel::RequestEncoderSwitch( + std::optional<SdpVideoFormat> format, + bool allow_default_fallback) { if (!worker_thread_->IsCurrent()) { worker_thread_->PostTask( SafeTask(task_safety_.flag(), [this, format, allow_default_fallback] { - RequestEncoderSwitch(format, allow_default_fallback); + RequestEncoderSwitch(std::move(format), allow_default_fallback); })); return; } RTC_DCHECK_RUN_ON(&thread_checker_); + RTC_DCHECK(format.has_value() || allow_default_fallback); - for (const VideoCodecSettings& codec_setting : negotiated_codecs_) { - if (format.IsSameCodec( - {codec_setting.codec.name, codec_setting.codec.params})) { - VideoCodecSettings new_codec_setting = codec_setting; - for (const auto& kv : format.parameters) { - new_codec_setting.codec.params[kv.first] = kv.second; - } + ChangedSenderParameters params; + if (!format) { + if (negotiated_codecs_.size() <= 1) { + RTC_LOG(LS_WARNING) + << "Encoder failed but no fallback codec is available"; + return; + } - if (send_codec() == new_codec_setting) { - // Already using this codec, no switch required. - return; - } + params.negotiated_codecs = negotiated_codecs_; + params.negotiated_codecs->erase(params.negotiated_codecs->begin()); + params.send_codec = params.negotiated_codecs->front(); + } else { + auto it = absl::c_find_if( + negotiated_codecs_, [&](const VideoCodecSettings& codec_setting) { + return format->IsSameCodec( + {codec_setting.codec.name, codec_setting.codec.params}); + }); + if (it == negotiated_codecs_.end()) { + RTC_LOG(LS_WARNING) << "Failed to switch encoder to: " + << format->ToString() + << ". Is default fallback allowed: " + << allow_default_fallback; - ChangedSenderParameters params; - params.send_codec = new_codec_setting; - if (ApplyChangedParams(params) && parameters_changed_callback_) { - parameters_changed_callback_(); + if (allow_default_fallback) { + RequestEncoderSwitch(std::nullopt, true); } return; } + + VideoCodecSettings new_codec_setting = *it; + for (const auto& kv : format->parameters) { + new_codec_setting.codec.params[kv.first] = kv.second; + } + + if (send_codec() == new_codec_setting) { + return; + } + + params.send_codec = new_codec_setting; } - RTC_LOG(LS_WARNING) << "Failed to switch encoder to: " << format.ToString() - << ". Is default fallback allowed: " - << allow_default_fallback; - - if (allow_default_fallback) { - RequestEncoderFallback(); + if (ApplyChangedParams(params) && parameters_changed_callback_) { + parameters_changed_callback_(); } } @@ -1581,7 +1576,6 @@ config.encoder_settings.encoder_factory = encoder_factory_; config.encoder_settings.bitrate_allocator_factory = bitrate_allocator_factory_; - config.encoder_settings.encoder_switch_request_callback = this; config.crypto_options = crypto_options_; config.rtp.extmap_allow_mixed = ExtmapAllowMixed(); @@ -1590,7 +1584,7 @@ video_config_.enable_send_packet_batching; WebRtcVideoSendStream* stream = new WebRtcVideoSendStream( - env_, call_, sp, std::move(config), default_send_options_, + this, env_, call_, sp, std::move(config), default_send_options_, video_config_.enable_cpu_adaptation, bitrate_config_.max_bitrate_bps, send_codec(), send_codecs_, send_rtp_extensions_, send_params_); @@ -1814,6 +1808,7 @@ codec_settings_list(codec_settings_list) {} WebRtcVideoSendChannel::WebRtcVideoSendStream::WebRtcVideoSendStream( + WebRtcVideoSendChannel* send_channel, const Environment& env, Call* call, const StreamParams& sp, @@ -1827,7 +1822,8 @@ // TODO(deadbeef): Don't duplicate information between send_params, // rtp_extensions, options, etc. const VideoSenderParameters& send_params) - : env_(env), + : send_channel_(send_channel), + env_(env), worker_thread_(call->worker_thread()), ssrcs_(sp.ssrcs), ssrc_groups_(sp.ssrc_groups), @@ -2702,6 +2698,13 @@ ConfigureVideoEncoderSettings(parameters_.codec_settings->codec); VideoSendStream::Config config = parameters_.config.Copy(); + + auto encoder_switch_request_callback = + [send_channel = send_channel_](std::optional<SdpVideoFormat> format, + bool allow_default_fallback) { + send_channel->RequestEncoderSwitch(std::move(format), + allow_default_fallback); + }; if (!config.rtp.rtx.ssrcs.empty() && config.rtp.rtx.payload_type == -1) { RTC_LOG(LS_WARNING) << "RTX SSRCs configured but there's no configured RTX " "payload type the set codec. Ignoring RTX."; @@ -2728,8 +2731,9 @@ // GetStats and DestroyVideoSendStream. VideoSendStream::Stats stats = stream_->GetStats(); call_->DestroyVideoSendStream(stream_); - stream_ = call_->CreateVideoSendStream(std::move(config), - parameters_.encoder_config.Copy()); + stream_ = call_->CreateVideoSendStream( + std::move(config), parameters_.encoder_config.Copy(), + std::move(encoder_switch_request_callback)); // A new stream is created without any scaling or limitations, so these // flags don't apply until the new stream experiences an adaptation event. @@ -2741,8 +2745,9 @@ stream_->SetStats(stats); } else { - stream_ = call_->CreateVideoSendStream(std::move(config), - parameters_.encoder_config.Copy()); + stream_ = call_->CreateVideoSendStream( + std::move(config), parameters_.encoder_config.Copy(), + std::move(encoder_switch_request_callback)); } if (!rtp_parameters_.encodings.empty() && rtp_parameters_.encodings[0].csrcs.has_value()) {
diff --git a/media/engine/webrtc_video_engine.h b/media/engine/webrtc_video_engine.h index f0a3412..307768f 100644 --- a/media/engine/webrtc_video_engine.h +++ b/media/engine/webrtc_video_engine.h
@@ -47,7 +47,6 @@ #include "api/video/video_frame.h" #include "api/video/video_sink_interface.h" #include "api/video/video_source_interface.h" -#include "api/video/video_stream_encoder_settings.h" #include "api/video_codecs/sdp_video_format.h" #include "api/video_codecs/video_encoder_factory.h" #include "call/call.h" @@ -159,8 +158,7 @@ }; class WebRtcVideoSendChannel : public MediaChannelUtil, - public VideoMediaSendChannelInterface, - public EncoderSwitchRequestCallback { + public VideoMediaSendChannelInterface { public: WebRtcVideoSendChannel( const Environment& env, @@ -253,10 +251,10 @@ ADAPTREASON_BANDWIDTH = 2, }; - // Implements EncoderSwitchRequestCallback. - void RequestEncoderFallback() override; - void RequestEncoderSwitch(const SdpVideoFormat& format, - bool allow_default_fallback) override; + // Called to request an encoder switch or fallback. + // See also EncoderSwitchRequestCallback. + void RequestEncoderSwitch(std::optional<SdpVideoFormat> format, + bool allow_default_fallback); void GenerateSendKeyFrame(uint32_t ssrc, const std::vector<std::string>& rids) override; @@ -318,6 +316,7 @@ class WebRtcVideoSendStream { public: WebRtcVideoSendStream( + WebRtcVideoSendChannel* send_channel, const Environment& env, Call* call, const StreamParams& sp, @@ -402,6 +401,7 @@ DegradationPreference GetDegradationPreference() const RTC_EXCLUSIVE_LOCKS_REQUIRED(&thread_checker_); + WebRtcVideoSendChannel* const send_channel_; const Environment env_; RTC_NO_UNIQUE_ADDRESS SequenceChecker thread_checker_; TaskQueueBase* const worker_thread_;
diff --git a/media/engine/webrtc_video_engine_unittest.cc b/media/engine/webrtc_video_engine_unittest.cc index 311d728..d6f9d38 100644 --- a/media/engine/webrtc_video_engine_unittest.cc +++ b/media/engine/webrtc_video_engine_unittest.cc
@@ -2598,19 +2598,19 @@ ASSERT_TRUE(codec); EXPECT_EQ("VP9", codec->name); - SendImpl()->RequestEncoderFallback(); + SendImpl()->RequestEncoderSwitch(std::nullopt, true); time_controller_.AdvanceTime(kFrameDuration); codec = send_channel_->GetSendCodec(); ASSERT_TRUE(codec); EXPECT_EQ("AV1", codec->name); - SendImpl()->RequestEncoderFallback(); + SendImpl()->RequestEncoderSwitch(std::nullopt, true); time_controller_.AdvanceTime(kFrameDuration); codec = send_channel_->GetSendCodec(); ASSERT_TRUE(codec); EXPECT_EQ("VP8", codec->name); - SendImpl()->RequestEncoderFallback(); + SendImpl()->RequestEncoderSwitch(std::nullopt, true); time_controller_.AdvanceTime(kFrameDuration); FrameForwarder frame_forwarder; @@ -2620,7 +2620,7 @@ #if defined(RTC_ENABLE_VP9) -TEST_F(WebRtcVideoChannelBaseTest, RequestEncoderFallback) { +TEST_F(WebRtcVideoChannelBaseTest, RequestEncoderSwitchWithNullopt) { VideoSenderParameters parameters; parameters.codecs.push_back(GetEngineCodec("VP9")); parameters.codecs.push_back(GetEngineCodec("VP8")); @@ -2630,16 +2630,16 @@ ASSERT_TRUE(codec); EXPECT_EQ("VP9", codec->name); - // RequestEncoderFallback will post a task to the worker thread (which is also + // RequestEncoderSwitch will post a task to the worker thread (which is also // the current thread), hence the ProcessMessages call. - SendImpl()->RequestEncoderFallback(); + SendImpl()->RequestEncoderSwitch(std::nullopt, true); time_controller_.AdvanceTime(kFrameDuration); codec = send_channel_->GetSendCodec(); ASSERT_TRUE(codec); EXPECT_EQ("VP8", codec->name); // No other codec to fall back to, keep using VP8. - SendImpl()->RequestEncoderFallback(); + SendImpl()->RequestEncoderSwitch(std::nullopt, true); time_controller_.AdvanceTime(kFrameDuration); codec = send_channel_->GetSendCodec(); ASSERT_TRUE(codec); @@ -2712,9 +2712,9 @@ ASSERT_EQ(send_codecs.size(), 2u); EXPECT_THAT("VP9", send_codecs[0].name); - // RequestEncoderFallback will post a task to the worker thread (which is also + // RequestEncoderSwitch will post a task to the worker thread (which is also // the current thread), hence the ProcessMessages call. - SendImpl()->RequestEncoderFallback(); + SendImpl()->RequestEncoderSwitch(std::nullopt, true); time_controller_.AdvanceTime(kFrameDuration); send_codecs = send_channel_->GetRtpSendParameters(kSsrc).codecs; @@ -3903,8 +3903,6 @@ FakeVideoSendStream* stream = AddSendStream(CreateSimStreamParams("cname", ssrcs)); - VideoSendStream::Config config = stream->GetConfig().Copy(); - FrameForwarder frame_forwarder; EXPECT_TRUE(send_channel_->SetVideoSend(ssrcs[0], nullptr, &frame_forwarder)); send_channel_->SetSend(true); @@ -3932,7 +3930,7 @@ FakeVideoSendStream* stream = AddSendStream(CreateSimStreamParams("cname", ssrcs)); - VideoSendStream::Config config = stream->GetConfig().Copy(); + const VideoSendStream::Config& config = stream->GetConfig(); // Despite 3 ssrcs provided, single layer is used. EXPECT_EQ(1u, config.rtp.ssrcs.size()); @@ -3994,8 +3992,6 @@ FakeVideoSendStream* stream = AddSendStream(CreateSimStreamParams("cname", ssrcs)); - VideoSendStream::Config config = stream->GetConfig().Copy(); - FrameForwarder frame_forwarder; EXPECT_TRUE(send_channel_->SetVideoSend(ssrcs[0], nullptr, &frame_forwarder)); send_channel_->SetSend(true); @@ -4037,8 +4033,6 @@ FakeVideoSendStream* stream = AddSendStream(CreateSimStreamParams("cname", ssrcs)); - VideoSendStream::Config config = stream->GetConfig().Copy(); - FrameForwarder frame_forwarder; EXPECT_TRUE(send_channel_->SetVideoSend(ssrcs[0], nullptr, &frame_forwarder)); send_channel_->SetSend(true); @@ -4386,7 +4380,7 @@ const std::vector<uint32_t> rtx_ssrcs = MAKE_VECTOR(kRtxSsrcs1); FakeVideoSendStream* stream = AddSendStream(CreateSimWithRtxStreamParams("cname", ssrcs, rtx_ssrcs)); - VideoSendStream::Config config = stream->GetConfig().Copy(); + const VideoSendStream::Config& config = stream->GetConfig(); // Make sure NACK and FEC are enabled on the correct payload types. EXPECT_EQ(1000, config.rtp.nack.rtp_history_ms); @@ -4405,7 +4399,7 @@ EXPECT_TRUE(send_channel_->SetSenderParameters(parameters)); FakeVideoSendStream* stream = AddSendStream(); - const VideoSendStream::Config config = stream->GetConfig().Copy(); + const VideoSendStream::Config& config = stream->GetConfig(); EXPECT_FALSE(config.rtp.raw_payload); } @@ -4416,7 +4410,7 @@ EXPECT_TRUE(send_channel_->SetSenderParameters(parameters)); FakeVideoSendStream* stream = AddSendStream(); - const VideoSendStream::Config config = stream->GetConfig().Copy(); + const VideoSendStream::Config& config = stream->GetConfig(); EXPECT_TRUE(config.rtp.raw_payload); } @@ -4426,7 +4420,7 @@ // default. TEST_F(WebRtcVideoChannelTest, FlexfecSendCodecWithoutSsrcNotExposedByDefault) { FakeVideoSendStream* stream = AddSendStream(); - VideoSendStream::Config config = stream->GetConfig().Copy(); + const VideoSendStream::Config& config = stream->GetConfig(); EXPECT_EQ(-1, config.rtp.flexfec.payload_type); EXPECT_EQ(0U, config.rtp.flexfec.ssrc); @@ -4436,7 +4430,7 @@ TEST_F(WebRtcVideoChannelTest, FlexfecSendCodecWithSsrcNotExposedByDefault) { FakeVideoSendStream* stream = AddSendStream( CreatePrimaryWithFecFrStreamParams("cname", kSsrcs1[0], kFlexfecSsrc)); - VideoSendStream::Config config = stream->GetConfig().Copy(); + const VideoSendStream::Config& config = stream->GetConfig(); EXPECT_EQ(-1, config.rtp.flexfec.payload_type); EXPECT_EQ(0U, config.rtp.flexfec.ssrc); @@ -4634,7 +4628,7 @@ TEST_F(WebRtcVideoChannelFlexfecSendRecvTest, SetDefaultSendCodecsWithoutSsrc) { FakeVideoSendStream* stream = AddSendStream(); - VideoSendStream::Config config = stream->GetConfig().Copy(); + const VideoSendStream::Config& config = stream->GetConfig(); EXPECT_EQ(GetEngineCodec("flexfec-03").id, config.rtp.flexfec.payload_type); EXPECT_EQ(0U, config.rtp.flexfec.ssrc); @@ -4644,7 +4638,7 @@ TEST_F(WebRtcVideoChannelFlexfecSendRecvTest, SetDefaultSendCodecsWithSsrc) { FakeVideoSendStream* stream = AddSendStream( CreatePrimaryWithFecFrStreamParams("cname", kSsrcs1[0], kFlexfecSsrc)); - VideoSendStream::Config config = stream->GetConfig().Copy(); + const VideoSendStream::Config& config = stream->GetConfig(); EXPECT_EQ(GetEngineCodec("flexfec-03").id, config.rtp.flexfec.payload_type); EXPECT_EQ(kFlexfecSsrc, config.rtp.flexfec.ssrc); @@ -4658,7 +4652,7 @@ ASSERT_TRUE(send_channel_->SetSenderParameters(parameters)); FakeVideoSendStream* stream = AddSendStream(); - VideoSendStream::Config config = stream->GetConfig().Copy(); + const VideoSendStream::Config& config = stream->GetConfig(); EXPECT_EQ(-1, config.rtp.ulpfec.ulpfec_payload_type); EXPECT_EQ(-1, config.rtp.ulpfec.red_payload_type); @@ -4670,7 +4664,7 @@ ASSERT_TRUE(send_channel_->SetSenderParameters(parameters)); FakeVideoSendStream* stream = AddSendStream(); - VideoSendStream::Config config = stream->GetConfig().Copy(); + const VideoSendStream::Config& config = stream->GetConfig(); EXPECT_EQ(-1, config.rtp.flexfec.payload_type); } @@ -4717,7 +4711,7 @@ ASSERT_TRUE(send_channel_->SetSenderParameters(parameters)); FakeVideoSendStream* stream = AddSendStream(); - VideoSendStream::Config config = stream->GetConfig().Copy(); + const VideoSendStream::Config& config = stream->GetConfig(); EXPECT_EQ(-1, config.rtp.flexfec.payload_type); EXPECT_EQ(0u, config.rtp.flexfec.ssrc); @@ -4733,7 +4727,7 @@ FakeVideoSendStream* stream = AddSendStream( CreatePrimaryWithFecFrStreamParams("cname", kSsrcs1[0], kFlexfecSsrc)); - VideoSendStream::Config config = stream->GetConfig().Copy(); + const VideoSendStream::Config& config = stream->GetConfig(); EXPECT_EQ(-1, config.rtp.flexfec.payload_type); EXPECT_EQ(0u, config.rtp.flexfec.ssrc); @@ -4820,7 +4814,7 @@ ASSERT_TRUE(send_channel_->SetSenderParameters(parameters)); FakeVideoSendStream* stream = AddSendStream(); - VideoSendStream::Config config = stream->GetConfig().Copy(); + const VideoSendStream::Config& config = stream->GetConfig(); EXPECT_EQ(GetEngineCodec("ulpfec").id, config.rtp.ulpfec.ulpfec_payload_type); @@ -4828,8 +4822,8 @@ ASSERT_TRUE(send_channel_->SetSenderParameters(parameters)); stream = fake_call_->GetVideoSendStreams()[0]; ASSERT_TRUE(stream != nullptr); - config = stream->GetConfig().Copy(); - EXPECT_EQ(-1, config.rtp.ulpfec.ulpfec_payload_type) + const VideoSendStream::Config& config2 = stream->GetConfig(); + EXPECT_EQ(-1, config2.rtp.ulpfec.ulpfec_payload_type) << "SetSendCodec without ULPFEC should disable current ULPFEC."; } @@ -4842,7 +4836,7 @@ FakeVideoSendStream* stream = AddSendStream( CreatePrimaryWithFecFrStreamParams("cname", kSsrcs1[0], kFlexfecSsrc)); - VideoSendStream::Config config = stream->GetConfig().Copy(); + const VideoSendStream::Config& config = stream->GetConfig(); EXPECT_EQ(GetEngineCodec("flexfec-03").id, config.rtp.flexfec.payload_type); EXPECT_EQ(kFlexfecSsrc, config.rtp.flexfec.ssrc); @@ -4853,8 +4847,8 @@ ASSERT_TRUE(send_channel_->SetSenderParameters(parameters)); stream = fake_call_->GetVideoSendStreams()[0]; ASSERT_TRUE(stream != nullptr); - config = stream->GetConfig().Copy(); - EXPECT_EQ(-1, config.rtp.flexfec.payload_type) + const VideoSendStream::Config& config2 = stream->GetConfig(); + EXPECT_EQ(-1, config2.rtp.flexfec.payload_type) << "SetSendCodec without FlexFEC should disable current FlexFEC."; }
diff --git a/pc/peer_connection_rtp_unittest.cc b/pc/peer_connection_rtp_unittest.cc index d0d8352..f2fcba4 100644 --- a/pc/peer_connection_rtp_unittest.cc +++ b/pc/peer_connection_rtp_unittest.cc
@@ -36,7 +36,6 @@ #include "api/test/rtc_error_matchers.h" #include "api/units/data_rate.h" #include "api/video/render_resolution.h" -#include "api/video/video_stream_encoder_settings.h" #include "api/video_codecs/sdp_video_format.h" #include "api/video_codecs/video_decoder_factory_template.h" #include "api/video_codecs/video_decoder_factory_template_dav1d_adapter.h" @@ -2138,11 +2137,10 @@ worker_thread->BlockingCall([&] { // Simulate VideoStreamEncoder calling RequestEncoderSwitch after getting // the format from the EncoderSelector. - auto* switch_callback = static_cast<webrtc::EncoderSwitchRequestCallback*>( - static_cast<webrtc::WebRtcVideoSendChannel*>( - media_channel->AsVideoSendChannel())); - switch_callback->RequestEncoderSwitch(format_to_switch_to, - /*allow_default_fallback=*/false); + auto* video_send_channel = static_cast<webrtc::WebRtcVideoSendChannel*>( + media_channel->AsVideoSendChannel()); + video_send_channel->RequestEncoderSwitch(std::move(format_to_switch_to), + /*allow_default_fallback=*/false); }); // Allow the signaling thread to process the cache invalidation task posted @@ -2186,15 +2184,13 @@ worker_thread->BlockingCall([&] { // Simulate an encoder fallback on the worker thread. - auto* fallback_callback = - static_cast<webrtc::EncoderSwitchRequestCallback*>( - static_cast<webrtc::WebRtcVideoSendChannel*>( - media_channel->AsVideoSendChannel())); - fallback_callback->RequestEncoderFallback(); + auto* video_send_channel = static_cast<webrtc::WebRtcVideoSendChannel*>( + media_channel->AsVideoSendChannel()); + video_send_channel->RequestEncoderSwitch(std::nullopt, true); }); // Allow the signaling thread to process the cache invalidation task posted - // by RequestEncoderFallback. + // by RequestEncoderSwitch(std::nullopt, true). run_loop_.Flush(); // Call GetParameters. This triggers an internal consistency check in the
diff --git a/pc/rtp_transceiver.cc b/pc/rtp_transceiver.cc index 5205092..0701dca 100644 --- a/pc/rtp_transceiver.cc +++ b/pc/rtp_transceiver.cc
@@ -389,7 +389,7 @@ // This should be possible without a blocking call to the worker, perhaps done // asynchronously. At the moment this is complicated by the fact that // construction of the channels actually changes the settings of the engine. - context_->worker_thread()->BlockingCall([&]() mutable { + context_->worker_thread()->BlockingCall([&]() { RTC_DCHECK_RUN_ON(this->context()->worker_thread()); auto channels = CreateMediaContentChannels( media_type_, env_, media_engine(), call, media_config, audio_options,
diff --git a/test/call_test.cc b/test/call_test.cc index c25a6c8..40cbc44 100644 --- a/test/call_test.cc +++ b/test/call_test.cc
@@ -607,7 +607,7 @@ if (fec_controller_factory_) { video_send_streams_[i] = sender_call_->CreateVideoSendStream( video_send_configs_[i].Copy(), video_encoder_configs_[i].Copy(), - fec_controller_factory_->CreateFecController(send_env_)); + nullptr, fec_controller_factory_->CreateFecController(send_env_)); } else { video_send_streams_[i] = sender_call_->CreateVideoSendStream( video_send_configs_[i].Copy(), video_encoder_configs_[i].Copy());
diff --git a/test/scenario/video_stream.cc b/test/scenario/video_stream.cc index 8cffa68..86e5111 100644 --- a/test/scenario/video_stream.cc +++ b/test/scenario/video_stream.cc
@@ -428,7 +428,7 @@ sender_->SendTask([&] { if (config.stream.fec_controller_factory) { send_stream_ = sender_->call_->CreateVideoSendStream( - std::move(send_config), std::move(encoder_config), + std::move(send_config), std::move(encoder_config), nullptr, config.stream.fec_controller_factory->CreateFecController( sender_->env_)); } else {
diff --git a/video/video_send_stream_impl.cc b/video/video_send_stream_impl.cc index d6ff87e..ad9130b 100644 --- a/video/video_send_stream_impl.cc +++ b/video/video_send_stream_impl.cc
@@ -343,11 +343,12 @@ const Environment& env, int num_cpu_cores, SendStatisticsProxy* stats_proxy, - const VideoStreamEncoderSettings& encoder_settings, + VideoStreamEncoderSettings encoder_settings, VideoStreamEncoder::BitrateAllocationCallbackType bitrate_allocation_callback_type, Metronome* metronome, - VideoEncoderFactory::EncoderSelectorInterface* encoder_selector) { + VideoEncoderFactory::EncoderSelectorInterface* encoder_selector, + EncoderSwitchRequestCallback encoder_switch_request_callback) { std::unique_ptr<TaskQueueBase, TaskQueueDeleter> encoder_queue = env.task_queue_factory().CreateTaskQueue( "VideoEncoderQueue", @@ -356,13 +357,13 @@ : TaskQueueFactory::Priority::kNormal); TaskQueueBase* encoder_queue_ptr = encoder_queue.get(); return std::make_unique<VideoStreamEncoder>( - env, num_cpu_cores, stats_proxy, encoder_settings, + env, num_cpu_cores, stats_proxy, std::move(encoder_settings), std::make_unique<OveruseFrameDetector>(env, stats_proxy), FrameCadenceAdapterInterface::Create( &env.clock(), encoder_queue_ptr, metronome, /*worker_queue=*/TaskQueueBase::Current(), env.field_trials()), std::move(encoder_queue), bitrate_allocation_callback_type, - encoder_selector); + encoder_selector, std::move(encoder_switch_request_callback)); } bool HasActiveEncodings(const VideoEncoderConfig& config) { @@ -398,6 +399,7 @@ const std::map<uint32_t, RtpState>& suspended_ssrcs, const std::map<uint32_t, RtpPayloadState>& suspended_payload_states, std::unique_ptr<FecController> fec_controller, + EncoderSwitchRequestCallback encoder_switch_request_callback, std::unique_ptr<VideoStreamEncoderInterface> video_stream_encoder_for_test) : env_(env), transport_(transport), @@ -415,11 +417,12 @@ env_, num_cpu_cores, &stats_proxy_, - config_.encoder_settings, + std::move(config_.encoder_settings), GetBitrateAllocationCallbackType(config_, env_.field_trials()), metronome, - config_.encoder_selector)), + config_.encoder_selector, + std::move(encoder_switch_request_callback))), encoder_feedback_( env_, SupportsPerLayerPictureLossIndication(
diff --git a/video/video_send_stream_impl.h b/video/video_send_stream_impl.h index 9ed2308..88845a1 100644 --- a/video/video_send_stream_impl.h +++ b/video/video_send_stream_impl.h
@@ -41,6 +41,7 @@ #include "api/video/video_frame.h" #include "api/video/video_layers_allocation.h" #include "api/video/video_source_interface.h" +#include "api/video/video_stream_encoder_settings.h" #include "api/video_codecs/video_encoder.h" #include "call/bitrate_allocator.h" #include "call/rtp_config.h" @@ -88,20 +89,22 @@ using RtpStateMap = std::map<uint32_t, RtpState>; using RtpPayloadStateMap = std::map<uint32_t, RtpPayloadState>; - VideoSendStreamImpl(const Environment& env, - int num_cpu_cores, - RtcpRttStats* call_stats, - RtpTransportControllerSendInterface* transport, - Metronome* metronome, - BitrateAllocatorInterface* bitrate_allocator, - SendDelayStats* send_delay_stats, - VideoSendStream::Config config, - VideoEncoderConfig encoder_config, - const RtpStateMap& suspended_ssrcs, - const RtpPayloadStateMap& suspended_payload_states, - std::unique_ptr<FecController> fec_controller, - std::unique_ptr<VideoStreamEncoderInterface> - video_stream_encoder_for_test = nullptr); + VideoSendStreamImpl( + const Environment& env, + int num_cpu_cores, + RtcpRttStats* call_stats, + RtpTransportControllerSendInterface* transport, + Metronome* metronome, + BitrateAllocatorInterface* bitrate_allocator, + SendDelayStats* send_delay_stats, + VideoSendStream::Config config, + VideoEncoderConfig encoder_config, + const RtpStateMap& suspended_ssrcs, + const RtpPayloadStateMap& suspended_payload_states, + std::unique_ptr<FecController> fec_controller, + EncoderSwitchRequestCallback encoder_switch_request_callback = nullptr, + std::unique_ptr<VideoStreamEncoderInterface> + video_stream_encoder_for_test = nullptr); ~VideoSendStreamImpl() override; void DeliverRtcp(std::span<const uint8_t> packet);
diff --git a/video/video_send_stream_impl_unittest.cc b/video/video_send_stream_impl_unittest.cc index 1c30024..4bead83 100644 --- a/video/video_send_stream_impl_unittest.cc +++ b/video/video_send_stream_impl_unittest.cc
@@ -207,7 +207,9 @@ /*metronome=*/nullptr, &bitrate_allocator_, &send_delay_stats_, config_.Copy(), std::move(encoder_config), suspended_ssrcs, suspended_payload_states, - /*fec_controller=*/nullptr, std::move(video_stream_encoder)); + /*fec_controller=*/nullptr, + /*encoder_switch_request_callback=*/nullptr, + std::move(video_stream_encoder)); // The call to GetStartBitrate() executes asynchronously on the tq. // Ensure all tasks get to run.
diff --git a/video/video_stream_encoder.cc b/video/video_stream_encoder.cc index 3a56e77..177ae42 100644 --- a/video/video_stream_encoder.cc +++ b/video/video_stream_encoder.cc
@@ -706,23 +706,26 @@ const Environment& env, uint32_t number_of_cores, VideoStreamEncoderObserver* encoder_stats_observer, - const VideoStreamEncoderSettings& settings, + VideoStreamEncoderSettings settings, std::unique_ptr<OveruseFrameDetector> overuse_detector, std::unique_ptr<FrameCadenceAdapterInterface> frame_cadence_adapter, std::unique_ptr<TaskQueueBase, TaskQueueDeleter> encoder_queue, BitrateAllocationCallbackType allocation_cb_type, - VideoEncoderFactory::EncoderSelectorInterface* encoder_selector) + VideoEncoderFactory::EncoderSelectorInterface* encoder_selector, + EncoderSwitchRequestCallback encoder_switch_request_callback) : env_(env), worker_queue_(TaskQueueBase::Current()), number_of_cores_(number_of_cores), - settings_(settings), + settings_(std::move(settings)), + encoder_switch_request_callback_( + std::move(encoder_switch_request_callback)), allocation_cb_type_(allocation_cb_type), rate_control_settings_(env_.field_trials()), encoder_selector_from_constructor_(encoder_selector), encoder_selector_from_factory_( encoder_selector_from_constructor_ ? nullptr - : settings.encoder_factory->GetEncoderSelector()), + : settings_.encoder_factory->GetEncoderSelector()), encoder_selector_(encoder_selector_from_constructor_ ? encoder_selector_from_constructor_ : encoder_selector_from_factory_.get()), @@ -1568,7 +1571,7 @@ void VideoStreamEncoder::RequestEncoderSwitch() { bool is_encoder_switching_supported = - settings_.encoder_switch_request_callback != nullptr; + encoder_switch_request_callback_ != nullptr; bool is_encoder_selector_available = encoder_selector_ != nullptr; RTC_LOG(LS_INFO) << "RequestEncoderSwitch." @@ -1591,7 +1594,8 @@ if (!env_.field_trials().IsDisabled( kSwitchEncoderFollowCodecPreferenceOrderFieldTrial)) { encoder_fallback_requested_ = true; - settings_.encoder_switch_request_callback->RequestEncoderFallback(); + encoder_switch_request_callback_(std::nullopt, + /*allow_default_fallback=*/false); return; } else { preferred_fallback_encoder = @@ -1599,8 +1603,8 @@ } } - settings_.encoder_switch_request_callback->RequestEncoderSwitch( - *preferred_fallback_encoder, /*allow_default_fallback=*/true); + encoder_switch_request_callback_(*preferred_fallback_encoder, + /*allow_default_fallback=*/true); } void VideoStreamEncoder::OnEncoderSettingsChanged() { @@ -1936,11 +1940,11 @@ video_frame.is_texture() != last_frame_info_->is_texture) { if ((!last_frame_info_ || video_frame.width() != last_frame_info_->width || video_frame.height() != last_frame_info_->height) && - settings_.encoder_switch_request_callback && encoder_selector_) { + encoder_switch_request_callback_ && encoder_selector_) { if (auto encoder = encoder_selector_->OnResolutionChange( {video_frame.width(), video_frame.height()})) { - settings_.encoder_switch_request_callback->RequestEncoderSwitch( - *encoder, /*allow_default_fallback=*/false); + encoder_switch_request_callback_(*encoder, + /*allow_default_fallback=*/false); } } @@ -2526,11 +2530,11 @@ 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 (!video_is_suspended && encoder_switch_request_callback_ && encoder_selector_) { if (auto encoder = encoder_selector_->OnAvailableBitrate(link_allocation)) { - settings_.encoder_switch_request_callback->RequestEncoderSwitch( - *encoder, /*allow_default_fallback=*/false); + encoder_switch_request_callback_(*encoder, + /*allow_default_fallback=*/false); } }
diff --git a/video/video_stream_encoder.h b/video/video_stream_encoder.h index 2e28008..f6c4ca7 100644 --- a/video/video_stream_encoder.h +++ b/video/video_stream_encoder.h
@@ -93,13 +93,13 @@ const Environment& env, uint32_t number_of_cores, VideoStreamEncoderObserver* encoder_stats_observer, - const VideoStreamEncoderSettings& settings, + VideoStreamEncoderSettings settings, std::unique_ptr<OveruseFrameDetector> overuse_detector, std::unique_ptr<FrameCadenceAdapterInterface> frame_cadence_adapter, std::unique_ptr<TaskQueueBase, TaskQueueDeleter> encoder_queue, BitrateAllocationCallbackType allocation_cb_type, - VideoEncoderFactory::EncoderSelectorInterface* encoder_selector = - nullptr); + VideoEncoderFactory::EncoderSelectorInterface* encoder_selector = nullptr, + EncoderSwitchRequestCallback encoder_switch_request_callback = nullptr); ~VideoStreamEncoder() override; VideoStreamEncoder(const VideoStreamEncoder&) = delete; @@ -307,6 +307,7 @@ EncoderSink* sink_ = nullptr; const VideoStreamEncoderSettings settings_; + EncoderSwitchRequestCallback encoder_switch_request_callback_; const BitrateAllocationCallbackType allocation_cb_type_; const RateControlSettings rate_control_settings_;
diff --git a/video/video_stream_encoder_unittest.cc b/video/video_stream_encoder_unittest.cc index 5a3eba7..41c91a7 100644 --- a/video/video_stream_encoder_unittest.cc +++ b/video/video_stream_encoder_unittest.cc
@@ -138,6 +138,7 @@ using ::testing::Lt; using ::testing::Matcher; using ::testing::Mock; +using ::testing::MockFunction; using ::testing::NiceMock; using ::testing::Optional; using ::testing::Return; @@ -440,21 +441,24 @@ std::unique_ptr<FrameCadenceAdapterInterface> cadence_adapter, std::unique_ptr<TaskQueueBase, TaskQueueDeleter> encoder_queue, SendStatisticsProxy* stats_proxy, - const VideoStreamEncoderSettings& settings, + VideoStreamEncoderSettings settings, VideoStreamEncoder::BitrateAllocationCallbackType allocation_callback_type, - int num_cores) + int num_cores, + EncoderSwitchRequestCallback encoder_switch_request_callback = nullptr) : VideoStreamEncoder( env, num_cores, stats_proxy, - settings, + std::move(settings), std::unique_ptr<OveruseFrameDetector>( overuse_detector_proxy_ = new CpuOveruseDetectorProxy(env, stats_proxy)), std::move(cadence_adapter), std::move(encoder_queue), - allocation_callback_type), + allocation_callback_type, + nullptr, // encoder_selector + std::move(encoder_switch_request_callback)), time_controller_(time_controller), fake_cpu_resource_(FakeResource::Create("FakeResource[CPU]")), fake_quality_resource_(FakeResource::Create("FakeResource[QP]")), @@ -760,7 +764,7 @@ auto result = std::make_unique<AdaptedVideoStreamEncoder>( env_, /*number_of_cores=*/1, - /*stats_proxy=*/stats_proxy_.get(), encoder_settings_, + /*stats_proxy=*/stats_proxy_.get(), std::move(encoder_settings_), std::make_unique<CpuOveruseDetectorProxy>(env_, /*stats_proxy=*/nullptr), std::move(zero_hertz_adapter), std::move(encoder_queue), @@ -902,7 +906,8 @@ video_send_config_, VideoEncoderConfig::ContentType::kRealtimeVideo, field_trials_)), - sink_(&time_controller_, &fake_encoder_) {} + sink_(&time_controller_, &fake_encoder_), + encoder_switch_request_callback_(nullptr) {} void SetUp() override { metrics::Reset(); @@ -953,11 +958,12 @@ env_ = factory.Create(); } + VideoStreamEncoderSettings settings = video_send_config_.encoder_settings; video_stream_encoder_ = std::make_unique<VideoStreamEncoderUnderTest>( env_, &time_controller_, std::move(cadence_adapter), - std::move(encoder_queue), stats_proxy_.get(), - video_send_config_.encoder_settings, allocation_callback_type, - num_cores); + std::move(encoder_queue), stats_proxy_.get(), std::move(settings), + allocation_callback_type, num_cores, + std::move(encoder_switch_request_callback_)); video_stream_encoder_->SetSink(&sink_, /*rotation_applied=*/false); video_stream_encoder_->SetSource(&video_source_, DegradationPreference::MAINTAIN_FRAMERATE); @@ -1770,6 +1776,7 @@ TestSink sink_; AdaptingFrameForwarder video_source_{&time_controller_}; std::unique_ptr<VideoStreamEncoderUnderTest> video_stream_encoder_; + EncoderSwitchRequestCallback encoder_switch_request_callback_; }; TEST_F(VideoStreamEncoderTest, EncodeOneFrame) { @@ -8429,13 +8436,6 @@ video_stream_encoder_->Stop(); } -struct MockEncoderSwitchRequestCallback : public EncoderSwitchRequestCallback { - MOCK_METHOD(void, RequestEncoderFallback, (), (override)); - MOCK_METHOD(void, - RequestEncoderSwitch, - (const SdpVideoFormat& format, bool allow_default_fallback), - (override)); -}; TEST_F(VideoStreamEncoderTest, EncoderSelectorCurrentEncoderIsSignaled) { constexpr int kDontCare = 100; @@ -8465,9 +8465,9 @@ constexpr int kDontCare = 100; NiceMock<MockEncoderSelector> encoder_selector; - StrictMock<MockEncoderSwitchRequestCallback> switch_callback; - video_send_config_.encoder_settings.encoder_switch_request_callback = - &switch_callback; + StrictMock<MockFunction<void(std::optional<SdpVideoFormat>, bool)>> + switch_callback; + encoder_switch_request_callback_ = switch_callback.AsStdFunction(); auto encoder_factory = std::make_unique<test::VideoEncoderProxyFactory>( &fake_encoder_, &encoder_selector); video_send_config_.encoder_settings.encoder_factory = encoder_factory.get(); @@ -8478,8 +8478,8 @@ ON_CALL(encoder_selector, OnAvailableBitrate) .WillByDefault(Return(SdpVideoFormat("AV1"))); EXPECT_CALL(switch_callback, - RequestEncoderSwitch(Field(&SdpVideoFormat::name, "AV1"), - /*allow_default_fallback=*/false)); + Call(Optional(Field(&SdpVideoFormat::name, "AV1")), + /*allow_default_fallback=*/false)); video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources( /*target_bitrate=*/DataRate::KilobitsPerSec(50), @@ -8495,9 +8495,9 @@ TEST_F(VideoStreamEncoderTest, EncoderSelectorResolutionSwitch) { NiceMock<MockEncoderSelector> encoder_selector; - StrictMock<MockEncoderSwitchRequestCallback> switch_callback; - video_send_config_.encoder_settings.encoder_switch_request_callback = - &switch_callback; + StrictMock<MockFunction<void(std::optional<SdpVideoFormat>, bool)>> + switch_callback; + encoder_switch_request_callback_ = switch_callback.AsStdFunction(); auto encoder_factory = std::make_unique<test::VideoEncoderProxyFactory>( &fake_encoder_, &encoder_selector); video_send_config_.encoder_settings.encoder_factory = encoder_factory.get(); @@ -8510,8 +8510,8 @@ EXPECT_CALL(encoder_selector, OnResolutionChange(RenderResolution(320, 240))) .WillOnce(Return(SdpVideoFormat("AV1"))); EXPECT_CALL(switch_callback, - RequestEncoderSwitch(Field(&SdpVideoFormat::name, "AV1"), - /*allow_default_fallback=*/false)); + Call(Optional(Field(&SdpVideoFormat::name, "AV1")), + /*allow_default_fallback=*/false)); video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources( /*target_bitrate=*/DataRate::KilobitsPerSec(800), @@ -8536,9 +8536,9 @@ NiceMock<MockVideoEncoder> video_encoder; NiceMock<MockEncoderSelector> encoder_selector; - StrictMock<MockEncoderSwitchRequestCallback> switch_callback; - video_send_config_.encoder_settings.encoder_switch_request_callback = - &switch_callback; + StrictMock<MockFunction<void(std::optional<SdpVideoFormat>, bool)>> + switch_callback; + encoder_switch_request_callback_ = switch_callback.AsStdFunction(); auto encoder_factory = std::make_unique<test::VideoEncoderProxyFactory>( &video_encoder, &encoder_selector); video_send_config_.encoder_settings.encoder_factory = encoder_factory.get(); @@ -8564,8 +8564,8 @@ Event encode_attempted; EXPECT_CALL(switch_callback, - RequestEncoderSwitch(Field(&SdpVideoFormat::name, "AV2"), - /*allow_default_fallback=*/true)) + Call(Optional(Field(&SdpVideoFormat::name, "AV2")), + /*allow_default_fallback=*/true)) .WillOnce([&encode_attempted]() { encode_attempted.Set(); }); video_source_.IncomingCapturedFrame(CreateFrame(1, kDontCare, kDontCare)); @@ -8585,9 +8585,9 @@ TEST_F(VideoStreamEncoderTest, SwitchEncoderOnInitFailureWithEncoderSelector) { NiceMock<MockVideoEncoder> video_encoder; NiceMock<MockEncoderSelector> encoder_selector; - StrictMock<MockEncoderSwitchRequestCallback> switch_callback; - video_send_config_.encoder_settings.encoder_switch_request_callback = - &switch_callback; + StrictMock<MockFunction<void(std::optional<SdpVideoFormat>, bool)>> + switch_callback; + encoder_switch_request_callback_ = switch_callback.AsStdFunction(); auto encoder_factory = std::make_unique<test::VideoEncoderProxyFactory>( &video_encoder, &encoder_selector); video_send_config_.encoder_settings.encoder_factory = encoder_factory.get(); @@ -8608,8 +8608,8 @@ Event encode_attempted; EXPECT_CALL(switch_callback, - RequestEncoderSwitch(Field(&SdpVideoFormat::name, "AV2"), - /*allow_default_fallback=*/true)) + Call(Optional(Field(&SdpVideoFormat::name, "AV2")), + /*allow_default_fallback=*/true)) .WillOnce([&encode_attempted]() { encode_attempted.Set(); }); video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr)); @@ -8632,9 +8632,9 @@ "WebRTC-SwitchEncoderFollowCodecPreferenceOrder", "Disabled"); NiceMock<MockVideoEncoder> video_encoder; - StrictMock<MockEncoderSwitchRequestCallback> switch_callback; - video_send_config_.encoder_settings.encoder_switch_request_callback = - &switch_callback; + StrictMock<MockFunction<void(std::optional<SdpVideoFormat>, bool)>> + switch_callback; + encoder_switch_request_callback_ = switch_callback.AsStdFunction(); auto encoder_factory = std::make_unique<test::VideoEncoderProxyFactory>( &video_encoder, /*encoder_selector=*/nullptr); video_send_config_.encoder_settings.encoder_factory = encoder_factory.get(); @@ -8656,8 +8656,8 @@ Event encode_attempted; EXPECT_CALL(switch_callback, - RequestEncoderSwitch(Field(&SdpVideoFormat::name, "VP8"), - /*allow_default_fallback=*/true)) + Call(Optional(Field(&SdpVideoFormat::name, "VP8")), + /*allow_default_fallback=*/true)) .WillOnce([&encode_attempted]() { encode_attempted.Set(); }); video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr)); @@ -8682,9 +8682,9 @@ constexpr int kDontCare = 100; NiceMock<MockEncoderSelector> encoder_selector; - StrictMock<MockEncoderSwitchRequestCallback> switch_callback; - video_send_config_.encoder_settings.encoder_switch_request_callback = - &switch_callback; + StrictMock<MockFunction<void(std::optional<SdpVideoFormat>, bool)>> + switch_callback; + encoder_switch_request_callback_ = switch_callback.AsStdFunction(); auto encoder_factory = std::make_unique<test::VideoEncoderNullableProxyFactory>( /*encoder=*/nullptr, &encoder_selector); @@ -8706,8 +8706,8 @@ .WillByDefault(Return(SdpVideoFormat("AV2"))); Event encode_attempted; EXPECT_CALL(switch_callback, - RequestEncoderSwitch(Field(&SdpVideoFormat::name, "AV2"), - /*allow_default_fallback=*/_)) + Call(Optional(Field(&SdpVideoFormat::name, "AV2")), + /*allow_default_fallback=*/_)) .WillOnce([&encode_attempted]() { encode_attempted.Set(); }); video_source_.IncomingCapturedFrame(CreateFrame(1, kDontCare, kDontCare)); @@ -8730,9 +8730,9 @@ constexpr int kNumFrames = 8; NiceMock<MockVideoEncoder> video_encoder; - StrictMock<MockEncoderSwitchRequestCallback> switch_callback; - video_send_config_.encoder_settings.encoder_switch_request_callback = - &switch_callback; + StrictMock<MockFunction<void(std::optional<SdpVideoFormat>, bool)>> + switch_callback; + encoder_switch_request_callback_ = switch_callback.AsStdFunction(); auto encoder_factory = std::make_unique<test::VideoEncoderProxyFactory>( &video_encoder, /*encoder_selector=*/nullptr); video_send_config_.encoder_settings.encoder_factory = encoder_factory.get(); @@ -8754,7 +8754,7 @@ EXPECT_CALL(video_encoder, Encode) .WillOnce(Return(WEBRTC_VIDEO_CODEC_ENCODER_FAILURE)); - EXPECT_CALL(switch_callback, RequestEncoderFallback()); + EXPECT_CALL(switch_callback, Call(Eq(std::nullopt), _)); VideoFrame frame = CreateFrame(1, kDontCare, kDontCare); for (int i = 0; i < kNumFrames; ++i) { @@ -8791,9 +8791,9 @@ "WebRTC-SwitchEncoderFollowCodecPreferenceOrder", "Enabled"); NiceMock<MockVideoEncoder> video_encoder; - StrictMock<MockEncoderSwitchRequestCallback> switch_callback; - video_send_config_.encoder_settings.encoder_switch_request_callback = - &switch_callback; + StrictMock<MockFunction<void(std::optional<SdpVideoFormat>, bool)>> + switch_callback; + encoder_switch_request_callback_ = switch_callback.AsStdFunction(); auto encoder_factory = std::make_unique<test::VideoEncoderProxyFactory>( &video_encoder, /*encoder_selector=*/nullptr); video_send_config_.encoder_settings.encoder_factory = encoder_factory.get(); @@ -8820,7 +8820,7 @@ .WillOnce(Return(WEBRTC_VIDEO_CODEC_ENCODER_FAILURE)) .WillRepeatedly(Return(WEBRTC_VIDEO_CODEC_OK)); - EXPECT_CALL(switch_callback, RequestEncoderFallback()); + EXPECT_CALL(switch_callback, Call(Eq(std::nullopt), _)); // Encode() will be called once and will return a failure code. All subsequent // frames will be dropped. @@ -8866,9 +8866,9 @@ "WebRTC-SwitchEncoderFollowCodecPreferenceOrder", "Disabled"); NiceMock<MockVideoEncoder> video_encoder; - StrictMock<MockEncoderSwitchRequestCallback> switch_callback; - video_send_config_.encoder_settings.encoder_switch_request_callback = - &switch_callback; + StrictMock<MockFunction<void(std::optional<SdpVideoFormat>, bool)>> + switch_callback; + encoder_switch_request_callback_ = switch_callback.AsStdFunction(); auto encoder_factory = std::make_unique<test::VideoEncoderProxyFactory>( &video_encoder, /*encoder_selector=*/nullptr); video_send_config_.encoder_settings.encoder_factory = encoder_factory.get(); @@ -8896,8 +8896,8 @@ // Fallback request will be asking for switching to VP8. EXPECT_CALL(switch_callback, - RequestEncoderSwitch(Field(&SdpVideoFormat::name, "VP8"), - /*allow_default_fallback=*/true)); + Call(Optional(Field(&SdpVideoFormat::name, "VP8")), + /*allow_default_fallback=*/true)); VideoFrame frame = CreateFrame(1, kDontCare, kDontCare); video_source_.IncomingCapturedFrame(frame); @@ -10433,7 +10433,7 @@ // doing anything else. This should be fine since the posted init task will // simply be deleted. VideoStreamEncoder encoder( - env, 1, &stats_proxy, encoder_settings, + env, 1, &stats_proxy, std::move(encoder_settings), std::make_unique<CpuOveruseDetectorProxy>(env, &stats_proxy), std::move(adapter), std::move(encoder_queue), VideoStreamEncoder::BitrateAllocationCallbackType::