diff --git a/api/test/mock_video_encoder_factory.h b/api/test/mock_video_encoder_factory.h index 845251bdef..a694b636e0 100644 --- a/api/test/mock_video_encoder_factory.h +++ b/api/test/mock_video_encoder_factory.h @@ -24,6 +24,8 @@ class MockVideoEncoderFactory : public webrtc::VideoEncoderFactory { public: MOCK_CONST_METHOD0(GetSupportedFormats, std::vector()); + MOCK_CONST_METHOD1(QueryVideoEncoder, + CodecInfo(const webrtc::SdpVideoFormat&)); // We need to proxy to a return type that is copyable. std::unique_ptr CreateVideoEncoder( diff --git a/api/test/video/function_video_encoder_factory.h b/api/test/video/function_video_encoder_factory.h index 514bd489cf..85f848cd1f 100644 --- a/api/test/video/function_video_encoder_factory.h +++ b/api/test/video/function_video_encoder_factory.h @@ -41,6 +41,14 @@ class FunctionVideoEncoderFactory final : public VideoEncoderFactory { return {}; } + CodecInfo QueryVideoEncoder( + const SdpVideoFormat& /* format */) const override { + CodecInfo codec_info; + codec_info.is_hardware_accelerated = false; + codec_info.has_internal_source = false; + return codec_info; + } + std::unique_ptr CreateVideoEncoder( const SdpVideoFormat& format) override { return create_(format); diff --git a/api/video_codecs/BUILD.gn b/api/video_codecs/BUILD.gn index 0fd0b99f44..534a34e561 100644 --- a/api/video_codecs/BUILD.gn +++ b/api/video_codecs/BUILD.gn @@ -27,7 +27,6 @@ rtc_source_set("video_codecs_api") { "video_encoder.h", "video_encoder_config.cc", "video_encoder_config.h", - "video_encoder_factory.cc", "video_encoder_factory.h", "vp8_temporal_layers.h", ] diff --git a/api/video_codecs/builtin_video_encoder_factory.cc b/api/video_codecs/builtin_video_encoder_factory.cc index e687871cc3..1778c218cb 100644 --- a/api/video_codecs/builtin_video_encoder_factory.cc +++ b/api/video_codecs/builtin_video_encoder_factory.cc @@ -44,6 +44,17 @@ class BuiltinVideoEncoderFactory : public VideoEncoderFactory { BuiltinVideoEncoderFactory() : internal_encoder_factory_(new InternalEncoderFactory()) {} + VideoEncoderFactory::CodecInfo QueryVideoEncoder( + const SdpVideoFormat& format) const override { + // Format must be one of the internal formats. + RTC_DCHECK(IsFormatSupported( + internal_encoder_factory_->GetSupportedFormats(), format)); + VideoEncoderFactory::CodecInfo info; + info.has_internal_source = false; + info.is_hardware_accelerated = false; + return info; + } + std::unique_ptr CreateVideoEncoder( const SdpVideoFormat& format) override { // Try creating internal encoder. diff --git a/api/video_codecs/video_encoder_factory.cc b/api/video_codecs/video_encoder_factory.cc deleted file mode 100644 index de71aa6bd4..0000000000 --- a/api/video_codecs/video_encoder_factory.cc +++ /dev/null @@ -1,26 +0,0 @@ -/* - * 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. - */ - -#include "api/video_codecs/video_encoder_factory.h" - -// TODO(webrtc:10065) Remove once downstream projects have been updated. -namespace webrtc { - -VideoEncoderFactory::CodecInfo::CodecInfo() - : is_hardware_accelerated(false), has_internal_source(false) {} - -VideoEncoderFactory::CodecInfo::~CodecInfo() = default; - -VideoEncoderFactory::CodecInfo VideoEncoderFactory::QueryVideoEncoder( - const SdpVideoFormat& format) const { - return CodecInfo(); -} - -} // namespace webrtc diff --git a/api/video_codecs/video_encoder_factory.h b/api/video_codecs/video_encoder_factory.h index 7b2b156f2f..7958d16acc 100644 --- a/api/video_codecs/video_encoder_factory.h +++ b/api/video_codecs/video_encoder_factory.h @@ -25,9 +25,6 @@ class VideoEncoderFactory { public: // TODO(magjed): Try to get rid of this struct. struct CodecInfo { - CodecInfo(); - ~CodecInfo(); - // |is_hardware_accelerated| is true if the encoders created by this factory // of the given codec will use hardware support. bool is_hardware_accelerated; @@ -46,7 +43,7 @@ class VideoEncoderFactory { // Returns information about how this format will be encoded. The specified // format must be one of the supported formats by this factory. // TODO(magjed): Try to get rid of this method. - virtual CodecInfo QueryVideoEncoder(const SdpVideoFormat& format) const; + virtual CodecInfo QueryVideoEncoder(const SdpVideoFormat& format) const = 0; // Creates a VideoEncoder for the specified format. virtual std::unique_ptr CreateVideoEncoder( diff --git a/media/engine/convert_legacy_video_factory.cc b/media/engine/convert_legacy_video_factory.cc index e9a21d1c04..4c30dc24a5 100644 --- a/media/engine/convert_legacy_video_factory.cc +++ b/media/engine/convert_legacy_video_factory.cc @@ -60,6 +60,21 @@ class CricketToWebRtcEncoderFactory : public webrtc::VideoEncoderFactory { std::unique_ptr external_encoder_factory) : external_encoder_factory_(std::move(external_encoder_factory)) {} + webrtc::VideoEncoderFactory::CodecInfo QueryVideoEncoder( + const webrtc::SdpVideoFormat& format) const override { + CodecInfo info; + info.has_internal_source = false; + info.is_hardware_accelerated = false; + if (!external_encoder_factory_) + return info; + + info.has_internal_source = + external_encoder_factory_->EncoderTypeHasInternalSource( + webrtc::PayloadStringToCodecType(format.name)); + info.is_hardware_accelerated = true; + return info; + } + std::vector GetSupportedFormats() const override { if (!external_encoder_factory_) return std::vector(); @@ -98,6 +113,22 @@ class EncoderAdapter : public webrtc::VideoEncoderFactory { : internal_encoder_factory_(new webrtc::InternalEncoderFactory()), external_encoder_factory_(std::move(external_encoder_factory)) {} + webrtc::VideoEncoderFactory::CodecInfo QueryVideoEncoder( + const webrtc::SdpVideoFormat& format) const override { + if (IsFormatSupported(external_encoder_factory_->GetSupportedFormats(), + format)) { + return external_encoder_factory_->QueryVideoEncoder(format); + } + + // Format must be one of the internal formats. + RTC_DCHECK(IsFormatSupported( + internal_encoder_factory_->GetSupportedFormats(), format)); + webrtc::VideoEncoderFactory::CodecInfo info; + info.has_internal_source = false; + info.is_hardware_accelerated = false; + return info; + } + std::unique_ptr CreateVideoEncoder( const webrtc::SdpVideoFormat& format) override { // Try creating internal encoder. diff --git a/media/engine/fakewebrtcvideoengine.cc b/media/engine/fakewebrtcvideoengine.cc index 331516aa2a..897f8f4a98 100644 --- a/media/engine/fakewebrtcvideoengine.cc +++ b/media/engine/fakewebrtcvideoengine.cc @@ -187,17 +187,10 @@ int FakeWebRtcVideoEncoder::GetNumEncodedFrames() { return num_frames_encoded_; } -webrtc::VideoEncoder::EncoderInfo FakeWebRtcVideoEncoder::GetEncoderInfo() - const { - EncoderInfo info; - info.is_hardware_accelerated = true; - info.has_internal_source = false; - return info; -} - // Video encoder factory. FakeWebRtcVideoEncoderFactory::FakeWebRtcVideoEncoderFactory() : num_created_encoders_(0), + encoders_have_internal_sources_(false), vp8_factory_mode_(false) {} std::vector @@ -237,6 +230,15 @@ FakeWebRtcVideoEncoderFactory::CreateVideoEncoder( return encoder; } +webrtc::VideoEncoderFactory::CodecInfo +FakeWebRtcVideoEncoderFactory::QueryVideoEncoder( + const webrtc::SdpVideoFormat& format) const { + webrtc::VideoEncoderFactory::CodecInfo info; + info.has_internal_source = encoders_have_internal_sources_; + info.is_hardware_accelerated = true; + return info; +} + bool FakeWebRtcVideoEncoderFactory::WaitForCreatedVideoEncoders( int num_encoders) { int64_t start_offset_ms = rtc::TimeMillis(); @@ -256,6 +258,11 @@ void FakeWebRtcVideoEncoderFactory::EncoderDestroyed( encoders_.end()); } +void FakeWebRtcVideoEncoderFactory::set_encoders_have_internal_sources( + bool internal_source) { + encoders_have_internal_sources_ = internal_source; +} + void FakeWebRtcVideoEncoderFactory::AddSupportedVideoCodec( const webrtc::SdpVideoFormat& format) { formats_.push_back(format); diff --git a/media/engine/fakewebrtcvideoengine.h b/media/engine/fakewebrtcvideoengine.h index 0f06c33249..1d1839a554 100644 --- a/media/engine/fakewebrtcvideoengine.h +++ b/media/engine/fakewebrtcvideoengine.h @@ -96,7 +96,6 @@ class FakeWebRtcVideoEncoder : public webrtc::VideoEncoder { int32_t Release() override; int32_t SetRateAllocation(const webrtc::VideoBitrateAllocation& allocation, uint32_t framerate) override; - webrtc::VideoEncoder::EncoderInfo GetEncoderInfo() const override; bool WaitForInitEncode(); webrtc::VideoCodec GetCodecSettings(); @@ -118,6 +117,8 @@ class FakeWebRtcVideoEncoderFactory : public webrtc::VideoEncoderFactory { std::vector GetSupportedFormats() const override; std::unique_ptr CreateVideoEncoder( const webrtc::SdpVideoFormat& format) override; + CodecInfo QueryVideoEncoder( + const webrtc::SdpVideoFormat& format) const override; bool WaitForCreatedVideoEncoders(int num_encoders); void EncoderDestroyed(FakeWebRtcVideoEncoder* encoder); diff --git a/media/engine/internalencoderfactory.cc b/media/engine/internalencoderfactory.cc index 8c6b360ebd..bf940a1f04 100644 --- a/media/engine/internalencoderfactory.cc +++ b/media/engine/internalencoderfactory.cc @@ -34,6 +34,14 @@ std::vector InternalEncoderFactory::GetSupportedFormats() return supported_codecs; } +VideoEncoderFactory::CodecInfo InternalEncoderFactory::QueryVideoEncoder( + const SdpVideoFormat& format) const { + CodecInfo info; + info.is_hardware_accelerated = false; + info.has_internal_source = false; + return info; +} + std::unique_ptr InternalEncoderFactory::CreateVideoEncoder( const SdpVideoFormat& format) { if (absl::EqualsIgnoreCase(format.name, cricket::kVp8CodecName)) diff --git a/media/engine/internalencoderfactory.h b/media/engine/internalencoderfactory.h index 0373a88092..d30335e2c5 100644 --- a/media/engine/internalencoderfactory.h +++ b/media/engine/internalencoderfactory.h @@ -24,6 +24,8 @@ class InternalEncoderFactory : public VideoEncoderFactory { public: std::vector GetSupportedFormats() const override; + CodecInfo QueryVideoEncoder(const SdpVideoFormat& format) const override; + std::unique_ptr CreateVideoEncoder( const SdpVideoFormat& format) override; }; diff --git a/media/engine/multiplexcodecfactory.cc b/media/engine/multiplexcodecfactory.cc index 38a0d53c68..76f60ec14a 100644 --- a/media/engine/multiplexcodecfactory.cc +++ b/media/engine/multiplexcodecfactory.cc @@ -57,6 +57,14 @@ std::vector MultiplexEncoderFactory::GetSupportedFormats() return formats; } +VideoEncoderFactory::CodecInfo MultiplexEncoderFactory::QueryVideoEncoder( + const SdpVideoFormat& format) const { + if (!IsMultiplexCodec(cricket::VideoCodec(format))) + return factory_->QueryVideoEncoder(format); + return factory_->QueryVideoEncoder( + SdpVideoFormat(kMultiplexAssociatedCodecName)); +} + std::unique_ptr MultiplexEncoderFactory::CreateVideoEncoder( const SdpVideoFormat& format) { if (!IsMultiplexCodec(cricket::VideoCodec(format))) diff --git a/media/engine/multiplexcodecfactory.h b/media/engine/multiplexcodecfactory.h index d5bf3fb24c..48a29847b1 100644 --- a/media/engine/multiplexcodecfactory.h +++ b/media/engine/multiplexcodecfactory.h @@ -49,6 +49,7 @@ class RTC_EXPORT MultiplexEncoderFactory : public VideoEncoderFactory { bool supports_augmenting_data = false); std::vector GetSupportedFormats() const override; + CodecInfo QueryVideoEncoder(const SdpVideoFormat& format) const override; std::unique_ptr CreateVideoEncoder( const SdpVideoFormat& format) override; diff --git a/media/engine/simulcast_encoder_adapter_unittest.cc b/media/engine/simulcast_encoder_adapter_unittest.cc index 32e6e74497..88a247e5e5 100644 --- a/media/engine/simulcast_encoder_adapter_unittest.cc +++ b/media/engine/simulcast_encoder_adapter_unittest.cc @@ -159,6 +159,8 @@ class MockVideoEncoderFactory : public VideoEncoderFactory { std::unique_ptr CreateVideoEncoder( const SdpVideoFormat& format) override; + CodecInfo QueryVideoEncoder(const SdpVideoFormat& format) const override; + const std::vector& encoders() const; void SetEncoderNames(const std::vector& encoder_names); void set_init_encode_return_value(int32_t value); @@ -308,6 +310,11 @@ void MockVideoEncoderFactory::DestroyVideoEncoder(VideoEncoder* encoder) { } } +VideoEncoderFactory::CodecInfo MockVideoEncoderFactory::QueryVideoEncoder( + const SdpVideoFormat& format) const { + return CodecInfo(); +} + const std::vector& MockVideoEncoderFactory::encoders() const { return encoders_; diff --git a/media/engine/webrtcvideoengine_unittest.cc b/media/engine/webrtcvideoengine_unittest.cc index d4213ff268..4ba3c489dc 100644 --- a/media/engine/webrtcvideoengine_unittest.cc +++ b/media/engine/webrtcvideoengine_unittest.cc @@ -1090,7 +1090,12 @@ TEST(WebRtcVideoEngineNewVideoCodecFactoryTest, Vp8) { VerifyCodecHasDefaultFeedbackParams(engine_codecs.at(0)); // Mock encoder creation. |engine| take ownership of the encoder. + webrtc::VideoEncoderFactory::CodecInfo codec_info; + codec_info.is_hardware_accelerated = false; + codec_info.has_internal_source = false; const webrtc::SdpVideoFormat format("VP8"); + EXPECT_CALL(*encoder_factory, QueryVideoEncoder(format)) + .WillRepeatedly(testing::Return(codec_info)); FakeWebRtcVideoEncoder* const encoder = new FakeWebRtcVideoEncoder(nullptr); rtc::Event encoder_created; EXPECT_CALL(*encoder_factory, CreateVideoEncoderProxy(format)) diff --git a/sdk/android/src/jni/videoencoderfactorywrapper.cc b/sdk/android/src/jni/videoencoderfactorywrapper.cc index bd725a83fd..44026662db 100644 --- a/sdk/android/src/jni/videoencoderfactorywrapper.cc +++ b/sdk/android/src/jni/videoencoderfactorywrapper.cc @@ -50,5 +50,20 @@ std::vector VideoEncoderFactoryWrapper::GetSupportedFormats() return supported_formats_; } +VideoEncoderFactory::CodecInfo VideoEncoderFactoryWrapper::QueryVideoEncoder( + const SdpVideoFormat& format) const { + JNIEnv* jni = AttachCurrentThreadIfNeeded(); + ScopedJavaLocalRef j_codec_info = + SdpVideoFormatToVideoCodecInfo(jni, format); + ScopedJavaLocalRef encoder = Java_VideoEncoderFactory_createEncoder( + jni, encoder_factory_, j_codec_info); + + CodecInfo codec_info; + // Check if this is a wrapped native software encoder implementation. + codec_info.is_hardware_accelerated = IsHardwareVideoEncoder(jni, encoder); + codec_info.has_internal_source = false; + return codec_info; +} + } // namespace jni } // namespace webrtc diff --git a/sdk/android/src/jni/videoencoderfactorywrapper.h b/sdk/android/src/jni/videoencoderfactorywrapper.h index 7fe9dca815..2c2dadcaec 100644 --- a/sdk/android/src/jni/videoencoderfactorywrapper.h +++ b/sdk/android/src/jni/videoencoderfactorywrapper.h @@ -35,6 +35,8 @@ class VideoEncoderFactoryWrapper : public VideoEncoderFactory { // Returns a list of supported codecs in order of preference. std::vector GetSupportedFormats() const override; + CodecInfo QueryVideoEncoder(const SdpVideoFormat& format) const override; + private: const ScopedJavaGlobalRef encoder_factory_; std::vector supported_formats_; diff --git a/sdk/objc/native/src/objc_video_encoder_factory.h b/sdk/objc/native/src/objc_video_encoder_factory.h index e9e615b701..7bf56bd081 100644 --- a/sdk/objc/native/src/objc_video_encoder_factory.h +++ b/sdk/objc/native/src/objc_video_encoder_factory.h @@ -29,6 +29,7 @@ class ObjCVideoEncoderFactory : public VideoEncoderFactory { std::vector GetSupportedFormats() const override; std::unique_ptr CreateVideoEncoder( const SdpVideoFormat& format) override; + CodecInfo QueryVideoEncoder(const SdpVideoFormat& format) const override; private: id encoder_factory_; diff --git a/sdk/objc/native/src/objc_video_encoder_factory.mm b/sdk/objc/native/src/objc_video_encoder_factory.mm index 4eed67dff0..ca61c4dc54 100644 --- a/sdk/objc/native/src/objc_video_encoder_factory.mm +++ b/sdk/objc/native/src/objc_video_encoder_factory.mm @@ -129,6 +129,19 @@ std::vector ObjCVideoEncoderFactory::GetSupportedFormats() const return supported_formats; } +VideoEncoderFactory::CodecInfo ObjCVideoEncoderFactory::QueryVideoEncoder( + const SdpVideoFormat &format) const { + // TODO(andersc): This is a hack until we figure out how this should be done properly. + NSString *formatName = [NSString stringForStdString:format.name]; + NSSet *wrappedSoftwareFormats = + [NSSet setWithObjects:kRTCVideoCodecVp8Name, kRTCVideoCodecVp9Name, nil]; + + CodecInfo codec_info; + codec_info.is_hardware_accelerated = ![wrappedSoftwareFormats containsObject:formatName]; + codec_info.has_internal_source = false; + return codec_info; +} + std::unique_ptr ObjCVideoEncoderFactory::CreateVideoEncoder( const SdpVideoFormat &format) { RTCVideoCodecInfo *info = [[RTCVideoCodecInfo alloc] initWithNativeSdpVideoFormat:format]; diff --git a/test/fake_encoder.cc b/test/fake_encoder.cc index 8707c1723a..06329c680a 100644 --- a/test/fake_encoder.cc +++ b/test/fake_encoder.cc @@ -54,8 +54,6 @@ FakeEncoder::FakeEncoder(Clock* clock) max_target_bitrate_kbps_(-1), pending_keyframe_(true), counter_(0), - is_hardware_accelerated_(false), - has_internal_source_(false), debt_bytes_(0) { // Generate some arbitrary not-all-zero data for (size_t i = 0; i < sizeof(encoded_buffer_); ++i) { @@ -269,19 +267,9 @@ const char* FakeEncoder::kImplementationName = "fake_encoder"; VideoEncoder::EncoderInfo FakeEncoder::GetEncoderInfo() const { EncoderInfo info; info.implementation_name = kImplementationName; - info.is_hardware_accelerated = is_hardware_accelerated_; - info.has_internal_source = has_internal_source_; return info; } -void FakeEncoder::SetIsHardwareAccelerated(bool is_hardware_accelerated) { - is_hardware_accelerated_ = is_hardware_accelerated; -} - -void FakeEncoder::SetHasInternalSource(bool has_internal_source) { - has_internal_source_ = has_internal_source; -} - int FakeEncoder::GetConfiguredInputFramerate() const { rtc::CritScope cs(&crit_sect_); return configured_input_framerate_; diff --git a/test/fake_encoder.h b/test/fake_encoder.h index a3f5a7a2fc..753b1eaf7b 100644 --- a/test/fake_encoder.h +++ b/test/fake_encoder.h @@ -55,9 +55,6 @@ class FakeEncoder : public VideoEncoder { int GetConfiguredInputFramerate() const; EncoderInfo GetEncoderInfo() const override; - void SetIsHardwareAccelerated(bool is_hardware_accelerated); - void SetHasInternalSource(bool has_internal_source); - static const char* kImplementationName; protected: @@ -94,9 +91,6 @@ class FakeEncoder : public VideoEncoder { uint32_t counter_ RTC_GUARDED_BY(crit_sect_); rtc::CriticalSection crit_sect_; - bool is_hardware_accelerated_; - bool has_internal_source_; - uint8_t encoded_buffer_[100000]; bool used_layers_[kMaxSimulcastStreams]; diff --git a/test/video_encoder_proxy_factory.h b/test/video_encoder_proxy_factory.h index 888200b85f..9e5ea12ce2 100644 --- a/test/video_encoder_proxy_factory.h +++ b/test/video_encoder_proxy_factory.h @@ -26,8 +26,10 @@ namespace test { // a proxy for the same encoder, typically an instance of FakeEncoder. class VideoEncoderProxyFactory final : public VideoEncoderFactory { public: - explicit VideoEncoderProxyFactory(VideoEncoder* encoder) - : encoder_(encoder) {} + explicit VideoEncoderProxyFactory(VideoEncoder* encoder) : encoder_(encoder) { + codec_info_.is_hardware_accelerated = false; + codec_info_.has_internal_source = false; + } // Unused by tests. std::vector GetSupportedFormats() const override { @@ -35,11 +37,22 @@ class VideoEncoderProxyFactory final : public VideoEncoderFactory { return {}; } + CodecInfo QueryVideoEncoder(const SdpVideoFormat& format) const override { + return codec_info_; + } + std::unique_ptr CreateVideoEncoder( const SdpVideoFormat& format) override { return absl::make_unique(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. @@ -75,6 +88,7 @@ class VideoEncoderProxyFactory final : public VideoEncoderFactory { }; VideoEncoder* const encoder_; + CodecInfo codec_info_; }; } // namespace test diff --git a/video/video_send_stream_tests.cc b/video/video_send_stream_tests.cc index 75ce726f4d..ea77cd6529 100644 --- a/video/video_send_stream_tests.cc +++ b/video/video_send_stream_tests.cc @@ -2043,10 +2043,10 @@ TEST_P(VideoSendStreamTest, CanReconfigureToUseStartBitrateAbovePreviousMax) { bitrate_config); StartBitrateObserver encoder; + test::VideoEncoderProxyFactory 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. - encoder.SetHasInternalSource(true); - test::VideoEncoderProxyFactory encoder_factory(&encoder); + encoder_factory.SetHasInternalSource(true); GetVideoSendConfig()->encoder_settings.encoder_factory = &encoder_factory; CreateVideoStreams(); @@ -2125,8 +2125,8 @@ class StartStopBitrateObserver : public test::FakeEncoder { TEST_P(VideoSendStreamTest, VideoSendStreamStopSetEncoderRateToZero) { test::NullTransport transport; StartStopBitrateObserver encoder; - encoder.SetHasInternalSource(true); test::VideoEncoderProxyFactory encoder_factory(&encoder); + encoder_factory.SetHasInternalSource(true); test::FrameForwarder forwarder; task_queue_.SendTask([this, &transport, &encoder_factory, &forwarder]() { @@ -2168,8 +2168,8 @@ TEST_P(VideoSendStreamTest, VideoSendStreamStopSetEncoderRateToZero) { TEST_P(VideoSendStreamTest, VideoSendStreamUpdateActiveSimulcastLayers) { test::NullTransport transport; StartStopBitrateObserver encoder; - encoder.SetHasInternalSource(true); test::VideoEncoderProxyFactory encoder_factory(&encoder); + encoder_factory.SetHasInternalSource(true); test::FrameForwarder forwarder; task_queue_.SendTask([this, &transport, &encoder_factory, &forwarder]() { diff --git a/video/video_stream_encoder.cc b/video/video_stream_encoder.cc index d6d3ba10d5..410c331359 100644 --- a/video/video_stream_encoder.cc +++ b/video/video_stream_encoder.cc @@ -363,6 +363,7 @@ VideoStreamEncoder::VideoStreamEncoder( pre_encode_callback_(pre_encode_callback), max_framerate_(-1), pending_encoder_reconfiguration_(false), + pending_encoder_creation_(false), crop_width_(0), crop_height_(0), encoder_start_bitrate_bps_(0), @@ -438,9 +439,8 @@ void VideoStreamEncoder::SetSource( } degradation_preference_ = degradation_preference; - if (encoder_) { + if (encoder_) ConfigureQualityScaler(); - } if (!IsFramerateScalingEnabled(degradation_preference) && max_framerate_ != -1) { @@ -491,13 +491,8 @@ void VideoStreamEncoder::ConfigureEncoderOnTaskQueue( RTC_LOG(LS_INFO) << "ConfigureEncoder requested."; max_data_payload_length_ = max_data_payload_length; - if (!encoder_ || encoder_config_.video_format != config.video_format) { - pending_encoder_ = - settings_.encoder_factory->CreateVideoEncoder(config.video_format); - // TODO(nisse): What to do if creating the encoder fails? Crash, - // or just discard incoming frames? - RTC_CHECK(pending_encoder_); - } + pending_encoder_creation_ = + (!encoder_ || encoder_config_.video_format != config.video_format); encoder_config_ = std::move(config); pending_encoder_reconfiguration_ = true; @@ -507,13 +502,11 @@ void VideoStreamEncoder::ConfigureEncoderOnTaskQueue( // The codec configuration depends on incoming video frame size. if (last_frame_info_) { ReconfigureEncoder(); - } else { - VideoEncoder* encoder = - pending_encoder_ ? pending_encoder_.get() : encoder_.get(); - if (encoder->GetEncoderInfo().has_internal_source) { - last_frame_info_ = VideoFrameInfo(176, 144, false); - ReconfigureEncoder(); - } + } else if (settings_.encoder_factory + ->QueryVideoEncoder(encoder_config_.video_format) + .has_internal_source) { + last_frame_info_ = VideoFrameInfo(176, 144, false); + ReconfigureEncoder(); } } @@ -591,21 +584,28 @@ void VideoStreamEncoder::ReconfigureEncoder() { source_proxy_->SetMaxFramerate(max_framerate); // Keep the same encoder, as long as the video_format is unchanged. - if (pending_encoder_) { + if (pending_encoder_creation_) { + pending_encoder_creation_ = false; if (encoder_) { video_sender_.RegisterExternalEncoder(nullptr, false); } - encoder_ = std::move(pending_encoder_); - const VideoEncoder::EncoderInfo& encoder_info = encoder_->GetEncoderInfo(); + 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_); + + const webrtc::VideoEncoderFactory::CodecInfo info = + settings_.encoder_factory->QueryVideoEncoder( + encoder_config_.video_format); overuse_detector_->StopCheckForOveruse(); overuse_detector_->StartCheckForOveruse( - GetCpuOveruseOptions(settings_, encoder_info.is_hardware_accelerated), - this); + GetCpuOveruseOptions(settings_, info.is_hardware_accelerated), this); video_sender_.RegisterExternalEncoder(encoder_.get(), - encoder_info.has_internal_source); + info.has_internal_source); } // RegisterSendCodec implies an unconditional call to // encoder_->InitEncode(). diff --git a/video/video_stream_encoder.h b/video/video_stream_encoder.h index 04d22de1e6..8c5efbe5c3 100644 --- a/video/video_stream_encoder.h +++ b/video/video_stream_encoder.h @@ -202,9 +202,6 @@ class VideoStreamEncoder : public VideoStreamEncoderInterface, rtc::ThreadChecker thread_checker_; VideoEncoderConfig encoder_config_ RTC_GUARDED_BY(&encoder_queue_); - // Pending encoder object (e.g. because of a codec change). - std::unique_ptr pending_encoder_ RTC_GUARDED_BY(&encoder_queue_) - RTC_PT_GUARDED_BY(&encoder_queue_); std::unique_ptr encoder_ RTC_GUARDED_BY(&encoder_queue_) RTC_PT_GUARDED_BY(&encoder_queue_); std::unique_ptr rate_allocator_ @@ -216,6 +213,9 @@ class VideoStreamEncoder : public VideoStreamEncoderInterface, // 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_); absl::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 684b4323d6..05a23c05b4 100644 --- a/video/video_stream_encoder_unittest.cc +++ b/video/video_stream_encoder_unittest.cc @@ -511,8 +511,8 @@ class VideoStreamEncoderTest : public ::testing::Test { } VideoEncoder::EncoderInfo GetEncoderInfo() const override { + EncoderInfo info; rtc::CritScope lock(&local_crit_sect_); - EncoderInfo info = FakeEncoder::GetEncoderInfo(); if (quality_scaling_) { info.scaling_settings = VideoEncoder::ScalingSettings(1, 2, kMinPixelsPerFrame); @@ -3198,7 +3198,7 @@ TEST_F(VideoStreamEncoderTest, CpuOveruseOptions hardware_options; hardware_options.low_encode_usage_threshold_percent = 150; hardware_options.high_encode_usage_threshold_percent = 200; - fake_encoder_.SetIsHardwareAccelerated(true); + encoder_factory_.SetIsHardwareAccelerated(true); video_stream_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0); video_source_.IncomingCapturedFrame(