| Index: webrtc/modules/video_coding/codecs/vp8/screenshare_layers_unittest.cc
|
| diff --git a/webrtc/modules/video_coding/codecs/vp8/screenshare_layers_unittest.cc b/webrtc/modules/video_coding/codecs/vp8/screenshare_layers_unittest.cc
|
| index f6b4beb37983f596eea090727eec6d506940f7eb..9cac0b0a420a6108095262108631667993acfb96 100644
|
| --- a/webrtc/modules/video_coding/codecs/vp8/screenshare_layers_unittest.cc
|
| +++ b/webrtc/modules/video_coding/codecs/vp8/screenshare_layers_unittest.cc
|
| @@ -49,28 +49,44 @@ const int kTl1SyncFlags = VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_REF_GF |
|
| class ScreenshareLayerTest : public ::testing::Test {
|
| protected:
|
| ScreenshareLayerTest()
|
| - : min_qp_(2), max_qp_(kDefaultQp), frame_size_(-1), clock_(1) {}
|
| + : min_qp_(2),
|
| + max_qp_(kDefaultQp),
|
| + frame_size_(-1),
|
| + clock_(1),
|
| + timestamp_(90),
|
| + config_updated_(false) {}
|
| virtual ~ScreenshareLayerTest() {}
|
|
|
| - void SetUp() override { layers_.reset(new ScreenshareLayers(2, 0, &clock_)); }
|
| -
|
| - void EncodeFrame(uint32_t timestamp,
|
| - bool base_sync,
|
| - CodecSpecificInfoVP8* vp8_info,
|
| - int* flags) {
|
| - TemporalLayers::FrameConfig tl_config =
|
| - layers_->UpdateLayerConfig(timestamp);
|
| - if (tl_config.drop_frame) {
|
| - *flags = -1;
|
| - return;
|
| + void SetUp() override {
|
| + layers_.reset(new ScreenshareLayers(2, 0, &clock_));
|
| + cfg_ = ConfigureBitrates();
|
| + }
|
| +
|
| + int EncodeFrame(bool base_sync) {
|
| + int flags = ConfigureFrame(base_sync);
|
| + if (flags != -1)
|
| + layers_->FrameEncoded(frame_size_, kDefaultQp);
|
| + return flags;
|
| + }
|
| +
|
| + int ConfigureFrame(bool key_frame) {
|
| + tl_config_ = layers_->UpdateLayerConfig(timestamp_);
|
| + if (tl_config_.drop_frame) {
|
| + return -1;
|
| }
|
| - *flags = VP8EncoderImpl::EncodeFlags(tl_config);
|
| - layers_->PopulateCodecSpecific(base_sync, tl_config, vp8_info, timestamp);
|
| - ASSERT_NE(-1, frame_size_);
|
| - layers_->FrameEncoded(frame_size_, kDefaultQp);
|
| + config_updated_ = layers_->UpdateConfiguration(&cfg_);
|
| + int flags = VP8EncoderImpl::EncodeFlags(tl_config_);
|
| + layers_->PopulateCodecSpecific(key_frame, tl_config_, &vp8_info_,
|
| + timestamp_);
|
| + EXPECT_NE(-1, frame_size_);
|
| + return flags;
|
| }
|
|
|
| - void ConfigureBitrates() {
|
| + int FrameSizeForBitrate(int bitrate_kbps) {
|
| + return ((bitrate_kbps * 1000) / 8) / kFrameRate;
|
| + }
|
| +
|
| + vpx_codec_enc_cfg_t ConfigureBitrates() {
|
| vpx_codec_enc_cfg_t vpx_cfg;
|
| memset(&vpx_cfg, 0, sizeof(vpx_codec_enc_cfg_t));
|
| vpx_cfg.rc_min_quantizer = min_qp_;
|
| @@ -80,7 +96,8 @@ class ScreenshareLayerTest : public ::testing::Test {
|
| ElementsAre(kDefaultTl0BitrateKbps,
|
| kDefaultTl1BitrateKbps - kDefaultTl0BitrateKbps));
|
| EXPECT_TRUE(layers_->UpdateConfiguration(&vpx_cfg));
|
| - frame_size_ = ((vpx_cfg.rc_target_bitrate * 1000) / 8) / kFrameRate;
|
| + frame_size_ = FrameSizeForBitrate(vpx_cfg.rc_target_bitrate);
|
| + return vpx_cfg;
|
| }
|
|
|
| void WithQpLimits(int min_qp, int max_qp) {
|
| @@ -88,51 +105,39 @@ class ScreenshareLayerTest : public ::testing::Test {
|
| max_qp_ = max_qp;
|
| }
|
|
|
| - int RunGracePeriod() {
|
| - int flags = 0;
|
| - uint32_t timestamp = 0;
|
| - CodecSpecificInfoVP8 vp8_info;
|
| + // Runs a few initial frames and makes sure we have seen frames on both
|
| + // temporal layers.
|
| + bool RunGracePeriod() {
|
| bool got_tl0 = false;
|
| bool got_tl1 = false;
|
| for (int i = 0; i < 10; ++i) {
|
| - EncodeFrame(timestamp, false, &vp8_info, &flags);
|
| - timestamp += kTimestampDelta5Fps;
|
| - if (vp8_info.temporalIdx == 0) {
|
| + EXPECT_NE(-1, EncodeFrame(false));
|
| + timestamp_ += kTimestampDelta5Fps;
|
| + if (vp8_info_.temporalIdx == 0) {
|
| got_tl0 = true;
|
| } else {
|
| got_tl1 = true;
|
| }
|
| if (got_tl0 && got_tl1)
|
| - return timestamp;
|
| + return true;
|
| }
|
| - ADD_FAILURE() << "Frames from both layers not received in time.";
|
| - return 0;
|
| + return false;
|
| }
|
|
|
| - int SkipUntilTl(int layer, int timestamp) {
|
| - CodecSpecificInfoVP8 vp8_info;
|
| + // Adds frames until we get one in the specified temporal layer. The last
|
| + // FrameEncoded() call will be omitted and needs to be done by the caller.
|
| + void SkipUntilTl(int layer) {
|
| for (int i = 0; i < 5; ++i) {
|
| - TemporalLayers::FrameConfig tl_config =
|
| - layers_->UpdateLayerConfig(timestamp);
|
| - VP8EncoderImpl::EncodeFlags(tl_config);
|
| - timestamp += kTimestampDelta5Fps;
|
| - layers_->PopulateCodecSpecific(false, tl_config, &vp8_info, timestamp);
|
| - if (vp8_info.temporalIdx != layer) {
|
| + ConfigureFrame(false);
|
| + timestamp_ += kTimestampDelta5Fps;
|
| + if (vp8_info_.temporalIdx != layer) {
|
| layers_->FrameEncoded(frame_size_, kDefaultQp);
|
| } else {
|
| - return timestamp;
|
| + // Found frame form sought layer.
|
| + return;
|
| }
|
| }
|
| ADD_FAILURE() << "Did not get a frame of TL" << layer << " in time.";
|
| - return 0;
|
| - }
|
| -
|
| - vpx_codec_enc_cfg_t GetConfig() {
|
| - vpx_codec_enc_cfg_t cfg;
|
| - memset(&cfg, 0, sizeof(cfg));
|
| - cfg.rc_min_quantizer = 2;
|
| - cfg.rc_max_quantizer = kDefaultQp;
|
| - return cfg;
|
| }
|
|
|
| int min_qp_;
|
| @@ -140,99 +145,41 @@ class ScreenshareLayerTest : public ::testing::Test {
|
| int frame_size_;
|
| SimulatedClock clock_;
|
| std::unique_ptr<ScreenshareLayers> layers_;
|
| +
|
| + uint32_t timestamp_;
|
| + TemporalLayers::FrameConfig tl_config_;
|
| + vpx_codec_enc_cfg_t cfg_;
|
| + bool config_updated_;
|
| + CodecSpecificInfoVP8 vp8_info_;
|
| };
|
|
|
| TEST_F(ScreenshareLayerTest, 1Layer) {
|
| layers_.reset(new ScreenshareLayers(1, 0, &clock_));
|
| ConfigureBitrates();
|
| - int flags = 0;
|
| - uint32_t timestamp = 0;
|
| - CodecSpecificInfoVP8 vp8_info;
|
| // One layer screenshare should not use the frame dropper as all frames will
|
| // belong to the base layer.
|
| const int kSingleLayerFlags = 0;
|
| - TemporalLayers::FrameConfig tl_config;
|
| - tl_config = layers_->UpdateLayerConfig(timestamp);
|
| - flags = VP8EncoderImpl::EncodeFlags(tl_config);
|
| - EXPECT_EQ(kSingleLayerFlags, flags);
|
| - layers_->PopulateCodecSpecific(false, tl_config, &vp8_info, timestamp);
|
| - EXPECT_EQ(static_cast<uint8_t>(kNoTemporalIdx), vp8_info.temporalIdx);
|
| - EXPECT_FALSE(vp8_info.layerSync);
|
| - EXPECT_EQ(kNoTl0PicIdx, vp8_info.tl0PicIdx);
|
| - layers_->FrameEncoded(frame_size_, kDefaultQp);
|
| - tl_config = layers_->UpdateLayerConfig(timestamp);
|
| - flags = VP8EncoderImpl::EncodeFlags(tl_config);
|
| - EXPECT_EQ(kSingleLayerFlags, flags);
|
| - timestamp += kTimestampDelta5Fps;
|
| - layers_->PopulateCodecSpecific(false, tl_config, &vp8_info, timestamp);
|
| - EXPECT_EQ(static_cast<uint8_t>(kNoTemporalIdx), vp8_info.temporalIdx);
|
| - EXPECT_FALSE(vp8_info.layerSync);
|
| - EXPECT_EQ(kNoTl0PicIdx, vp8_info.tl0PicIdx);
|
| - layers_->FrameEncoded(frame_size_, kDefaultQp);
|
| -}
|
| -
|
| -TEST_F(ScreenshareLayerTest, 2Layer) {
|
| - ConfigureBitrates();
|
| - int flags = 0;
|
| - uint32_t timestamp = 0;
|
| - uint8_t expected_tl0_idx = 0;
|
| - CodecSpecificInfoVP8 vp8_info;
|
| - EncodeFrame(timestamp, false, &vp8_info, &flags);
|
| - EXPECT_EQ(kTl0Flags, flags);
|
| - EXPECT_EQ(0, vp8_info.temporalIdx);
|
| - EXPECT_FALSE(vp8_info.layerSync);
|
| - ++expected_tl0_idx;
|
| - EXPECT_EQ(expected_tl0_idx, vp8_info.tl0PicIdx);
|
| -
|
| - // Insert 5 frames, cover grace period. All should be in TL0.
|
| - for (int i = 0; i < 5; ++i) {
|
| - timestamp += kTimestampDelta5Fps;
|
| - EncodeFrame(timestamp, false, &vp8_info, &flags);
|
| - EXPECT_EQ(0, vp8_info.temporalIdx);
|
| - EXPECT_FALSE(vp8_info.layerSync);
|
| - ++expected_tl0_idx;
|
| - EXPECT_EQ(expected_tl0_idx, vp8_info.tl0PicIdx);
|
| - }
|
| + int flags = EncodeFrame(false);
|
| + timestamp_ += kTimestampDelta5Fps;
|
| + EXPECT_EQ(static_cast<uint8_t>(kNoTemporalIdx), vp8_info_.temporalIdx);
|
| + EXPECT_FALSE(vp8_info_.layerSync);
|
| + EXPECT_EQ(kNoTl0PicIdx, vp8_info_.tl0PicIdx);
|
|
|
| - // First frame in TL0.
|
| - timestamp += kTimestampDelta5Fps;
|
| - EncodeFrame(timestamp, false, &vp8_info, &flags);
|
| - EXPECT_EQ(kTl0Flags, flags);
|
| - EXPECT_EQ(0, vp8_info.temporalIdx);
|
| - EXPECT_FALSE(vp8_info.layerSync);
|
| - ++expected_tl0_idx;
|
| - EXPECT_EQ(expected_tl0_idx, vp8_info.tl0PicIdx);
|
| -
|
| - // Drop two frames from TL0, thus being coded in TL1.
|
| - timestamp += kTimestampDelta5Fps;
|
| - EncodeFrame(timestamp, false, &vp8_info, &flags);
|
| - // First frame is sync frame.
|
| - EXPECT_EQ(kTl1SyncFlags, flags);
|
| - EXPECT_EQ(1, vp8_info.temporalIdx);
|
| - EXPECT_TRUE(vp8_info.layerSync);
|
| - EXPECT_EQ(expected_tl0_idx, vp8_info.tl0PicIdx);
|
| -
|
| - timestamp += kTimestampDelta5Fps;
|
| - EncodeFrame(timestamp, false, &vp8_info, &flags);
|
| - EXPECT_EQ(kTl1Flags, flags);
|
| - EXPECT_EQ(1, vp8_info.temporalIdx);
|
| - EXPECT_FALSE(vp8_info.layerSync);
|
| - EXPECT_EQ(expected_tl0_idx, vp8_info.tl0PicIdx);
|
| + flags = EncodeFrame(false);
|
| + EXPECT_EQ(kSingleLayerFlags, flags);
|
| + EXPECT_EQ(static_cast<uint8_t>(kNoTemporalIdx), vp8_info_.temporalIdx);
|
| + EXPECT_FALSE(vp8_info_.layerSync);
|
| + EXPECT_EQ(kNoTl0PicIdx, vp8_info_.tl0PicIdx);
|
| }
|
|
|
| TEST_F(ScreenshareLayerTest, 2LayersPeriodicSync) {
|
| - ConfigureBitrates();
|
| - int flags = 0;
|
| - uint32_t timestamp = 0;
|
| - CodecSpecificInfoVP8 vp8_info;
|
| std::vector<int> sync_times;
|
| -
|
| const int kNumFrames = kSyncPeriodSeconds * kFrameRate * 2 - 1;
|
| for (int i = 0; i < kNumFrames; ++i) {
|
| - timestamp += kTimestampDelta5Fps;
|
| - EncodeFrame(timestamp, false, &vp8_info, &flags);
|
| - if (vp8_info.temporalIdx == 1 && vp8_info.layerSync) {
|
| - sync_times.push_back(timestamp);
|
| + EncodeFrame(false);
|
| + timestamp_ += kTimestampDelta5Fps;
|
| + if (vp8_info_.temporalIdx == 1 && vp8_info_.layerSync) {
|
| + sync_times.push_back(timestamp_);
|
| }
|
| }
|
|
|
| @@ -241,27 +188,24 @@ TEST_F(ScreenshareLayerTest, 2LayersPeriodicSync) {
|
| }
|
|
|
| TEST_F(ScreenshareLayerTest, 2LayersSyncAfterTimeout) {
|
| - ConfigureBitrates();
|
| - uint32_t timestamp = 0;
|
| - CodecSpecificInfoVP8 vp8_info;
|
| std::vector<int> sync_times;
|
| -
|
| const int kNumFrames = kMaxSyncPeriodSeconds * kFrameRate * 2 - 1;
|
| for (int i = 0; i < kNumFrames; ++i) {
|
| - timestamp += kTimestampDelta5Fps;
|
| - TemporalLayers::FrameConfig tl_config =
|
| - layers_->UpdateLayerConfig(timestamp);
|
| - layers_->PopulateCodecSpecific(false, tl_config, &vp8_info, timestamp);
|
| + tl_config_ = layers_->UpdateLayerConfig(timestamp_);
|
| + config_updated_ = layers_->UpdateConfiguration(&cfg_);
|
| + layers_->PopulateCodecSpecific(false, tl_config_, &vp8_info_, timestamp_);
|
|
|
| // Simulate TL1 being at least 8 qp steps better.
|
| - if (vp8_info.temporalIdx == 0) {
|
| + if (vp8_info_.temporalIdx == 0) {
|
| layers_->FrameEncoded(frame_size_, kDefaultQp);
|
| } else {
|
| layers_->FrameEncoded(frame_size_, kDefaultQp - 8);
|
| }
|
|
|
| - if (vp8_info.temporalIdx == 1 && vp8_info.layerSync)
|
| - sync_times.push_back(timestamp);
|
| + if (vp8_info_.temporalIdx == 1 && vp8_info_.layerSync)
|
| + sync_times.push_back(timestamp_);
|
| +
|
| + timestamp_ += kTimestampDelta5Fps;
|
| }
|
|
|
| ASSERT_EQ(2u, sync_times.size());
|
| @@ -269,70 +213,59 @@ TEST_F(ScreenshareLayerTest, 2LayersSyncAfterTimeout) {
|
| }
|
|
|
| TEST_F(ScreenshareLayerTest, 2LayersSyncAfterSimilarQP) {
|
| - ConfigureBitrates();
|
| - uint32_t timestamp = 0;
|
| - CodecSpecificInfoVP8 vp8_info;
|
| std::vector<int> sync_times;
|
|
|
| const int kNumFrames = (kSyncPeriodSeconds +
|
| ((kMaxSyncPeriodSeconds - kSyncPeriodSeconds) / 2)) *
|
| kFrameRate;
|
| for (int i = 0; i < kNumFrames; ++i) {
|
| - timestamp += kTimestampDelta5Fps;
|
| - TemporalLayers::FrameConfig tl_config =
|
| - layers_->UpdateLayerConfig(timestamp);
|
| - layers_->PopulateCodecSpecific(false, tl_config, &vp8_info, timestamp);
|
| + ConfigureFrame(false);
|
|
|
| // Simulate TL1 being at least 8 qp steps better.
|
| - if (vp8_info.temporalIdx == 0) {
|
| + if (vp8_info_.temporalIdx == 0) {
|
| layers_->FrameEncoded(frame_size_, kDefaultQp);
|
| } else {
|
| layers_->FrameEncoded(frame_size_, kDefaultQp - 8);
|
| }
|
|
|
| - if (vp8_info.temporalIdx == 1 && vp8_info.layerSync)
|
| - sync_times.push_back(timestamp);
|
| + if (vp8_info_.temporalIdx == 1 && vp8_info_.layerSync)
|
| + sync_times.push_back(timestamp_);
|
| +
|
| + timestamp_ += kTimestampDelta5Fps;
|
| }
|
|
|
| ASSERT_EQ(1u, sync_times.size());
|
|
|
| bool bumped_tl0_quality = false;
|
| for (int i = 0; i < 3; ++i) {
|
| - timestamp += kTimestampDelta5Fps;
|
| - TemporalLayers::FrameConfig tl_config =
|
| - layers_->UpdateLayerConfig(timestamp);
|
| - int flags = VP8EncoderImpl::EncodeFlags(tl_config);
|
| - layers_->PopulateCodecSpecific(false, tl_config, &vp8_info, timestamp);
|
| -
|
| - if (vp8_info.temporalIdx == 0) {
|
| + int flags = ConfigureFrame(false);
|
| + if (vp8_info_.temporalIdx == 0) {
|
| // Bump TL0 to same quality as TL1.
|
| layers_->FrameEncoded(frame_size_, kDefaultQp - 8);
|
| bumped_tl0_quality = true;
|
| } else {
|
| layers_->FrameEncoded(frame_size_, kDefaultQp - 8);
|
| if (bumped_tl0_quality) {
|
| - EXPECT_TRUE(vp8_info.layerSync);
|
| + EXPECT_TRUE(vp8_info_.layerSync);
|
| EXPECT_EQ(kTl1SyncFlags, flags);
|
| return;
|
| }
|
| }
|
| + timestamp_ += kTimestampDelta5Fps;
|
| }
|
| ADD_FAILURE() << "No TL1 frame arrived within time limit.";
|
| }
|
|
|
| TEST_F(ScreenshareLayerTest, 2LayersToggling) {
|
| - ConfigureBitrates();
|
| - int flags = 0;
|
| - CodecSpecificInfoVP8 vp8_info;
|
| - uint32_t timestamp = RunGracePeriod();
|
| + EXPECT_TRUE(RunGracePeriod());
|
|
|
| // Insert 50 frames. 2/5 should be TL0.
|
| int tl0_frames = 0;
|
| int tl1_frames = 0;
|
| for (int i = 0; i < 50; ++i) {
|
| - timestamp += kTimestampDelta5Fps;
|
| - EncodeFrame(timestamp, false, &vp8_info, &flags);
|
| - switch (vp8_info.temporalIdx) {
|
| + EncodeFrame(false);
|
| + timestamp_ += kTimestampDelta5Fps;
|
| + switch (vp8_info_.temporalIdx) {
|
| case 0:
|
| ++tl0_frames;
|
| break;
|
| @@ -348,39 +281,31 @@ TEST_F(ScreenshareLayerTest, 2LayersToggling) {
|
| }
|
|
|
| TEST_F(ScreenshareLayerTest, AllFitsLayer0) {
|
| - ConfigureBitrates();
|
| - frame_size_ = ((kDefaultTl0BitrateKbps * 1000) / 8) / kFrameRate;
|
| + frame_size_ = FrameSizeForBitrate(kDefaultTl0BitrateKbps);
|
|
|
| - int flags = 0;
|
| - uint32_t timestamp = 0;
|
| - CodecSpecificInfoVP8 vp8_info;
|
| // Insert 50 frames, small enough that all fits in TL0.
|
| for (int i = 0; i < 50; ++i) {
|
| - EncodeFrame(timestamp, false, &vp8_info, &flags);
|
| - timestamp += kTimestampDelta5Fps;
|
| + int flags = EncodeFrame(false);
|
| + timestamp_ += kTimestampDelta5Fps;
|
| EXPECT_EQ(kTl0Flags, flags);
|
| - EXPECT_EQ(0, vp8_info.temporalIdx);
|
| + EXPECT_EQ(0, vp8_info_.temporalIdx);
|
| }
|
| }
|
|
|
| TEST_F(ScreenshareLayerTest, TooHighBitrate) {
|
| - ConfigureBitrates();
|
| - frame_size_ = 2 * ((kDefaultTl1BitrateKbps * 1000) / 8) / kFrameRate;
|
| - int flags = 0;
|
| - CodecSpecificInfoVP8 vp8_info;
|
| - uint32_t timestamp = RunGracePeriod();
|
| + frame_size_ = 2 * FrameSizeForBitrate(kDefaultTl1BitrateKbps);
|
|
|
| // Insert 100 frames. Half should be dropped.
|
| int tl0_frames = 0;
|
| int tl1_frames = 0;
|
| int dropped_frames = 0;
|
| for (int i = 0; i < 100; ++i) {
|
| - timestamp += kTimestampDelta5Fps;
|
| - EncodeFrame(timestamp, false, &vp8_info, &flags);
|
| + int flags = EncodeFrame(false);
|
| + timestamp_ += kTimestampDelta5Fps;
|
| if (flags == -1) {
|
| ++dropped_frames;
|
| } else {
|
| - switch (vp8_info.temporalIdx) {
|
| + switch (vp8_info_.temporalIdx) {
|
| case 0:
|
| ++tl0_frames;
|
| break;
|
| @@ -388,107 +313,99 @@ TEST_F(ScreenshareLayerTest, TooHighBitrate) {
|
| ++tl1_frames;
|
| break;
|
| default:
|
| - abort();
|
| + ADD_FAILURE() << "Unexpected temporal id";
|
| }
|
| }
|
| }
|
|
|
| - EXPECT_EQ(50, tl0_frames + tl1_frames);
|
| - EXPECT_EQ(50, dropped_frames);
|
| + EXPECT_NEAR(50, tl0_frames + tl1_frames, 1);
|
| + EXPECT_NEAR(50, dropped_frames, 1);
|
| }
|
|
|
| TEST_F(ScreenshareLayerTest, TargetBitrateCappedByTL0) {
|
| - vpx_codec_enc_cfg_t cfg = GetConfig();
|
| const int kTl0_kbps = 100;
|
| const int kTl1_kbps = 1000;
|
| layers_->OnRatesUpdated(kTl0_kbps, kTl1_kbps, 5);
|
|
|
| EXPECT_THAT(layers_->OnRatesUpdated(kTl0_kbps, kTl1_kbps, 5),
|
| ElementsAre(kTl0_kbps, kTl1_kbps - kTl0_kbps));
|
| - EXPECT_TRUE(layers_->UpdateConfiguration(&cfg));
|
| + EXPECT_TRUE(layers_->UpdateConfiguration(&cfg_));
|
|
|
| EXPECT_EQ(static_cast<unsigned int>(
|
| ScreenshareLayers::kMaxTL0FpsReduction * kTl0_kbps + 0.5),
|
| - cfg.rc_target_bitrate);
|
| + cfg_.rc_target_bitrate);
|
| }
|
|
|
| TEST_F(ScreenshareLayerTest, TargetBitrateCappedByTL1) {
|
| - vpx_codec_enc_cfg_t cfg = GetConfig();
|
| const int kTl0_kbps = 100;
|
| const int kTl1_kbps = 450;
|
| EXPECT_THAT(layers_->OnRatesUpdated(kTl0_kbps, kTl1_kbps, 5),
|
| ElementsAre(kTl0_kbps, kTl1_kbps - kTl0_kbps));
|
| - EXPECT_TRUE(layers_->UpdateConfiguration(&cfg));
|
| + EXPECT_TRUE(layers_->UpdateConfiguration(&cfg_));
|
|
|
| EXPECT_EQ(static_cast<unsigned int>(
|
| kTl1_kbps / ScreenshareLayers::kAcceptableTargetOvershoot),
|
| - cfg.rc_target_bitrate);
|
| + cfg_.rc_target_bitrate);
|
| }
|
|
|
| TEST_F(ScreenshareLayerTest, TargetBitrateBelowTL0) {
|
| - vpx_codec_enc_cfg_t cfg = GetConfig();
|
| const int kTl0_kbps = 100;
|
| const int kTl1_kbps = 100;
|
| EXPECT_THAT(layers_->OnRatesUpdated(kTl0_kbps, kTl1_kbps, 5),
|
| ElementsAre(kTl0_kbps));
|
| - EXPECT_TRUE(layers_->UpdateConfiguration(&cfg));
|
| + EXPECT_TRUE(layers_->UpdateConfiguration(&cfg_));
|
|
|
| - EXPECT_EQ(static_cast<uint32_t>(kTl1_kbps), cfg.rc_target_bitrate);
|
| + EXPECT_EQ(static_cast<uint32_t>(kTl1_kbps), cfg_.rc_target_bitrate);
|
| }
|
|
|
| TEST_F(ScreenshareLayerTest, EncoderDrop) {
|
| - ConfigureBitrates();
|
| - CodecSpecificInfoVP8 vp8_info;
|
| - vpx_codec_enc_cfg_t cfg = GetConfig();
|
| - // Updates cfg with current target bitrate.
|
| - EXPECT_TRUE(layers_->UpdateConfiguration(&cfg));
|
| -
|
| - uint32_t timestamp = RunGracePeriod();
|
| - timestamp = SkipUntilTl(0, timestamp);
|
| + EXPECT_TRUE(RunGracePeriod());
|
| + SkipUntilTl(0);
|
|
|
| // Size 0 indicates dropped frame.
|
| layers_->FrameEncoded(0, kDefaultQp);
|
| - timestamp += kTimestampDelta5Fps;
|
| - EXPECT_FALSE(layers_->UpdateConfiguration(&cfg));
|
| - TemporalLayers::FrameConfig tl_config = layers_->UpdateLayerConfig(timestamp);
|
| - EXPECT_EQ(kTl0Flags, VP8EncoderImpl::EncodeFlags(tl_config));
|
| - layers_->PopulateCodecSpecific(false, tl_config, &vp8_info, timestamp);
|
| - layers_->FrameEncoded(frame_size_, kDefaultQp);
|
|
|
| - timestamp = SkipUntilTl(0, timestamp);
|
| - EXPECT_TRUE(layers_->UpdateConfiguration(&cfg));
|
| - EXPECT_LT(cfg.rc_max_quantizer, static_cast<unsigned int>(kDefaultQp));
|
| + // Re-encode frame (so don't advance timestamp).
|
| + int flags = EncodeFrame(false);
|
| + timestamp_ += kTimestampDelta5Fps;
|
| + EXPECT_FALSE(config_updated_);
|
| + EXPECT_EQ(kTl0Flags, flags);
|
| +
|
| + // Next frame should have boosted quality...
|
| + SkipUntilTl(0);
|
| + EXPECT_TRUE(config_updated_);
|
| + EXPECT_LT(cfg_.rc_max_quantizer, static_cast<unsigned int>(kDefaultQp));
|
| layers_->FrameEncoded(frame_size_, kDefaultQp);
|
| + timestamp_ += kTimestampDelta5Fps;
|
|
|
| - tl_config = layers_->UpdateLayerConfig(timestamp);
|
| - timestamp += kTimestampDelta5Fps;
|
| - EXPECT_TRUE(layers_->UpdateConfiguration(&cfg));
|
| - layers_->PopulateCodecSpecific(false, tl_config, &vp8_info, timestamp);
|
| - EXPECT_EQ(cfg.rc_max_quantizer, static_cast<unsigned int>(kDefaultQp));
|
| + // ...then back to standard setup.
|
| + SkipUntilTl(0);
|
| layers_->FrameEncoded(frame_size_, kDefaultQp);
|
| + timestamp_ += kTimestampDelta5Fps;
|
| + EXPECT_EQ(cfg_.rc_max_quantizer, static_cast<unsigned int>(kDefaultQp));
|
|
|
| // Next drop in TL1.
|
| -
|
| - timestamp = SkipUntilTl(1, timestamp);
|
| + SkipUntilTl(1);
|
| layers_->FrameEncoded(0, kDefaultQp);
|
| - timestamp += kTimestampDelta5Fps;
|
| - EXPECT_FALSE(layers_->UpdateConfiguration(&cfg));
|
| - tl_config = layers_->UpdateLayerConfig(timestamp);
|
| - EXPECT_EQ(kTl1Flags, VP8EncoderImpl::EncodeFlags(tl_config));
|
| - layers_->PopulateCodecSpecific(false, tl_config, &vp8_info, timestamp);
|
| - layers_->FrameEncoded(frame_size_, kDefaultQp);
|
|
|
| - timestamp = SkipUntilTl(1, timestamp);
|
| - EXPECT_TRUE(layers_->UpdateConfiguration(&cfg));
|
| - EXPECT_LT(cfg.rc_max_quantizer, static_cast<unsigned int>(kDefaultQp));
|
| + // Re-encode frame (so don't advance timestamp).
|
| + flags = EncodeFrame(false);
|
| + timestamp_ += kTimestampDelta5Fps;
|
| + EXPECT_FALSE(config_updated_);
|
| + EXPECT_EQ(kTl1Flags, flags);
|
| +
|
| + // Next frame should have boosted QP.
|
| + SkipUntilTl(1);
|
| + EXPECT_TRUE(config_updated_);
|
| + EXPECT_LT(cfg_.rc_max_quantizer, static_cast<unsigned int>(kDefaultQp));
|
| layers_->FrameEncoded(frame_size_, kDefaultQp);
|
| + timestamp_ += kTimestampDelta5Fps;
|
|
|
| - tl_config = layers_->UpdateLayerConfig(timestamp);
|
| - timestamp += kTimestampDelta5Fps;
|
| - EXPECT_TRUE(layers_->UpdateConfiguration(&cfg));
|
| - layers_->PopulateCodecSpecific(false, tl_config, &vp8_info, timestamp);
|
| - EXPECT_EQ(cfg.rc_max_quantizer, static_cast<unsigned int>(kDefaultQp));
|
| + // ...and back to normal.
|
| + SkipUntilTl(1);
|
| + EXPECT_EQ(cfg_.rc_max_quantizer, static_cast<unsigned int>(kDefaultQp));
|
| layers_->FrameEncoded(frame_size_, kDefaultQp);
|
| + timestamp_ += kTimestampDelta5Fps;
|
| }
|
|
|
| TEST_F(ScreenshareLayerTest, RespectsMaxIntervalBetweenFrames) {
|
| @@ -496,9 +413,8 @@ TEST_F(ScreenshareLayerTest, RespectsMaxIntervalBetweenFrames) {
|
| const int kLargeFrameSizeBytes = 100000;
|
| const uint32_t kStartTimestamp = 1234;
|
|
|
| - vpx_codec_enc_cfg_t cfg = GetConfig();
|
| layers_->OnRatesUpdated(kLowBitrateKbps, kLowBitrateKbps, 5);
|
| - layers_->UpdateConfiguration(&cfg);
|
| + layers_->UpdateConfiguration(&cfg_);
|
|
|
| EXPECT_EQ(kTl0Flags, VP8EncoderImpl::EncodeFlags(
|
| layers_->UpdateLayerConfig(kStartTimestamp)));
|
| @@ -520,8 +436,6 @@ TEST_F(ScreenshareLayerTest, RespectsMaxIntervalBetweenFrames) {
|
|
|
| TEST_F(ScreenshareLayerTest, UpdatesHistograms) {
|
| metrics::Reset();
|
| - ConfigureBitrates();
|
| - vpx_codec_enc_cfg_t cfg = GetConfig();
|
| bool trigger_drop = false;
|
| bool dropped_frame = false;
|
| bool overshoot = false;
|
| @@ -530,15 +444,14 @@ TEST_F(ScreenshareLayerTest, UpdatesHistograms) {
|
| for (int64_t timestamp = 0;
|
| timestamp < kTimestampDelta5Fps * 5 * metrics::kMinRunTimeInSeconds;
|
| timestamp += kTimestampDelta5Fps) {
|
| - TemporalLayers::FrameConfig tl_config =
|
| - layers_->UpdateLayerConfig(timestamp);
|
| - if (tl_config.drop_frame) {
|
| + tl_config_ = layers_->UpdateLayerConfig(timestamp);
|
| + if (tl_config_.drop_frame) {
|
| dropped_frame = true;
|
| continue;
|
| }
|
| - int flags = VP8EncoderImpl::EncodeFlags(tl_config);
|
| + int flags = VP8EncoderImpl::EncodeFlags(tl_config_);
|
| if (flags != -1)
|
| - layers_->UpdateConfiguration(&cfg);
|
| + layers_->UpdateConfiguration(&cfg_);
|
|
|
| if (timestamp >= kTimestampDelta5Fps * 5 && !overshoot && flags != -1) {
|
| // Simulate one overshoot.
|
| @@ -551,7 +464,7 @@ TEST_F(ScreenshareLayerTest, UpdatesHistograms) {
|
| if (flags == kTl0Flags) {
|
| if (timestamp >= kTimestampDelta5Fps * 20 && !trigger_drop) {
|
| // Simulate a too large frame, to cause frame drop.
|
| - layers_->FrameEncoded(frame_size_ * 5, kTl0Qp);
|
| + layers_->FrameEncoded(frame_size_ * 10, kTl0Qp);
|
| trigger_drop = true;
|
| } else {
|
| layers_->FrameEncoded(frame_size_, kTl0Qp);
|
| @@ -603,13 +516,13 @@ TEST_F(ScreenshareLayerTest, UpdatesHistograms) {
|
| }
|
|
|
| TEST_F(ScreenshareLayerTest, AllowsUpdateConfigBeforeSetRates) {
|
| - vpx_codec_enc_cfg_t cfg = GetConfig();
|
| - EXPECT_FALSE(layers_->UpdateConfiguration(&cfg));
|
| + layers_.reset(new ScreenshareLayers(2, 0, &clock_));
|
| + // New layer instance, OnRatesUpdated() never called.
|
| + // UpdateConfiguration() call should not cause crash.
|
| + layers_->UpdateConfiguration(&cfg_);
|
| }
|
|
|
| TEST_F(ScreenshareLayerTest, RespectsConfiguredFramerate) {
|
| - ConfigureBitrates();
|
| -
|
| int64_t kTestSpanMs = 2000;
|
| int64_t kFrameIntervalsMs = 1000 / kFrameRate;
|
|
|
|
|