Index: webrtc/video/vie_encoder_unittest.cc |
diff --git a/webrtc/video/vie_encoder_unittest.cc b/webrtc/video/vie_encoder_unittest.cc |
index f6046be652c0f5e3fdc0df8f7df82057560224e6..71e68d3ae584e81e097d79e3c9b64a64b30a26c8 100644 |
--- a/webrtc/video/vie_encoder_unittest.cc |
+++ b/webrtc/video/vie_encoder_unittest.cc |
@@ -23,6 +23,9 @@ |
namespace webrtc { |
namespace { |
+const size_t kMaxPayloadLength = 1440; |
+const int kTargetBitrateBps = 100000; |
+ |
class TestBuffer : public webrtc::I420Buffer { |
public: |
TestBuffer(rtc::Event* event, int width, int height) |
@@ -67,6 +70,29 @@ class ViEEncoderUnderTest : public ViEEncoder { |
} |
}; |
+class VideoStreamFactory |
+ : public VideoEncoderConfig::VideoStreamFactoryInterface { |
+ public: |
+ explicit VideoStreamFactory(size_t num_temporal_layers) |
+ : num_temporal_layers_(num_temporal_layers) { |
+ EXPECT_GT(num_temporal_layers, 0u); |
+ } |
+ |
+ private: |
+ std::vector<VideoStream> CreateEncoderStreams( |
+ int width, |
+ int height, |
+ const VideoEncoderConfig& encoder_config) override { |
+ std::vector<VideoStream> streams = |
+ test::CreateVideoStreams(width, height, encoder_config); |
+ for (VideoStream& stream : streams) { |
+ stream.temporal_layer_thresholds_bps.resize(num_temporal_layers_ - 1); |
+ } |
+ return streams; |
+ } |
+ const size_t num_temporal_layers_; |
+}; |
+ |
} // namespace |
class ViEEncoderTest : public ::testing::Test { |
@@ -94,13 +120,35 @@ class ViEEncoderTest : public ::testing::Test { |
VideoEncoderConfig video_encoder_config; |
test::FillEncoderConfiguration(1, &video_encoder_config); |
video_encoder_config_ = video_encoder_config.Copy(); |
+ ConfigureEncoder(std::move(video_encoder_config), true /* nack_enabled */); |
+ } |
+ |
+ void ConfigureEncoder(VideoEncoderConfig video_encoder_config, |
+ bool nack_enabled) { |
+ if (vie_encoder_) |
+ vie_encoder_->Stop(); |
vie_encoder_.reset(new ViEEncoderUnderTest( |
stats_proxy_.get(), video_send_config_.encoder_settings)); |
vie_encoder_->SetSink(&sink_, false /* rotation_applied */); |
vie_encoder_->SetSource(&video_source_, |
VideoSendStream::DegradationPreference::kBalanced); |
vie_encoder_->SetStartBitrate(10000); |
- vie_encoder_->ConfigureEncoder(std::move(video_encoder_config), 1440); |
+ vie_encoder_->ConfigureEncoder(std::move(video_encoder_config), |
+ kMaxPayloadLength, nack_enabled); |
+ } |
+ |
+ void ResetEncoder(const std::string& payload_name, |
+ size_t num_streams, |
+ size_t num_temporal_layers, |
+ bool nack_enabled) { |
+ video_send_config_.encoder_settings.payload_name = payload_name; |
+ |
+ VideoEncoderConfig video_encoder_config; |
+ video_encoder_config.number_of_streams = num_streams; |
+ video_encoder_config.max_bitrate_bps = 1000000; |
+ video_encoder_config.video_stream_factory = |
+ new rtc::RefCountedObject<VideoStreamFactory>(num_temporal_layers); |
+ ConfigureEncoder(std::move(video_encoder_config), nack_enabled); |
} |
VideoFrame CreateFrame(int64_t ntp_ts, rtc::Event* destruction_event) const { |
@@ -248,7 +296,6 @@ class ViEEncoderTest : public ::testing::Test { |
}; |
TEST_F(ViEEncoderTest, EncodeOneFrame) { |
- const int kTargetBitrateBps = 100000; |
vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0); |
rtc::Event frame_destroyed_event(false, false); |
video_source_.IncomingCapturedFrame(CreateFrame(1, &frame_destroyed_event)); |
@@ -263,7 +310,6 @@ TEST_F(ViEEncoderTest, DropsFramesBeforeFirstOnBitrateUpdated) { |
video_source_.IncomingCapturedFrame(CreateFrame(1, &frame_destroyed_event)); |
EXPECT_TRUE(frame_destroyed_event.Wait(kDefaultTimeoutMs)); |
- const int kTargetBitrateBps = 100000; |
vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0); |
video_source_.IncomingCapturedFrame(CreateFrame(2, nullptr)); |
@@ -272,7 +318,6 @@ TEST_F(ViEEncoderTest, DropsFramesBeforeFirstOnBitrateUpdated) { |
} |
TEST_F(ViEEncoderTest, DropsFramesWhenRateSetToZero) { |
- const int kTargetBitrateBps = 100000; |
vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0); |
video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr)); |
sink_.WaitForEncodedFrame(1); |
@@ -288,7 +333,6 @@ TEST_F(ViEEncoderTest, DropsFramesWhenRateSetToZero) { |
} |
TEST_F(ViEEncoderTest, DropsFramesWithSameOrOldNtpTimestamp) { |
- const int kTargetBitrateBps = 100000; |
vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0); |
video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr)); |
sink_.WaitForEncodedFrame(1); |
@@ -302,7 +346,6 @@ TEST_F(ViEEncoderTest, DropsFramesWithSameOrOldNtpTimestamp) { |
} |
TEST_F(ViEEncoderTest, DropsFrameAfterStop) { |
- const int kTargetBitrateBps = 100000; |
vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0); |
video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr)); |
@@ -316,7 +359,6 @@ TEST_F(ViEEncoderTest, DropsFrameAfterStop) { |
} |
TEST_F(ViEEncoderTest, DropsPendingFramesOnSlowEncode) { |
- const int kTargetBitrateBps = 100000; |
vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0); |
fake_encoder_.BlockNextEncode(); |
@@ -333,7 +375,6 @@ TEST_F(ViEEncoderTest, DropsPendingFramesOnSlowEncode) { |
} |
TEST_F(ViEEncoderTest, ConfigureEncoderTriggersOnEncoderConfigurationChanged) { |
- const int kTargetBitrateBps = 100000; |
vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0); |
EXPECT_EQ(0, sink_.number_of_reconfigurations()); |
@@ -347,7 +388,8 @@ TEST_F(ViEEncoderTest, ConfigureEncoderTriggersOnEncoderConfigurationChanged) { |
VideoEncoderConfig video_encoder_config; |
test::FillEncoderConfiguration(1, &video_encoder_config); |
video_encoder_config.min_transmit_bitrate_bps = 9999; |
- vie_encoder_->ConfigureEncoder(std::move(video_encoder_config), 1440); |
+ vie_encoder_->ConfigureEncoder(std::move(video_encoder_config), |
+ kMaxPayloadLength, true /* nack_enabled */); |
// Capture a frame and wait for it to synchronize with the encoder thread. |
video_source_.IncomingCapturedFrame(CreateFrame(2, nullptr)); |
@@ -359,7 +401,6 @@ TEST_F(ViEEncoderTest, ConfigureEncoderTriggersOnEncoderConfigurationChanged) { |
} |
TEST_F(ViEEncoderTest, FrameResolutionChangeReconfigureEncoder) { |
- const int kTargetBitrateBps = 100000; |
vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0); |
// Capture a frame and wait for it to synchronize with the encoder thread. |
@@ -383,6 +424,86 @@ TEST_F(ViEEncoderTest, FrameResolutionChangeReconfigureEncoder) { |
vie_encoder_->Stop(); |
} |
+TEST_F(ViEEncoderTest, Vp8ResilienceIsOffFor1S1TLWithNackEnabled) { |
+ const bool kNackEnabled = true; |
+ const size_t kNumStreams = 1; |
+ const size_t kNumTl = 1; |
+ ResetEncoder("VP8", kNumStreams, kNumTl, kNackEnabled); |
+ vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0); |
+ |
+ // Capture a frame and wait for it to synchronize with the encoder thread. |
+ video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr)); |
+ sink_.WaitForEncodedFrame(1); |
+ // The encoder have been configured once when the first frame is received. |
+ EXPECT_EQ(1, sink_.number_of_reconfigurations()); |
+ EXPECT_EQ(kVideoCodecVP8, fake_encoder_.codec_config().codecType); |
+ EXPECT_EQ(kNumStreams, fake_encoder_.codec_config().numberOfSimulcastStreams); |
+ EXPECT_EQ(kNumTl, fake_encoder_.codec_config().VP8()->numberOfTemporalLayers); |
+ // Resilience is off for no temporal layers with nack on. |
+ EXPECT_EQ(kResilienceOff, fake_encoder_.codec_config().VP8()->resilience); |
+ vie_encoder_->Stop(); |
+} |
+ |
+TEST_F(ViEEncoderTest, Vp8ResilienceIsOffFor2S1TlWithNackEnabled) { |
+ const bool kNackEnabled = true; |
+ const size_t kNumStreams = 2; |
+ const size_t kNumTl = 1; |
+ ResetEncoder("VP8", kNumStreams, kNumTl, kNackEnabled); |
+ vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0); |
+ |
+ // Capture a frame and wait for it to synchronize with the encoder thread. |
+ video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr)); |
+ sink_.WaitForEncodedFrame(1); |
+ // The encoder have been configured once when the first frame is received. |
+ EXPECT_EQ(1, sink_.number_of_reconfigurations()); |
+ EXPECT_EQ(kVideoCodecVP8, fake_encoder_.codec_config().codecType); |
+ EXPECT_EQ(kNumStreams, fake_encoder_.codec_config().numberOfSimulcastStreams); |
+ EXPECT_EQ(kNumTl, fake_encoder_.codec_config().VP8()->numberOfTemporalLayers); |
+ // Resilience is off for no temporal layers and >1 streams with nack on. |
+ EXPECT_EQ(kResilienceOff, fake_encoder_.codec_config().VP8()->resilience); |
+ vie_encoder_->Stop(); |
+} |
+ |
+TEST_F(ViEEncoderTest, Vp8ResilienceIsOnFor1S1TLWithNackDisabled) { |
+ const bool kNackEnabled = false; |
+ const size_t kNumStreams = 1; |
+ const size_t kNumTl = 1; |
+ ResetEncoder("VP8", kNumStreams, kNumTl, kNackEnabled); |
+ vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0); |
+ |
+ // Capture a frame and wait for it to synchronize with the encoder thread. |
+ video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr)); |
+ sink_.WaitForEncodedFrame(1); |
+ // The encoder have been configured once when the first frame is received. |
+ EXPECT_EQ(1, sink_.number_of_reconfigurations()); |
+ EXPECT_EQ(kVideoCodecVP8, fake_encoder_.codec_config().codecType); |
+ EXPECT_EQ(kNumStreams, fake_encoder_.codec_config().numberOfSimulcastStreams); |
+ EXPECT_EQ(kNumTl, fake_encoder_.codec_config().VP8()->numberOfTemporalLayers); |
+ // Resilience is on for no temporal layers with nack off. |
+ EXPECT_EQ(kResilientStream, fake_encoder_.codec_config().VP8()->resilience); |
+ vie_encoder_->Stop(); |
+} |
+ |
+TEST_F(ViEEncoderTest, Vp8ResilienceIsOnFor1S2TlWithNackEnabled) { |
+ const bool kNackEnabled = true; |
+ const size_t kNumStreams = 1; |
+ const size_t kNumTl = 2; |
+ ResetEncoder("VP8", kNumStreams, kNumTl, kNackEnabled); |
+ vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0); |
+ |
+ // Capture a frame and wait for it to synchronize with the encoder thread. |
+ video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr)); |
+ sink_.WaitForEncodedFrame(1); |
+ // The encoder have been configured once when the first frame is received. |
+ EXPECT_EQ(1, sink_.number_of_reconfigurations()); |
+ EXPECT_EQ(kVideoCodecVP8, fake_encoder_.codec_config().codecType); |
+ EXPECT_EQ(kNumStreams, fake_encoder_.codec_config().numberOfSimulcastStreams); |
+ EXPECT_EQ(kNumTl, fake_encoder_.codec_config().VP8()->numberOfTemporalLayers); |
+ // Resilience is on for temporal layers. |
+ EXPECT_EQ(kResilientStream, fake_encoder_.codec_config().VP8()->resilience); |
+ vie_encoder_->Stop(); |
+} |
+ |
TEST_F(ViEEncoderTest, SwitchSourceDeregisterEncoderAsSink) { |
EXPECT_TRUE(video_source_.has_sinks()); |
test::FrameForwarder new_video_source; |
@@ -402,7 +523,6 @@ TEST_F(ViEEncoderTest, SinkWantsRotationApplied) { |
} |
TEST_F(ViEEncoderTest, SinkWantsFromOveruseDetector) { |
- const int kTargetBitrateBps = 100000; |
vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0); |
EXPECT_FALSE(video_source_.sink_wants().max_pixel_count); |
@@ -452,7 +572,6 @@ TEST_F(ViEEncoderTest, SinkWantsFromOveruseDetector) { |
TEST_F(ViEEncoderTest, |
ResolutionSinkWantsResetOnSetSourceWithDisabledResolutionScaling) { |
- const int kTargetBitrateBps = 100000; |
vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0); |
EXPECT_FALSE(video_source_.sink_wants().max_pixel_count); |
@@ -499,7 +618,6 @@ TEST_F(ViEEncoderTest, |
} |
TEST_F(ViEEncoderTest, StatsTracksAdaptationStats) { |
- const int kTargetBitrateBps = 100000; |
vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0); |
int frame_width = 1280; |
@@ -536,7 +654,6 @@ TEST_F(ViEEncoderTest, StatsTracksAdaptationStats) { |
} |
TEST_F(ViEEncoderTest, StatsTracksAdaptationStatsWhenSwitchingSource) { |
- const int kTargetBitrateBps = 100000; |
vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0); |
// Trigger CPU overuse. |
@@ -598,7 +715,6 @@ TEST_F(ViEEncoderTest, StatsTracksAdaptationStatsWhenSwitchingSource) { |
} |
TEST_F(ViEEncoderTest, StatsTracksPreferredBitrate) { |
- const int kTargetBitrateBps = 100000; |
vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0); |
video_source_.IncomingCapturedFrame(CreateFrame(1, 1280, 720)); |
@@ -612,7 +728,6 @@ TEST_F(ViEEncoderTest, StatsTracksPreferredBitrate) { |
} |
TEST_F(ViEEncoderTest, UMACpuLimitedResolutionInPercent) { |
- const int kTargetBitrateBps = 100000; |
vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0); |
int frame_width = 640; |