diff --git a/media/engine/simulcast_encoder_adapter.cc b/media/engine/simulcast_encoder_adapter.cc index f2717b38ab..e4d0b0bbe9 100644 --- a/media/engine/simulcast_encoder_adapter.cc +++ b/media/engine/simulcast_encoder_adapter.cc @@ -19,6 +19,7 @@ #include "api/video_codecs/video_encoder_factory.h" #include "modules/video_coding/utility/simulcast_rate_allocator.h" #include "rtc_base/checks.h" +#include "rtc_base/logging.h" #include "system_wrappers/include/clock.h" #include "system_wrappers/include/field_trial.h" #include "third_party/libyuv/include/libyuv/scale.h" @@ -126,9 +127,9 @@ SimulcastEncoderAdapter::SimulcastEncoderAdapter(VideoEncoderFactory* factory, factory_(factory), video_format_(format), encoded_complete_callback_(nullptr), - implementation_name_("SimulcastEncoderAdapter"), experimental_boosted_screenshare_qp_(GetScreenshareBoostedQpValue()) { RTC_DCHECK(factory_); + encoder_info_.implementation_name = "SimulcastEncoderAdapter"; // The adapter is typically created on the worker thread, but operated on // the encoder task queue. @@ -202,7 +203,8 @@ int SimulcastEncoderAdapter::InitEncode(const VideoCodec* inst, start_bitrates.push_back(stream_bitrate); } - std::string implementation_name; + encoder_info_.supports_native_handle = true; + encoder_info_.scaling_settings.thresholds = absl::nullopt; // Create |number_of_streams| of encoder instances and init them. for (int i = 0; i < number_of_streams; ++i) { VideoCodec stream_codec; @@ -211,6 +213,7 @@ int SimulcastEncoderAdapter::InitEncode(const VideoCodec* inst, if (!doing_simulcast) { stream_codec = codec_; stream_codec.numberOfSimulcastStreams = 1; + } else { // Cap start bitrate to the min bitrate in order to avoid strange codec // behavior. Since sending will be false, this should not matter. @@ -253,18 +256,39 @@ int SimulcastEncoderAdapter::InitEncode(const VideoCodec* inst, stream_codec.width, stream_codec.height, send_stream); - if (i != 0) { - implementation_name += ", "; + if (!doing_simulcast) { + // Without simulcast, just pass through the encoder info from the one + // active encoder. + encoder_info_ = streaminfos_[0].encoder->GetEncoderInfo(); + } else { + const EncoderInfo encoder_impl_info = + streaminfos_[i].encoder->GetEncoderInfo(); + + if (i == 0) { + // Quality scaling not enabled for simulcast. + encoder_info_.scaling_settings = VideoEncoder::ScalingSettings::kOff; + + // Encoder name indicates names of all sub-encoders. + encoder_info_.implementation_name = "SimulcastEncoderAdapter ("; + encoder_info_.implementation_name += + encoder_impl_info.implementation_name; + + encoder_info_.supports_native_handle = + encoder_impl_info.supports_native_handle; + } else { + encoder_info_.implementation_name += ", "; + encoder_info_.implementation_name += + encoder_impl_info.implementation_name; + + // Native handle supported only if all encoders supports it. + encoder_info_.supports_native_handle &= + encoder_impl_info.supports_native_handle; + } } - implementation_name += - streaminfos_[i].encoder->GetEncoderInfo().implementation_name; } if (doing_simulcast) { - implementation_name_ = - "SimulcastEncoderAdapter (" + implementation_name + ")"; - } else { - implementation_name_ = implementation_name; + encoder_info_.implementation_name += ")"; } // To save memory, don't store encoders that we don't use. @@ -508,23 +532,7 @@ void SimulcastEncoderAdapter::DestroyStoredEncoders() { } VideoEncoder::EncoderInfo SimulcastEncoderAdapter::GetEncoderInfo() const { - EncoderInfo info; - - if (Initialized() && NumberOfStreams(codec_) > 1) { - info = streaminfos_[0].encoder->GetEncoderInfo(); - } - - info.supports_native_handle = true; - for (const auto& streaminfo : streaminfos_) { - if (!streaminfo.encoder->GetEncoderInfo().supports_native_handle) { - info.supports_native_handle = false; - break; - } - } - - info.implementation_name = implementation_name_; - - return info; + return encoder_info_; } } // namespace webrtc diff --git a/media/engine/simulcast_encoder_adapter.h b/media/engine/simulcast_encoder_adapter.h index 6cb47ef37b..783c342d6b 100644 --- a/media/engine/simulcast_encoder_adapter.h +++ b/media/engine/simulcast_encoder_adapter.h @@ -100,7 +100,7 @@ class SimulcastEncoderAdapter : public VideoEncoder { VideoCodec codec_; std::vector streaminfos_; EncodedImageCallback* encoded_complete_callback_; - std::string implementation_name_; + EncoderInfo encoder_info_; // Used for checking the single-threaded access of the encoder interface. rtc::SequencedTaskChecker encoder_queue_; diff --git a/media/engine/simulcast_encoder_adapter_unittest.cc b/media/engine/simulcast_encoder_adapter_unittest.cc index d99b414001..4854725a70 100644 --- a/media/engine/simulcast_encoder_adapter_unittest.cc +++ b/media/engine/simulcast_encoder_adapter_unittest.cc @@ -56,7 +56,6 @@ std::unique_ptr CreateSpecificSimulcastTestFixture( std::move(decoder_factory), SdpVideoFormat(cricket::kVp8CodecName)); } - } // namespace TEST(SimulcastEncoderAdapterSimulcastTest, TestKeyFrameRequestsOnAllStreams) { @@ -177,7 +176,9 @@ class MockVideoEncoderFactory : public VideoEncoderFactory { class MockVideoEncoder : public VideoEncoder { public: explicit MockVideoEncoder(MockVideoEncoderFactory* factory) - : factory_(factory), callback_(nullptr) {} + : factory_(factory), + scaling_settings_(VideoEncoder::ScalingSettings::kOff), + callback_(nullptr) {} // TODO(nisse): Valid overrides commented out, because the gmock // methods don't use any override declarations, and we want to avoid @@ -214,6 +215,7 @@ class MockVideoEncoder : public VideoEncoder { EncoderInfo info; info.supports_native_handle = supports_native_handle_; info.implementation_name = implementation_name_; + info.scaling_settings = scaling_settings_; return info; } @@ -244,12 +246,17 @@ class MockVideoEncoder : public VideoEncoder { init_encode_return_value_ = value; } + void set_scaling_settings(const VideoEncoder::ScalingSettings& settings) { + scaling_settings_ = settings; + } + VideoBitrateAllocation last_set_bitrate() const { return last_set_bitrate_; } private: MockVideoEncoderFactory* const factory_; bool supports_native_handle_ = false; std::string implementation_name_ = "unknown"; + VideoEncoder::ScalingSettings scaling_settings_; int32_t init_encode_return_value_ = 0; VideoBitrateAllocation last_set_bitrate_; @@ -722,8 +729,10 @@ TEST_F(TestSimulcastEncoderAdapterFake, SupportsNativeHandleForSingleStreams) { adapter_->RegisterEncodeCompleteCallback(this); ASSERT_EQ(1u, helper_->factory()->encoders().size()); helper_->factory()->encoders()[0]->set_supports_native_handle(true); + EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200)); EXPECT_TRUE(adapter_->GetEncoderInfo().supports_native_handle); helper_->factory()->encoders()[0]->set_supports_native_handle(false); + EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200)); EXPECT_FALSE(adapter_->GetEncoderInfo().supports_native_handle); } @@ -796,6 +805,7 @@ TEST_F(TestSimulcastEncoderAdapterFake, EXPECT_FALSE(adapter_->GetEncoderInfo().supports_native_handle); // Once all do, then the adapter claims support. helper_->factory()->encoders()[0]->set_supports_native_handle(true); + EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200)); EXPECT_TRUE(adapter_->GetEncoderInfo().supports_native_handle); } @@ -832,6 +842,7 @@ TEST_F(TestSimulcastEncoderAdapterFake, ASSERT_EQ(3u, helper_->factory()->encoders().size()); for (MockVideoEncoder* encoder : helper_->factory()->encoders()) encoder->set_supports_native_handle(true); + EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200)); EXPECT_TRUE(adapter_->GetEncoderInfo().supports_native_handle); rtc::scoped_refptr buffer(