Move creating encoder to VideoStreamEncoder.
This used to be in WebRtcVideoChannel::WebRtcVideoSendStream.
One implication is that encoder is not created until the first
frame arrives, and some of the tests needed updates to emit a
frame or two.
Bug: webrtc:8830
Change-Id: I78169b2bb4dfa4197b4b4229af9fd69d0f747835
Reviewed-on: https://webrtc-review.googlesource.com/64885
Commit-Queue: Niels Moller <nisse@webrtc.org>
Reviewed-by: Erik Språng <sprang@webrtc.org>
Reviewed-by: Karl Wiberg <kwiberg@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#22905}
diff --git a/call/bitrate_estimator_tests.cc b/call/bitrate_estimator_tests.cc
index b4f808f..ea48a97 100644
--- a/call/bitrate_estimator_tests.cc
+++ b/call/bitrate_estimator_tests.cc
@@ -116,8 +116,8 @@
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 @@
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 @@
VideoSendStream* send_stream_;
VideoReceiveStream* video_receive_stream_;
std::unique_ptr<test::FrameGeneratorCapturer> 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 703e5eb..486195f 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 @@
std::vector<double> bitrate_kbps_list_;
} test(pad_to_min_bitrate);
- fake_encoder_.SetMaxBitrate(kMaxEncodeBitrateKbps);
+ fake_encoder_max_bitrate_ = kMaxEncodeBitrateKbps;
RunBaseTest(&test);
}
@@ -687,7 +688,8 @@
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,
@@ -738,7 +740,7 @@
VideoSendStream::Config* send_config,
std::vector<VideoReceiveStream::Config>* 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<VideoStreamFactory>();
@@ -773,6 +775,7 @@
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 8fccd32..ec701d0 100644
--- a/call/video_send_stream.cc
+++ b/call/video_send_stream.cc
@@ -93,7 +93,6 @@
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 0019a95..cdb9483 100644
--- a/call/video_send_stream.h
+++ b/call/video_send_stream.h
@@ -113,18 +113,8 @@
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 @@
// 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 0aa9cb0..728193e 100644
--- a/media/engine/fakewebrtccall.cc
+++ b/media/engine/fakewebrtccall.cc
@@ -123,7 +123,7 @@
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 7f6508b..e9ceaaa 100644
--- a/media/engine/webrtcvideoengine.cc
+++ b/media/engine/webrtcvideoengine.cc
@@ -1656,8 +1656,6 @@
if (stream_ != NULL) {
call_->DestroyVideoSendStream(stream_);
}
- // Release |allocated_encoder_|.
- allocated_encoder_.reset();
}
bool WebRtcVideoChannel::WebRtcVideoSendStream::SetVideoSend(
@@ -1729,26 +1727,6 @@
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<webrtc::VideoEncoder> 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 @@
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 @@
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 bffe344..e17da3d 100644
--- a/media/engine/webrtcvideoengine.h
+++ b/media/engine/webrtcvideoengine.h
@@ -350,8 +350,6 @@
// 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<webrtc::VideoEncoder> 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 cbc3446..86ba066 100644
--- a/media/engine/webrtcvideoengine_unittest.cc
+++ b/media/engine/webrtcvideoengine_unittest.cc
@@ -496,40 +496,6 @@
codecs, FindMatchingCodec(codecs, h264_high)->id));
}
-void WebRtcVideoEngineTest::TestExtendedEncoderOveruse(
- bool use_external_encoder) {
- std::unique_ptr<VideoMediaChannel> 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, ChannelWithExternalH264CanChangeToInternalVp8) {
encoder_factory_->AddSupportedVideoCodecType("H264");
+ // Set capturer.
+ FakeVideoCapturerWithTaskQueue capturer;
+ EXPECT_EQ(cricket::CS_RUNNING,
+ capturer.Start(capturer.GetSupportedFormats()->front()));
+
std::unique_ptr<VideoMediaChannel> 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 @@
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 @@
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 @@
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 @@
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 @@
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<VideoMediaChannel> recv_channel(
diff --git a/test/BUILD.gn b/test/BUILD.gn
index 7a26e63..ece4003 100644
--- a/test/BUILD.gn
+++ b/test/BUILD.gn
@@ -509,6 +509,7 @@
"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 @@
"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 4e62865..e3a73e8 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 @@
video_send_stream_(nullptr),
audio_send_config_(nullptr),
audio_send_stream_(nullptr),
- fake_encoder_(clock_),
+ fake_encoder_factory_([this]() {
+ auto encoder = rtc::MakeUnique<test::FakeEncoder>(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 @@
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 c096b0d..4191f43 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 @@
std::vector<FlexfecReceiveStream*> flexfec_receive_streams_;
std::unique_ptr<test::FrameGeneratorCapturer> frame_generator_capturer_;
- test::FakeEncoder fake_encoder_;
+ test::FunctionVideoEncoderFactory fake_encoder_factory_;
+ int fake_encoder_max_bitrate_ = -1;
std::vector<std::unique_ptr<VideoDecoder>> 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 0000000..9c7ff0c
--- /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 <memory>
+#include <vector>
+
+#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<SdpVideoFormat> GetSupportedFormats() const override {
+ RTC_NOTREACHED();
+ return {};
+ }
+
+ CodecInfo QueryVideoEncoder(const SdpVideoFormat& format) const override {
+ return codec_info_;
+ }
+
+ std::unique_ptr<VideoEncoder> CreateVideoEncoder(
+ const SdpVideoFormat& format) override {
+ return rtc::MakeUnique<EncoderProxy>(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<FrameType>* 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 0000000..22cf744
--- /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 <functional>
+#include <memory>
+#include <utility>
+#include <vector>
+
+#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<std::unique_ptr<VideoEncoder>()> create)
+ : create_(std::move(create)) {
+ codec_info_.is_hardware_accelerated = false;
+ codec_info_.has_internal_source = false;
+ }
+
+ // Unused by tests.
+ std::vector<SdpVideoFormat> GetSupportedFormats() const override {
+ RTC_NOTREACHED();
+ return {};
+ }
+
+ CodecInfo QueryVideoEncoder(
+ const SdpVideoFormat& /* format */) const override {
+ return codec_info_;
+ }
+
+ std::unique_ptr<VideoEncoder> CreateVideoEncoder(
+ const SdpVideoFormat& /* format */) override {
+ return create_();
+ }
+
+ private:
+ const std::function<std::unique_ptr<VideoEncoder>()> 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 fbe590b..ec5a1ce 100644
--- a/video/encoder_rtcp_feedback_unittest.cc
+++ b/video/encoder_rtcp_feedback_unittest.cc
@@ -24,12 +24,11 @@
class MockVideoStreamEncoder : public VideoStreamEncoder {
public:
explicit MockVideoStreamEncoder(SendStatisticsProxy* send_stats_proxy)
- : VideoStreamEncoder(
- 1,
- send_stats_proxy,
- VideoSendStream::Config::EncoderSettings(nullptr),
- nullptr,
- rtc::MakeUnique<OveruseFrameDetector>(nullptr)) {}
+ : VideoStreamEncoder(1,
+ send_stats_proxy,
+ VideoSendStream::Config::EncoderSettings(),
+ nullptr,
+ rtc::MakeUnique<OveruseFrameDetector>(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 e77f402..50e874b 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 @@
FakeEncoder(Clock::GetRealTimeClock()),
task_queue_(task_queue),
send_stream_(nullptr),
+ encoder_factory_(this),
bitrate_kbps_(0) {}
void OnVideoStreamsCreated(
@@ -292,7 +295,7 @@
VideoSendStream::Config* send_config,
std::vector<VideoReceiveStream::Config>* 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::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 1607382..71034cc 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 @@
CodecObserver(int no_frames_to_wait_for,
VideoRotation rotation_to_test,
const std::string& payload_name,
- std::unique_ptr<webrtc::VideoEncoder> encoder,
+ VideoEncoderFactory* encoder_factory,
std::unique_ptr<webrtc::VideoDecoder> decoder)
: EndToEndTest(4 * CodecEndToEndTest::kDefaultTimeoutMs),
// TODO(hta): This timeout (120 seconds) is excessive.
@@ -55,7 +56,7 @@
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 @@
std::vector<VideoReceiveStream::Config>* 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 @@
int no_frames_to_wait_for_;
VideoRotation expected_rotation_;
std::string payload_name_;
- std::unique_ptr<webrtc::VideoEncoder> encoder_;
+ VideoEncoderFactory* encoder_factory_;
std::unique_ptr<webrtc::VideoDecoder> 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<MultiplexEncoderAdapter>(
+ &internal_encoder_factory, SdpVideoFormat(cricket::kVp9CodecName));
+ });
CodecObserver test(
- 5, kVideoRotation_0, "multiplex",
- rtc::MakeUnique<MultiplexEncoderAdapter>(
- &encoder_factory, SdpVideoFormat(cricket::kVp9CodecName)),
+ 5, kVideoRotation_0, "multiplex", &encoder_factory,
rtc::MakeUnique<MultiplexDecoderAdapter>(
&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<MultiplexEncoderAdapter>(
+ &internal_encoder_factory, SdpVideoFormat(cricket::kVp9CodecName));
+ });
CodecObserver test(
- 5, kVideoRotation_90, "multiplex",
- rtc::MakeUnique<MultiplexEncoderAdapter>(
- &encoder_factory, SdpVideoFormat(cricket::kVp9CodecName)),
+ 5, kVideoRotation_90, "multiplex", &encoder_factory,
rtc::MakeUnique<MultiplexDecoderAdapter>(
&decoder_factory, SdpVideoFormat(cricket::kVp9CodecName)));
RunBaseTest(&test);
@@ -167,15 +182,17 @@
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, 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, 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 80a97cd..67bfdeb 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 @@
public:
UlpfecRenderObserver()
: EndToEndTest(kDefaultTimeoutMs),
- encoder_(VP8Encoder::Create()),
+ encoder_factory_([]() { return VP8Encoder::Create(); }),
random_(0xcafef00d1),
num_packets_sent_(0) {}
@@ -102,7 +103,7 @@
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 @@
rtc::CriticalSection crit_;
std::unique_ptr<VideoEncoder> encoder_;
+ test::FunctionVideoEncoderFactory encoder_factory_;
std::unique_ptr<VideoDecoder> decoder_;
std::set<uint32_t> dropped_sequence_numbers_ RTC_GUARDED_BY(crit_);
// Several packets can have the same timestamp.
@@ -335,7 +337,7 @@
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 @@
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 @@
bool has_last_sequence_number_;
uint16_t last_sequence_number_;
std::unique_ptr<webrtc::VideoEncoder> encoder_;
+ test::FunctionVideoEncoderFactory encoder_factory_;
std::unique_ptr<webrtc::VideoDecoder> decoder_;
} test;
diff --git a/video/end_to_end_tests/histogram_tests.cc b/video/end_to_end_tests/histogram_tests.cc
index decbb77..3096c2a 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 @@
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 @@
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 @@
const bool use_rtx_;
const bool use_fec_;
const bool screenshare_;
- const std::unique_ptr<VideoEncoder> 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 2695667..391c3d0 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 @@
explicit LogEncodingObserver(LogEndToEndTest* fixture)
: EndToEndTest(kDefaultTimeoutMs),
fixture_(fixture),
+ encoder_factory_([]() { return VP8Encoder::Create(); }),
recorded_frames_(0) {}
void PerformTest() override {
@@ -73,12 +75,11 @@
VideoSendStream::Config* send_config,
std::vector<VideoReceiveStream::Config>* 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 @@
private:
LogEndToEndTest* const fixture_;
- std::unique_ptr<VideoEncoder> encoder_;
+ test::FunctionVideoEncoderFactory encoder_factory_;
std::unique_ptr<VideoDecoder> 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 2d501c1..e818cf4 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 @@
VideoReceiveStream* receive_streams[kNumStreams];
test::FrameGeneratorCapturer* frame_generators[kNumStreams];
std::vector<std::unique_ptr<VideoDecoder>> allocated_decoders;
- std::unique_ptr<VideoEncoder> encoders[kNumStreams];
+ test::FunctionVideoEncoderFactory encoder_factory(
+ []() { return VP8Encoder::Create(); });
task_queue_->SendTask([&]() {
sender_call = rtc::WrapUnique(Call::Create(config));
@@ -61,9 +63,6 @@
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 @@
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 1222363..9af0c47 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 @@
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 @@
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 @@
VideoSendStream::Config* send_config,
std::vector<VideoReceiveStream::Config>* 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 @@
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 aefb02c..425c0c2 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 @@
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 @@
// 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 @@
const int payload_type_;
const uint32_t retransmission_ssrc_;
const int retransmission_payload_type_;
- std::unique_ptr<VideoEncoder> 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 c12b988..5317242 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 @@
std::unique_ptr<test::PacketTransport> send_transport;
std::unique_ptr<test::PacketTransport> receive_transport;
- std::unique_ptr<VideoEncoder> encoder;
+ test::FunctionVideoEncoderFactory encoder_factory(
+ []() { return VP8Encoder::Create(); });
task_queue_.SendTask([&]() {
CreateCalls(config, config);
@@ -494,8 +495,8 @@
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 643b6c1..f3d2194 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 @@
public:
StatsObserver()
: EndToEndTest(kLongTimeoutMs),
- encoder_(Clock::GetRealTimeClock(), 10),
+ encoder_factory_([]() {
+ return rtc::MakeUnique<test::DelayedEncoder>(
+ Clock::GetRealTimeClock(), 10);
+ }),
send_stream_(nullptr),
expected_send_ssrcs_(),
check_stats_event_(false, false) {}
@@ -297,7 +302,7 @@
// 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::DelayedEncoder encoder_;
+ test::FunctionVideoEncoderFactory encoder_factory_;
std::vector<VideoReceiveStream*> receive_streams_;
std::map<std::string, bool> receive_stats_filled_;
diff --git a/video/overuse_frame_detector.cc b/video/overuse_frame_detector.cc
index 1d6b0e1..4bccdf3 100644
--- a/video/overuse_frame_detector.cc
+++ b/video/overuse_frame_detector.cc
@@ -543,8 +543,10 @@
}
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 3aa0db1..3525a97 100644
--- a/video/overuse_frame_detector.h
+++ b/video/overuse_frame_detector.h
@@ -118,6 +118,8 @@
void CheckForOveruse(AdaptationObserverInterface* overuse_observer);
void SetOptions(const CpuOveruseOptions& options);
+ CpuOveruseOptions options_;
+
private:
class CheckOveruseTask;
@@ -137,8 +139,6 @@
// Owned by the task queue from where StartCheckForOveruse is called.
CheckOveruseTask* check_overuse_task_;
- CpuOveruseOptions options_;
-
// Stats metrics.
CpuOveruseMetricsObserver* const metrics_observer_;
rtc::Optional<CpuOveruseMetrics> metrics_ RTC_GUARDED_BY(task_checker_);
diff --git a/video/picture_id_tests.cc b/video/picture_id_tests.cc
index ff62ddc..33aed38 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 @@
});
}
- void SetupEncoder(VideoEncoder* encoder, const std::string& payload_name);
+ void SetupEncoder(VideoEncoderFactory* encoder_factory,
+ const std::string& payload_name);
void TestPictureIdContinuousAfterReconfigure(
const std::vector<int>& ssrc_counts);
void TestPictureIdIncreaseAfterRecreateStreams(
@@ -292,12 +294,12 @@
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 @@
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 @@
}
TEST_P(PictureIdTest, ContinuousAfterReconfigureVp8) {
- std::unique_ptr<VideoEncoder> 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<VideoEncoder> 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<VideoEncoder> 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<SimulcastEncoderAdapter>(
+ &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<SimulcastEncoderAdapter>(
+ &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<SimulcastEncoderAdapter>(
+ &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<VideoEncoder> 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 0a477c4..d0edfc7 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 @@
const int64_t start_ms_;
};
+// Not used by these tests.
+std::vector<SdpVideoFormat>
+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<VideoEncoder>
+VideoQualityTest::TestVideoEncoderFactory::CreateVideoEncoder(
+ const SdpVideoFormat& format) {
+ if (format.name == "VP8") {
+ return rtc::MakeUnique<VP8EncoderSimulcastProxy>(
+ &internal_encoder_factory_);
+ } else if (format.name == "multiplex") {
+ return rtc::MakeUnique<MultiplexEncoderAdapter>(
+ &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 @@
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 @@
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 @@
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<VP8EncoderSimulcastProxy>(&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<MultiplexEncoderAdapter>(
- &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 @@
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::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 @@
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 688a004..749d092 100644
--- a/video/video_quality_test.h
+++ b/video/video_quality_test.h
@@ -112,6 +112,18 @@
const std::vector<std::string>& sl_descriptors);
protected:
+ class TestVideoEncoderFactory : public VideoEncoderFactory {
+ std::vector<SdpVideoFormat> GetSupportedFormats() const override;
+
+ CodecInfo QueryVideoEncoder(const SdpVideoFormat& format) const override;
+
+ std::unique_ptr<VideoEncoder> CreateVideoEncoder(
+ const SdpVideoFormat& format) override;
+
+ private:
+ InternalEncoderFactory internal_encoder_factory_;
+ };
+
std::map<uint8_t, webrtc::MediaType> payload_type_map_;
std::unique_ptr<FecControllerFactoryInterface> fec_controller_factory_;
@@ -148,10 +160,8 @@
std::vector<std::unique_ptr<test::VideoCapturer>> video_capturers_;
std::vector<std::unique_ptr<test::VideoCapturer>> thumbnail_capturers_;
- InternalEncoderFactory internal_encoder_factory_;
- std::vector<std::unique_ptr<VideoEncoder>> video_encoders_;
+ TestVideoEncoderFactory video_encoder_factory_;
- std::vector<std::unique_ptr<VideoEncoder>> thumbnail_encoders_;
std::vector<VideoSendStream::Config> thumbnail_send_configs_;
std::vector<VideoEncoderConfig> thumbnail_encoder_configs_;
std::vector<VideoSendStream*> thumbnail_send_streams_;
diff --git a/video/video_send_stream.cc b/video/video_send_stream.cc
index 4152efd..27f8ef5 100644
--- a/video/video_send_stream.cc
+++ b/video/video_send_stream.cc
@@ -512,6 +512,8 @@
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<VideoStreamEncoder>(
num_cpu_cores, &stats_proxy_,
config_.encoder_settings,
@@ -826,7 +828,6 @@
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 9985b85..deac1e6 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 @@
class TransmissionTimeOffsetObserver : public test::SendTest {
public:
TransmissionTimeOffsetObserver()
- : SendTest(kDefaultTimeoutMs),
- encoder_(Clock::GetRealTimeClock(), kEncodeDelayMs) {
+ : SendTest(kDefaultTimeoutMs), encoder_factory_([]() {
+ return rtc::MakeUnique<test::DelayedEncoder>(
+ Clock::GetRealTimeClock(), kEncodeDelayMs);
+ }) {
EXPECT_TRUE(parser_->RegisterRtpHeaderExtension(
kRtpExtensionTransmissionTimeOffset, test::kTOffsetExtensionId));
}
@@ -222,7 +226,7 @@
VideoSendStream::Config* send_config,
std::vector<VideoReceiveStream::Config>* 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 @@
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 @@
class TransportWideSequenceNumberObserver : public test::SendTest {
public:
TransportWideSequenceNumberObserver()
- : SendTest(kDefaultTimeoutMs), encoder_(Clock::GetRealTimeClock()) {
+ : SendTest(kDefaultTimeoutMs), encoder_factory_([]() {
+ return rtc::MakeUnique<test::FakeEncoder>(
+ Clock::GetRealTimeClock());
+ }) {
EXPECT_TRUE(parser_->RegisterRtpHeaderExtension(
kRtpExtensionTransportSequenceNumber, kExtensionId));
}
@@ -266,14 +273,14 @@
VideoSendStream::Config* send_config,
std::vector<VideoReceiveStream::Config>* 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 @@
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 @@
(*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 @@
<< "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 @@
};
TEST_F(VideoSendStreamTest, SupportsUlpfecWithExtensions) {
- std::unique_ptr<VideoEncoder> 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<VideoEncoder> 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 @@
};
TEST_F(VideoSendStreamWithoutUlpfecTest, NoUlpfecIfDisabledThroughFieldTrial) {
- std::unique_ptr<VideoEncoder> 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 @@
// 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<VideoEncoder> encoder(
- new test::FakeH264Encoder(Clock::GetRealTimeClock()));
- UlpfecObserver test(false, true, true, false, "H264", encoder.get());
+ test::FunctionVideoEncoderFactory encoder_factory([]() {
+ return rtc::MakeUnique<test::FakeH264Encoder>(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<VideoEncoder> encoder(
- new test::FakeH264Encoder(Clock::GetRealTimeClock()));
- UlpfecObserver test(false, false, true, true, "H264", encoder.get());
+ test::FunctionVideoEncoderFactory encoder_factory([]() {
+ return rtc::MakeUnique<test::FakeH264Encoder>(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<VideoEncoder> 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<VideoEncoder> 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<VideoEncoder> encoder(
- new test::MultithreadedFakeH264Encoder(Clock::GetRealTimeClock()));
- UlpfecObserver test(false, false, true, true, "H264", encoder.get());
+ test::FunctionVideoEncoderFactory encoder_factory([]() {
+ return rtc::MakeUnique<test::MultithreadedFakeH264Encoder>(
+ Clock::GetRealTimeClock());
+ });
+ UlpfecObserver test(false, false, true, true, "H264", &encoder_factory);
RunBaseTest(&test);
}
@@ -642,10 +658,10 @@
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 @@
(*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 @@
<< "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 @@
};
TEST_F(VideoSendStreamTest, SupportsFlexfecVp8) {
- std::unique_ptr<VideoEncoder> 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<VideoEncoder> 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<VideoEncoder> 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<VideoEncoder> 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<VideoEncoder> 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<VideoEncoder> 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<VideoEncoder> encoder(
- new test::FakeH264Encoder(Clock::GetRealTimeClock()));
- FlexfecObserver test(false, false, "H264", encoder.get(), 1);
+ test::FunctionVideoEncoderFactory encoder_factory([]() {
+ return rtc::MakeUnique<test::FakeH264Encoder>(Clock::GetRealTimeClock());
+ });
+ FlexfecObserver test(false, false, "H264", &encoder_factory, 1);
RunBaseTest(&test);
}
TEST_F(VideoSendStreamTest, SupportsFlexfecWithNackH264) {
- std::unique_ptr<VideoEncoder> encoder(
- new test::FakeH264Encoder(Clock::GetRealTimeClock()));
- FlexfecObserver test(false, true, "H264", encoder.get(), 1);
+ test::FunctionVideoEncoderFactory encoder_factory([]() {
+ return rtc::MakeUnique<test::FakeH264Encoder>(Clock::GetRealTimeClock());
+ });
+ FlexfecObserver test(false, true, "H264", &encoder_factory, 1);
RunBaseTest(&test);
}
TEST_F(VideoSendStreamTest, SupportsFlexfecWithMultithreadedH264) {
- std::unique_ptr<VideoEncoder> encoder(
- new test::MultithreadedFakeH264Encoder(Clock::GetRealTimeClock()));
- FlexfecObserver test(false, false, "H264", encoder.get(), 1);
+ test::FunctionVideoEncoderFactory encoder_factory([]() {
+ return rtc::MakeUnique<test::MultithreadedFakeH264Encoder>(
+ Clock::GetRealTimeClock());
+ });
+
+ FlexfecObserver test(false, false, "H264", &encoder_factory, 1);
RunBaseTest(&test);
}
@@ -921,6 +948,7 @@
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 @@
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 @@
std::unique_ptr<internal::TransportAdapter> 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::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,13 +2013,21 @@
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();
+ // Inject a frame, to force encoder creation.
+ video_send_stream_->Start();
+ test::FrameForwarder forwarder;
+ video_send_stream_->SetSource(
+ &forwarder, VideoSendStream::DegradationPreference::kDegradationDisabled);
+ forwarder.IncomingCapturedFrame(CreateVideoFrame(640, 480, 4));
+
EXPECT_TRUE(encoder.WaitForStartBitrate());
EXPECT_EQ(video_encoder_config_.max_bitrate_bps / 1000,
encoder.GetStartBitrateKbps());
@@ -2066,17 +2103,24 @@
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 +2153,28 @@
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 +2323,8 @@
initialized_(false),
callback_registered_(false),
num_releases_(0),
- released_(false) {}
+ released_(false),
+ encoder_factory_(this) {}
bool IsReleased() {
rtc::CritScope lock(&crit_);
@@ -2346,7 +2400,7 @@
VideoSendStream::Config* send_config,
std::vector<VideoReceiveStream::Config>* 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 +2429,7 @@
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 +2448,15 @@
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<VideoReceiveStream::Config>* 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 +2500,7 @@
rtc::Event init_encode_event_;
size_t num_initializations_;
VideoSendStream* stream_;
+ test::EncoderProxyFactory encoder_factory_;
VideoEncoderConfig encoder_config_;
} test;
@@ -2463,7 +2520,8 @@
codec_name_(codec_name),
init_encode_event_(false, false),
num_initializations_(0),
- stream_(nullptr) {
+ stream_(nullptr),
+ encoder_factory_(this) {
InitCodecSpecifics();
}
@@ -2492,7 +2550,7 @@
VideoSendStream::Config* send_config,
std::vector<VideoReceiveStream::Config>* 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 +2610,7 @@
rtc::Event init_encode_event_;
size_t num_initializations_;
VideoSendStream* stream_;
+ test::EncoderProxyFactory encoder_factory_;
VideoEncoderConfig encoder_config_;
};
@@ -2738,7 +2797,8 @@
public:
ScreencastTargetBitrateTest()
: SendTest(kDefaultTimeoutMs),
- test::FakeEncoder(Clock::GetRealTimeClock()) {}
+ test::FakeEncoder(Clock::GetRealTimeClock()),
+ encoder_factory_(this) {}
private:
int32_t InitEncode(const VideoCodec* config,
@@ -2754,7 +2814,7 @@
VideoSendStream::Config* send_config,
std::vector<VideoReceiveStream::Config>* 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<VideoStreamFactory>();
@@ -2765,6 +2825,7 @@
EXPECT_TRUE(Wait())
<< "Timed out while waiting for the encoder to be initialized.";
}
+ test::EncoderProxyFactory encoder_factory_;
} test;
RunBaseTest(&test);
@@ -2792,7 +2853,8 @@
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 +2944,7 @@
VideoSendStream::Config* send_config,
std::vector<VideoReceiveStream::Config>* 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 +3007,7 @@
int num_initializations_;
webrtc::Call* call_;
webrtc::VideoSendStream* send_stream_;
+ test::EncoderProxyFactory encoder_factory_;
webrtc::VideoEncoderConfig encoder_config_;
} test(&task_queue_);
@@ -2965,7 +3028,8 @@
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 +3067,7 @@
VideoSendStream::Config* send_config,
std::vector<VideoReceiveStream::Config>* 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 +3097,7 @@
}
VideoSendStream* send_stream_;
+ test::EncoderProxyFactory encoder_factory_;
} test;
RunBaseTest(&test);
@@ -3043,7 +3108,7 @@
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 +3149,7 @@
VideoSendStream::Config* send_config,
std::vector<VideoReceiveStream::Config>* 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 +3411,7 @@
VerifyTl0Idx(vp9);
}
- std::unique_ptr<VP9Encoder> vp9_encoder_;
+ test::FunctionVideoEncoderFactory encoder_factory_;
VideoCodecVP9 vp9_settings_;
webrtc::VideoEncoderConfig encoder_config_;
RTPHeader last_header_;
@@ -3593,6 +3658,7 @@
: 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 +3685,7 @@
std::vector<VideoReceiveStream::Config>* 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 +3712,8 @@
// 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 +3722,7 @@
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 952d4ed..7bb17b0 100644
--- a/video/video_stream_encoder.cc
+++ b/video/video_stream_encoder.cc
@@ -91,10 +91,11 @@
// 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 @@
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 @@
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 @@
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 @@
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,9 +485,6 @@
// The codec configuration depends on incoming video frame size.
if (last_frame_info_) {
ReconfigureEncoder();
- } else if (settings_.internal_source) {
- last_frame_info_ = VideoFrameInfo(176, 144, false);
- ReconfigureEncoder();
}
}
@@ -528,6 +525,34 @@
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<uint32_t>(max_data_payload_length_)) == VCM_OK;
@@ -563,13 +588,11 @@
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 +612,8 @@
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 +748,24 @@
<< ", 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);
@@ -737,17 +780,6 @@
}
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()) {
if (pending_frame_)
@@ -971,7 +1003,7 @@
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 a81160e..ac4f254 100644
--- a/video/video_stream_encoder.h
+++ b/video/video_stream_encoder.h
@@ -231,6 +231,8 @@
rtc::ThreadChecker thread_checker_;
VideoEncoderConfig encoder_config_ RTC_GUARDED_BY(&encoder_queue_);
+ std::unique_ptr<VideoEncoder> encoder_ RTC_GUARDED_BY(&encoder_queue_)
+ RTC_PT_GUARDED_BY(&encoder_queue_);
std::unique_ptr<VideoBitrateAllocator> rate_allocator_
RTC_GUARDED_BY(&encoder_queue_)
RTC_PT_GUARDED_BY(&encoder_queue_);
@@ -241,6 +243,9 @@
// 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<VideoFrameInfo> 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 8a6d4e1..4b39223 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 @@
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 @@
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 @@
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 @@
int codec_height_;
int max_framerate_;
TestEncoder fake_encoder_;
+ test::EncoderProxyFactory encoder_factory_;
std::unique_ptr<MockableSendStatisticsProxy> stats_proxy_;
TestSink sink_;
AdaptingFrameForwarder video_source_;
@@ -1437,11 +1442,16 @@
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 @@
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 @@
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