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; |