diff --git a/call/bitrate_estimator_tests.cc b/call/bitrate_estimator_tests.cc index b4f808f30a..ea48a973ea 100644 --- a/call/bitrate_estimator_tests.cc +++ b/call/bitrate_estimator_tests.cc @@ -116,8 +116,8 @@ class BitrateEstimatorTest : public test::CallTest { video_send_config_ = VideoSendStream::Config(send_transport_.get()); video_send_config_.rtp.ssrcs.push_back(kVideoSendSsrcs[0]); - // Encoders will be set separately per stream. - video_send_config_.encoder_settings.encoder = nullptr; + video_send_config_.encoder_settings.encoder_factory = + &fake_encoder_factory_; video_send_config_.rtp.payload_name = "FAKE"; video_send_config_.rtp.payload_type = kFakeVideoSendPayloadType; test::FillEncoderConfiguration(kVideoCodecVP8, 1, &video_encoder_config_); @@ -162,10 +162,8 @@ class BitrateEstimatorTest : public test::CallTest { is_sending_receiving_(false), send_stream_(nullptr), frame_generator_capturer_(), - fake_encoder_(Clock::GetRealTimeClock()), fake_decoder_() { test_->video_send_config_.rtp.ssrcs[0]++; - test_->video_send_config_.encoder_settings.encoder = &fake_encoder_; send_stream_ = test_->sender_call_->CreateVideoSendStream( test_->video_send_config_.Copy(), test_->video_encoder_config_.Copy()); @@ -223,7 +221,6 @@ class BitrateEstimatorTest : public test::CallTest { VideoSendStream* send_stream_; VideoReceiveStream* video_receive_stream_; std::unique_ptr frame_generator_capturer_; - test::FakeEncoder fake_encoder_; test::FakeDecoder fake_decoder_; }; diff --git a/call/call_perf_tests.cc b/call/call_perf_tests.cc index 1337809db0..6520e6fcf9 100644 --- a/call/call_perf_tests.cc +++ b/call/call_perf_tests.cc @@ -29,6 +29,7 @@ #include "test/call_test.h" #include "test/direct_transport.h" #include "test/drifting_clock.h" +#include "test/encoder_proxy_factory.h" #include "test/encoder_settings.h" #include "test/fake_encoder.h" #include "test/field_trial.h" @@ -637,7 +638,7 @@ void CallPerfTest::TestMinTransmitBitrate(bool pad_to_min_bitrate) { std::vector bitrate_kbps_list_; } test(pad_to_min_bitrate); - fake_encoder_.SetMaxBitrate(kMaxEncodeBitrateKbps); + fake_encoder_max_bitrate_ = kMaxEncodeBitrateKbps; RunBaseTest(&test); } @@ -686,7 +687,8 @@ TEST_F(CallPerfTest, MAYBE_KeepsHighBitrateWhenReconfiguringSender) { encoder_inits_(0), last_set_bitrate_kbps_(0), send_stream_(nullptr), - frame_generator_(nullptr) {} + frame_generator_(nullptr), + encoder_factory_(this) {} int32_t InitEncode(const VideoCodec* config, int32_t number_of_cores, @@ -735,7 +737,7 @@ TEST_F(CallPerfTest, MAYBE_KeepsHighBitrateWhenReconfiguringSender) { VideoSendStream::Config* send_config, std::vector* receive_configs, VideoEncoderConfig* encoder_config) override { - send_config->encoder_settings.encoder = this; + send_config->encoder_settings.encoder_factory = &encoder_factory_; encoder_config->max_bitrate_bps = 2 * kReconfigureThresholdKbps * 1000; encoder_config->video_stream_factory = new rtc::RefCountedObject(); @@ -770,6 +772,7 @@ TEST_F(CallPerfTest, MAYBE_KeepsHighBitrateWhenReconfiguringSender) { uint32_t last_set_bitrate_kbps_; VideoSendStream* send_stream_; test::FrameGeneratorCapturer* frame_generator_; + test::EncoderProxyFactory encoder_factory_; VideoEncoderConfig encoder_config_; } test; diff --git a/call/video_send_stream.cc b/call/video_send_stream.cc index 8fccd32c77..ec701d0c7b 100644 --- a/call/video_send_stream.cc +++ b/call/video_send_stream.cc @@ -93,7 +93,6 @@ std::string VideoSendStream::Config::EncoderSettings::ToString() const { rtc::SimpleStringBuilder ss(buf); ss << "{encoder_factory: " << (encoder_factory ? "(VideoEncoderFactory)" : "(nullptr)"); - ss << ", encoder: " << (encoder ? "(VideoEncoder)" : "nullptr"); ss << '}'; return ss.str(); } diff --git a/call/video_send_stream.h b/call/video_send_stream.h index 0019a95c65..cdb948395f 100644 --- a/call/video_send_stream.h +++ b/call/video_send_stream.h @@ -113,18 +113,8 @@ class VideoSendStream { struct EncoderSettings { EncoderSettings() = default; - explicit EncoderSettings(VideoEncoder* encoder) : encoder(encoder) {} std::string ToString() const; - // TODO(sophiechang): Delete this field when no one is using internal - // sources anymore. - bool internal_source = false; - - // Allow 100% encoder utilization. Used for HW encoders where CPU isn't - // expected to be the limiting factor, but a chip could be running at - // 30fps (for example) exactly. - bool full_overuse_time = false; - // Enables the new method to estimate the cpu load from encoding, used for // cpu adaptation. bool experiment_cpu_load_estimator = false; @@ -132,9 +122,8 @@ class VideoSendStream { // Ownership stays with WebrtcVideoEngine (delegated from PeerConnection). VideoEncoderFactory* encoder_factory = nullptr; - // TODO(nisse): Delete, let VideoStreamEncoder create the encoder. - // Uninitialized VideoEncoder instance to be used for encoding. Will be - // initialized from inside the VideoSendStream. + // TODO(nisse): Unused! But kept temporarily to transition downstream + // projects. VideoEncoder* encoder = nullptr; } encoder_settings; diff --git a/media/engine/fakewebrtccall.cc b/media/engine/fakewebrtccall.cc index 0aa9cb0967..728193e775 100644 --- a/media/engine/fakewebrtccall.cc +++ b/media/engine/fakewebrtccall.cc @@ -123,7 +123,7 @@ FakeVideoSendStream::FakeVideoSendStream( framerate_scaling_enabled_(false), source_(nullptr), num_swapped_frames_(0) { - RTC_DCHECK(config.encoder_settings.encoder != NULL); + RTC_DCHECK(config.encoder_settings.encoder_factory != nullptr); ReconfigureVideoEncoder(std::move(encoder_config)); } diff --git a/media/engine/webrtcvideoengine.cc b/media/engine/webrtcvideoengine.cc index 7f6508bc48..e9ceaaad66 100644 --- a/media/engine/webrtcvideoengine.cc +++ b/media/engine/webrtcvideoengine.cc @@ -1656,8 +1656,6 @@ WebRtcVideoChannel::WebRtcVideoSendStream::~WebRtcVideoSendStream() { if (stream_ != NULL) { call_->DestroyVideoSendStream(stream_); } - // Release |allocated_encoder_|. - allocated_encoder_.reset(); } bool WebRtcVideoChannel::WebRtcVideoSendStream::SetVideoSend( @@ -1729,26 +1727,6 @@ void WebRtcVideoChannel::WebRtcVideoSendStream::SetCodec( parameters_.encoder_config = CreateVideoEncoderConfig(codec_settings.codec); RTC_DCHECK_GT(parameters_.encoder_config.number_of_streams, 0); - const webrtc::SdpVideoFormat format(codec_settings.codec.name, - codec_settings.codec.params); - - // We can't overwrite |allocated_encoder_| immediately, because we - // need to release it after the RecreateWebRtcStream() call. - std::unique_ptr new_encoder = - // TODO(nisse): Leave to VideoStreamEncoder. - parameters_.config.encoder_settings.encoder_factory->CreateVideoEncoder( - format); - - parameters_.config.encoder_settings.encoder = new_encoder.get(); - - const webrtc::VideoEncoderFactory::CodecInfo info = - parameters_.config.encoder_settings.encoder_factory->QueryVideoEncoder( - format); - parameters_.config.encoder_settings.full_overuse_time = - info.is_hardware_accelerated; - parameters_.config.encoder_settings.internal_source = - info.has_internal_source; - parameters_.config.rtp.payload_name = codec_settings.codec.name; parameters_.config.rtp.payload_type = codec_settings.codec.id; parameters_.config.rtp.ulpfec = codec_settings.ulpfec; @@ -1772,9 +1750,10 @@ void WebRtcVideoChannel::WebRtcVideoSendStream::SetCodec( parameters_.codec_settings = codec_settings; + // TODO(nisse): Avoid recreation, it should be enough to call + // ReconfigureEncoder. RTC_LOG(LS_INFO) << "RecreateWebRtcStream (send) because of SetCodec."; RecreateWebRtcStream(); - allocated_encoder_ = std::move(new_encoder); } void WebRtcVideoChannel::WebRtcVideoSendStream::SetSendParameters( @@ -1907,6 +1886,8 @@ WebRtcVideoChannel::WebRtcVideoSendStream::CreateVideoEncoderConfig( RTC_DCHECK_RUN_ON(&thread_checker_); webrtc::VideoEncoderConfig encoder_config; encoder_config.codec_type = webrtc::PayloadStringToCodecType(codec.name); + encoder_config.video_format = + webrtc::SdpVideoFormat(codec.name, codec.params); bool is_screencast = parameters_.options.is_screencast.value_or(false); if (is_screencast) { diff --git a/media/engine/webrtcvideoengine.h b/media/engine/webrtcvideoengine.h index bffe344dff..e17da3d7ba 100644 --- a/media/engine/webrtcvideoengine.h +++ b/media/engine/webrtcvideoengine.h @@ -350,8 +350,6 @@ class WebRtcVideoChannel : public VideoMediaChannel, public webrtc::Transport { // TODO(skvlad): Combine parameters_ and rtp_parameters_ once we have only // one stream per MediaChannel. webrtc::RtpParameters rtp_parameters_ RTC_GUARDED_BY(&thread_checker_); - std::unique_ptr allocated_encoder_ - RTC_GUARDED_BY(&thread_checker_); bool sending_ RTC_GUARDED_BY(&thread_checker_); }; diff --git a/media/engine/webrtcvideoengine_unittest.cc b/media/engine/webrtcvideoengine_unittest.cc index cbc34468d2..86ba0668b2 100644 --- a/media/engine/webrtcvideoengine_unittest.cc +++ b/media/engine/webrtcvideoengine_unittest.cc @@ -496,40 +496,6 @@ TEST_F(WebRtcVideoEngineTest, RtxCodecAddedForExternalCodec) { codecs, FindMatchingCodec(codecs, h264_high)->id)); } -void WebRtcVideoEngineTest::TestExtendedEncoderOveruse( - bool use_external_encoder) { - std::unique_ptr channel; - FakeCall* fake_call = new FakeCall(); - call_.reset(fake_call); - if (use_external_encoder) { - encoder_factory_->AddSupportedVideoCodecType("VP8"); - channel.reset(SetUpForExternalEncoderFactory()); - } else { - channel.reset( - engine_.CreateChannel(call_.get(), GetMediaConfig(), VideoOptions())); - } - ASSERT_TRUE( - channel->AddSendStream(cricket::StreamParams::CreateLegacy(kSsrc))); - cricket::VideoSendParameters parameters; - parameters.codecs.push_back(GetEngineCodec("VP8")); - EXPECT_TRUE(channel->SetSendParameters(parameters)); - EXPECT_TRUE(channel->SetSend(true)); - FakeVideoSendStream* stream = fake_call->GetVideoSendStreams()[0]; - - EXPECT_EQ(use_external_encoder, - stream->GetConfig().encoder_settings.full_overuse_time); - // Remove stream previously added to free the external encoder instance. - EXPECT_TRUE(channel->RemoveSendStream(kSsrc)); -} - -TEST_F(WebRtcVideoEngineTest, EnablesFullEncoderTimeForExternalEncoders) { - TestExtendedEncoderOveruse(true); -} - -TEST_F(WebRtcVideoEngineTest, DisablesFullEncoderTimeForNonExternalEncoders) { - TestExtendedEncoderOveruse(false); -} - #if !defined(RTC_DISABLE_VP9) TEST_F(WebRtcVideoEngineTest, CanConstructDecoderForVp9EncoderFactory) { encoder_factory_->AddSupportedVideoCodecType("VP9"); @@ -688,16 +654,29 @@ TEST_F(WebRtcVideoEngineTest, UsesSimulcastAdapterForVp8Factories) { TEST_F(WebRtcVideoEngineTest, ChannelWithExternalH264CanChangeToInternalVp8) { encoder_factory_->AddSupportedVideoCodecType("H264"); + // Set capturer. + FakeVideoCapturerWithTaskQueue capturer; + EXPECT_EQ(cricket::CS_RUNNING, + capturer.Start(capturer.GetSupportedFormats()->front())); + std::unique_ptr channel(SetUpForExternalEncoderFactory()); EXPECT_TRUE( channel->AddSendStream(cricket::StreamParams::CreateLegacy(kSsrc))); - ASSERT_EQ(1u, encoder_factory_->encoders().size()); + EXPECT_TRUE(channel->SetVideoSend(kSsrc, nullptr, &capturer)); + // Sending one frame will have allocate the encoder. + EXPECT_TRUE(capturer.CaptureFrame()); + + ASSERT_EQ_WAIT(1u, encoder_factory_->encoders().size(), kTimeout); cricket::VideoSendParameters parameters; parameters.codecs.push_back(GetEngineCodec("VP8")); EXPECT_TRUE(channel->SetSendParameters(parameters)); - ASSERT_EQ(0u, encoder_factory_->encoders().size()); + + // Sending one frame will switch encoder. + EXPECT_TRUE(capturer.CaptureFrame()); + + EXPECT_EQ_WAIT(0u, encoder_factory_->encoders().size(), kTimeout); } TEST_F(WebRtcVideoEngineTest, @@ -765,7 +744,6 @@ TEST_F(WebRtcVideoEngineTest, EXPECT_TRUE( channel->AddSendStream(cricket::StreamParams::CreateLegacy(kSsrc))); - ASSERT_EQ(1u, encoder_factory_->encoders().size()); // Send a frame of 720p. This should trigger a "real" encoder initialization. cricket::VideoFormat format( @@ -774,6 +752,8 @@ TEST_F(WebRtcVideoEngineTest, EXPECT_TRUE(channel->SetVideoSend(kSsrc, nullptr, &capturer)); EXPECT_EQ(cricket::CS_RUNNING, capturer.Start(format)); EXPECT_TRUE(capturer.CaptureFrame()); + ASSERT_TRUE(encoder_factory_->WaitForCreatedVideoEncoders(1)); + ASSERT_EQ(1u, encoder_factory_->encoders().size()); ASSERT_TRUE(encoder_factory_->encoders()[0]->WaitForInitEncode()); EXPECT_EQ(webrtc::kVideoCodecH264, encoder_factory_->encoders()[0]->GetCodecSettings().codecType); @@ -800,6 +780,7 @@ TEST_F(WebRtcVideoEngineTest, SimulcastDisabledForH264) { EXPECT_EQ(cricket::CS_RUNNING, capturer.Start(format)); EXPECT_TRUE(capturer.CaptureFrame()); + ASSERT_TRUE(encoder_factory_->WaitForCreatedVideoEncoders(1)); ASSERT_EQ(1u, encoder_factory_->encoders().size()); FakeWebRtcVideoEncoder* encoder = encoder_factory_->encoders()[0]; ASSERT_TRUE(encoder_factory_->encoders()[0]->WaitForInitEncode()); @@ -988,8 +969,12 @@ TEST(WebRtcVideoEngineNewVideoCodecFactoryTest, Vp8) { EXPECT_CALL(*encoder_factory, QueryVideoEncoder(format)) .WillRepeatedly(testing::Return(codec_info)); FakeWebRtcVideoEncoder* const encoder = new FakeWebRtcVideoEncoder(); + rtc::Event encoder_created(false, false); EXPECT_CALL(*encoder_factory, CreateVideoEncoderProxy(format)) - .WillOnce(testing::Return(encoder)); + .WillOnce( + ::testing::DoAll(::testing::InvokeWithoutArgs( + [&encoder_created]() { encoder_created.Set(); }), + ::testing::Return(encoder))); // Mock decoder creation. |engine| take ownership of the decoder. FakeWebRtcVideoDecoder* const decoder = new FakeWebRtcVideoDecoder(); @@ -1013,6 +998,15 @@ TEST(WebRtcVideoEngineNewVideoCodecFactoryTest, Vp8) { send_channel->AddSendStream(StreamParams::CreateLegacy(send_ssrc))); EXPECT_TRUE(send_channel->SetSend(true)); + // Set capturer. + FakeVideoCapturerWithTaskQueue capturer; + EXPECT_EQ(cricket::CS_RUNNING, + capturer.Start(capturer.GetSupportedFormats()->front())); + EXPECT_TRUE(send_channel->SetVideoSend(send_ssrc, nullptr, &capturer)); + // Sending one frame will allocate the encoder. + EXPECT_TRUE(capturer.CaptureFrame()); + encoder_created.Wait(kTimeout); + // Create recv channel. const int recv_ssrc = 321; std::unique_ptr recv_channel( diff --git a/test/BUILD.gn b/test/BUILD.gn index 7a26e6384e..ece4003acb 100644 --- a/test/BUILD.gn +++ b/test/BUILD.gn @@ -509,6 +509,7 @@ rtc_source_set("test_common") { "constants.h", "drifting_clock.cc", "drifting_clock.h", + "encoder_proxy_factory.h", "encoder_settings.cc", "encoder_settings.h", "fake_decoder.cc", @@ -516,6 +517,7 @@ rtc_source_set("test_common") { "fake_encoder.cc", "fake_encoder.h", "fake_videorenderer.h", + "function_video_encoder_factory.h", "layer_filtering_transport.cc", "layer_filtering_transport.h", "mock_transport.cc", diff --git a/test/call_test.cc b/test/call_test.cc index 4e628657d6..e3a73e850f 100644 --- a/test/call_test.cc +++ b/test/call_test.cc @@ -20,6 +20,7 @@ #include "rtc_base/checks.h" #include "rtc_base/event.h" #include "rtc_base/ptr_util.h" +#include "test/fake_encoder.h" #include "test/testsupport/fileutils.h" namespace webrtc { @@ -37,7 +38,11 @@ CallTest::CallTest() video_send_stream_(nullptr), audio_send_config_(nullptr), audio_send_stream_(nullptr), - fake_encoder_(clock_), + fake_encoder_factory_([this]() { + auto encoder = rtc::MakeUnique(clock_); + encoder->SetMaxBitrate(fake_encoder_max_bitrate_); + return encoder; + }), num_video_streams_(1), num_audio_streams_(0), num_flexfec_streams_(0), @@ -193,7 +198,7 @@ void CallTest::CreateVideoSendConfig(VideoSendStream::Config* video_config, Transport* send_transport) { RTC_DCHECK_LE(num_video_streams + num_used_ssrcs, kNumSsrcs); *video_config = VideoSendStream::Config(send_transport); - video_config->encoder_settings.encoder = &fake_encoder_; + video_config->encoder_settings.encoder_factory = &fake_encoder_factory_; video_config->rtp.payload_name = "FAKE"; video_config->rtp.payload_type = kFakeVideoSendPayloadType; video_config->rtp.extensions.push_back( diff --git a/test/call_test.h b/test/call_test.h index c096b0d29f..4191f43e5f 100644 --- a/test/call_test.h +++ b/test/call_test.h @@ -19,9 +19,9 @@ #include "modules/audio_device/include/test_audio_device.h" #include "test/encoder_settings.h" #include "test/fake_decoder.h" -#include "test/fake_encoder.h" #include "test/fake_videorenderer.h" #include "test/frame_generator_capturer.h" +#include "test/function_video_encoder_factory.h" #include "test/rtp_rtcp_observer.h" #include "test/single_threaded_task_queue.h" @@ -138,7 +138,8 @@ class CallTest : public ::testing::Test { std::vector flexfec_receive_streams_; std::unique_ptr frame_generator_capturer_; - test::FakeEncoder fake_encoder_; + test::FunctionVideoEncoderFactory fake_encoder_factory_; + int fake_encoder_max_bitrate_ = -1; std::vector> allocated_decoders_; size_t num_video_streams_; size_t num_audio_streams_; diff --git a/test/encoder_proxy_factory.h b/test/encoder_proxy_factory.h new file mode 100644 index 0000000000..9c7ff0c652 --- /dev/null +++ b/test/encoder_proxy_factory.h @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2018 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 TEST_ENCODER_PROXY_FACTORY_H_ +#define TEST_ENCODER_PROXY_FACTORY_H_ + +#include +#include + +#include "api/video_codecs/video_encoder.h" +#include "api/video_codecs/video_encoder_factory.h" +#include "rtc_base/ptr_util.h" + +namespace webrtc { +namespace test { + +// An encoder factory with a single underlying VideoEncoder object, +// intended for test purposes. Each call to CreateVideoEncoder returns +// a proxy for the same encoder, typically an instance of FakeEncoder. +class EncoderProxyFactory final : public VideoEncoderFactory { + public: + explicit EncoderProxyFactory(VideoEncoder* encoder) : encoder_(encoder) { + codec_info_.is_hardware_accelerated = false; + codec_info_.has_internal_source = false; + } + + // Unused by tests. + std::vector GetSupportedFormats() const override { + RTC_NOTREACHED(); + return {}; + } + + CodecInfo QueryVideoEncoder(const SdpVideoFormat& format) const override { + return codec_info_; + } + + std::unique_ptr CreateVideoEncoder( + const SdpVideoFormat& format) override { + return rtc::MakeUnique(encoder_); + } + + void SetIsHardwareAccelerated(bool is_hardware_accelerated) { + codec_info_.is_hardware_accelerated = is_hardware_accelerated; + } + void SetHasInternalSource(bool has_internal_source) { + codec_info_.has_internal_source = has_internal_source; + } + + private: + // Wrapper class, since CreateVideoEncoder needs to surrender + // ownership to the object it returns. + class EncoderProxy final : public VideoEncoder { + public: + explicit EncoderProxy(VideoEncoder* encoder) : encoder_(encoder) {} + + private: + int32_t Encode(const VideoFrame& input_image, + const CodecSpecificInfo* codec_specific_info, + const std::vector* frame_types) override { + return encoder_->Encode(input_image, codec_specific_info, frame_types); + } + int32_t InitEncode(const VideoCodec* config, + int32_t number_of_cores, + size_t max_payload_size) override { + return encoder_->InitEncode(config, number_of_cores, max_payload_size); + } + VideoEncoder::ScalingSettings GetScalingSettings() const override { + return encoder_->GetScalingSettings(); + } + int32_t RegisterEncodeCompleteCallback( + EncodedImageCallback* callback) override { + return encoder_->RegisterEncodeCompleteCallback(callback); + } + int32_t Release() override { return encoder_->Release(); } + int32_t SetChannelParameters(uint32_t packet_loss, int64_t rtt) override { + return encoder_->SetChannelParameters(packet_loss, rtt); + } + int32_t SetRateAllocation(const BitrateAllocation& rate_allocation, + uint32_t framerate) override { + return encoder_->SetRateAllocation(rate_allocation, framerate); + } + const char* ImplementationName() const override { + return encoder_->ImplementationName(); + } + + VideoEncoder* const encoder_; + }; + + VideoEncoder* const encoder_; + CodecInfo codec_info_; +}; + +} // namespace test +} // namespace webrtc + +#endif // TEST_ENCODER_PROXY_FACTORY_H_ diff --git a/test/function_video_encoder_factory.h b/test/function_video_encoder_factory.h new file mode 100644 index 0000000000..22cf7441a6 --- /dev/null +++ b/test/function_video_encoder_factory.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2018 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 TEST_FUNCTION_VIDEO_ENCODER_FACTORY_H_ +#define TEST_FUNCTION_VIDEO_ENCODER_FACTORY_H_ + +#include +#include +#include +#include + +#include "api/video_codecs/video_encoder_factory.h" + +namespace webrtc { +namespace test { + +// An encoder factory producing encoders by calling a supplied create +// function. +class FunctionVideoEncoderFactory final : public VideoEncoderFactory { + public: + explicit FunctionVideoEncoderFactory( + std::function()> create) + : create_(std::move(create)) { + codec_info_.is_hardware_accelerated = false; + codec_info_.has_internal_source = false; + } + + // Unused by tests. + std::vector GetSupportedFormats() const override { + RTC_NOTREACHED(); + return {}; + } + + CodecInfo QueryVideoEncoder( + const SdpVideoFormat& /* format */) const override { + return codec_info_; + } + + std::unique_ptr CreateVideoEncoder( + const SdpVideoFormat& /* format */) override { + return create_(); + } + + private: + const std::function()> create_; + CodecInfo codec_info_; +}; + +} // namespace test +} // namespace webrtc + +#endif // TEST_FUNCTION_VIDEO_ENCODER_FACTORY_H_ diff --git a/video/encoder_rtcp_feedback_unittest.cc b/video/encoder_rtcp_feedback_unittest.cc index fbe590b8e5..ec5a1ce011 100644 --- a/video/encoder_rtcp_feedback_unittest.cc +++ b/video/encoder_rtcp_feedback_unittest.cc @@ -24,12 +24,11 @@ namespace webrtc { class MockVideoStreamEncoder : public VideoStreamEncoder { public: explicit MockVideoStreamEncoder(SendStatisticsProxy* send_stats_proxy) - : VideoStreamEncoder( - 1, - send_stats_proxy, - VideoSendStream::Config::EncoderSettings(nullptr), - nullptr, - rtc::MakeUnique(nullptr)) {} + : VideoStreamEncoder(1, + send_stats_proxy, + VideoSendStream::Config::EncoderSettings(), + nullptr, + rtc::MakeUnique(nullptr)) {} ~MockVideoStreamEncoder() { Stop(); } MOCK_METHOD0(SendKeyFrame, void()); diff --git a/video/end_to_end_tests/bandwidth_tests.cc b/video/end_to_end_tests/bandwidth_tests.cc index e77f4026ae..50e874b661 100644 --- a/video/end_to_end_tests/bandwidth_tests.cc +++ b/video/end_to_end_tests/bandwidth_tests.cc @@ -12,6 +12,8 @@ #include "rtc_base/rate_limiter.h" #include "system_wrappers/include/sleep.h" #include "test/call_test.h" +#include "test/encoder_proxy_factory.h" +#include "test/fake_encoder.h" #include "test/field_trial.h" #include "test/gtest.h" #include "test/rtcp_packet_parser.h" @@ -280,6 +282,7 @@ TEST_P(BandwidthEndToEndTest, ReportsSetEncoderRates) { FakeEncoder(Clock::GetRealTimeClock()), task_queue_(task_queue), send_stream_(nullptr), + encoder_factory_(this), bitrate_kbps_(0) {} void OnVideoStreamsCreated( @@ -292,7 +295,7 @@ TEST_P(BandwidthEndToEndTest, ReportsSetEncoderRates) { VideoSendStream::Config* send_config, std::vector* receive_configs, VideoEncoderConfig* encoder_config) override { - send_config->encoder_settings.encoder = this; + send_config->encoder_settings.encoder_factory = &encoder_factory_; RTC_DCHECK_EQ(1, encoder_config->number_of_streams); } @@ -350,6 +353,7 @@ TEST_P(BandwidthEndToEndTest, ReportsSetEncoderRates) { test::SingleThreadedTaskQueueForTesting* const task_queue_; rtc::CriticalSection crit_; VideoSendStream* send_stream_; + test::EncoderProxyFactory encoder_factory_; uint32_t bitrate_kbps_ RTC_GUARDED_BY(crit_); } test(&task_queue_); diff --git a/video/end_to_end_tests/codec_tests.cc b/video/end_to_end_tests/codec_tests.cc index 1607382799..71034cc66d 100644 --- a/video/end_to_end_tests/codec_tests.cc +++ b/video/end_to_end_tests/codec_tests.cc @@ -18,6 +18,7 @@ #include "test/call_test.h" #include "test/encoder_settings.h" #include "test/field_trial.h" +#include "test/function_video_encoder_factory.h" #include "test/gtest.h" namespace webrtc { @@ -47,7 +48,7 @@ class CodecObserver : public test::EndToEndTest, CodecObserver(int no_frames_to_wait_for, VideoRotation rotation_to_test, const std::string& payload_name, - std::unique_ptr encoder, + VideoEncoderFactory* encoder_factory, std::unique_ptr decoder) : EndToEndTest(4 * CodecEndToEndTest::kDefaultTimeoutMs), // TODO(hta): This timeout (120 seconds) is excessive. @@ -55,7 +56,7 @@ class CodecObserver : public test::EndToEndTest, no_frames_to_wait_for_(no_frames_to_wait_for), expected_rotation_(rotation_to_test), payload_name_(payload_name), - encoder_(std::move(encoder)), + encoder_factory_(encoder_factory), decoder_(std::move(decoder)), frame_counter_(0) {} @@ -69,7 +70,7 @@ class CodecObserver : public test::EndToEndTest, std::vector* receive_configs, VideoEncoderConfig* encoder_config) override { encoder_config->codec_type = PayloadStringToCodecType(payload_name_); - send_config->encoder_settings.encoder = encoder_.get(); + send_config->encoder_settings.encoder_factory = encoder_factory_; send_config->rtp.payload_name = payload_name_; send_config->rtp.payload_type = test::CallTest::kVideoSendPayloadType; @@ -97,56 +98,70 @@ class CodecObserver : public test::EndToEndTest, int no_frames_to_wait_for_; VideoRotation expected_rotation_; std::string payload_name_; - std::unique_ptr encoder_; + VideoEncoderFactory* encoder_factory_; std::unique_ptr decoder_; int frame_counter_; }; TEST_P(CodecEndToEndTest, SendsAndReceivesVP8) { - CodecObserver test(5, kVideoRotation_0, "VP8", VP8Encoder::Create(), + test::FunctionVideoEncoderFactory encoder_factory( + []() { return VP8Encoder::Create(); }); + CodecObserver test(5, kVideoRotation_0, "VP8", &encoder_factory, VP8Decoder::Create()); RunBaseTest(&test); } TEST_P(CodecEndToEndTest, SendsAndReceivesVP8Rotation90) { - CodecObserver test(5, kVideoRotation_90, "VP8", VP8Encoder::Create(), + test::FunctionVideoEncoderFactory encoder_factory( + []() { return VP8Encoder::Create(); }); + CodecObserver test(5, kVideoRotation_90, "VP8", &encoder_factory, VP8Decoder::Create()); RunBaseTest(&test); } #if !defined(RTC_DISABLE_VP9) TEST_P(CodecEndToEndTest, SendsAndReceivesVP9) { - CodecObserver test(500, kVideoRotation_0, "VP9", VP9Encoder::Create(), + test::FunctionVideoEncoderFactory encoder_factory( + []() { return VP9Encoder::Create(); }); + CodecObserver test(500, kVideoRotation_0, "VP9", &encoder_factory, VP9Decoder::Create()); RunBaseTest(&test); } TEST_P(CodecEndToEndTest, SendsAndReceivesVP9VideoRotation90) { - CodecObserver test(5, kVideoRotation_90, "VP9", VP9Encoder::Create(), + test::FunctionVideoEncoderFactory encoder_factory( + []() { return VP9Encoder::Create(); }); + CodecObserver test(5, kVideoRotation_90, "VP9", &encoder_factory, VP9Decoder::Create()); RunBaseTest(&test); } // Mutiplex tests are using VP9 as the underlying implementation. TEST_P(CodecEndToEndTest, SendsAndReceivesMultiplex) { - InternalEncoderFactory encoder_factory; + InternalEncoderFactory internal_encoder_factory; InternalDecoderFactory decoder_factory; + test::FunctionVideoEncoderFactory encoder_factory( + [&internal_encoder_factory]() { + return rtc::MakeUnique( + &internal_encoder_factory, SdpVideoFormat(cricket::kVp9CodecName)); + }); CodecObserver test( - 5, kVideoRotation_0, "multiplex", - rtc::MakeUnique( - &encoder_factory, SdpVideoFormat(cricket::kVp9CodecName)), + 5, kVideoRotation_0, "multiplex", &encoder_factory, rtc::MakeUnique( &decoder_factory, SdpVideoFormat(cricket::kVp9CodecName))); RunBaseTest(&test); } TEST_P(CodecEndToEndTest, SendsAndReceivesMultiplexVideoRotation90) { - InternalEncoderFactory encoder_factory; + InternalEncoderFactory internal_encoder_factory; InternalDecoderFactory decoder_factory; + test::FunctionVideoEncoderFactory encoder_factory( + [&internal_encoder_factory]() { + return rtc::MakeUnique( + &internal_encoder_factory, SdpVideoFormat(cricket::kVp9CodecName)); + }); CodecObserver test( - 5, kVideoRotation_90, "multiplex", - rtc::MakeUnique( - &encoder_factory, SdpVideoFormat(cricket::kVp9CodecName)), + 5, kVideoRotation_90, "multiplex", &encoder_factory, rtc::MakeUnique( &decoder_factory, SdpVideoFormat(cricket::kVp9CodecName))); RunBaseTest(&test); @@ -167,15 +182,17 @@ INSTANTIATE_TEST_CASE_P(SpsPpsIdrIsKeyframe, h264_field_trial_combinations); TEST_P(EndToEndTestH264, SendsAndReceivesH264) { - CodecObserver test(500, kVideoRotation_0, "H264", - H264Encoder::Create(cricket::VideoCodec("H264")), + test::FunctionVideoEncoderFactory encoder_factory( + []() { return H264Encoder::Create(cricket::VideoCodec("H264")); }); + CodecObserver test(500, kVideoRotation_0, "H264", &encoder_factory, H264Decoder::Create()); RunBaseTest(&test); } TEST_P(EndToEndTestH264, SendsAndReceivesH264VideoRotation90) { - CodecObserver test(5, kVideoRotation_90, "H264", - H264Encoder::Create(cricket::VideoCodec("H264")), + test::FunctionVideoEncoderFactory encoder_factory( + []() { return H264Encoder::Create(cricket::VideoCodec("H264")); }); + CodecObserver test(5, kVideoRotation_90, "H264", &encoder_factory, H264Decoder::Create()); RunBaseTest(&test); } @@ -183,7 +200,9 @@ TEST_P(EndToEndTestH264, SendsAndReceivesH264VideoRotation90) { TEST_P(EndToEndTestH264, SendsAndReceivesH264PacketizationMode0) { cricket::VideoCodec codec = cricket::VideoCodec("H264"); codec.SetParam(cricket::kH264FmtpPacketizationMode, "0"); - CodecObserver test(500, kVideoRotation_0, "H264", H264Encoder::Create(codec), + test::FunctionVideoEncoderFactory encoder_factory( + [codec]() { return H264Encoder::Create(codec); }); + CodecObserver test(500, kVideoRotation_0, "H264", &encoder_factory, H264Decoder::Create()); RunBaseTest(&test); } @@ -191,7 +210,9 @@ TEST_P(EndToEndTestH264, SendsAndReceivesH264PacketizationMode0) { TEST_P(EndToEndTestH264, SendsAndReceivesH264PacketizationMode1) { cricket::VideoCodec codec = cricket::VideoCodec("H264"); codec.SetParam(cricket::kH264FmtpPacketizationMode, "1"); - CodecObserver test(500, kVideoRotation_0, "H264", H264Encoder::Create(codec), + test::FunctionVideoEncoderFactory encoder_factory( + [codec]() { return H264Encoder::Create(codec); }); + CodecObserver test(500, kVideoRotation_0, "H264", &encoder_factory, H264Decoder::Create()); RunBaseTest(&test); } diff --git a/video/end_to_end_tests/fec_tests.cc b/video/end_to_end_tests/fec_tests.cc index 80a97cd2c8..67bfdeb6a6 100644 --- a/video/end_to_end_tests/fec_tests.cc +++ b/video/end_to_end_tests/fec_tests.cc @@ -12,6 +12,7 @@ #include "modules/video_coding/codecs/vp8/include/vp8.h" #include "test/call_test.h" #include "test/field_trial.h" +#include "test/function_video_encoder_factory.h" #include "test/gtest.h" #include "test/rtcp_packet_parser.h" @@ -42,7 +43,7 @@ TEST_P(FecEndToEndTest, ReceivesUlpfec) { public: UlpfecRenderObserver() : EndToEndTest(kDefaultTimeoutMs), - encoder_(VP8Encoder::Create()), + encoder_factory_([]() { return VP8Encoder::Create(); }), random_(0xcafef00d1), num_packets_sent_(0) {} @@ -102,7 +103,7 @@ TEST_P(FecEndToEndTest, ReceivesUlpfec) { VideoEncoderConfig* encoder_config) override { // Use VP8 instead of FAKE, since the latter does not have PictureID // in the packetization headers. - send_config->encoder_settings.encoder = encoder_.get(); + send_config->encoder_settings.encoder_factory = &encoder_factory_; send_config->rtp.payload_name = "VP8"; send_config->rtp.payload_type = kVideoSendPayloadType; encoder_config->codec_type = kVideoCodecVP8; @@ -128,6 +129,7 @@ TEST_P(FecEndToEndTest, ReceivesUlpfec) { rtc::CriticalSection crit_; std::unique_ptr encoder_; + test::FunctionVideoEncoderFactory encoder_factory_; std::unique_ptr decoder_; std::set dropped_sequence_numbers_ RTC_GUARDED_BY(crit_); // Several packets can have the same timestamp. @@ -335,7 +337,7 @@ TEST_P(FecEndToEndTest, ReceivedUlpfecPacketsNotNacked) { ulpfec_sequence_number_(0), has_last_sequence_number_(false), last_sequence_number_(0), - encoder_(VP8Encoder::Create()), + encoder_factory_([]() { return VP8Encoder::Create(); }), decoder_(VP8Decoder::Create()) {} private: @@ -452,7 +454,7 @@ TEST_P(FecEndToEndTest, ReceivedUlpfecPacketsNotNacked) { send_config->rtp.ulpfec.red_payload_type = kRedPayloadType; send_config->rtp.ulpfec.ulpfec_payload_type = kUlpfecPayloadType; // Set codec to VP8, otherwise NACK/FEC hybrid will be disabled. - send_config->encoder_settings.encoder = encoder_.get(); + send_config->encoder_settings.encoder_factory = &encoder_factory_; send_config->rtp.payload_name = "VP8"; send_config->rtp.payload_type = kFakeVideoSendPayloadType; encoder_config->codec_type = kVideoCodecVP8; @@ -488,6 +490,7 @@ TEST_P(FecEndToEndTest, ReceivedUlpfecPacketsNotNacked) { bool has_last_sequence_number_; uint16_t last_sequence_number_; std::unique_ptr encoder_; + test::FunctionVideoEncoderFactory encoder_factory_; std::unique_ptr decoder_; } test; diff --git a/video/end_to_end_tests/histogram_tests.cc b/video/end_to_end_tests/histogram_tests.cc index decbb77486..3096c2a285 100644 --- a/video/end_to_end_tests/histogram_tests.cc +++ b/video/end_to_end_tests/histogram_tests.cc @@ -12,6 +12,7 @@ #include "system_wrappers/include/metrics.h" #include "system_wrappers/include/metrics_default.h" #include "test/call_test.h" +#include "test/function_video_encoder_factory.h" #include "test/gtest.h" #include "test/rtcp_packet_parser.h" @@ -34,7 +35,7 @@ void HistogramTest::VerifyHistogramStats(bool use_rtx, use_fec_(use_fec), screenshare_(screenshare), // This test uses NACK, so to send FEC we can't use a fake encoder. - vp8_encoder_(use_fec ? VP8Encoder::Create() : nullptr), + encoder_factory_([]() { return VP8Encoder::Create(); }), sender_call_(nullptr), receiver_call_(nullptr), start_runtime_ms_(-1), @@ -88,7 +89,7 @@ void HistogramTest::VerifyHistogramStats(bool use_rtx, if (use_fec_) { send_config->rtp.ulpfec.ulpfec_payload_type = kUlpfecPayloadType; send_config->rtp.ulpfec.red_payload_type = kRedPayloadType; - send_config->encoder_settings.encoder = vp8_encoder_.get(); + send_config->encoder_settings.encoder_factory = &encoder_factory_; send_config->rtp.payload_name = "VP8"; encoder_config->codec_type = kVideoCodecVP8; (*receive_configs)[0].decoders[0].payload_name = "VP8"; @@ -130,7 +131,7 @@ void HistogramTest::VerifyHistogramStats(bool use_rtx, const bool use_rtx_; const bool use_fec_; const bool screenshare_; - const std::unique_ptr vp8_encoder_; + test::FunctionVideoEncoderFactory encoder_factory_; Call* sender_call_; Call* receiver_call_; int64_t start_runtime_ms_; diff --git a/video/end_to_end_tests/log_tests.cc b/video/end_to_end_tests/log_tests.cc index 2695667a3e..391c3d0fee 100644 --- a/video/end_to_end_tests/log_tests.cc +++ b/video/end_to_end_tests/log_tests.cc @@ -11,6 +11,7 @@ #include "modules/video_coding/codecs/vp8/include/vp8.h" #include "rtc_base/file.h" #include "test/call_test.h" +#include "test/function_video_encoder_factory.h" #include "test/testsupport/fileutils.h" namespace webrtc { @@ -61,6 +62,7 @@ TEST_F(LogEndToEndTest, LogsEncodedFramesWhenRequested) { explicit LogEncodingObserver(LogEndToEndTest* fixture) : EndToEndTest(kDefaultTimeoutMs), fixture_(fixture), + encoder_factory_([]() { return VP8Encoder::Create(); }), recorded_frames_(0) {} void PerformTest() override { @@ -73,12 +75,11 @@ TEST_F(LogEndToEndTest, LogsEncodedFramesWhenRequested) { VideoSendStream::Config* send_config, std::vector* receive_configs, VideoEncoderConfig* encoder_config) override { - encoder_ = VP8Encoder::Create(); decoder_ = VP8Decoder::Create(); send_config->post_encode_callback = this; send_config->rtp.payload_name = "VP8"; - send_config->encoder_settings.encoder = encoder_.get(); + send_config->encoder_settings.encoder_factory = &encoder_factory_; encoder_config->codec_type = kVideoCodecVP8; (*receive_configs)[0].decoders.resize(1); @@ -107,7 +108,7 @@ TEST_F(LogEndToEndTest, LogsEncodedFramesWhenRequested) { private: LogEndToEndTest* const fixture_; - std::unique_ptr encoder_; + test::FunctionVideoEncoderFactory encoder_factory_; std::unique_ptr decoder_; rtc::CriticalSection crit_; int recorded_frames_ RTC_GUARDED_BY(crit_); diff --git a/video/end_to_end_tests/multi_stream_tester.cc b/video/end_to_end_tests/multi_stream_tester.cc index 2d501c15d1..e818cf47a1 100644 --- a/video/end_to_end_tests/multi_stream_tester.cc +++ b/video/end_to_end_tests/multi_stream_tester.cc @@ -18,6 +18,7 @@ #include "modules/video_coding/codecs/vp8/include/vp8.h" #include "test/call_test.h" #include "test/encoder_settings.h" +#include "test/function_video_encoder_factory.h" namespace webrtc { @@ -48,7 +49,8 @@ void MultiStreamTester::RunTest() { VideoReceiveStream* receive_streams[kNumStreams]; test::FrameGeneratorCapturer* frame_generators[kNumStreams]; std::vector> allocated_decoders; - std::unique_ptr encoders[kNumStreams]; + test::FunctionVideoEncoderFactory encoder_factory( + []() { return VP8Encoder::Create(); }); task_queue_->SendTask([&]() { sender_call = rtc::WrapUnique(Call::Create(config)); @@ -61,9 +63,6 @@ void MultiStreamTester::RunTest() { sender_transport->SetReceiver(receiver_call->Receiver()); receiver_transport->SetReceiver(sender_call->Receiver()); - for (size_t i = 0; i < kNumStreams; ++i) - encoders[i] = VP8Encoder::Create(); - for (size_t i = 0; i < kNumStreams; ++i) { uint32_t ssrc = codec_settings[i].ssrc; int width = codec_settings[i].width; @@ -71,7 +70,7 @@ void MultiStreamTester::RunTest() { VideoSendStream::Config send_config(sender_transport.get()); send_config.rtp.ssrcs.push_back(ssrc); - send_config.encoder_settings.encoder = encoders[i].get(); + send_config.encoder_settings.encoder_factory = &encoder_factory; send_config.rtp.payload_name = "VP8"; send_config.rtp.payload_type = kVideoPayloadType; VideoEncoderConfig encoder_config; diff --git a/video/end_to_end_tests/network_state_tests.cc b/video/end_to_end_tests/network_state_tests.cc index 1222363141..9af0c47dfc 100644 --- a/video/end_to_end_tests/network_state_tests.cc +++ b/video/end_to_end_tests/network_state_tests.cc @@ -10,6 +10,8 @@ #include "system_wrappers/include/sleep.h" #include "test/call_test.h" +#include "test/encoder_proxy_factory.h" +#include "test/fake_encoder.h" #include "test/gtest.h" namespace webrtc { @@ -77,12 +79,15 @@ void NetworkStateEndToEndTest::VerifyNewVideoSendStreamsRespectNetworkState( MediaType network_to_bring_up, VideoEncoder* encoder, Transport* transport) { - task_queue_.SendTask([this, network_to_bring_up, encoder, transport]() { + test::EncoderProxyFactory encoder_factory(encoder); + + task_queue_.SendTask([this, network_to_bring_up, &encoder_factory, + transport]() { CreateSenderCall(Call::Config(event_log_.get())); sender_call_->SignalChannelNetworkState(network_to_bring_up, kNetworkUp); CreateSendConfig(1, 0, 0, transport); - video_send_config_.encoder_settings.encoder = encoder; + video_send_config_.encoder_settings.encoder_factory = &encoder_factory; CreateVideoStreams(); CreateFrameGeneratorCapturer(kDefaultFramerate, kDefaultWidth, kDefaultHeight); @@ -151,6 +156,7 @@ TEST_F(NetworkStateEndToEndTest, RespectsNetworkState) { packet_event_(false, false), sender_call_(nullptr), receiver_call_(nullptr), + encoder_factory_(this), sender_state_(kNetworkUp), sender_rtp_(0), sender_padding_(0), @@ -197,7 +203,7 @@ TEST_F(NetworkStateEndToEndTest, RespectsNetworkState) { VideoSendStream::Config* send_config, std::vector* receive_configs, VideoEncoderConfig* encoder_config) override { - send_config->encoder_settings.encoder = this; + send_config->encoder_settings.encoder_factory = &encoder_factory_; } void PerformTest() override { @@ -329,6 +335,7 @@ TEST_F(NetworkStateEndToEndTest, RespectsNetworkState) { rtc::Event packet_event_; Call* sender_call_; Call* receiver_call_; + test::EncoderProxyFactory encoder_factory_; NetworkState sender_state_ RTC_GUARDED_BY(test_crit_); int sender_rtp_ RTC_GUARDED_BY(test_crit_); int sender_padding_ RTC_GUARDED_BY(test_crit_); diff --git a/video/end_to_end_tests/retransmission_tests.cc b/video/end_to_end_tests/retransmission_tests.cc index aefb02c252..425c0c279a 100644 --- a/video/end_to_end_tests/retransmission_tests.cc +++ b/video/end_to_end_tests/retransmission_tests.cc @@ -12,6 +12,7 @@ #include "system_wrappers/include/sleep.h" #include "test/call_test.h" #include "test/field_trial.h" +#include "test/function_video_encoder_factory.h" #include "test/gtest.h" #include "test/rtcp_packet_parser.h" @@ -339,7 +340,7 @@ void RetransmissionEndToEndTest::DecodesRetransmittedFrame(bool enable_rtx, retransmission_ssrc_(enable_rtx ? kSendRtxSsrcs[0] : kVideoSendSsrcs[0]), retransmission_payload_type_(GetPayloadType(enable_rtx, enable_red)), - encoder_(VP8Encoder::Create()), + encoder_factory_([]() { return VP8Encoder::Create(); }), marker_bits_observed_(0), retransmitted_timestamp_(0) {} @@ -437,7 +438,7 @@ void RetransmissionEndToEndTest::DecodesRetransmittedFrame(bool enable_rtx, // Configure encoding and decoding with VP8, since generic packetization // doesn't support FEC with NACK. RTC_DCHECK_EQ(1, (*receive_configs)[0].decoders.size()); - send_config->encoder_settings.encoder = encoder_.get(); + send_config->encoder_settings.encoder_factory = &encoder_factory_; send_config->rtp.payload_name = "VP8"; encoder_config->codec_type = kVideoCodecVP8; (*receive_configs)[0].decoders[0].payload_name = "VP8"; @@ -469,7 +470,7 @@ void RetransmissionEndToEndTest::DecodesRetransmittedFrame(bool enable_rtx, const int payload_type_; const uint32_t retransmission_ssrc_; const int retransmission_payload_type_; - std::unique_ptr encoder_; + test::FunctionVideoEncoderFactory encoder_factory_; const std::string payload_name_; int marker_bits_observed_; uint32_t retransmitted_timestamp_ RTC_GUARDED_BY(&crit_); diff --git a/video/end_to_end_tests/rtp_rtcp_tests.cc b/video/end_to_end_tests/rtp_rtcp_tests.cc index c12b9887a1..53172420e1 100644 --- a/video/end_to_end_tests/rtp_rtcp_tests.cc +++ b/video/end_to_end_tests/rtp_rtcp_tests.cc @@ -468,7 +468,8 @@ TEST_F(RtpRtcpEndToEndTest, TestFlexfecRtpStatePreservation) { std::unique_ptr send_transport; std::unique_ptr receive_transport; - std::unique_ptr encoder; + test::FunctionVideoEncoderFactory encoder_factory( + []() { return VP8Encoder::Create(); }); task_queue_.SendTask([&]() { CreateCalls(config, config); @@ -494,8 +495,8 @@ TEST_F(RtpRtcpEndToEndTest, TestFlexfecRtpStatePreservation) { const int kNumFlexfecStreams = 1; CreateSendConfig(kNumVideoStreams, 0, kNumFlexfecStreams, send_transport.get()); - encoder = VP8Encoder::Create(); - video_send_config_.encoder_settings.encoder = encoder.get(); + + video_send_config_.encoder_settings.encoder_factory = &encoder_factory; video_send_config_.rtp.payload_name = "VP8"; video_send_config_.rtp.payload_type = kVideoSendPayloadType; video_send_config_.rtp.nack.rtp_history_ms = kNackRtpHistoryMs; diff --git a/video/end_to_end_tests/stats_tests.cc b/video/end_to_end_tests/stats_tests.cc index 643b6c1508..f3d2194439 100644 --- a/video/end_to_end_tests/stats_tests.cc +++ b/video/end_to_end_tests/stats_tests.cc @@ -14,6 +14,8 @@ #include "system_wrappers/include/metrics_default.h" #include "system_wrappers/include/sleep.h" #include "test/call_test.h" +#include "test/fake_encoder.h" +#include "test/function_video_encoder_factory.h" #include "test/gtest.h" #include "test/rtcp_packet_parser.h" @@ -37,7 +39,10 @@ TEST_F(StatsEndToEndTest, GetStats) { public: StatsObserver() : EndToEndTest(kLongTimeoutMs), - encoder_(Clock::GetRealTimeClock(), 10), + encoder_factory_([]() { + return rtc::MakeUnique( + Clock::GetRealTimeClock(), 10); + }), send_stream_(nullptr), expected_send_ssrcs_(), check_stats_event_(false, false) {} @@ -297,7 +302,7 @@ TEST_F(StatsEndToEndTest, GetStats) { // Use a delayed encoder to make sure we see CpuOveruseMetrics stats that // are non-zero. - send_config->encoder_settings.encoder = &encoder_; + send_config->encoder_settings.encoder_factory = &encoder_factory_; } size_t GetNumVideoStreams() const override { return kNumSimulcastStreams; } @@ -349,7 +354,7 @@ TEST_F(StatsEndToEndTest, GetStats) { } } - test::DelayedEncoder encoder_; + test::FunctionVideoEncoderFactory encoder_factory_; std::vector receive_streams_; std::map receive_stats_filled_; diff --git a/video/overuse_frame_detector.cc b/video/overuse_frame_detector.cc index 1d6b0e182c..4bccdf3cbd 100644 --- a/video/overuse_frame_detector.cc +++ b/video/overuse_frame_detector.cc @@ -543,8 +543,10 @@ void OveruseFrameDetector::StartCheckForOveruse( } void OveruseFrameDetector::StopCheckForOveruse() { RTC_DCHECK_CALLED_SEQUENTIALLY(&task_checker_); - check_overuse_task_->Stop(); - check_overuse_task_ = nullptr; + if (check_overuse_task_) { + check_overuse_task_->Stop(); + check_overuse_task_ = nullptr; + } } void OveruseFrameDetector::EncodedFrameTimeMeasured(int encode_duration_ms) { diff --git a/video/overuse_frame_detector.h b/video/overuse_frame_detector.h index 3aa0db1093..3525a976ab 100644 --- a/video/overuse_frame_detector.h +++ b/video/overuse_frame_detector.h @@ -118,6 +118,8 @@ class OveruseFrameDetector { void CheckForOveruse(AdaptationObserverInterface* overuse_observer); void SetOptions(const CpuOveruseOptions& options); + CpuOveruseOptions options_; + private: class CheckOveruseTask; @@ -137,8 +139,6 @@ class OveruseFrameDetector { // Owned by the task queue from where StartCheckForOveruse is called. CheckOveruseTask* check_overuse_task_; - CpuOveruseOptions options_; - // Stats metrics. CpuOveruseMetricsObserver* const metrics_observer_; rtc::Optional metrics_ RTC_GUARDED_BY(task_checker_); diff --git a/video/picture_id_tests.cc b/video/picture_id_tests.cc index ff62ddca2b..33aed38f18 100644 --- a/video/picture_id_tests.cc +++ b/video/picture_id_tests.cc @@ -14,6 +14,7 @@ #include "rtc_base/numerics/safe_conversions.h" #include "rtc_base/numerics/sequence_number_util.h" #include "test/call_test.h" +#include "test/function_video_encoder_factory.h" namespace webrtc { namespace { @@ -235,7 +236,8 @@ class PictureIdTest : public test::CallTest, }); } - void SetupEncoder(VideoEncoder* encoder, const std::string& payload_name); + void SetupEncoder(VideoEncoderFactory* encoder_factory, + const std::string& payload_name); void TestPictureIdContinuousAfterReconfigure( const std::vector& ssrc_counts); void TestPictureIdIncreaseAfterRecreateStreams( @@ -292,12 +294,12 @@ class VideoStreamFactory const size_t num_of_temporal_layers_; }; -void PictureIdTest::SetupEncoder(VideoEncoder* encoder, +void PictureIdTest::SetupEncoder(VideoEncoderFactory* encoder_factory, const std::string& payload_name) { observer_.reset( new PictureIdObserver(PayloadNameToRtpVideoCodecType(payload_name))); - task_queue_.SendTask([this, &encoder, payload_name]() { + task_queue_.SendTask([this, encoder_factory, payload_name]() { Call::Config config(event_log_.get()); CreateCalls(config, config); @@ -307,7 +309,7 @@ void PictureIdTest::SetupEncoder(VideoEncoder* encoder, FakeNetworkPipe::Config())); CreateSendConfig(kNumSimulcastStreams, 0, 0, send_transport_.get()); - video_send_config_.encoder_settings.encoder = encoder; + video_send_config_.encoder_settings.encoder_factory = encoder_factory; video_send_config_.rtp.payload_name = payload_name; video_encoder_config_.codec_type = PayloadStringToCodecType(payload_name); video_encoder_config_.video_stream_factory = @@ -390,51 +392,67 @@ void PictureIdTest::TestPictureIdIncreaseAfterRecreateStreams( } TEST_P(PictureIdTest, ContinuousAfterReconfigureVp8) { - std::unique_ptr encoder(VP8Encoder::Create()); - SetupEncoder(encoder.get(), "VP8"); + test::FunctionVideoEncoderFactory encoder_factory( + []() { return VP8Encoder::Create(); }); + SetupEncoder(&encoder_factory, "VP8"); TestPictureIdContinuousAfterReconfigure({1, 3, 3, 1, 1}); } TEST_P(PictureIdTest, IncreasingAfterRecreateStreamVp8) { - std::unique_ptr encoder(VP8Encoder::Create()); - SetupEncoder(encoder.get(), "VP8"); + test::FunctionVideoEncoderFactory encoder_factory( + []() { return VP8Encoder::Create(); }); + SetupEncoder(&encoder_factory, "VP8"); TestPictureIdIncreaseAfterRecreateStreams({1, 3, 3, 1, 1}); } TEST_P(PictureIdTest, ContinuousAfterStreamCountChangeVp8) { - std::unique_ptr encoder(VP8Encoder::Create()); + test::FunctionVideoEncoderFactory encoder_factory( + []() { return VP8Encoder::Create(); }); // Make sure that the picture id is not reset if the stream count goes // down and then up. - SetupEncoder(encoder.get(), "VP8"); + SetupEncoder(&encoder_factory, "VP8"); TestPictureIdContinuousAfterReconfigure({3, 1, 3}); } TEST_P(PictureIdTest, ContinuousAfterReconfigureSimulcastEncoderAdapter) { InternalEncoderFactory internal_encoder_factory; - SimulcastEncoderAdapter simulcast_encoder_adapter(&internal_encoder_factory); - SetupEncoder(&simulcast_encoder_adapter, "VP8"); + test::FunctionVideoEncoderFactory encoder_factory( + [&internal_encoder_factory]() { + return rtc::MakeUnique( + &internal_encoder_factory); + }); + SetupEncoder(&encoder_factory, "VP8"); TestPictureIdContinuousAfterReconfigure({1, 3, 3, 1, 1}); } TEST_P(PictureIdTest, IncreasingAfterRecreateStreamSimulcastEncoderAdapter) { InternalEncoderFactory internal_encoder_factory; - SimulcastEncoderAdapter simulcast_encoder_adapter(&internal_encoder_factory); - SetupEncoder(&simulcast_encoder_adapter, "VP8"); + test::FunctionVideoEncoderFactory encoder_factory( + [&internal_encoder_factory]() { + return rtc::MakeUnique( + &internal_encoder_factory); + }); + SetupEncoder(&encoder_factory, "VP8"); TestPictureIdIncreaseAfterRecreateStreams({1, 3, 3, 1, 1}); } TEST_P(PictureIdTest, ContinuousAfterStreamCountChangeSimulcastEncoderAdapter) { InternalEncoderFactory internal_encoder_factory; - SimulcastEncoderAdapter simulcast_encoder_adapter(&internal_encoder_factory); + test::FunctionVideoEncoderFactory encoder_factory( + [&internal_encoder_factory]() { + return rtc::MakeUnique( + &internal_encoder_factory); + }); // Make sure that the picture id is not reset if the stream count goes // down and then up. - SetupEncoder(&simulcast_encoder_adapter, "VP8"); + SetupEncoder(&encoder_factory, "VP8"); TestPictureIdContinuousAfterReconfigure({3, 1, 3}); } TEST_P(PictureIdTest, IncreasingAfterRecreateStreamVp9) { - std::unique_ptr encoder(VP9Encoder::Create()); - SetupEncoder(encoder.get(), "VP9"); + test::FunctionVideoEncoderFactory encoder_factory( + []() { return VP9Encoder::Create(); }); + SetupEncoder(&encoder_factory, "VP9"); TestPictureIdIncreaseAfterRecreateStreams({1, 1}); } diff --git a/video/video_quality_test.cc b/video/video_quality_test.cc index 0a477c4b5b..d0edfc79fa 100644 --- a/video/video_quality_test.cc +++ b/video/video_quality_test.cc @@ -26,6 +26,7 @@ #include "modules/rtp_rtcp/source/rtp_utility.h" #include "modules/video_coding/codecs/h264/include/h264.h" #include "modules/video_coding/codecs/multiplex/include/multiplex_encoder_adapter.h" +#include "modules/video_coding/codecs/vp8/include/vp8.h" #include "modules/video_coding/codecs/vp8/include/vp8_common_types.h" #include "modules/video_coding/codecs/vp9/include/vp9.h" #include "rtc_base/cpu_time.h" @@ -1074,6 +1075,36 @@ class VideoAnalyzer : public PacketReceiver, const int64_t start_ms_; }; +// Not used by these tests. +std::vector +VideoQualityTest::TestVideoEncoderFactory::GetSupportedFormats() const { + RTC_NOTREACHED(); + return {}; +} + +VideoEncoderFactory::CodecInfo +VideoQualityTest::TestVideoEncoderFactory::QueryVideoEncoder( + const SdpVideoFormat& format) const { + CodecInfo codec_info; + codec_info.is_hardware_accelerated = false; + codec_info.has_internal_source = false; + return codec_info; +} + +std::unique_ptr +VideoQualityTest::TestVideoEncoderFactory::CreateVideoEncoder( + const SdpVideoFormat& format) { + if (format.name == "VP8") { + return rtc::MakeUnique( + &internal_encoder_factory_); + } else if (format.name == "multiplex") { + return rtc::MakeUnique( + &internal_encoder_factory_, SdpVideoFormat(cricket::kVp9CodecName)); + } else { + return internal_encoder_factory_.CreateVideoEncoder(format); + } +} + VideoQualityTest::VideoQualityTest() : clock_(Clock::GetRealTimeClock()), receive_logs_(0), send_logs_(0) { payload_type_map_ = test::CallTest::payload_type_map_; @@ -1354,7 +1385,6 @@ void VideoQualityTest::SetupVideo(Transport* send_transport, CreateMatchingAudioAndFecConfigs(recv_transport); video_receive_configs_.clear(); video_send_configs_.clear(); - video_encoders_.clear(); video_encoder_configs_.clear(); allocated_decoders_.clear(); bool decode_all_receive_streams = true; @@ -1363,7 +1393,6 @@ void VideoQualityTest::SetupVideo(Transport* send_transport, video_encoder_configs_.resize(num_video_streams_); for (size_t video_idx = 0; video_idx < num_video_streams_; ++video_idx) { video_send_configs_.push_back(VideoSendStream::Config(send_transport)); - video_encoders_.push_back(nullptr); video_encoder_configs_.push_back(VideoEncoderConfig()); num_video_substreams = params_.ss[video_idx].streams.size(); RTC_CHECK_GT(num_video_substreams, 0); @@ -1372,26 +1401,20 @@ void VideoQualityTest::SetupVideo(Transport* send_transport, int payload_type; if (params_.video[video_idx].codec == "H264") { - video_encoders_[video_idx] = - H264Encoder::Create(cricket::VideoCodec("H264")); payload_type = kPayloadTypeH264; } else if (params_.video[video_idx].codec == "VP8") { - video_encoders_[video_idx] = - rtc::MakeUnique(&internal_encoder_factory_); payload_type = kPayloadTypeVP8; } else if (params_.video[video_idx].codec == "VP9") { - video_encoders_[video_idx] = VP9Encoder::Create(); payload_type = kPayloadTypeVP9; } else if (params_.video[video_idx].codec == "multiplex") { - video_encoders_[video_idx] = rtc::MakeUnique( - &internal_encoder_factory_, SdpVideoFormat(cricket::kVp9CodecName)); payload_type = kPayloadTypeVP9; } else { RTC_NOTREACHED() << "Codec not supported!"; return; } - video_send_configs_[video_idx].encoder_settings.encoder = - video_encoders_[video_idx].get(); + video_send_configs_[video_idx].encoder_settings.encoder_factory = + &video_encoder_factory_; + video_send_configs_[video_idx].rtp.payload_name = params_.video[video_idx].codec; video_send_configs_[video_idx].rtp.payload_type = payload_type; @@ -1416,6 +1439,9 @@ void VideoQualityTest::SetupVideo(Transport* send_transport, video_send_configs_[video_idx].rtp.extensions.push_back(RtpExtension( RtpExtension::kVideoTimingUri, test::kVideoTimingExtensionId)); + video_encoder_configs_[video_idx].video_format.name = + params_.video[video_idx].codec; + video_encoder_configs_[video_idx].codec_type = PayloadStringToCodecType(params_.video[video_idx].codec); @@ -1600,14 +1626,13 @@ void VideoQualityTest::SetupVideo(Transport* send_transport, void VideoQualityTest::SetupThumbnails(Transport* send_transport, Transport* recv_transport) { for (int i = 0; i < params_.call.num_thumbnails; ++i) { - thumbnail_encoders_.emplace_back(VP8Encoder::Create()); - // Thumbnails will be send in the other way: from receiver_call to // sender_call. VideoSendStream::Config thumbnail_send_config(recv_transport); thumbnail_send_config.rtp.ssrcs.push_back(kThumbnailSendSsrcStart + i); - thumbnail_send_config.encoder_settings.encoder = - thumbnail_encoders_.back().get(); + // TODO(nisse): Could use a simpler VP8-only encoder factory. + thumbnail_send_config.encoder_settings.encoder_factory = + &video_encoder_factory_; thumbnail_send_config.rtp.payload_name = params_.video[0].codec; thumbnail_send_config.rtp.payload_type = kPayloadTypeVP8; thumbnail_send_config.rtp.nack.rtp_history_ms = kNackRtpHistoryMs; @@ -1625,6 +1650,7 @@ void VideoQualityTest::SetupThumbnails(Transport* send_transport, VideoEncoderConfig thumbnail_encoder_config; thumbnail_encoder_config.codec_type = kVideoCodecVP8; + thumbnail_encoder_config.video_format.name = "VP8"; thumbnail_encoder_config.min_transmit_bitrate_bps = 7500; thumbnail_send_config.suspend_below_min_bitrate = params_.video[0].suspend_below_min_bitrate; diff --git a/video/video_quality_test.h b/video/video_quality_test.h index 688a004a09..749d092e2f 100644 --- a/video/video_quality_test.h +++ b/video/video_quality_test.h @@ -112,6 +112,18 @@ class VideoQualityTest : public test::CallTest { const std::vector& sl_descriptors); protected: + class TestVideoEncoderFactory : public VideoEncoderFactory { + std::vector GetSupportedFormats() const override; + + CodecInfo QueryVideoEncoder(const SdpVideoFormat& format) const override; + + std::unique_ptr CreateVideoEncoder( + const SdpVideoFormat& format) override; + + private: + InternalEncoderFactory internal_encoder_factory_; + }; + std::map payload_type_map_; std::unique_ptr fec_controller_factory_; @@ -148,10 +160,8 @@ class VideoQualityTest : public test::CallTest { std::vector> video_capturers_; std::vector> thumbnail_capturers_; - InternalEncoderFactory internal_encoder_factory_; - std::vector> video_encoders_; + TestVideoEncoderFactory video_encoder_factory_; - std::vector> thumbnail_encoders_; std::vector thumbnail_send_configs_; std::vector thumbnail_encoder_configs_; std::vector thumbnail_send_streams_; diff --git a/video/video_send_stream.cc b/video/video_send_stream.cc index 02e8b17f9d..1dfb6933b4 100644 --- a/video/video_send_stream.cc +++ b/video/video_send_stream.cc @@ -77,6 +77,8 @@ VideoSendStream::VideoSendStream( encoder_config.content_type), config_(std::move(config)), content_type_(encoder_config.content_type) { + RTC_DCHECK(config_.encoder_settings.encoder_factory); + video_stream_encoder_ = rtc::MakeUnique( num_cpu_cores, &stats_proxy_, config_.encoder_settings, diff --git a/video/video_send_stream_impl.cc b/video/video_send_stream_impl.cc index 3cfdee2ccb..720f290fb3 100644 --- a/video/video_send_stream_impl.cc +++ b/video/video_send_stream_impl.cc @@ -444,7 +444,6 @@ VideoSendStreamImpl::VideoSendStreamImpl( transport_->RegisterPacketFeedbackObserver(this); } - RTC_DCHECK(config_->encoder_settings.encoder); RTC_DCHECK_GE(config_->rtp.payload_type, 0); RTC_DCHECK_LE(config_->rtp.payload_type, 127); diff --git a/video/video_send_stream_tests.cc b/video/video_send_stream_tests.cc index 9985b85059..1073a0c4d1 100644 --- a/video/video_send_stream_tests.cc +++ b/video/video_send_stream_tests.cc @@ -33,6 +33,8 @@ #include "system_wrappers/include/sleep.h" #include "test/call_test.h" #include "test/configurable_frame_size_encoder.h" +#include "test/encoder_proxy_factory.h" +#include "test/fake_encoder.h" #include "test/fake_texture_frame.h" #include "test/field_trial.h" #include "test/frame_generator.h" @@ -198,8 +200,10 @@ TEST_F(VideoSendStreamTest, SupportsTransmissionTimeOffset) { class TransmissionTimeOffsetObserver : public test::SendTest { public: TransmissionTimeOffsetObserver() - : SendTest(kDefaultTimeoutMs), - encoder_(Clock::GetRealTimeClock(), kEncodeDelayMs) { + : SendTest(kDefaultTimeoutMs), encoder_factory_([]() { + return rtc::MakeUnique( + Clock::GetRealTimeClock(), kEncodeDelayMs); + }) { EXPECT_TRUE(parser_->RegisterRtpHeaderExtension( kRtpExtensionTransmissionTimeOffset, test::kTOffsetExtensionId)); } @@ -222,7 +226,7 @@ TEST_F(VideoSendStreamTest, SupportsTransmissionTimeOffset) { VideoSendStream::Config* send_config, std::vector* receive_configs, VideoEncoderConfig* encoder_config) override { - send_config->encoder_settings.encoder = &encoder_; + send_config->encoder_settings.encoder_factory = &encoder_factory_; send_config->rtp.extensions.clear(); send_config->rtp.extensions.push_back(RtpExtension( RtpExtension::kTimestampOffsetUri, test::kTOffsetExtensionId)); @@ -232,7 +236,7 @@ TEST_F(VideoSendStreamTest, SupportsTransmissionTimeOffset) { EXPECT_TRUE(Wait()) << "Timed out while waiting for a single RTP packet."; } - test::DelayedEncoder encoder_; + test::FunctionVideoEncoderFactory encoder_factory_; } test; RunBaseTest(&test); @@ -243,7 +247,10 @@ TEST_F(VideoSendStreamTest, SupportsTransportWideSequenceNumbers) { class TransportWideSequenceNumberObserver : public test::SendTest { public: TransportWideSequenceNumberObserver() - : SendTest(kDefaultTimeoutMs), encoder_(Clock::GetRealTimeClock()) { + : SendTest(kDefaultTimeoutMs), encoder_factory_([]() { + return rtc::MakeUnique( + Clock::GetRealTimeClock()); + }) { EXPECT_TRUE(parser_->RegisterRtpHeaderExtension( kRtpExtensionTransportSequenceNumber, kExtensionId)); } @@ -266,14 +273,14 @@ TEST_F(VideoSendStreamTest, SupportsTransportWideSequenceNumbers) { VideoSendStream::Config* send_config, std::vector* receive_configs, VideoEncoderConfig* encoder_config) override { - send_config->encoder_settings.encoder = &encoder_; + send_config->encoder_settings.encoder_factory = &encoder_factory_; } void PerformTest() override { EXPECT_TRUE(Wait()) << "Timed out while waiting for a single RTP packet."; } - test::FakeEncoder encoder_; + test::FunctionVideoEncoderFactory encoder_factory_; } test; RunBaseTest(&test); @@ -431,9 +438,9 @@ class UlpfecObserver : public test::EndToEndTest { bool expect_red, bool expect_ulpfec, const std::string& codec, - VideoEncoder* encoder) + VideoEncoderFactory* encoder_factory) : EndToEndTest(kTimeoutMs), - encoder_(encoder), + encoder_factory_(encoder_factory), payload_name_(codec), use_nack_(use_nack), expect_red_(expect_red), @@ -531,7 +538,7 @@ class UlpfecObserver : public test::EndToEndTest { (*receive_configs)[0].rtp.nack.rtp_history_ms = VideoSendStreamTest::kNackRtpHistoryMs; } - send_config->encoder_settings.encoder = encoder_; + send_config->encoder_settings.encoder_factory = encoder_factory_; send_config->rtp.payload_name = payload_name_; send_config->rtp.ulpfec.red_payload_type = VideoSendStreamTest::kRedPayloadType; @@ -556,7 +563,7 @@ class UlpfecObserver : public test::EndToEndTest { << "Timed out waiting for ULPFEC and/or media packets."; } - VideoEncoder* const encoder_; + VideoEncoderFactory* encoder_factory_; std::string payload_name_; const bool use_nack_; const bool expect_red_; @@ -568,14 +575,16 @@ class UlpfecObserver : public test::EndToEndTest { }; TEST_F(VideoSendStreamTest, SupportsUlpfecWithExtensions) { - std::unique_ptr encoder(VP8Encoder::Create()); - UlpfecObserver test(true, false, true, true, "VP8", encoder.get()); + test::FunctionVideoEncoderFactory encoder_factory( + []() { return VP8Encoder::Create(); }); + UlpfecObserver test(true, false, true, true, "VP8", &encoder_factory); RunBaseTest(&test); } TEST_F(VideoSendStreamTest, SupportsUlpfecWithoutExtensions) { - std::unique_ptr encoder(VP8Encoder::Create()); - UlpfecObserver test(false, false, true, true, "VP8", encoder.get()); + test::FunctionVideoEncoderFactory encoder_factory( + []() { return VP8Encoder::Create(); }); + UlpfecObserver test(false, false, true, true, "VP8", &encoder_factory); RunBaseTest(&test); } @@ -588,8 +597,9 @@ class VideoSendStreamWithoutUlpfecTest : public VideoSendStreamTest { }; TEST_F(VideoSendStreamWithoutUlpfecTest, NoUlpfecIfDisabledThroughFieldTrial) { - std::unique_ptr encoder(VP8Encoder::Create()); - UlpfecObserver test(false, false, true, false, "VP8", encoder.get()); + test::FunctionVideoEncoderFactory encoder_factory( + []() { return VP8Encoder::Create(); }); + UlpfecObserver test(false, false, true, false, "VP8", &encoder_factory); RunBaseTest(&test); } @@ -598,40 +608,46 @@ TEST_F(VideoSendStreamWithoutUlpfecTest, NoUlpfecIfDisabledThroughFieldTrial) { // bandwidth since the receiver has to wait for FEC retransmissions to determine // that the received state is actually decodable. TEST_F(VideoSendStreamTest, DoesNotUtilizeUlpfecForH264WithNackEnabled) { - std::unique_ptr encoder( - new test::FakeH264Encoder(Clock::GetRealTimeClock())); - UlpfecObserver test(false, true, true, false, "H264", encoder.get()); + test::FunctionVideoEncoderFactory encoder_factory([]() { + return rtc::MakeUnique(Clock::GetRealTimeClock()); + }); + UlpfecObserver test(false, true, true, false, "H264", &encoder_factory); RunBaseTest(&test); } // Without retransmissions FEC for H264 is fine. TEST_F(VideoSendStreamTest, DoesUtilizeUlpfecForH264WithoutNackEnabled) { - std::unique_ptr encoder( - new test::FakeH264Encoder(Clock::GetRealTimeClock())); - UlpfecObserver test(false, false, true, true, "H264", encoder.get()); + test::FunctionVideoEncoderFactory encoder_factory([]() { + return rtc::MakeUnique(Clock::GetRealTimeClock()); + }); + UlpfecObserver test(false, false, true, true, "H264", &encoder_factory); RunBaseTest(&test); } // Disabled as flaky, see https://crbug.com/webrtc/7285 for details. TEST_F(VideoSendStreamTest, DISABLED_DoesUtilizeUlpfecForVp8WithNackEnabled) { - std::unique_ptr encoder(VP8Encoder::Create()); - UlpfecObserver test(false, true, true, true, "VP8", encoder.get()); + test::FunctionVideoEncoderFactory encoder_factory( + []() { return VP8Encoder::Create(); }); + UlpfecObserver test(false, true, true, true, "VP8", &encoder_factory); RunBaseTest(&test); } #if !defined(RTC_DISABLE_VP9) // Disabled as flaky, see https://crbug.com/webrtc/7285 for details. TEST_F(VideoSendStreamTest, DISABLED_DoesUtilizeUlpfecForVp9WithNackEnabled) { - std::unique_ptr encoder(VP9Encoder::Create()); - UlpfecObserver test(false, true, true, true, "VP9", encoder.get()); + test::FunctionVideoEncoderFactory encoder_factory( + []() { return VP9Encoder::Create(); }); + UlpfecObserver test(false, true, true, true, "VP9", &encoder_factory); RunBaseTest(&test); } #endif // !defined(RTC_DISABLE_VP9) TEST_F(VideoSendStreamTest, SupportsUlpfecWithMultithreadedH264) { - std::unique_ptr encoder( - new test::MultithreadedFakeH264Encoder(Clock::GetRealTimeClock())); - UlpfecObserver test(false, false, true, true, "H264", encoder.get()); + test::FunctionVideoEncoderFactory encoder_factory([]() { + return rtc::MakeUnique( + Clock::GetRealTimeClock()); + }); + UlpfecObserver test(false, false, true, true, "H264", &encoder_factory); RunBaseTest(&test); } @@ -642,10 +658,10 @@ class FlexfecObserver : public test::EndToEndTest { FlexfecObserver(bool header_extensions_enabled, bool use_nack, const std::string& codec, - VideoEncoder* encoder, + VideoEncoderFactory* encoder_factory, size_t num_video_streams) : EndToEndTest(VideoSendStreamTest::kDefaultTimeoutMs), - encoder_(encoder), + encoder_factory_(encoder_factory), payload_name_(codec), use_nack_(use_nack), sent_media_(false), @@ -709,7 +725,7 @@ class FlexfecObserver : public test::EndToEndTest { (*receive_configs)[0].rtp.nack.rtp_history_ms = VideoSendStreamTest::kNackRtpHistoryMs; } - send_config->encoder_settings.encoder = encoder_; + send_config->encoder_settings.encoder_factory = encoder_factory_; send_config->rtp.payload_name = payload_name_; if (header_extensions_enabled_) { send_config->rtp.extensions.push_back(RtpExtension( @@ -727,7 +743,7 @@ class FlexfecObserver : public test::EndToEndTest { << "Timed out waiting for FlexFEC and/or media packets."; } - VideoEncoder* const encoder_; + VideoEncoderFactory* encoder_factory_; std::string payload_name_; const bool use_nack_; bool sent_media_; @@ -737,61 +753,72 @@ class FlexfecObserver : public test::EndToEndTest { }; TEST_F(VideoSendStreamTest, SupportsFlexfecVp8) { - std::unique_ptr encoder(VP8Encoder::Create()); - FlexfecObserver test(false, false, "VP8", encoder.get(), 1); + test::FunctionVideoEncoderFactory encoder_factory( + []() { return VP8Encoder::Create(); }); + FlexfecObserver test(false, false, "VP8", &encoder_factory, 1); RunBaseTest(&test); } TEST_F(VideoSendStreamTest, SupportsFlexfecSimulcastVp8) { - std::unique_ptr encoder(VP8Encoder::Create()); - FlexfecObserver test(false, false, "VP8", encoder.get(), 2); + test::FunctionVideoEncoderFactory encoder_factory( + []() { return VP8Encoder::Create(); }); + FlexfecObserver test(false, false, "VP8", &encoder_factory, 2); RunBaseTest(&test); } TEST_F(VideoSendStreamTest, SupportsFlexfecWithNackVp8) { - std::unique_ptr encoder(VP8Encoder::Create()); - FlexfecObserver test(false, true, "VP8", encoder.get(), 1); + test::FunctionVideoEncoderFactory encoder_factory( + []() { return VP8Encoder::Create(); }); + FlexfecObserver test(false, true, "VP8", &encoder_factory, 1); RunBaseTest(&test); } TEST_F(VideoSendStreamTest, SupportsFlexfecWithRtpExtensionsVp8) { - std::unique_ptr encoder(VP8Encoder::Create()); - FlexfecObserver test(true, false, "VP8", encoder.get(), 1); + test::FunctionVideoEncoderFactory encoder_factory( + []() { return VP8Encoder::Create(); }); + FlexfecObserver test(true, false, "VP8", &encoder_factory, 1); RunBaseTest(&test); } #if !defined(RTC_DISABLE_VP9) TEST_F(VideoSendStreamTest, SupportsFlexfecVp9) { - std::unique_ptr encoder(VP9Encoder::Create()); - FlexfecObserver test(false, false, "VP9", encoder.get(), 1); + test::FunctionVideoEncoderFactory encoder_factory( + []() { return VP9Encoder::Create(); }); + FlexfecObserver test(false, false, "VP9", &encoder_factory, 1); RunBaseTest(&test); } TEST_F(VideoSendStreamTest, SupportsFlexfecWithNackVp9) { - std::unique_ptr encoder(VP9Encoder::Create()); - FlexfecObserver test(false, true, "VP9", encoder.get(), 1); + test::FunctionVideoEncoderFactory encoder_factory( + []() { return VP9Encoder::Create(); }); + FlexfecObserver test(false, true, "VP9", &encoder_factory, 1); RunBaseTest(&test); } #endif // defined(RTC_DISABLE_VP9) TEST_F(VideoSendStreamTest, SupportsFlexfecH264) { - std::unique_ptr encoder( - new test::FakeH264Encoder(Clock::GetRealTimeClock())); - FlexfecObserver test(false, false, "H264", encoder.get(), 1); + test::FunctionVideoEncoderFactory encoder_factory([]() { + return rtc::MakeUnique(Clock::GetRealTimeClock()); + }); + FlexfecObserver test(false, false, "H264", &encoder_factory, 1); RunBaseTest(&test); } TEST_F(VideoSendStreamTest, SupportsFlexfecWithNackH264) { - std::unique_ptr encoder( - new test::FakeH264Encoder(Clock::GetRealTimeClock())); - FlexfecObserver test(false, true, "H264", encoder.get(), 1); + test::FunctionVideoEncoderFactory encoder_factory([]() { + return rtc::MakeUnique(Clock::GetRealTimeClock()); + }); + FlexfecObserver test(false, true, "H264", &encoder_factory, 1); RunBaseTest(&test); } TEST_F(VideoSendStreamTest, SupportsFlexfecWithMultithreadedH264) { - std::unique_ptr encoder( - new test::MultithreadedFakeH264Encoder(Clock::GetRealTimeClock())); - FlexfecObserver test(false, false, "H264", encoder.get(), 1); + test::FunctionVideoEncoderFactory encoder_factory([]() { + return rtc::MakeUnique( + Clock::GetRealTimeClock()); + }); + + FlexfecObserver test(false, false, "H264", &encoder_factory, 1); RunBaseTest(&test); } @@ -921,6 +948,7 @@ void VideoSendStreamTest::TestPacketFragmentationSize(VideoFormat format, bool use_fec) : SendTest(kLongTimeoutMs), encoder_(stop), + encoder_factory_(&encoder_), max_packet_size_(max_packet_size), stop_size_(stop_size), test_generic_packetization_(test_generic_packetization), @@ -1076,8 +1104,7 @@ void VideoSendStreamTest::TestPacketFragmentationSize(VideoFormat format, if (!test_generic_packetization_) send_config->rtp.payload_name = "VP8"; - - send_config->encoder_settings.encoder = &encoder_; + send_config->encoder_settings.encoder_factory = &encoder_factory_; send_config->rtp.max_packet_size = kMaxPacketSize; send_config->post_encode_callback = this; @@ -1120,6 +1147,7 @@ void VideoSendStreamTest::TestPacketFragmentationSize(VideoFormat format, std::unique_ptr transport_adapter_; test::ConfigurableFrameSizeEncoder encoder_; + test::EncoderProxyFactory encoder_factory_; const size_t max_packet_size_; const size_t stop_size_; @@ -1908,11 +1936,12 @@ TEST_F(VideoSendStreamTest, test::NullTransport transport; EncoderObserver encoder; + test::EncoderProxyFactory encoder_factory(&encoder); - task_queue_.SendTask([this, &transport, &encoder]() { + task_queue_.SendTask([this, &transport, &encoder_factory]() { CreateSenderCall(Call::Config(event_log_.get())); CreateSendConfig(1, 0, 0, &transport); - video_send_config_.encoder_settings.encoder = &encoder; + video_send_config_.encoder_settings.encoder_factory = &encoder_factory; CreateVideoStreams(); CreateFrameGeneratorCapturer(kDefaultFramerate, kDefaultWidth, kDefaultHeight); @@ -1984,10 +2013,11 @@ TEST_F(VideoSendStreamTest, CanReconfigureToUseStartBitrateAbovePreviousMax) { bitrate_config); StartBitrateObserver encoder; - video_send_config_.encoder_settings.encoder = &encoder; + test::EncoderProxyFactory encoder_factory(&encoder); // Since this test does not use a capturer, set |internal_source| = true. // Encoder configuration is otherwise updated on the next video frame. - video_send_config_.encoder_settings.internal_source = true; + encoder_factory.SetHasInternalSource(true); + video_send_config_.encoder_settings.encoder_factory = &encoder_factory; CreateVideoStreams(); @@ -2066,17 +2096,24 @@ class StartStopBitrateObserver : public test::FakeEncoder { TEST_F(VideoSendStreamTest, VideoSendStreamStopSetEncoderRateToZero) { test::NullTransport transport; StartStopBitrateObserver encoder; + test::EncoderProxyFactory encoder_factory(&encoder); + encoder_factory.SetHasInternalSource(true); + test::FrameForwarder forwarder; - task_queue_.SendTask([this, &transport, &encoder]() { + task_queue_.SendTask([this, &transport, &encoder_factory, &forwarder]() { CreateSenderCall(Call::Config(event_log_.get())); CreateSendConfig(1, 0, 0, &transport); sender_call_->SignalChannelNetworkState(MediaType::VIDEO, kNetworkUp); - - video_send_config_.encoder_settings.encoder = &encoder; - video_send_config_.encoder_settings.internal_source = true; + video_send_config_.encoder_settings.encoder_factory = &encoder_factory; CreateVideoStreams(); + // Inject a frame, to force encoder creation. + video_send_stream_->Start(); + video_send_stream_->SetSource( + &forwarder, + VideoSendStream::DegradationPreference::kDegradationDisabled); + forwarder.IncomingCapturedFrame(CreateVideoFrame(640, 480, 4)); }); EXPECT_TRUE(encoder.WaitForEncoderInit()); @@ -2109,19 +2146,28 @@ TEST_F(VideoSendStreamTest, VideoSendStreamStopSetEncoderRateToZero) { TEST_F(VideoSendStreamTest, VideoSendStreamUpdateActiveSimulcastLayers) { test::NullTransport transport; StartStopBitrateObserver encoder; + test::EncoderProxyFactory encoder_factory(&encoder); + encoder_factory.SetHasInternalSource(true); + test::FrameForwarder forwarder; - task_queue_.SendTask([this, &transport, &encoder]() { + task_queue_.SendTask([this, &transport, &encoder_factory, &forwarder]() { CreateSenderCall(Call::Config(event_log_.get())); // Create two simulcast streams. CreateSendConfig(2, 0, 0, &transport); sender_call_->SignalChannelNetworkState(MediaType::VIDEO, kNetworkUp); + video_send_config_.encoder_settings.encoder_factory = &encoder_factory; - video_send_config_.encoder_settings.encoder = &encoder; - video_send_config_.encoder_settings.internal_source = true; video_send_config_.rtp.payload_name = "VP8"; CreateVideoStreams(); + + // Inject a frame, to force encoder creation. + video_send_stream_->Start(); + video_send_stream_->SetSource( + &forwarder, + VideoSendStream::DegradationPreference::kDegradationDisabled); + forwarder.IncomingCapturedFrame(CreateVideoFrame(640, 480, 4)); }); EXPECT_TRUE(encoder.WaitForEncoderInit()); @@ -2270,7 +2316,8 @@ TEST_F(VideoSendStreamTest, EncoderIsProperlyInitializedAndDestroyed) { initialized_(false), callback_registered_(false), num_releases_(0), - released_(false) {} + released_(false), + encoder_factory_(this) {} bool IsReleased() { rtc::CritScope lock(&crit_); @@ -2346,7 +2393,7 @@ TEST_F(VideoSendStreamTest, EncoderIsProperlyInitializedAndDestroyed) { VideoSendStream::Config* send_config, std::vector* receive_configs, VideoEncoderConfig* encoder_config) override { - send_config->encoder_settings.encoder = this; + send_config->encoder_settings.encoder_factory = &encoder_factory_; encoder_config_ = encoder_config->Copy(); } @@ -2375,6 +2422,7 @@ TEST_F(VideoSendStreamTest, EncoderIsProperlyInitializedAndDestroyed) { bool callback_registered_ RTC_GUARDED_BY(crit_); size_t num_releases_ RTC_GUARDED_BY(crit_); bool released_ RTC_GUARDED_BY(crit_); + test::EncoderProxyFactory encoder_factory_; VideoEncoderConfig encoder_config_; } test_encoder(&task_queue_); @@ -2393,14 +2441,15 @@ TEST_F(VideoSendStreamTest, EncoderSetupPropagatesCommonEncoderConfigValues) { FakeEncoder(Clock::GetRealTimeClock()), init_encode_event_(false, false), num_initializations_(0), - stream_(nullptr) {} + stream_(nullptr), + encoder_factory_(this) {} private: void ModifyVideoConfigs( VideoSendStream::Config* send_config, std::vector* receive_configs, VideoEncoderConfig* encoder_config) override { - send_config->encoder_settings.encoder = this; + send_config->encoder_settings.encoder_factory = &encoder_factory_; encoder_config->max_bitrate_bps = kFirstMaxBitrateBps; encoder_config_ = encoder_config->Copy(); } @@ -2444,6 +2493,7 @@ TEST_F(VideoSendStreamTest, EncoderSetupPropagatesCommonEncoderConfigValues) { rtc::Event init_encode_event_; size_t num_initializations_; VideoSendStream* stream_; + test::EncoderProxyFactory encoder_factory_; VideoEncoderConfig encoder_config_; } test; @@ -2463,7 +2513,8 @@ class VideoCodecConfigObserver : public test::SendTest, codec_name_(codec_name), init_encode_event_(false, false), num_initializations_(0), - stream_(nullptr) { + stream_(nullptr), + encoder_factory_(this) { InitCodecSpecifics(); } @@ -2492,7 +2543,7 @@ class VideoCodecConfigObserver : public test::SendTest, VideoSendStream::Config* send_config, std::vector* receive_configs, VideoEncoderConfig* encoder_config) override { - send_config->encoder_settings.encoder = this; + send_config->encoder_settings.encoder_factory = &encoder_factory_; send_config->rtp.payload_name = codec_name_; encoder_config->codec_type = video_codec_type_; @@ -2552,6 +2603,7 @@ class VideoCodecConfigObserver : public test::SendTest, rtc::Event init_encode_event_; size_t num_initializations_; VideoSendStream* stream_; + test::EncoderProxyFactory encoder_factory_; VideoEncoderConfig encoder_config_; }; @@ -2738,7 +2790,8 @@ TEST_F(VideoSendStreamTest, TranslatesTwoLayerScreencastToTargetBitrate) { public: ScreencastTargetBitrateTest() : SendTest(kDefaultTimeoutMs), - test::FakeEncoder(Clock::GetRealTimeClock()) {} + test::FakeEncoder(Clock::GetRealTimeClock()), + encoder_factory_(this) {} private: int32_t InitEncode(const VideoCodec* config, @@ -2754,7 +2807,7 @@ TEST_F(VideoSendStreamTest, TranslatesTwoLayerScreencastToTargetBitrate) { VideoSendStream::Config* send_config, std::vector* receive_configs, VideoEncoderConfig* encoder_config) override { - send_config->encoder_settings.encoder = this; + send_config->encoder_settings.encoder_factory = &encoder_factory_; EXPECT_EQ(1u, encoder_config->number_of_streams); encoder_config->video_stream_factory = new rtc::RefCountedObject(); @@ -2765,6 +2818,7 @@ TEST_F(VideoSendStreamTest, TranslatesTwoLayerScreencastToTargetBitrate) { EXPECT_TRUE(Wait()) << "Timed out while waiting for the encoder to be initialized."; } + test::EncoderProxyFactory encoder_factory_; } test; RunBaseTest(&test); @@ -2792,7 +2846,8 @@ TEST_F(VideoSendStreamTest, ReconfigureBitratesSetsEncoderBitratesCorrectly) { target_bitrate_(0), num_initializations_(0), call_(nullptr), - send_stream_(nullptr) {} + send_stream_(nullptr), + encoder_factory_(this) {} private: int32_t InitEncode(const VideoCodec* codecSettings, @@ -2882,7 +2937,7 @@ TEST_F(VideoSendStreamTest, ReconfigureBitratesSetsEncoderBitratesCorrectly) { VideoSendStream::Config* send_config, std::vector* receive_configs, VideoEncoderConfig* encoder_config) override { - send_config->encoder_settings.encoder = this; + send_config->encoder_settings.encoder_factory = &encoder_factory_; // Set bitrates lower/higher than min/max to make sure they are properly // capped. encoder_config->max_bitrate_bps = kMaxBitrateKbps * 1000; @@ -2945,6 +3000,7 @@ TEST_F(VideoSendStreamTest, ReconfigureBitratesSetsEncoderBitratesCorrectly) { int num_initializations_; webrtc::Call* call_; webrtc::VideoSendStream* send_stream_; + test::EncoderProxyFactory encoder_factory_; webrtc::VideoEncoderConfig encoder_config_; } test(&task_queue_); @@ -2965,7 +3021,8 @@ TEST_F(VideoSendStreamTest, ReportsSentResolution) { ScreencastTargetBitrateTest() : SendTest(kDefaultTimeoutMs), test::FakeEncoder(Clock::GetRealTimeClock()), - send_stream_(nullptr) {} + send_stream_(nullptr), + encoder_factory_(this) {} private: int32_t Encode(const VideoFrame& input_image, @@ -3003,7 +3060,7 @@ TEST_F(VideoSendStreamTest, ReportsSentResolution) { VideoSendStream::Config* send_config, std::vector* receive_configs, VideoEncoderConfig* encoder_config) override { - send_config->encoder_settings.encoder = this; + send_config->encoder_settings.encoder_factory = &encoder_factory_; EXPECT_EQ(kNumStreams, encoder_config->number_of_streams); } @@ -3033,6 +3090,7 @@ TEST_F(VideoSendStreamTest, ReportsSentResolution) { } VideoSendStream* send_stream_; + test::EncoderProxyFactory encoder_factory_; } test; RunBaseTest(&test); @@ -3043,7 +3101,7 @@ class Vp9HeaderObserver : public test::SendTest { public: Vp9HeaderObserver() : SendTest(VideoSendStreamTest::kLongTimeoutMs), - vp9_encoder_(VP9Encoder::Create()), + encoder_factory_([]() { return VP9Encoder::Create(); }), vp9_settings_(VideoEncoder::GetDefaultVp9Settings()), packets_sent_(0), frames_sent_(0), @@ -3084,7 +3142,7 @@ class Vp9HeaderObserver : public test::SendTest { VideoSendStream::Config* send_config, std::vector* receive_configs, VideoEncoderConfig* encoder_config) override { - send_config->encoder_settings.encoder = vp9_encoder_.get(); + send_config->encoder_settings.encoder_factory = &encoder_factory_; send_config->rtp.payload_name = "VP9"; send_config->rtp.payload_type = kVp9PayloadType; ModifyVideoConfigsHook(send_config, receive_configs, encoder_config); @@ -3346,7 +3404,7 @@ class Vp9HeaderObserver : public test::SendTest { VerifyTl0Idx(vp9); } - std::unique_ptr vp9_encoder_; + test::FunctionVideoEncoderFactory encoder_factory_; VideoCodecVP9 vp9_settings_; webrtc::VideoEncoderConfig encoder_config_; RTPHeader last_header_; @@ -3593,6 +3651,7 @@ TEST_F(VideoSendStreamTest, RemoveOverheadFromBandwidth) { : EndToEndTest(test::CallTest::kDefaultTimeoutMs), FakeEncoder(Clock::GetRealTimeClock()), task_queue_(task_queue), + encoder_factory_(this), call_(nullptr), max_bitrate_bps_(0), first_packet_sent_(false), @@ -3619,7 +3678,7 @@ TEST_F(VideoSendStreamTest, RemoveOverheadFromBandwidth) { std::vector* receive_configs, VideoEncoderConfig* encoder_config) override { send_config->rtp.max_packet_size = 1200; - send_config->encoder_settings.encoder = this; + send_config->encoder_settings.encoder_factory = &encoder_factory_; EXPECT_FALSE(send_config->rtp.extensions.empty()); } @@ -3646,7 +3705,8 @@ TEST_F(VideoSendStreamTest, RemoveOverheadFromBandwidth) { // At a bitrate of 60kbps with a packet size of 1200B video and an // overhead of 40B per packet video produces 2240bps overhead. // So the encoder BW should be set to 57760bps. - bitrate_changed_event_.Wait(VideoSendStreamTest::kDefaultTimeoutMs); + EXPECT_TRUE( + bitrate_changed_event_.Wait(VideoSendStreamTest::kDefaultTimeoutMs)); { rtc::CritScope lock(&crit_); EXPECT_LE(max_bitrate_bps_, 57760u); @@ -3655,6 +3715,7 @@ TEST_F(VideoSendStreamTest, RemoveOverheadFromBandwidth) { private: test::SingleThreadedTaskQueueForTesting* const task_queue_; + test::EncoderProxyFactory encoder_factory_; Call* call_; rtc::CriticalSection crit_; uint32_t max_bitrate_bps_ RTC_GUARDED_BY(&crit_); diff --git a/video/video_stream_encoder.cc b/video/video_stream_encoder.cc index 1e70cdb2cb..647dc800c6 100644 --- a/video/video_stream_encoder.cc +++ b/video/video_stream_encoder.cc @@ -91,10 +91,11 @@ bool IsFramerateScalingEnabled( // out). This should effectively turn off CPU adaptations for systems that // remotely cope with the load right now. CpuOveruseOptions GetCpuOveruseOptions( - const VideoSendStream::Config::EncoderSettings& settings) { + const VideoSendStream::Config::EncoderSettings& settings, + bool full_overuse_time) { CpuOveruseOptions options; - if (settings.full_overuse_time) { + if (full_overuse_time) { options.low_encode_usage_threshold_percent = 150; options.high_encode_usage_threshold_percent = 200; } @@ -338,6 +339,7 @@ VideoStreamEncoder::VideoStreamEncoder( pre_encode_callback_(pre_encode_callback), max_framerate_(-1), pending_encoder_reconfiguration_(false), + pending_encoder_creation_(false), encoder_start_bitrate_bps_(0), max_data_payload_length_(0), nack_enabled_(false), @@ -357,13 +359,6 @@ VideoStreamEncoder::VideoStreamEncoder( encoder_queue_("EncoderQueue") { RTC_DCHECK(stats_proxy); RTC_DCHECK(overuse_detector_); - encoder_queue_.PostTask([this] { - RTC_DCHECK_RUN_ON(&encoder_queue_); - overuse_detector_->StartCheckForOveruse(GetCpuOveruseOptions(settings_), - this); - video_sender_.RegisterExternalEncoder( - settings_.encoder, settings_.internal_source); - }); } VideoStreamEncoder::~VideoStreamEncoder() { @@ -422,7 +417,10 @@ void VideoStreamEncoder::SetSource( degradation_preference_ = degradation_preference; bool allow_scaling = IsResolutionScalingEnabled(degradation_preference_); initial_rampup_ = allow_scaling ? 0 : kMaxInitialFramedrop; - ConfigureQualityScaler(); + + stats_proxy_->SetAdaptationStats(GetActiveCounts(kCpu), + GetActiveCounts(kQuality)); + if (!IsFramerateScalingEnabled(degradation_preference) && max_framerate_ != -1) { // If frame rate scaling is no longer allowed, remove any potential @@ -476,6 +474,8 @@ void VideoStreamEncoder::ConfigureEncoderOnTaskQueue( max_data_payload_length_ = max_data_payload_length; nack_enabled_ = nack_enabled; + pending_encoder_creation_ = + (!encoder_ || encoder_config_.video_format != config.video_format); encoder_config_ = std::move(config); pending_encoder_reconfiguration_ = true; @@ -485,7 +485,8 @@ void VideoStreamEncoder::ConfigureEncoderOnTaskQueue( // The codec configuration depends on incoming video frame size. if (last_frame_info_) { ReconfigureEncoder(); - } else if (settings_.internal_source) { + } else if (settings_.encoder_factory->QueryVideoEncoder( + encoder_config_.video_format).has_internal_source) { last_frame_info_ = VideoFrameInfo(176, 144, false); ReconfigureEncoder(); } @@ -528,6 +529,34 @@ void VideoStreamEncoder::ReconfigureEncoder() { max_framerate_ = codec.maxFramerate; RTC_DCHECK_LE(max_framerate_, kMaxFramerateFps); + // Keep the same encoder, as long as the video_format is unchanged. + if (pending_encoder_creation_) { + pending_encoder_creation_ = false; + if (encoder_) { + video_sender_.RegisterExternalEncoder(nullptr, false); + } + + encoder_ = settings_.encoder_factory->CreateVideoEncoder( + encoder_config_.video_format); + // TODO(nisse): What to do if creating the encoder fails? Crash, + // or just discard incoming frames? + RTC_CHECK(encoder_); + + ConfigureQualityScaler(); + + const webrtc::VideoEncoderFactory::CodecInfo info = + settings_.encoder_factory->QueryVideoEncoder( + encoder_config_.video_format); + + overuse_detector_->StopCheckForOveruse(); + overuse_detector_->StartCheckForOveruse( + GetCpuOveruseOptions(settings_, info.is_hardware_accelerated), this); + + video_sender_.RegisterExternalEncoder(encoder_.get(), + info.has_internal_source); + } + // RegisterSendCodec implies an unconditional call to + // encoder_->InitEncode(). bool success = video_sender_.RegisterSendCodec( &codec, number_of_cores_, static_cast(max_data_payload_length_)) == VCM_OK; @@ -563,13 +592,11 @@ void VideoStreamEncoder::ReconfigureEncoder() { int target_framerate = std::min( max_framerate_, source_proxy_->GetActiveSinkWants().max_framerate_fps); overuse_detector_->OnTargetFramerateUpdated(target_framerate); - - ConfigureQualityScaler(); } void VideoStreamEncoder::ConfigureQualityScaler() { RTC_DCHECK_RUN_ON(&encoder_queue_); - const auto scaling_settings = settings_.encoder->GetScalingSettings(); + const auto scaling_settings = encoder_->GetScalingSettings(); const bool quality_scaling_allowed = IsResolutionScalingEnabled(degradation_preference_) && scaling_settings.thresholds; @@ -589,6 +616,8 @@ void VideoStreamEncoder::ConfigureQualityScaler() { initial_rampup_ = kMaxInitialFramedrop; } + // TODO(nisse): Is this still the right place to do this? This is + // now called when the encoder is created. stats_proxy_->SetAdaptationStats(GetActiveCounts(kCpu), GetActiveCounts(kQuality)); } @@ -723,6 +752,24 @@ void VideoStreamEncoder::MaybeEncodeVideoFrame(const VideoFrame& video_frame, << ", texture=" << last_frame_info_->is_texture << "."; } + // We have to create then encoder before the frame drop logic, + // because the latter depends on encoder_->GetScalingSettings. + // According to the testcase + // InitialFrameDropOffWhenEncoderDisabledScaling, the return value + // from GetScalingSettings should enable or disable the frame drop. + + int64_t now_ms = clock_->TimeInMilliseconds(); + if (pending_encoder_reconfiguration_) { + ReconfigureEncoder(); + last_parameters_update_ms_.emplace(now_ms); + } else if (!last_parameters_update_ms_ || + now_ms - *last_parameters_update_ms_ >= + vcm::VCMProcessTimer::kDefaultProcessIntervalMs) { + video_sender_.UpdateChannelParameters(rate_allocator_.get(), + bitrate_observer_); + last_parameters_update_ms_.emplace(now_ms); + } + if (DropDueToSize(video_frame.size())) { RTC_LOG(LS_INFO) << "Dropping frame. Too large for target bitrate."; int count = GetConstAdaptCounter().ResolutionCount(kQuality); @@ -744,17 +791,6 @@ void VideoStreamEncoder::MaybeEncodeVideoFrame(const VideoFrame& video_frame, } initial_rampup_ = kMaxInitialFramedrop; - int64_t now_ms = clock_->TimeInMilliseconds(); - if (pending_encoder_reconfiguration_) { - ReconfigureEncoder(); - last_parameters_update_ms_.emplace(now_ms); - } else if (!last_parameters_update_ms_ || - now_ms - *last_parameters_update_ms_ >= - vcm::VCMProcessTimer::kDefaultProcessIntervalMs) { - video_sender_.UpdateChannelParameters(rate_allocator_.get(), - bitrate_observer_); - last_parameters_update_ms_.emplace(now_ms); - } if (EncoderPaused()) { // Storing references to a native buffer risks blocking frame capture. @@ -986,7 +1022,7 @@ void VideoStreamEncoder::AdaptDown(AdaptReason reason) { bool min_pixels_reached = false; if (!source_proxy_->RequestResolutionLowerThan( adaptation_request.input_pixel_count_, - settings_.encoder->GetScalingSettings().min_pixels_per_frame, + encoder_->GetScalingSettings().min_pixels_per_frame, &min_pixels_reached)) { if (min_pixels_reached) stats_proxy_->OnMinPixelLimitReached(); diff --git a/video/video_stream_encoder.h b/video/video_stream_encoder.h index a81160e8c5..ac4f2549ff 100644 --- a/video/video_stream_encoder.h +++ b/video/video_stream_encoder.h @@ -231,6 +231,8 @@ class VideoStreamEncoder : public rtc::VideoSinkInterface, rtc::ThreadChecker thread_checker_; VideoEncoderConfig encoder_config_ RTC_GUARDED_BY(&encoder_queue_); + std::unique_ptr encoder_ RTC_GUARDED_BY(&encoder_queue_) + RTC_PT_GUARDED_BY(&encoder_queue_); std::unique_ptr rate_allocator_ RTC_GUARDED_BY(&encoder_queue_) RTC_PT_GUARDED_BY(&encoder_queue_); @@ -241,6 +243,9 @@ class VideoStreamEncoder : public rtc::VideoSinkInterface, // Set when ConfigureEncoder has been called in order to lazy reconfigure the // encoder on the next frame. bool pending_encoder_reconfiguration_ RTC_GUARDED_BY(&encoder_queue_); + // Set when configuration must create a new encoder object, e.g., + // because of a codec change. + bool pending_encoder_creation_ RTC_GUARDED_BY(&encoder_queue_); rtc::Optional last_frame_info_ RTC_GUARDED_BY(&encoder_queue_); int crop_width_ RTC_GUARDED_BY(&encoder_queue_); diff --git a/video/video_stream_encoder_unittest.cc b/video/video_stream_encoder_unittest.cc index 8a6d4e1c20..4b392239bb 100644 --- a/video/video_stream_encoder_unittest.cc +++ b/video/video_stream_encoder_unittest.cc @@ -21,6 +21,7 @@ #include "rtc_base/logging.h" #include "system_wrappers/include/metrics_default.h" #include "system_wrappers/include/sleep.h" +#include "test/encoder_proxy_factory.h" #include "test/encoder_settings.h" #include "test/fake_encoder.h" #include "test/frame_generator.h" @@ -83,6 +84,8 @@ class CpuOveruseDetectorProxy : public OveruseFrameDetector { return last_target_framerate_fps_; } + CpuOveruseOptions GetOptions() { return options_; } + private: rtc::CriticalSection lock_; int last_target_framerate_fps_ RTC_GUARDED_BY(lock_); @@ -272,6 +275,7 @@ class VideoStreamEncoderTest : public ::testing::Test { codec_height_(240), max_framerate_(30), fake_encoder_(), + encoder_factory_(&fake_encoder_), stats_proxy_(new MockableSendStatisticsProxy( Clock::GetRealTimeClock(), video_send_config_, @@ -281,7 +285,7 @@ class VideoStreamEncoderTest : public ::testing::Test { void SetUp() override { metrics::Reset(); video_send_config_ = VideoSendStream::Config(nullptr); - video_send_config_.encoder_settings.encoder = &fake_encoder_; + video_send_config_.encoder_settings.encoder_factory = &encoder_factory_; video_send_config_.rtp.payload_name = "FAKE"; video_send_config_.rtp.payload_type = 125; @@ -683,6 +687,7 @@ class VideoStreamEncoderTest : public ::testing::Test { int codec_height_; int max_framerate_; TestEncoder fake_encoder_; + test::EncoderProxyFactory encoder_factory_; std::unique_ptr stats_proxy_; TestSink sink_; AdaptingFrameForwarder video_source_; @@ -1437,11 +1442,16 @@ TEST_F(VideoStreamEncoderTest, EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_resolution); EXPECT_EQ(1, stats_proxy_->GetStats().number_of_cpu_adapt_changes); - // Set source with adaptation still enabled but quality scaler is off. + // Leave source unchanged, but disable quality scaler. fake_encoder_.SetQualityScaling(false); - video_stream_encoder_->SetSource( - &video_source_, - VideoSendStream::DegradationPreference::kMaintainFramerate); + + VideoEncoderConfig video_encoder_config; + test::FillEncoderConfiguration(kVideoCodecVP8, 1, &video_encoder_config); + // Make format different, to force recreation of encoder. + video_encoder_config.video_format.parameters["foo"] = "foo"; + video_stream_encoder_->ConfigureEncoder(std::move(video_encoder_config), + kMaxPayloadLength, + true /* nack_enabled */); video_source_.IncomingCapturedFrame(CreateFrame(4, kWidth, kHeight)); WaitForEncodedFrame(4); @@ -2516,6 +2526,14 @@ TEST_F(VideoStreamEncoderTest, InitialFrameDropOffWhenEncoderDisabledScaling) { const int kWidth = 640; const int kHeight = 360; fake_encoder_.SetQualityScaling(false); + + VideoEncoderConfig video_encoder_config; + test::FillEncoderConfiguration(kVideoCodecVP8, 1, &video_encoder_config); + // Make format different, to force recreation of encoder. + video_encoder_config.video_format.parameters["foo"] = "foo"; + video_stream_encoder_->ConfigureEncoder(std::move(video_encoder_config), + kMaxPayloadLength, + true /* nack_enabled */); video_stream_encoder_->OnBitrateUpdated(kLowTargetBitrateBps, 0, 0); // Force quality scaler reconfiguration by resetting the source. @@ -3314,4 +3332,44 @@ TEST_F(VideoStreamEncoderTest, DoesNotUpdateBitrateAllocationWhenSuspended) { video_stream_encoder_->Stop(); } +TEST_F(VideoStreamEncoderTest, + DefaultCpuAdaptationThresholdsForSoftwareEncoder) { + const int kFrameWidth = 1280; + const int kFrameHeight = 720; + const CpuOveruseOptions default_options; + video_stream_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0); + video_source_.IncomingCapturedFrame( + CreateFrame(1, kFrameWidth, kFrameHeight)); + WaitForEncodedFrame(1); + EXPECT_EQ(video_stream_encoder_->overuse_detector_proxy_->GetOptions() + .low_encode_usage_threshold_percent, + default_options.low_encode_usage_threshold_percent); + EXPECT_EQ(video_stream_encoder_->overuse_detector_proxy_->GetOptions() + .high_encode_usage_threshold_percent, + default_options.high_encode_usage_threshold_percent); + video_stream_encoder_->Stop(); +} + +TEST_F(VideoStreamEncoderTest, + HigherCpuAdaptationThresholdsForHardwareEncoder) { + const int kFrameWidth = 1280; + const int kFrameHeight = 720; + CpuOveruseOptions hardware_options; + hardware_options.low_encode_usage_threshold_percent = 150; + hardware_options.high_encode_usage_threshold_percent = 200; + encoder_factory_.SetIsHardwareAccelerated(true); + + video_stream_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0); + video_source_.IncomingCapturedFrame( + CreateFrame(1, kFrameWidth, kFrameHeight)); + WaitForEncodedFrame(1); + EXPECT_EQ(video_stream_encoder_->overuse_detector_proxy_->GetOptions() + .low_encode_usage_threshold_percent, + hardware_options.low_encode_usage_threshold_percent); + EXPECT_EQ(video_stream_encoder_->overuse_detector_proxy_->GetOptions() + .high_encode_usage_threshold_percent, + hardware_options.high_encode_usage_threshold_percent); + video_stream_encoder_->Stop(); +} + } // namespace webrtc