Reland "Move creating encoder to VideoStreamEncoder."

This is a reland of fb82fcc7f9c414dc8ba1ddd314e9524fee54cb80

Original change's description:
> 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}

TBR=magjed@webrtc.org,kwiberg@webrtc.org

Bug: webrtc:8830
Change-Id: I9565095ea1880fb49d15111198c08b2fcb84f18c
Reviewed-on: https://webrtc-review.googlesource.com/70740
Commit-Queue: Niels Moller <nisse@webrtc.org>
Reviewed-by: Niels Moller <nisse@webrtc.org>
Reviewed-by: Erik Språng <sprang@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#22930}
This commit is contained in:
Niels Möller 2018-04-19 09:04:13 +02:00 committed by Commit Bot
parent 5396232d03
commit 4db138e889
35 changed files with 693 additions and 303 deletions

View File

@ -116,8 +116,8 @@ class BitrateEstimatorTest : public test::CallTest {
video_send_config_ = VideoSendStream::Config(send_transport_.get());
video_send_config_.rtp.ssrcs.push_back(kVideoSendSsrcs[0]);
// Encoders will be set separately per stream.
video_send_config_.encoder_settings.encoder = nullptr;
video_send_config_.encoder_settings.encoder_factory =
&fake_encoder_factory_;
video_send_config_.rtp.payload_name = "FAKE";
video_send_config_.rtp.payload_type = kFakeVideoSendPayloadType;
test::FillEncoderConfiguration(kVideoCodecVP8, 1, &video_encoder_config_);
@ -162,10 +162,8 @@ class BitrateEstimatorTest : public test::CallTest {
is_sending_receiving_(false),
send_stream_(nullptr),
frame_generator_capturer_(),
fake_encoder_(Clock::GetRealTimeClock()),
fake_decoder_() {
test_->video_send_config_.rtp.ssrcs[0]++;
test_->video_send_config_.encoder_settings.encoder = &fake_encoder_;
send_stream_ = test_->sender_call_->CreateVideoSendStream(
test_->video_send_config_.Copy(),
test_->video_encoder_config_.Copy());
@ -223,7 +221,6 @@ class BitrateEstimatorTest : public test::CallTest {
VideoSendStream* send_stream_;
VideoReceiveStream* video_receive_stream_;
std::unique_ptr<test::FrameGeneratorCapturer> frame_generator_capturer_;
test::FakeEncoder fake_encoder_;
test::FakeDecoder fake_decoder_;
};

View File

@ -29,6 +29,7 @@
#include "test/call_test.h"
#include "test/direct_transport.h"
#include "test/drifting_clock.h"
#include "test/encoder_proxy_factory.h"
#include "test/encoder_settings.h"
#include "test/fake_encoder.h"
#include "test/field_trial.h"
@ -637,7 +638,7 @@ void CallPerfTest::TestMinTransmitBitrate(bool pad_to_min_bitrate) {
std::vector<double> bitrate_kbps_list_;
} test(pad_to_min_bitrate);
fake_encoder_.SetMaxBitrate(kMaxEncodeBitrateKbps);
fake_encoder_max_bitrate_ = kMaxEncodeBitrateKbps;
RunBaseTest(&test);
}
@ -686,7 +687,8 @@ TEST_F(CallPerfTest, MAYBE_KeepsHighBitrateWhenReconfiguringSender) {
encoder_inits_(0),
last_set_bitrate_kbps_(0),
send_stream_(nullptr),
frame_generator_(nullptr) {}
frame_generator_(nullptr),
encoder_factory_(this) {}
int32_t InitEncode(const VideoCodec* config,
int32_t number_of_cores,
@ -735,7 +737,7 @@ TEST_F(CallPerfTest, MAYBE_KeepsHighBitrateWhenReconfiguringSender) {
VideoSendStream::Config* send_config,
std::vector<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>();
@ -770,6 +772,7 @@ TEST_F(CallPerfTest, MAYBE_KeepsHighBitrateWhenReconfiguringSender) {
uint32_t last_set_bitrate_kbps_;
VideoSendStream* send_stream_;
test::FrameGeneratorCapturer* frame_generator_;
test::EncoderProxyFactory encoder_factory_;
VideoEncoderConfig encoder_config_;
} test;

View File

@ -93,7 +93,6 @@ std::string VideoSendStream::Config::EncoderSettings::ToString() const {
rtc::SimpleStringBuilder ss(buf);
ss << "{encoder_factory: "
<< (encoder_factory ? "(VideoEncoderFactory)" : "(nullptr)");
ss << ", encoder: " << (encoder ? "(VideoEncoder)" : "nullptr");
ss << '}';
return ss.str();
}

View File

@ -113,18 +113,8 @@ class VideoSendStream {
struct EncoderSettings {
EncoderSettings() = default;
explicit EncoderSettings(VideoEncoder* encoder) : encoder(encoder) {}
std::string ToString() const;
// TODO(sophiechang): Delete this field when no one is using internal
// sources anymore.
bool internal_source = false;
// Allow 100% encoder utilization. Used for HW encoders where CPU isn't
// expected to be the limiting factor, but a chip could be running at
// 30fps (for example) exactly.
bool full_overuse_time = false;
// Enables the new method to estimate the cpu load from encoding, used for
// cpu adaptation.
bool experiment_cpu_load_estimator = false;
@ -132,9 +122,8 @@ class VideoSendStream {
// Ownership stays with WebrtcVideoEngine (delegated from PeerConnection).
VideoEncoderFactory* encoder_factory = nullptr;
// TODO(nisse): Delete, let VideoStreamEncoder create the encoder.
// Uninitialized VideoEncoder instance to be used for encoding. Will be
// initialized from inside the VideoSendStream.
// TODO(nisse): Unused! But kept temporarily to transition downstream
// projects.
VideoEncoder* encoder = nullptr;
} encoder_settings;

View File

@ -123,7 +123,7 @@ FakeVideoSendStream::FakeVideoSendStream(
framerate_scaling_enabled_(false),
source_(nullptr),
num_swapped_frames_(0) {
RTC_DCHECK(config.encoder_settings.encoder != NULL);
RTC_DCHECK(config.encoder_settings.encoder_factory != nullptr);
ReconfigureVideoEncoder(std::move(encoder_config));
}

View File

@ -1656,8 +1656,6 @@ WebRtcVideoChannel::WebRtcVideoSendStream::~WebRtcVideoSendStream() {
if (stream_ != NULL) {
call_->DestroyVideoSendStream(stream_);
}
// Release |allocated_encoder_|.
allocated_encoder_.reset();
}
bool WebRtcVideoChannel::WebRtcVideoSendStream::SetVideoSend(
@ -1729,26 +1727,6 @@ void WebRtcVideoChannel::WebRtcVideoSendStream::SetCodec(
parameters_.encoder_config = CreateVideoEncoderConfig(codec_settings.codec);
RTC_DCHECK_GT(parameters_.encoder_config.number_of_streams, 0);
const webrtc::SdpVideoFormat format(codec_settings.codec.name,
codec_settings.codec.params);
// We can't overwrite |allocated_encoder_| immediately, because we
// need to release it after the RecreateWebRtcStream() call.
std::unique_ptr<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 @@ void WebRtcVideoChannel::WebRtcVideoSendStream::SetCodec(
parameters_.codec_settings = codec_settings;
// TODO(nisse): Avoid recreation, it should be enough to call
// ReconfigureEncoder.
RTC_LOG(LS_INFO) << "RecreateWebRtcStream (send) because of SetCodec.";
RecreateWebRtcStream();
allocated_encoder_ = std::move(new_encoder);
}
void WebRtcVideoChannel::WebRtcVideoSendStream::SetSendParameters(
@ -1907,6 +1886,8 @@ WebRtcVideoChannel::WebRtcVideoSendStream::CreateVideoEncoderConfig(
RTC_DCHECK_RUN_ON(&thread_checker_);
webrtc::VideoEncoderConfig encoder_config;
encoder_config.codec_type = webrtc::PayloadStringToCodecType(codec.name);
encoder_config.video_format =
webrtc::SdpVideoFormat(codec.name, codec.params);
bool is_screencast = parameters_.options.is_screencast.value_or(false);
if (is_screencast) {

View File

@ -350,8 +350,6 @@ class WebRtcVideoChannel : public VideoMediaChannel, public webrtc::Transport {
// TODO(skvlad): Combine parameters_ and rtp_parameters_ once we have only
// one stream per MediaChannel.
webrtc::RtpParameters rtp_parameters_ RTC_GUARDED_BY(&thread_checker_);
std::unique_ptr<webrtc::VideoEncoder> allocated_encoder_
RTC_GUARDED_BY(&thread_checker_);
bool sending_ RTC_GUARDED_BY(&thread_checker_);
};

View File

@ -496,40 +496,6 @@ TEST_F(WebRtcVideoEngineTest, RtxCodecAddedForExternalCodec) {
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, UsesSimulcastAdapterForVp8Factories) {
TEST_F(WebRtcVideoEngineTest, ChannelWithExternalH264CanChangeToInternalVp8) {
encoder_factory_->AddSupportedVideoCodecType("H264");
// Set capturer.
FakeVideoCapturerWithTaskQueue capturer;
EXPECT_EQ(cricket::CS_RUNNING,
capturer.Start(capturer.GetSupportedFormats()->front()));
std::unique_ptr<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 @@ TEST_F(WebRtcVideoEngineTest,
EXPECT_TRUE(
channel->AddSendStream(cricket::StreamParams::CreateLegacy(kSsrc)));
ASSERT_EQ(1u, encoder_factory_->encoders().size());
// Send a frame of 720p. This should trigger a "real" encoder initialization.
cricket::VideoFormat format(
@ -774,6 +752,8 @@ TEST_F(WebRtcVideoEngineTest,
EXPECT_TRUE(channel->SetVideoSend(kSsrc, nullptr, &capturer));
EXPECT_EQ(cricket::CS_RUNNING, capturer.Start(format));
EXPECT_TRUE(capturer.CaptureFrame());
ASSERT_TRUE(encoder_factory_->WaitForCreatedVideoEncoders(1));
ASSERT_EQ(1u, encoder_factory_->encoders().size());
ASSERT_TRUE(encoder_factory_->encoders()[0]->WaitForInitEncode());
EXPECT_EQ(webrtc::kVideoCodecH264,
encoder_factory_->encoders()[0]->GetCodecSettings().codecType);
@ -800,6 +780,7 @@ TEST_F(WebRtcVideoEngineTest, SimulcastDisabledForH264) {
EXPECT_EQ(cricket::CS_RUNNING, capturer.Start(format));
EXPECT_TRUE(capturer.CaptureFrame());
ASSERT_TRUE(encoder_factory_->WaitForCreatedVideoEncoders(1));
ASSERT_EQ(1u, encoder_factory_->encoders().size());
FakeWebRtcVideoEncoder* encoder = encoder_factory_->encoders()[0];
ASSERT_TRUE(encoder_factory_->encoders()[0]->WaitForInitEncode());
@ -988,8 +969,12 @@ TEST(WebRtcVideoEngineNewVideoCodecFactoryTest, Vp8) {
EXPECT_CALL(*encoder_factory, QueryVideoEncoder(format))
.WillRepeatedly(testing::Return(codec_info));
FakeWebRtcVideoEncoder* const encoder = new FakeWebRtcVideoEncoder();
rtc::Event encoder_created(false, false);
EXPECT_CALL(*encoder_factory, CreateVideoEncoderProxy(format))
.WillOnce(testing::Return(encoder));
.WillOnce(
::testing::DoAll(::testing::InvokeWithoutArgs(
[&encoder_created]() { encoder_created.Set(); }),
::testing::Return(encoder)));
// Mock decoder creation. |engine| take ownership of the decoder.
FakeWebRtcVideoDecoder* const decoder = new FakeWebRtcVideoDecoder();
@ -1013,6 +998,15 @@ TEST(WebRtcVideoEngineNewVideoCodecFactoryTest, Vp8) {
send_channel->AddSendStream(StreamParams::CreateLegacy(send_ssrc)));
EXPECT_TRUE(send_channel->SetSend(true));
// Set capturer.
FakeVideoCapturerWithTaskQueue capturer;
EXPECT_EQ(cricket::CS_RUNNING,
capturer.Start(capturer.GetSupportedFormats()->front()));
EXPECT_TRUE(send_channel->SetVideoSend(send_ssrc, nullptr, &capturer));
// Sending one frame will allocate the encoder.
EXPECT_TRUE(capturer.CaptureFrame());
encoder_created.Wait(kTimeout);
// Create recv channel.
const int recv_ssrc = 321;
std::unique_ptr<VideoMediaChannel> recv_channel(

View File

@ -509,6 +509,7 @@ rtc_source_set("test_common") {
"constants.h",
"drifting_clock.cc",
"drifting_clock.h",
"encoder_proxy_factory.h",
"encoder_settings.cc",
"encoder_settings.h",
"fake_decoder.cc",
@ -516,6 +517,7 @@ rtc_source_set("test_common") {
"fake_encoder.cc",
"fake_encoder.h",
"fake_videorenderer.h",
"function_video_encoder_factory.h",
"layer_filtering_transport.cc",
"layer_filtering_transport.h",
"mock_transport.cc",

View File

@ -20,6 +20,7 @@
#include "rtc_base/checks.h"
#include "rtc_base/event.h"
#include "rtc_base/ptr_util.h"
#include "test/fake_encoder.h"
#include "test/testsupport/fileutils.h"
namespace webrtc {
@ -37,7 +38,11 @@ CallTest::CallTest()
video_send_stream_(nullptr),
audio_send_config_(nullptr),
audio_send_stream_(nullptr),
fake_encoder_(clock_),
fake_encoder_factory_([this]() {
auto encoder = rtc::MakeUnique<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 @@ void CallTest::CreateVideoSendConfig(VideoSendStream::Config* video_config,
Transport* send_transport) {
RTC_DCHECK_LE(num_video_streams + num_used_ssrcs, kNumSsrcs);
*video_config = VideoSendStream::Config(send_transport);
video_config->encoder_settings.encoder = &fake_encoder_;
video_config->encoder_settings.encoder_factory = &fake_encoder_factory_;
video_config->rtp.payload_name = "FAKE";
video_config->rtp.payload_type = kFakeVideoSendPayloadType;
video_config->rtp.extensions.push_back(

View File

@ -19,9 +19,9 @@
#include "modules/audio_device/include/test_audio_device.h"
#include "test/encoder_settings.h"
#include "test/fake_decoder.h"
#include "test/fake_encoder.h"
#include "test/fake_videorenderer.h"
#include "test/frame_generator_capturer.h"
#include "test/function_video_encoder_factory.h"
#include "test/rtp_rtcp_observer.h"
#include "test/single_threaded_task_queue.h"
@ -138,7 +138,8 @@ class CallTest : public ::testing::Test {
std::vector<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_;

View File

@ -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_

View File

@ -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_

View File

@ -24,10 +24,9 @@ namespace webrtc {
class MockVideoStreamEncoder : public VideoStreamEncoder {
public:
explicit MockVideoStreamEncoder(SendStatisticsProxy* send_stats_proxy)
: VideoStreamEncoder(
1,
: VideoStreamEncoder(1,
send_stats_proxy,
VideoSendStream::Config::EncoderSettings(nullptr),
VideoSendStream::Config::EncoderSettings(),
nullptr,
rtc::MakeUnique<OveruseFrameDetector>(nullptr)) {}
~MockVideoStreamEncoder() { Stop(); }

View File

@ -12,6 +12,8 @@
#include "rtc_base/rate_limiter.h"
#include "system_wrappers/include/sleep.h"
#include "test/call_test.h"
#include "test/encoder_proxy_factory.h"
#include "test/fake_encoder.h"
#include "test/field_trial.h"
#include "test/gtest.h"
#include "test/rtcp_packet_parser.h"
@ -280,6 +282,7 @@ TEST_P(BandwidthEndToEndTest, ReportsSetEncoderRates) {
FakeEncoder(Clock::GetRealTimeClock()),
task_queue_(task_queue),
send_stream_(nullptr),
encoder_factory_(this),
bitrate_kbps_(0) {}
void OnVideoStreamsCreated(
@ -292,7 +295,7 @@ TEST_P(BandwidthEndToEndTest, ReportsSetEncoderRates) {
VideoSendStream::Config* send_config,
std::vector<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_P(BandwidthEndToEndTest, ReportsSetEncoderRates) {
test::SingleThreadedTaskQueueForTesting* const task_queue_;
rtc::CriticalSection crit_;
VideoSendStream* send_stream_;
test::EncoderProxyFactory encoder_factory_;
uint32_t bitrate_kbps_ RTC_GUARDED_BY(crit_);
} test(&task_queue_);

View File

@ -18,6 +18,7 @@
#include "test/call_test.h"
#include "test/encoder_settings.h"
#include "test/field_trial.h"
#include "test/function_video_encoder_factory.h"
#include "test/gtest.h"
namespace webrtc {
@ -47,7 +48,7 @@ class CodecObserver : public test::EndToEndTest,
CodecObserver(int no_frames_to_wait_for,
VideoRotation rotation_to_test,
const std::string& payload_name,
std::unique_ptr<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 @@ class CodecObserver : public test::EndToEndTest,
no_frames_to_wait_for_(no_frames_to_wait_for),
expected_rotation_(rotation_to_test),
payload_name_(payload_name),
encoder_(std::move(encoder)),
encoder_factory_(encoder_factory),
decoder_(std::move(decoder)),
frame_counter_(0) {}
@ -69,7 +70,7 @@ class CodecObserver : public test::EndToEndTest,
std::vector<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 @@ class CodecObserver : public test::EndToEndTest,
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 @@ INSTANTIATE_TEST_CASE_P(SpsPpsIdrIsKeyframe,
h264_field_trial_combinations);
TEST_P(EndToEndTestH264, SendsAndReceivesH264) {
CodecObserver test(500, kVideoRotation_0, "H264",
H264Encoder::Create(cricket::VideoCodec("H264")),
test::FunctionVideoEncoderFactory encoder_factory(
[]() { return H264Encoder::Create(cricket::VideoCodec("H264")); });
CodecObserver test(500, kVideoRotation_0, "H264", &encoder_factory,
H264Decoder::Create());
RunBaseTest(&test);
}
TEST_P(EndToEndTestH264, SendsAndReceivesH264VideoRotation90) {
CodecObserver test(5, kVideoRotation_90, "H264",
H264Encoder::Create(cricket::VideoCodec("H264")),
test::FunctionVideoEncoderFactory encoder_factory(
[]() { return H264Encoder::Create(cricket::VideoCodec("H264")); });
CodecObserver test(5, kVideoRotation_90, "H264", &encoder_factory,
H264Decoder::Create());
RunBaseTest(&test);
}
@ -183,7 +200,9 @@ TEST_P(EndToEndTestH264, SendsAndReceivesH264VideoRotation90) {
TEST_P(EndToEndTestH264, SendsAndReceivesH264PacketizationMode0) {
cricket::VideoCodec codec = cricket::VideoCodec("H264");
codec.SetParam(cricket::kH264FmtpPacketizationMode, "0");
CodecObserver test(500, kVideoRotation_0, "H264", H264Encoder::Create(codec),
test::FunctionVideoEncoderFactory encoder_factory(
[codec]() { return H264Encoder::Create(codec); });
CodecObserver test(500, kVideoRotation_0, "H264", &encoder_factory,
H264Decoder::Create());
RunBaseTest(&test);
}
@ -191,7 +210,9 @@ TEST_P(EndToEndTestH264, SendsAndReceivesH264PacketizationMode0) {
TEST_P(EndToEndTestH264, SendsAndReceivesH264PacketizationMode1) {
cricket::VideoCodec codec = cricket::VideoCodec("H264");
codec.SetParam(cricket::kH264FmtpPacketizationMode, "1");
CodecObserver test(500, kVideoRotation_0, "H264", H264Encoder::Create(codec),
test::FunctionVideoEncoderFactory encoder_factory(
[codec]() { return H264Encoder::Create(codec); });
CodecObserver test(500, kVideoRotation_0, "H264", &encoder_factory,
H264Decoder::Create());
RunBaseTest(&test);
}

View File

@ -12,6 +12,7 @@
#include "modules/video_coding/codecs/vp8/include/vp8.h"
#include "test/call_test.h"
#include "test/field_trial.h"
#include "test/function_video_encoder_factory.h"
#include "test/gtest.h"
#include "test/rtcp_packet_parser.h"
@ -42,7 +43,7 @@ TEST_P(FecEndToEndTest, ReceivesUlpfec) {
public:
UlpfecRenderObserver()
: EndToEndTest(kDefaultTimeoutMs),
encoder_(VP8Encoder::Create()),
encoder_factory_([]() { return VP8Encoder::Create(); }),
random_(0xcafef00d1),
num_packets_sent_(0) {}
@ -102,7 +103,7 @@ TEST_P(FecEndToEndTest, ReceivesUlpfec) {
VideoEncoderConfig* encoder_config) override {
// Use VP8 instead of FAKE, since the latter does not have PictureID
// in the packetization headers.
send_config->encoder_settings.encoder = encoder_.get();
send_config->encoder_settings.encoder_factory = &encoder_factory_;
send_config->rtp.payload_name = "VP8";
send_config->rtp.payload_type = kVideoSendPayloadType;
encoder_config->codec_type = kVideoCodecVP8;
@ -128,6 +129,7 @@ TEST_P(FecEndToEndTest, ReceivesUlpfec) {
rtc::CriticalSection crit_;
std::unique_ptr<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 @@ TEST_P(FecEndToEndTest, ReceivedUlpfecPacketsNotNacked) {
ulpfec_sequence_number_(0),
has_last_sequence_number_(false),
last_sequence_number_(0),
encoder_(VP8Encoder::Create()),
encoder_factory_([]() { return VP8Encoder::Create(); }),
decoder_(VP8Decoder::Create()) {}
private:
@ -452,7 +454,7 @@ TEST_P(FecEndToEndTest, ReceivedUlpfecPacketsNotNacked) {
send_config->rtp.ulpfec.red_payload_type = kRedPayloadType;
send_config->rtp.ulpfec.ulpfec_payload_type = kUlpfecPayloadType;
// Set codec to VP8, otherwise NACK/FEC hybrid will be disabled.
send_config->encoder_settings.encoder = encoder_.get();
send_config->encoder_settings.encoder_factory = &encoder_factory_;
send_config->rtp.payload_name = "VP8";
send_config->rtp.payload_type = kFakeVideoSendPayloadType;
encoder_config->codec_type = kVideoCodecVP8;
@ -488,6 +490,7 @@ TEST_P(FecEndToEndTest, ReceivedUlpfecPacketsNotNacked) {
bool has_last_sequence_number_;
uint16_t last_sequence_number_;
std::unique_ptr<webrtc::VideoEncoder> encoder_;
test::FunctionVideoEncoderFactory encoder_factory_;
std::unique_ptr<webrtc::VideoDecoder> decoder_;
} test;

View File

@ -12,6 +12,7 @@
#include "system_wrappers/include/metrics.h"
#include "system_wrappers/include/metrics_default.h"
#include "test/call_test.h"
#include "test/function_video_encoder_factory.h"
#include "test/gtest.h"
#include "test/rtcp_packet_parser.h"
@ -34,7 +35,7 @@ void HistogramTest::VerifyHistogramStats(bool use_rtx,
use_fec_(use_fec),
screenshare_(screenshare),
// This test uses NACK, so to send FEC we can't use a fake encoder.
vp8_encoder_(use_fec ? VP8Encoder::Create() : nullptr),
encoder_factory_([]() { return VP8Encoder::Create(); }),
sender_call_(nullptr),
receiver_call_(nullptr),
start_runtime_ms_(-1),
@ -88,7 +89,7 @@ void HistogramTest::VerifyHistogramStats(bool use_rtx,
if (use_fec_) {
send_config->rtp.ulpfec.ulpfec_payload_type = kUlpfecPayloadType;
send_config->rtp.ulpfec.red_payload_type = kRedPayloadType;
send_config->encoder_settings.encoder = vp8_encoder_.get();
send_config->encoder_settings.encoder_factory = &encoder_factory_;
send_config->rtp.payload_name = "VP8";
encoder_config->codec_type = kVideoCodecVP8;
(*receive_configs)[0].decoders[0].payload_name = "VP8";
@ -130,7 +131,7 @@ void HistogramTest::VerifyHistogramStats(bool use_rtx,
const bool use_rtx_;
const bool use_fec_;
const bool screenshare_;
const std::unique_ptr<VideoEncoder> vp8_encoder_;
test::FunctionVideoEncoderFactory encoder_factory_;
Call* sender_call_;
Call* receiver_call_;
int64_t start_runtime_ms_;

View File

@ -11,6 +11,7 @@
#include "modules/video_coding/codecs/vp8/include/vp8.h"
#include "rtc_base/file.h"
#include "test/call_test.h"
#include "test/function_video_encoder_factory.h"
#include "test/testsupport/fileutils.h"
namespace webrtc {
@ -61,6 +62,7 @@ TEST_F(LogEndToEndTest, LogsEncodedFramesWhenRequested) {
explicit LogEncodingObserver(LogEndToEndTest* fixture)
: EndToEndTest(kDefaultTimeoutMs),
fixture_(fixture),
encoder_factory_([]() { return VP8Encoder::Create(); }),
recorded_frames_(0) {}
void PerformTest() override {
@ -73,12 +75,11 @@ TEST_F(LogEndToEndTest, LogsEncodedFramesWhenRequested) {
VideoSendStream::Config* send_config,
std::vector<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 @@ TEST_F(LogEndToEndTest, LogsEncodedFramesWhenRequested) {
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_);

View File

@ -18,6 +18,7 @@
#include "modules/video_coding/codecs/vp8/include/vp8.h"
#include "test/call_test.h"
#include "test/encoder_settings.h"
#include "test/function_video_encoder_factory.h"
namespace webrtc {
@ -48,7 +49,8 @@ void MultiStreamTester::RunTest() {
VideoReceiveStream* receive_streams[kNumStreams];
test::FrameGeneratorCapturer* frame_generators[kNumStreams];
std::vector<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 @@ void MultiStreamTester::RunTest() {
sender_transport->SetReceiver(receiver_call->Receiver());
receiver_transport->SetReceiver(sender_call->Receiver());
for (size_t i = 0; i < kNumStreams; ++i)
encoders[i] = VP8Encoder::Create();
for (size_t i = 0; i < kNumStreams; ++i) {
uint32_t ssrc = codec_settings[i].ssrc;
int width = codec_settings[i].width;
@ -71,7 +70,7 @@ void MultiStreamTester::RunTest() {
VideoSendStream::Config send_config(sender_transport.get());
send_config.rtp.ssrcs.push_back(ssrc);
send_config.encoder_settings.encoder = encoders[i].get();
send_config.encoder_settings.encoder_factory = &encoder_factory;
send_config.rtp.payload_name = "VP8";
send_config.rtp.payload_type = kVideoPayloadType;
VideoEncoderConfig encoder_config;

View File

@ -10,6 +10,8 @@
#include "system_wrappers/include/sleep.h"
#include "test/call_test.h"
#include "test/encoder_proxy_factory.h"
#include "test/fake_encoder.h"
#include "test/gtest.h"
namespace webrtc {
@ -77,12 +79,15 @@ void NetworkStateEndToEndTest::VerifyNewVideoSendStreamsRespectNetworkState(
MediaType network_to_bring_up,
VideoEncoder* encoder,
Transport* transport) {
task_queue_.SendTask([this, network_to_bring_up, encoder, transport]() {
test::EncoderProxyFactory encoder_factory(encoder);
task_queue_.SendTask([this, network_to_bring_up, &encoder_factory,
transport]() {
CreateSenderCall(Call::Config(event_log_.get()));
sender_call_->SignalChannelNetworkState(network_to_bring_up, kNetworkUp);
CreateSendConfig(1, 0, 0, transport);
video_send_config_.encoder_settings.encoder = encoder;
video_send_config_.encoder_settings.encoder_factory = &encoder_factory;
CreateVideoStreams();
CreateFrameGeneratorCapturer(kDefaultFramerate, kDefaultWidth,
kDefaultHeight);
@ -151,6 +156,7 @@ TEST_F(NetworkStateEndToEndTest, RespectsNetworkState) {
packet_event_(false, false),
sender_call_(nullptr),
receiver_call_(nullptr),
encoder_factory_(this),
sender_state_(kNetworkUp),
sender_rtp_(0),
sender_padding_(0),
@ -197,7 +203,7 @@ TEST_F(NetworkStateEndToEndTest, RespectsNetworkState) {
VideoSendStream::Config* send_config,
std::vector<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 @@ TEST_F(NetworkStateEndToEndTest, RespectsNetworkState) {
rtc::Event packet_event_;
Call* sender_call_;
Call* receiver_call_;
test::EncoderProxyFactory encoder_factory_;
NetworkState sender_state_ RTC_GUARDED_BY(test_crit_);
int sender_rtp_ RTC_GUARDED_BY(test_crit_);
int sender_padding_ RTC_GUARDED_BY(test_crit_);

View File

@ -12,6 +12,7 @@
#include "system_wrappers/include/sleep.h"
#include "test/call_test.h"
#include "test/field_trial.h"
#include "test/function_video_encoder_factory.h"
#include "test/gtest.h"
#include "test/rtcp_packet_parser.h"
@ -339,7 +340,7 @@ void RetransmissionEndToEndTest::DecodesRetransmittedFrame(bool enable_rtx,
retransmission_ssrc_(enable_rtx ? kSendRtxSsrcs[0]
: kVideoSendSsrcs[0]),
retransmission_payload_type_(GetPayloadType(enable_rtx, enable_red)),
encoder_(VP8Encoder::Create()),
encoder_factory_([]() { return VP8Encoder::Create(); }),
marker_bits_observed_(0),
retransmitted_timestamp_(0) {}
@ -437,7 +438,7 @@ void RetransmissionEndToEndTest::DecodesRetransmittedFrame(bool enable_rtx,
// Configure encoding and decoding with VP8, since generic packetization
// doesn't support FEC with NACK.
RTC_DCHECK_EQ(1, (*receive_configs)[0].decoders.size());
send_config->encoder_settings.encoder = encoder_.get();
send_config->encoder_settings.encoder_factory = &encoder_factory_;
send_config->rtp.payload_name = "VP8";
encoder_config->codec_type = kVideoCodecVP8;
(*receive_configs)[0].decoders[0].payload_name = "VP8";
@ -469,7 +470,7 @@ void RetransmissionEndToEndTest::DecodesRetransmittedFrame(bool enable_rtx,
const int payload_type_;
const uint32_t retransmission_ssrc_;
const int retransmission_payload_type_;
std::unique_ptr<VideoEncoder> encoder_;
test::FunctionVideoEncoderFactory encoder_factory_;
const std::string payload_name_;
int marker_bits_observed_;
uint32_t retransmitted_timestamp_ RTC_GUARDED_BY(&crit_);

View File

@ -468,7 +468,8 @@ TEST_F(RtpRtcpEndToEndTest, TestFlexfecRtpStatePreservation) {
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 @@ TEST_F(RtpRtcpEndToEndTest, TestFlexfecRtpStatePreservation) {
const int kNumFlexfecStreams = 1;
CreateSendConfig(kNumVideoStreams, 0, kNumFlexfecStreams,
send_transport.get());
encoder = VP8Encoder::Create();
video_send_config_.encoder_settings.encoder = encoder.get();
video_send_config_.encoder_settings.encoder_factory = &encoder_factory;
video_send_config_.rtp.payload_name = "VP8";
video_send_config_.rtp.payload_type = kVideoSendPayloadType;
video_send_config_.rtp.nack.rtp_history_ms = kNackRtpHistoryMs;

View File

@ -14,6 +14,8 @@
#include "system_wrappers/include/metrics_default.h"
#include "system_wrappers/include/sleep.h"
#include "test/call_test.h"
#include "test/fake_encoder.h"
#include "test/function_video_encoder_factory.h"
#include "test/gtest.h"
#include "test/rtcp_packet_parser.h"
@ -37,7 +39,10 @@ TEST_F(StatsEndToEndTest, GetStats) {
public:
StatsObserver()
: EndToEndTest(kLongTimeoutMs),
encoder_(Clock::GetRealTimeClock(), 10),
encoder_factory_([]() {
return rtc::MakeUnique<test::DelayedEncoder>(
Clock::GetRealTimeClock(), 10);
}),
send_stream_(nullptr),
expected_send_ssrcs_(),
check_stats_event_(false, false) {}
@ -297,7 +302,7 @@ TEST_F(StatsEndToEndTest, GetStats) {
// Use a delayed encoder to make sure we see CpuOveruseMetrics stats that
// are non-zero.
send_config->encoder_settings.encoder = &encoder_;
send_config->encoder_settings.encoder_factory = &encoder_factory_;
}
size_t GetNumVideoStreams() const override { return kNumSimulcastStreams; }
@ -349,7 +354,7 @@ TEST_F(StatsEndToEndTest, GetStats) {
}
}
test::DelayedEncoder encoder_;
test::FunctionVideoEncoderFactory encoder_factory_;
std::vector<VideoReceiveStream*> receive_streams_;
std::map<std::string, bool> receive_stats_filled_;

View File

@ -543,8 +543,10 @@ void OveruseFrameDetector::StartCheckForOveruse(
}
void OveruseFrameDetector::StopCheckForOveruse() {
RTC_DCHECK_CALLED_SEQUENTIALLY(&task_checker_);
if (check_overuse_task_) {
check_overuse_task_->Stop();
check_overuse_task_ = nullptr;
}
}
void OveruseFrameDetector::EncodedFrameTimeMeasured(int encode_duration_ms) {

View File

@ -118,6 +118,8 @@ class OveruseFrameDetector {
void CheckForOveruse(AdaptationObserverInterface* overuse_observer);
void SetOptions(const CpuOveruseOptions& options);
CpuOveruseOptions options_;
private:
class CheckOveruseTask;
@ -137,8 +139,6 @@ class OveruseFrameDetector {
// Owned by the task queue from where StartCheckForOveruse is called.
CheckOveruseTask* check_overuse_task_;
CpuOveruseOptions options_;
// Stats metrics.
CpuOveruseMetricsObserver* const metrics_observer_;
rtc::Optional<CpuOveruseMetrics> metrics_ RTC_GUARDED_BY(task_checker_);

View File

@ -14,6 +14,7 @@
#include "rtc_base/numerics/safe_conversions.h"
#include "rtc_base/numerics/sequence_number_util.h"
#include "test/call_test.h"
#include "test/function_video_encoder_factory.h"
namespace webrtc {
namespace {
@ -235,7 +236,8 @@ class PictureIdTest : public test::CallTest,
});
}
void SetupEncoder(VideoEncoder* encoder, const std::string& payload_name);
void SetupEncoder(VideoEncoderFactory* encoder_factory,
const std::string& payload_name);
void TestPictureIdContinuousAfterReconfigure(
const std::vector<int>& ssrc_counts);
void TestPictureIdIncreaseAfterRecreateStreams(
@ -292,12 +294,12 @@ class VideoStreamFactory
const size_t num_of_temporal_layers_;
};
void PictureIdTest::SetupEncoder(VideoEncoder* encoder,
void PictureIdTest::SetupEncoder(VideoEncoderFactory* encoder_factory,
const std::string& payload_name) {
observer_.reset(
new PictureIdObserver(PayloadNameToRtpVideoCodecType(payload_name)));
task_queue_.SendTask([this, &encoder, payload_name]() {
task_queue_.SendTask([this, encoder_factory, payload_name]() {
Call::Config config(event_log_.get());
CreateCalls(config, config);
@ -307,7 +309,7 @@ void PictureIdTest::SetupEncoder(VideoEncoder* encoder,
FakeNetworkPipe::Config()));
CreateSendConfig(kNumSimulcastStreams, 0, 0, send_transport_.get());
video_send_config_.encoder_settings.encoder = encoder;
video_send_config_.encoder_settings.encoder_factory = encoder_factory;
video_send_config_.rtp.payload_name = payload_name;
video_encoder_config_.codec_type = PayloadStringToCodecType(payload_name);
video_encoder_config_.video_stream_factory =
@ -390,51 +392,67 @@ void PictureIdTest::TestPictureIdIncreaseAfterRecreateStreams(
}
TEST_P(PictureIdTest, ContinuousAfterReconfigureVp8) {
std::unique_ptr<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});
}

View File

@ -26,6 +26,7 @@
#include "modules/rtp_rtcp/source/rtp_utility.h"
#include "modules/video_coding/codecs/h264/include/h264.h"
#include "modules/video_coding/codecs/multiplex/include/multiplex_encoder_adapter.h"
#include "modules/video_coding/codecs/vp8/include/vp8.h"
#include "modules/video_coding/codecs/vp8/include/vp8_common_types.h"
#include "modules/video_coding/codecs/vp9/include/vp9.h"
#include "rtc_base/cpu_time.h"
@ -1074,6 +1075,36 @@ class VideoAnalyzer : public PacketReceiver,
const int64_t start_ms_;
};
// Not used by these tests.
std::vector<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 @@ void VideoQualityTest::SetupVideo(Transport* send_transport,
CreateMatchingAudioAndFecConfigs(recv_transport);
video_receive_configs_.clear();
video_send_configs_.clear();
video_encoders_.clear();
video_encoder_configs_.clear();
allocated_decoders_.clear();
bool decode_all_receive_streams = true;
@ -1363,7 +1393,6 @@ void VideoQualityTest::SetupVideo(Transport* send_transport,
video_encoder_configs_.resize(num_video_streams_);
for (size_t video_idx = 0; video_idx < num_video_streams_; ++video_idx) {
video_send_configs_.push_back(VideoSendStream::Config(send_transport));
video_encoders_.push_back(nullptr);
video_encoder_configs_.push_back(VideoEncoderConfig());
num_video_substreams = params_.ss[video_idx].streams.size();
RTC_CHECK_GT(num_video_substreams, 0);
@ -1372,26 +1401,20 @@ void VideoQualityTest::SetupVideo(Transport* send_transport,
int payload_type;
if (params_.video[video_idx].codec == "H264") {
video_encoders_[video_idx] =
H264Encoder::Create(cricket::VideoCodec("H264"));
payload_type = kPayloadTypeH264;
} else if (params_.video[video_idx].codec == "VP8") {
video_encoders_[video_idx] =
rtc::MakeUnique<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 @@ void VideoQualityTest::SetupVideo(Transport* send_transport,
video_send_configs_[video_idx].rtp.extensions.push_back(RtpExtension(
RtpExtension::kVideoTimingUri, test::kVideoTimingExtensionId));
video_encoder_configs_[video_idx].video_format.name =
params_.video[video_idx].codec;
video_encoder_configs_[video_idx].codec_type =
PayloadStringToCodecType(params_.video[video_idx].codec);
@ -1600,14 +1626,13 @@ void VideoQualityTest::SetupVideo(Transport* send_transport,
void VideoQualityTest::SetupThumbnails(Transport* send_transport,
Transport* recv_transport) {
for (int i = 0; i < params_.call.num_thumbnails; ++i) {
thumbnail_encoders_.emplace_back(VP8Encoder::Create());
// Thumbnails will be send in the other way: from receiver_call to
// sender_call.
VideoSendStream::Config thumbnail_send_config(recv_transport);
thumbnail_send_config.rtp.ssrcs.push_back(kThumbnailSendSsrcStart + i);
thumbnail_send_config.encoder_settings.encoder =
thumbnail_encoders_.back().get();
// TODO(nisse): Could use a simpler VP8-only encoder factory.
thumbnail_send_config.encoder_settings.encoder_factory =
&video_encoder_factory_;
thumbnail_send_config.rtp.payload_name = params_.video[0].codec;
thumbnail_send_config.rtp.payload_type = kPayloadTypeVP8;
thumbnail_send_config.rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
@ -1625,6 +1650,7 @@ void VideoQualityTest::SetupThumbnails(Transport* send_transport,
VideoEncoderConfig thumbnail_encoder_config;
thumbnail_encoder_config.codec_type = kVideoCodecVP8;
thumbnail_encoder_config.video_format.name = "VP8";
thumbnail_encoder_config.min_transmit_bitrate_bps = 7500;
thumbnail_send_config.suspend_below_min_bitrate =
params_.video[0].suspend_below_min_bitrate;

View File

@ -112,6 +112,18 @@ class VideoQualityTest : public test::CallTest {
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 @@ class VideoQualityTest : public test::CallTest {
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_;

View File

@ -77,6 +77,8 @@ VideoSendStream::VideoSendStream(
encoder_config.content_type),
config_(std::move(config)),
content_type_(encoder_config.content_type) {
RTC_DCHECK(config_.encoder_settings.encoder_factory);
video_stream_encoder_ = rtc::MakeUnique<VideoStreamEncoder>(
num_cpu_cores, &stats_proxy_,
config_.encoder_settings,

View File

@ -444,7 +444,6 @@ VideoSendStreamImpl::VideoSendStreamImpl(
transport_->RegisterPacketFeedbackObserver(this);
}
RTC_DCHECK(config_->encoder_settings.encoder);
RTC_DCHECK_GE(config_->rtp.payload_type, 0);
RTC_DCHECK_LE(config_->rtp.payload_type, 127);

View File

@ -33,6 +33,8 @@
#include "system_wrappers/include/sleep.h"
#include "test/call_test.h"
#include "test/configurable_frame_size_encoder.h"
#include "test/encoder_proxy_factory.h"
#include "test/fake_encoder.h"
#include "test/fake_texture_frame.h"
#include "test/field_trial.h"
#include "test/frame_generator.h"
@ -198,8 +200,10 @@ TEST_F(VideoSendStreamTest, SupportsTransmissionTimeOffset) {
class TransmissionTimeOffsetObserver : public test::SendTest {
public:
TransmissionTimeOffsetObserver()
: SendTest(kDefaultTimeoutMs),
encoder_(Clock::GetRealTimeClock(), kEncodeDelayMs) {
: SendTest(kDefaultTimeoutMs), encoder_factory_([]() {
return rtc::MakeUnique<test::DelayedEncoder>(
Clock::GetRealTimeClock(), kEncodeDelayMs);
}) {
EXPECT_TRUE(parser_->RegisterRtpHeaderExtension(
kRtpExtensionTransmissionTimeOffset, test::kTOffsetExtensionId));
}
@ -222,7 +226,7 @@ TEST_F(VideoSendStreamTest, SupportsTransmissionTimeOffset) {
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 @@ TEST_F(VideoSendStreamTest, SupportsTransmissionTimeOffset) {
EXPECT_TRUE(Wait()) << "Timed out while waiting for a single RTP packet.";
}
test::DelayedEncoder encoder_;
test::FunctionVideoEncoderFactory encoder_factory_;
} test;
RunBaseTest(&test);
@ -243,7 +247,10 @@ TEST_F(VideoSendStreamTest, SupportsTransportWideSequenceNumbers) {
class TransportWideSequenceNumberObserver : public test::SendTest {
public:
TransportWideSequenceNumberObserver()
: SendTest(kDefaultTimeoutMs), encoder_(Clock::GetRealTimeClock()) {
: SendTest(kDefaultTimeoutMs), encoder_factory_([]() {
return rtc::MakeUnique<test::FakeEncoder>(
Clock::GetRealTimeClock());
}) {
EXPECT_TRUE(parser_->RegisterRtpHeaderExtension(
kRtpExtensionTransportSequenceNumber, kExtensionId));
}
@ -266,14 +273,14 @@ TEST_F(VideoSendStreamTest, SupportsTransportWideSequenceNumbers) {
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 @@ class UlpfecObserver : public test::EndToEndTest {
bool expect_red,
bool expect_ulpfec,
const std::string& codec,
VideoEncoder* encoder)
VideoEncoderFactory* encoder_factory)
: EndToEndTest(kTimeoutMs),
encoder_(encoder),
encoder_factory_(encoder_factory),
payload_name_(codec),
use_nack_(use_nack),
expect_red_(expect_red),
@ -531,7 +538,7 @@ class UlpfecObserver : public test::EndToEndTest {
(*receive_configs)[0].rtp.nack.rtp_history_ms =
VideoSendStreamTest::kNackRtpHistoryMs;
}
send_config->encoder_settings.encoder = encoder_;
send_config->encoder_settings.encoder_factory = encoder_factory_;
send_config->rtp.payload_name = payload_name_;
send_config->rtp.ulpfec.red_payload_type =
VideoSendStreamTest::kRedPayloadType;
@ -556,7 +563,7 @@ class UlpfecObserver : public test::EndToEndTest {
<< "Timed out waiting for ULPFEC and/or media packets.";
}
VideoEncoder* const encoder_;
VideoEncoderFactory* encoder_factory_;
std::string payload_name_;
const bool use_nack_;
const bool expect_red_;
@ -568,14 +575,16 @@ class UlpfecObserver : public test::EndToEndTest {
};
TEST_F(VideoSendStreamTest, SupportsUlpfecWithExtensions) {
std::unique_ptr<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 @@ class VideoSendStreamWithoutUlpfecTest : public VideoSendStreamTest {
};
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 @@ TEST_F(VideoSendStreamWithoutUlpfecTest, NoUlpfecIfDisabledThroughFieldTrial) {
// bandwidth since the receiver has to wait for FEC retransmissions to determine
// that the received state is actually decodable.
TEST_F(VideoSendStreamTest, DoesNotUtilizeUlpfecForH264WithNackEnabled) {
std::unique_ptr<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 @@ class FlexfecObserver : public test::EndToEndTest {
FlexfecObserver(bool header_extensions_enabled,
bool use_nack,
const std::string& codec,
VideoEncoder* encoder,
VideoEncoderFactory* encoder_factory,
size_t num_video_streams)
: EndToEndTest(VideoSendStreamTest::kDefaultTimeoutMs),
encoder_(encoder),
encoder_factory_(encoder_factory),
payload_name_(codec),
use_nack_(use_nack),
sent_media_(false),
@ -709,7 +725,7 @@ class FlexfecObserver : public test::EndToEndTest {
(*receive_configs)[0].rtp.nack.rtp_history_ms =
VideoSendStreamTest::kNackRtpHistoryMs;
}
send_config->encoder_settings.encoder = encoder_;
send_config->encoder_settings.encoder_factory = encoder_factory_;
send_config->rtp.payload_name = payload_name_;
if (header_extensions_enabled_) {
send_config->rtp.extensions.push_back(RtpExtension(
@ -727,7 +743,7 @@ class FlexfecObserver : public test::EndToEndTest {
<< "Timed out waiting for FlexFEC and/or media packets.";
}
VideoEncoder* const encoder_;
VideoEncoderFactory* encoder_factory_;
std::string payload_name_;
const bool use_nack_;
bool sent_media_;
@ -737,61 +753,72 @@ class FlexfecObserver : public test::EndToEndTest {
};
TEST_F(VideoSendStreamTest, SupportsFlexfecVp8) {
std::unique_ptr<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 @@ void VideoSendStreamTest::TestPacketFragmentationSize(VideoFormat format,
bool use_fec)
: SendTest(kLongTimeoutMs),
encoder_(stop),
encoder_factory_(&encoder_),
max_packet_size_(max_packet_size),
stop_size_(stop_size),
test_generic_packetization_(test_generic_packetization),
@ -1076,8 +1104,7 @@ void VideoSendStreamTest::TestPacketFragmentationSize(VideoFormat format,
if (!test_generic_packetization_)
send_config->rtp.payload_name = "VP8";
send_config->encoder_settings.encoder = &encoder_;
send_config->encoder_settings.encoder_factory = &encoder_factory_;
send_config->rtp.max_packet_size = kMaxPacketSize;
send_config->post_encode_callback = this;
@ -1120,6 +1147,7 @@ void VideoSendStreamTest::TestPacketFragmentationSize(VideoFormat format,
std::unique_ptr<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_F(VideoSendStreamTest,
test::NullTransport transport;
EncoderObserver encoder;
test::EncoderProxyFactory encoder_factory(&encoder);
task_queue_.SendTask([this, &transport, &encoder]() {
task_queue_.SendTask([this, &transport, &encoder_factory]() {
CreateSenderCall(Call::Config(event_log_.get()));
CreateSendConfig(1, 0, 0, &transport);
video_send_config_.encoder_settings.encoder = &encoder;
video_send_config_.encoder_settings.encoder_factory = &encoder_factory;
CreateVideoStreams();
CreateFrameGeneratorCapturer(kDefaultFramerate, kDefaultWidth,
kDefaultHeight);
@ -1984,10 +2013,11 @@ TEST_F(VideoSendStreamTest, CanReconfigureToUseStartBitrateAbovePreviousMax) {
bitrate_config);
StartBitrateObserver encoder;
video_send_config_.encoder_settings.encoder = &encoder;
test::EncoderProxyFactory encoder_factory(&encoder);
// Since this test does not use a capturer, set |internal_source| = true.
// Encoder configuration is otherwise updated on the next video frame.
video_send_config_.encoder_settings.internal_source = true;
encoder_factory.SetHasInternalSource(true);
video_send_config_.encoder_settings.encoder_factory = &encoder_factory;
CreateVideoStreams();
@ -2066,17 +2096,24 @@ class StartStopBitrateObserver : public test::FakeEncoder {
TEST_F(VideoSendStreamTest, VideoSendStreamStopSetEncoderRateToZero) {
test::NullTransport transport;
StartStopBitrateObserver encoder;
test::EncoderProxyFactory encoder_factory(&encoder);
encoder_factory.SetHasInternalSource(true);
test::FrameForwarder forwarder;
task_queue_.SendTask([this, &transport, &encoder]() {
task_queue_.SendTask([this, &transport, &encoder_factory, &forwarder]() {
CreateSenderCall(Call::Config(event_log_.get()));
CreateSendConfig(1, 0, 0, &transport);
sender_call_->SignalChannelNetworkState(MediaType::VIDEO, kNetworkUp);
video_send_config_.encoder_settings.encoder = &encoder;
video_send_config_.encoder_settings.internal_source = true;
video_send_config_.encoder_settings.encoder_factory = &encoder_factory;
CreateVideoStreams();
// Inject a frame, to force encoder creation.
video_send_stream_->Start();
video_send_stream_->SetSource(
&forwarder,
VideoSendStream::DegradationPreference::kDegradationDisabled);
forwarder.IncomingCapturedFrame(CreateVideoFrame(640, 480, 4));
});
EXPECT_TRUE(encoder.WaitForEncoderInit());
@ -2109,19 +2146,28 @@ TEST_F(VideoSendStreamTest, VideoSendStreamStopSetEncoderRateToZero) {
TEST_F(VideoSendStreamTest, VideoSendStreamUpdateActiveSimulcastLayers) {
test::NullTransport transport;
StartStopBitrateObserver encoder;
test::EncoderProxyFactory encoder_factory(&encoder);
encoder_factory.SetHasInternalSource(true);
test::FrameForwarder forwarder;
task_queue_.SendTask([this, &transport, &encoder]() {
task_queue_.SendTask([this, &transport, &encoder_factory, &forwarder]() {
CreateSenderCall(Call::Config(event_log_.get()));
// Create two simulcast streams.
CreateSendConfig(2, 0, 0, &transport);
sender_call_->SignalChannelNetworkState(MediaType::VIDEO, kNetworkUp);
video_send_config_.encoder_settings.encoder_factory = &encoder_factory;
video_send_config_.encoder_settings.encoder = &encoder;
video_send_config_.encoder_settings.internal_source = true;
video_send_config_.rtp.payload_name = "VP8";
CreateVideoStreams();
// Inject a frame, to force encoder creation.
video_send_stream_->Start();
video_send_stream_->SetSource(
&forwarder,
VideoSendStream::DegradationPreference::kDegradationDisabled);
forwarder.IncomingCapturedFrame(CreateVideoFrame(640, 480, 4));
});
EXPECT_TRUE(encoder.WaitForEncoderInit());
@ -2270,7 +2316,8 @@ TEST_F(VideoSendStreamTest, EncoderIsProperlyInitializedAndDestroyed) {
initialized_(false),
callback_registered_(false),
num_releases_(0),
released_(false) {}
released_(false),
encoder_factory_(this) {}
bool IsReleased() {
rtc::CritScope lock(&crit_);
@ -2346,7 +2393,7 @@ TEST_F(VideoSendStreamTest, EncoderIsProperlyInitializedAndDestroyed) {
VideoSendStream::Config* send_config,
std::vector<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 +2422,7 @@ TEST_F(VideoSendStreamTest, EncoderIsProperlyInitializedAndDestroyed) {
bool callback_registered_ RTC_GUARDED_BY(crit_);
size_t num_releases_ RTC_GUARDED_BY(crit_);
bool released_ RTC_GUARDED_BY(crit_);
test::EncoderProxyFactory encoder_factory_;
VideoEncoderConfig encoder_config_;
} test_encoder(&task_queue_);
@ -2393,14 +2441,15 @@ TEST_F(VideoSendStreamTest, EncoderSetupPropagatesCommonEncoderConfigValues) {
FakeEncoder(Clock::GetRealTimeClock()),
init_encode_event_(false, false),
num_initializations_(0),
stream_(nullptr) {}
stream_(nullptr),
encoder_factory_(this) {}
private:
void ModifyVideoConfigs(
VideoSendStream::Config* send_config,
std::vector<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 +2493,7 @@ TEST_F(VideoSendStreamTest, EncoderSetupPropagatesCommonEncoderConfigValues) {
rtc::Event init_encode_event_;
size_t num_initializations_;
VideoSendStream* stream_;
test::EncoderProxyFactory encoder_factory_;
VideoEncoderConfig encoder_config_;
} test;
@ -2463,7 +2513,8 @@ class VideoCodecConfigObserver : public test::SendTest,
codec_name_(codec_name),
init_encode_event_(false, false),
num_initializations_(0),
stream_(nullptr) {
stream_(nullptr),
encoder_factory_(this) {
InitCodecSpecifics();
}
@ -2492,7 +2543,7 @@ class VideoCodecConfigObserver : public test::SendTest,
VideoSendStream::Config* send_config,
std::vector<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 +2603,7 @@ class VideoCodecConfigObserver : public test::SendTest,
rtc::Event init_encode_event_;
size_t num_initializations_;
VideoSendStream* stream_;
test::EncoderProxyFactory encoder_factory_;
VideoEncoderConfig encoder_config_;
};
@ -2738,7 +2790,8 @@ TEST_F(VideoSendStreamTest, TranslatesTwoLayerScreencastToTargetBitrate) {
public:
ScreencastTargetBitrateTest()
: SendTest(kDefaultTimeoutMs),
test::FakeEncoder(Clock::GetRealTimeClock()) {}
test::FakeEncoder(Clock::GetRealTimeClock()),
encoder_factory_(this) {}
private:
int32_t InitEncode(const VideoCodec* config,
@ -2754,7 +2807,7 @@ TEST_F(VideoSendStreamTest, TranslatesTwoLayerScreencastToTargetBitrate) {
VideoSendStream::Config* send_config,
std::vector<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 +2818,7 @@ TEST_F(VideoSendStreamTest, TranslatesTwoLayerScreencastToTargetBitrate) {
EXPECT_TRUE(Wait())
<< "Timed out while waiting for the encoder to be initialized.";
}
test::EncoderProxyFactory encoder_factory_;
} test;
RunBaseTest(&test);
@ -2792,7 +2846,8 @@ TEST_F(VideoSendStreamTest, ReconfigureBitratesSetsEncoderBitratesCorrectly) {
target_bitrate_(0),
num_initializations_(0),
call_(nullptr),
send_stream_(nullptr) {}
send_stream_(nullptr),
encoder_factory_(this) {}
private:
int32_t InitEncode(const VideoCodec* codecSettings,
@ -2882,7 +2937,7 @@ TEST_F(VideoSendStreamTest, ReconfigureBitratesSetsEncoderBitratesCorrectly) {
VideoSendStream::Config* send_config,
std::vector<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 +3000,7 @@ TEST_F(VideoSendStreamTest, ReconfigureBitratesSetsEncoderBitratesCorrectly) {
int num_initializations_;
webrtc::Call* call_;
webrtc::VideoSendStream* send_stream_;
test::EncoderProxyFactory encoder_factory_;
webrtc::VideoEncoderConfig encoder_config_;
} test(&task_queue_);
@ -2965,7 +3021,8 @@ TEST_F(VideoSendStreamTest, ReportsSentResolution) {
ScreencastTargetBitrateTest()
: SendTest(kDefaultTimeoutMs),
test::FakeEncoder(Clock::GetRealTimeClock()),
send_stream_(nullptr) {}
send_stream_(nullptr),
encoder_factory_(this) {}
private:
int32_t Encode(const VideoFrame& input_image,
@ -3003,7 +3060,7 @@ TEST_F(VideoSendStreamTest, ReportsSentResolution) {
VideoSendStream::Config* send_config,
std::vector<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 +3090,7 @@ TEST_F(VideoSendStreamTest, ReportsSentResolution) {
}
VideoSendStream* send_stream_;
test::EncoderProxyFactory encoder_factory_;
} test;
RunBaseTest(&test);
@ -3043,7 +3101,7 @@ class Vp9HeaderObserver : public test::SendTest {
public:
Vp9HeaderObserver()
: SendTest(VideoSendStreamTest::kLongTimeoutMs),
vp9_encoder_(VP9Encoder::Create()),
encoder_factory_([]() { return VP9Encoder::Create(); }),
vp9_settings_(VideoEncoder::GetDefaultVp9Settings()),
packets_sent_(0),
frames_sent_(0),
@ -3084,7 +3142,7 @@ class Vp9HeaderObserver : public test::SendTest {
VideoSendStream::Config* send_config,
std::vector<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 +3404,7 @@ class Vp9HeaderObserver : public test::SendTest {
VerifyTl0Idx(vp9);
}
std::unique_ptr<VP9Encoder> vp9_encoder_;
test::FunctionVideoEncoderFactory encoder_factory_;
VideoCodecVP9 vp9_settings_;
webrtc::VideoEncoderConfig encoder_config_;
RTPHeader last_header_;
@ -3593,6 +3651,7 @@ TEST_F(VideoSendStreamTest, RemoveOverheadFromBandwidth) {
: EndToEndTest(test::CallTest::kDefaultTimeoutMs),
FakeEncoder(Clock::GetRealTimeClock()),
task_queue_(task_queue),
encoder_factory_(this),
call_(nullptr),
max_bitrate_bps_(0),
first_packet_sent_(false),
@ -3619,7 +3678,7 @@ TEST_F(VideoSendStreamTest, RemoveOverheadFromBandwidth) {
std::vector<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 +3705,8 @@ TEST_F(VideoSendStreamTest, RemoveOverheadFromBandwidth) {
// At a bitrate of 60kbps with a packet size of 1200B video and an
// overhead of 40B per packet video produces 2240bps overhead.
// So the encoder BW should be set to 57760bps.
bitrate_changed_event_.Wait(VideoSendStreamTest::kDefaultTimeoutMs);
EXPECT_TRUE(
bitrate_changed_event_.Wait(VideoSendStreamTest::kDefaultTimeoutMs));
{
rtc::CritScope lock(&crit_);
EXPECT_LE(max_bitrate_bps_, 57760u);
@ -3655,6 +3715,7 @@ TEST_F(VideoSendStreamTest, RemoveOverheadFromBandwidth) {
private:
test::SingleThreadedTaskQueueForTesting* const task_queue_;
test::EncoderProxyFactory encoder_factory_;
Call* call_;
rtc::CriticalSection crit_;
uint32_t max_bitrate_bps_ RTC_GUARDED_BY(&crit_);

View File

@ -91,10 +91,11 @@ bool IsFramerateScalingEnabled(
// out). This should effectively turn off CPU adaptations for systems that
// remotely cope with the load right now.
CpuOveruseOptions GetCpuOveruseOptions(
const VideoSendStream::Config::EncoderSettings& settings) {
const VideoSendStream::Config::EncoderSettings& settings,
bool full_overuse_time) {
CpuOveruseOptions options;
if (settings.full_overuse_time) {
if (full_overuse_time) {
options.low_encode_usage_threshold_percent = 150;
options.high_encode_usage_threshold_percent = 200;
}
@ -338,6 +339,7 @@ VideoStreamEncoder::VideoStreamEncoder(
pre_encode_callback_(pre_encode_callback),
max_framerate_(-1),
pending_encoder_reconfiguration_(false),
pending_encoder_creation_(false),
encoder_start_bitrate_bps_(0),
max_data_payload_length_(0),
nack_enabled_(false),
@ -357,13 +359,6 @@ VideoStreamEncoder::VideoStreamEncoder(
encoder_queue_("EncoderQueue") {
RTC_DCHECK(stats_proxy);
RTC_DCHECK(overuse_detector_);
encoder_queue_.PostTask([this] {
RTC_DCHECK_RUN_ON(&encoder_queue_);
overuse_detector_->StartCheckForOveruse(GetCpuOveruseOptions(settings_),
this);
video_sender_.RegisterExternalEncoder(
settings_.encoder, settings_.internal_source);
});
}
VideoStreamEncoder::~VideoStreamEncoder() {
@ -422,7 +417,10 @@ void VideoStreamEncoder::SetSource(
degradation_preference_ = degradation_preference;
bool allow_scaling = IsResolutionScalingEnabled(degradation_preference_);
initial_rampup_ = allow_scaling ? 0 : kMaxInitialFramedrop;
ConfigureQualityScaler();
stats_proxy_->SetAdaptationStats(GetActiveCounts(kCpu),
GetActiveCounts(kQuality));
if (!IsFramerateScalingEnabled(degradation_preference) &&
max_framerate_ != -1) {
// If frame rate scaling is no longer allowed, remove any potential
@ -476,6 +474,8 @@ void VideoStreamEncoder::ConfigureEncoderOnTaskQueue(
max_data_payload_length_ = max_data_payload_length;
nack_enabled_ = nack_enabled;
pending_encoder_creation_ =
(!encoder_ || encoder_config_.video_format != config.video_format);
encoder_config_ = std::move(config);
pending_encoder_reconfiguration_ = true;
@ -485,7 +485,8 @@ void VideoStreamEncoder::ConfigureEncoderOnTaskQueue(
// The codec configuration depends on incoming video frame size.
if (last_frame_info_) {
ReconfigureEncoder();
} else if (settings_.internal_source) {
} else if (settings_.encoder_factory->QueryVideoEncoder(
encoder_config_.video_format).has_internal_source) {
last_frame_info_ = VideoFrameInfo(176, 144, false);
ReconfigureEncoder();
}
@ -528,6 +529,34 @@ void VideoStreamEncoder::ReconfigureEncoder() {
max_framerate_ = codec.maxFramerate;
RTC_DCHECK_LE(max_framerate_, kMaxFramerateFps);
// Keep the same encoder, as long as the video_format is unchanged.
if (pending_encoder_creation_) {
pending_encoder_creation_ = false;
if (encoder_) {
video_sender_.RegisterExternalEncoder(nullptr, false);
}
encoder_ = settings_.encoder_factory->CreateVideoEncoder(
encoder_config_.video_format);
// TODO(nisse): What to do if creating the encoder fails? Crash,
// or just discard incoming frames?
RTC_CHECK(encoder_);
ConfigureQualityScaler();
const webrtc::VideoEncoderFactory::CodecInfo info =
settings_.encoder_factory->QueryVideoEncoder(
encoder_config_.video_format);
overuse_detector_->StopCheckForOveruse();
overuse_detector_->StartCheckForOveruse(
GetCpuOveruseOptions(settings_, info.is_hardware_accelerated), this);
video_sender_.RegisterExternalEncoder(encoder_.get(),
info.has_internal_source);
}
// RegisterSendCodec implies an unconditional call to
// encoder_->InitEncode().
bool success = video_sender_.RegisterSendCodec(
&codec, number_of_cores_,
static_cast<uint32_t>(max_data_payload_length_)) == VCM_OK;
@ -563,13 +592,11 @@ void VideoStreamEncoder::ReconfigureEncoder() {
int target_framerate = std::min(
max_framerate_, source_proxy_->GetActiveSinkWants().max_framerate_fps);
overuse_detector_->OnTargetFramerateUpdated(target_framerate);
ConfigureQualityScaler();
}
void VideoStreamEncoder::ConfigureQualityScaler() {
RTC_DCHECK_RUN_ON(&encoder_queue_);
const auto scaling_settings = settings_.encoder->GetScalingSettings();
const auto scaling_settings = encoder_->GetScalingSettings();
const bool quality_scaling_allowed =
IsResolutionScalingEnabled(degradation_preference_) &&
scaling_settings.thresholds;
@ -589,6 +616,8 @@ void VideoStreamEncoder::ConfigureQualityScaler() {
initial_rampup_ = kMaxInitialFramedrop;
}
// TODO(nisse): Is this still the right place to do this? This is
// now called when the encoder is created.
stats_proxy_->SetAdaptationStats(GetActiveCounts(kCpu),
GetActiveCounts(kQuality));
}
@ -723,6 +752,24 @@ void VideoStreamEncoder::MaybeEncodeVideoFrame(const VideoFrame& video_frame,
<< ", texture=" << last_frame_info_->is_texture << ".";
}
// We have to create then encoder before the frame drop logic,
// because the latter depends on encoder_->GetScalingSettings.
// According to the testcase
// InitialFrameDropOffWhenEncoderDisabledScaling, the return value
// from GetScalingSettings should enable or disable the frame drop.
int64_t now_ms = clock_->TimeInMilliseconds();
if (pending_encoder_reconfiguration_) {
ReconfigureEncoder();
last_parameters_update_ms_.emplace(now_ms);
} else if (!last_parameters_update_ms_ ||
now_ms - *last_parameters_update_ms_ >=
vcm::VCMProcessTimer::kDefaultProcessIntervalMs) {
video_sender_.UpdateChannelParameters(rate_allocator_.get(),
bitrate_observer_);
last_parameters_update_ms_.emplace(now_ms);
}
if (DropDueToSize(video_frame.size())) {
RTC_LOG(LS_INFO) << "Dropping frame. Too large for target bitrate.";
int count = GetConstAdaptCounter().ResolutionCount(kQuality);
@ -744,17 +791,6 @@ void VideoStreamEncoder::MaybeEncodeVideoFrame(const VideoFrame& video_frame,
}
initial_rampup_ = kMaxInitialFramedrop;
int64_t now_ms = clock_->TimeInMilliseconds();
if (pending_encoder_reconfiguration_) {
ReconfigureEncoder();
last_parameters_update_ms_.emplace(now_ms);
} else if (!last_parameters_update_ms_ ||
now_ms - *last_parameters_update_ms_ >=
vcm::VCMProcessTimer::kDefaultProcessIntervalMs) {
video_sender_.UpdateChannelParameters(rate_allocator_.get(),
bitrate_observer_);
last_parameters_update_ms_.emplace(now_ms);
}
if (EncoderPaused()) {
// Storing references to a native buffer risks blocking frame capture.
@ -986,7 +1022,7 @@ void VideoStreamEncoder::AdaptDown(AdaptReason reason) {
bool min_pixels_reached = false;
if (!source_proxy_->RequestResolutionLowerThan(
adaptation_request.input_pixel_count_,
settings_.encoder->GetScalingSettings().min_pixels_per_frame,
encoder_->GetScalingSettings().min_pixels_per_frame,
&min_pixels_reached)) {
if (min_pixels_reached)
stats_proxy_->OnMinPixelLimitReached();

View File

@ -231,6 +231,8 @@ class VideoStreamEncoder : public rtc::VideoSinkInterface<VideoFrame>,
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 @@ class VideoStreamEncoder : public rtc::VideoSinkInterface<VideoFrame>,
// 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_);

View File

@ -21,6 +21,7 @@
#include "rtc_base/logging.h"
#include "system_wrappers/include/metrics_default.h"
#include "system_wrappers/include/sleep.h"
#include "test/encoder_proxy_factory.h"
#include "test/encoder_settings.h"
#include "test/fake_encoder.h"
#include "test/frame_generator.h"
@ -83,6 +84,8 @@ class CpuOveruseDetectorProxy : public OveruseFrameDetector {
return last_target_framerate_fps_;
}
CpuOveruseOptions GetOptions() { return options_; }
private:
rtc::CriticalSection lock_;
int last_target_framerate_fps_ RTC_GUARDED_BY(lock_);
@ -272,6 +275,7 @@ class VideoStreamEncoderTest : public ::testing::Test {
codec_height_(240),
max_framerate_(30),
fake_encoder_(),
encoder_factory_(&fake_encoder_),
stats_proxy_(new MockableSendStatisticsProxy(
Clock::GetRealTimeClock(),
video_send_config_,
@ -281,7 +285,7 @@ class VideoStreamEncoderTest : public ::testing::Test {
void SetUp() override {
metrics::Reset();
video_send_config_ = VideoSendStream::Config(nullptr);
video_send_config_.encoder_settings.encoder = &fake_encoder_;
video_send_config_.encoder_settings.encoder_factory = &encoder_factory_;
video_send_config_.rtp.payload_name = "FAKE";
video_send_config_.rtp.payload_type = 125;
@ -683,6 +687,7 @@ class VideoStreamEncoderTest : public ::testing::Test {
int codec_height_;
int max_framerate_;
TestEncoder fake_encoder_;
test::EncoderProxyFactory encoder_factory_;
std::unique_ptr<MockableSendStatisticsProxy> stats_proxy_;
TestSink sink_;
AdaptingFrameForwarder video_source_;
@ -1437,11 +1442,16 @@ TEST_F(VideoStreamEncoderTest,
EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_resolution);
EXPECT_EQ(1, stats_proxy_->GetStats().number_of_cpu_adapt_changes);
// Set source with adaptation still enabled but quality scaler is off.
// Leave source unchanged, but disable quality scaler.
fake_encoder_.SetQualityScaling(false);
video_stream_encoder_->SetSource(
&video_source_,
VideoSendStream::DegradationPreference::kMaintainFramerate);
VideoEncoderConfig video_encoder_config;
test::FillEncoderConfiguration(kVideoCodecVP8, 1, &video_encoder_config);
// Make format different, to force recreation of encoder.
video_encoder_config.video_format.parameters["foo"] = "foo";
video_stream_encoder_->ConfigureEncoder(std::move(video_encoder_config),
kMaxPayloadLength,
true /* nack_enabled */);
video_source_.IncomingCapturedFrame(CreateFrame(4, kWidth, kHeight));
WaitForEncodedFrame(4);
@ -2516,6 +2526,14 @@ TEST_F(VideoStreamEncoderTest, InitialFrameDropOffWhenEncoderDisabledScaling) {
const int kWidth = 640;
const int kHeight = 360;
fake_encoder_.SetQualityScaling(false);
VideoEncoderConfig video_encoder_config;
test::FillEncoderConfiguration(kVideoCodecVP8, 1, &video_encoder_config);
// Make format different, to force recreation of encoder.
video_encoder_config.video_format.parameters["foo"] = "foo";
video_stream_encoder_->ConfigureEncoder(std::move(video_encoder_config),
kMaxPayloadLength,
true /* nack_enabled */);
video_stream_encoder_->OnBitrateUpdated(kLowTargetBitrateBps, 0, 0);
// Force quality scaler reconfiguration by resetting the source.
@ -3314,4 +3332,44 @@ TEST_F(VideoStreamEncoderTest, DoesNotUpdateBitrateAllocationWhenSuspended) {
video_stream_encoder_->Stop();
}
TEST_F(VideoStreamEncoderTest,
DefaultCpuAdaptationThresholdsForSoftwareEncoder) {
const int kFrameWidth = 1280;
const int kFrameHeight = 720;
const CpuOveruseOptions default_options;
video_stream_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
video_source_.IncomingCapturedFrame(
CreateFrame(1, kFrameWidth, kFrameHeight));
WaitForEncodedFrame(1);
EXPECT_EQ(video_stream_encoder_->overuse_detector_proxy_->GetOptions()
.low_encode_usage_threshold_percent,
default_options.low_encode_usage_threshold_percent);
EXPECT_EQ(video_stream_encoder_->overuse_detector_proxy_->GetOptions()
.high_encode_usage_threshold_percent,
default_options.high_encode_usage_threshold_percent);
video_stream_encoder_->Stop();
}
TEST_F(VideoStreamEncoderTest,
HigherCpuAdaptationThresholdsForHardwareEncoder) {
const int kFrameWidth = 1280;
const int kFrameHeight = 720;
CpuOveruseOptions hardware_options;
hardware_options.low_encode_usage_threshold_percent = 150;
hardware_options.high_encode_usage_threshold_percent = 200;
encoder_factory_.SetIsHardwareAccelerated(true);
video_stream_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
video_source_.IncomingCapturedFrame(
CreateFrame(1, kFrameWidth, kFrameHeight));
WaitForEncodedFrame(1);
EXPECT_EQ(video_stream_encoder_->overuse_detector_proxy_->GetOptions()
.low_encode_usage_threshold_percent,
hardware_options.low_encode_usage_threshold_percent);
EXPECT_EQ(video_stream_encoder_->overuse_detector_proxy_->GetOptions()
.high_encode_usage_threshold_percent,
hardware_options.high_encode_usage_threshold_percent);
video_stream_encoder_->Stop();
}
} // namespace webrtc