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 e12f9ce0884b227717481fc0d74bee4b2aa5579f..198be2a09fb25465e361a105e64955837426c682 100644 |
--- a/webrtc/modules/video_coding/codecs/vp8/screenshare_layers_unittest.cc |
+++ b/webrtc/modules/video_coding/codecs/vp8/screenshare_layers_unittest.cc |
@@ -22,62 +22,19 @@ using ::testing::Return; |
namespace webrtc { |
-enum { kTimestampDelta5Fps = 90000 / 5 }; // 5 frames per second at 90 kHz. |
-enum { kTimestampDelta30Fps = 90000 / 30 }; // 30 frames per second at 90 kHz. |
-enum { kFrameSize = 2500 }; |
- |
-const int kFlagsTL0 = VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF | |
- VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF; |
-const int kFlagsTL1 = VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_ARF | |
- VP8_EFLAG_NO_UPD_LAST; |
-const int kFlagsTL1Sync = VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_REF_GF | |
- VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST; |
- |
-class ScreenshareLayersFT : public ScreenshareLayers { |
- public: |
- ScreenshareLayersFT(int num_temporal_layers, |
- uint8_t initial_tl0_pic_idx, |
- FrameDropper* tl0_frame_dropper, |
- FrameDropper* tl1_frame_dropper) |
- : ScreenshareLayers(num_temporal_layers, |
- initial_tl0_pic_idx, |
- tl0_frame_dropper, |
- tl1_frame_dropper) {} |
- virtual ~ScreenshareLayersFT() {} |
-}; |
+// 5 frames per second at 90 kHz. |
+const uint32_t kTimestampDelta5Fps = 90000 / 5; |
+const int kDefaultQp = 54; |
+const int kDefaultTl0BitrateKbps = 200; |
+const int kDefaultTl1BitrateKbps = 2000; |
+const int kFrameRate = 5; |
+const int kSyncPeriodSeconds = 5; |
+const int kMaxSyncPeriodSeconds = 10; |
class ScreenshareLayerTest : public ::testing::Test { |
protected: |
- void SetEncodeExpectations(bool drop_tl0, bool drop_tl1, int framerate) { |
- EXPECT_CALL(tl0_frame_dropper_, DropFrame()) |
- .Times(1) |
- .WillRepeatedly(Return(drop_tl0)); |
- if (drop_tl0) { |
- EXPECT_CALL(tl1_frame_dropper_, DropFrame()) |
- .Times(1) |
- .WillRepeatedly(Return(drop_tl1)); |
- } |
- EXPECT_CALL(tl0_frame_dropper_, Leak(framerate)) |
- .Times(1); |
- EXPECT_CALL(tl1_frame_dropper_, Leak(framerate)) |
- .Times(1); |
- if (drop_tl0) { |
- EXPECT_CALL(tl0_frame_dropper_, Fill(_, _)) |
- .Times(0); |
- if (drop_tl1) { |
- EXPECT_CALL(tl1_frame_dropper_, Fill(_, _)) |
- .Times(0); |
- } else { |
- EXPECT_CALL(tl1_frame_dropper_, Fill(kFrameSize, true)) |
- .Times(1); |
- } |
- } else { |
- EXPECT_CALL(tl0_frame_dropper_, Fill(kFrameSize, true)) |
- .Times(1); |
- EXPECT_CALL(tl1_frame_dropper_, Fill(kFrameSize, true)) |
- .Times(1); |
- } |
- } |
+ ScreenshareLayerTest() : min_qp_(2), max_qp_(kDefaultQp), frame_size_(-1) {} |
+ virtual ~ScreenshareLayerTest() {} |
void EncodeFrame(uint32_t timestamp, |
bool base_sync, |
@@ -85,39 +42,83 @@ class ScreenshareLayerTest : public ::testing::Test { |
int* flags) { |
*flags = layers_->EncodeFlags(timestamp); |
layers_->PopulateCodecSpecific(base_sync, vp8_info, timestamp); |
- layers_->FrameEncoded(kFrameSize, timestamp); |
+ ASSERT_NE(-1, frame_size_); |
+ layers_->FrameEncoded(frame_size_, timestamp, kDefaultQp); |
+ } |
+ |
+ void 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_; |
+ vpx_cfg.rc_max_quantizer = max_qp_; |
+ EXPECT_TRUE(layers_->ConfigureBitrates( |
+ kDefaultTl0BitrateKbps, kDefaultTl1BitrateKbps, kFrameRate, &vpx_cfg)); |
+ frame_size_ = ((vpx_cfg.rc_target_bitrate * 1000) / 8) / kFrameRate; |
+ } |
+ |
+ void WithQpLimits(int min_qp, int max_qp) { |
+ min_qp_ = min_qp; |
+ max_qp_ = max_qp; |
+ } |
+ |
+ int RunGracePeriod() { |
+ int flags = 0; |
+ uint32_t timestamp = 0; |
+ CodecSpecificInfoVP8 vp8_info; |
+ 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) { |
+ got_tl0 = true; |
+ } else { |
+ got_tl1 = true; |
+ } |
+ if (got_tl0 && got_tl1) |
+ return timestamp; |
+ } |
+ ADD_FAILURE() << "Frames from both layers not received in time."; |
+ return 0; |
} |
- NiceMock<MockFrameDropper> tl0_frame_dropper_; |
- NiceMock<MockFrameDropper> tl1_frame_dropper_; |
- rtc::scoped_ptr<ScreenshareLayersFT> layers_; |
+ int SkipUntilTl(int layer, int timestamp) { |
+ CodecSpecificInfoVP8 vp8_info; |
+ for (int i = 0; i < 5; ++i) { |
+ layers_->EncodeFlags(timestamp); |
+ timestamp += kTimestampDelta5Fps; |
+ layers_->PopulateCodecSpecific(false, &vp8_info, timestamp); |
+ if (vp8_info.temporalIdx != layer) { |
+ layers_->FrameEncoded(frame_size_, timestamp, kDefaultQp); |
+ } else { |
+ return timestamp; |
+ } |
+ } |
+ ADD_FAILURE() << "Did not get a frame of TL" << layer << " in time."; |
+ return 0; |
+ } |
+ |
+ int min_qp_; |
+ int max_qp_; |
+ int frame_size_; |
+ rtc::scoped_ptr<ScreenshareLayers> layers_; |
}; |
TEST_F(ScreenshareLayerTest, 1Layer) { |
- layers_.reset( |
- new ScreenshareLayersFT(1, 0, &tl0_frame_dropper_, &tl1_frame_dropper_)); |
- EXPECT_TRUE(layers_->ConfigureBitrates(100, 1000, 5, NULL)); |
+ layers_.reset(new ScreenshareLayers(1, 0)); |
+ 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. |
- EXPECT_CALL(tl0_frame_dropper_, DropFrame()) |
- .Times(0); |
- EXPECT_CALL(tl1_frame_dropper_, DropFrame()) |
- .Times(0); |
flags = layers_->EncodeFlags(timestamp); |
EXPECT_EQ(0, flags); |
layers_->PopulateCodecSpecific(false, &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(kFrameSize, timestamp); |
- |
- EXPECT_CALL(tl0_frame_dropper_, DropFrame()) |
- .Times(0); |
- EXPECT_CALL(tl1_frame_dropper_, DropFrame()) |
- .Times(0); |
+ layers_->FrameEncoded(frame_size_, timestamp, kDefaultQp); |
flags = layers_->EncodeFlags(timestamp); |
EXPECT_EQ(0, flags); |
timestamp += kTimestampDelta5Fps; |
@@ -125,139 +126,241 @@ TEST_F(ScreenshareLayerTest, 1Layer) { |
EXPECT_EQ(static_cast<uint8_t>(kNoTemporalIdx), vp8_info.temporalIdx); |
EXPECT_FALSE(vp8_info.layerSync); |
EXPECT_EQ(kNoTl0PicIdx, vp8_info.tl0PicIdx); |
- layers_->FrameEncoded(kFrameSize, timestamp); |
+ layers_->FrameEncoded(frame_size_, timestamp, kDefaultQp); |
} |
TEST_F(ScreenshareLayerTest, 2Layer) { |
- layers_.reset( |
- new ScreenshareLayersFT(2, 0, &tl0_frame_dropper_, &tl1_frame_dropper_)); |
- EXPECT_TRUE(layers_->ConfigureBitrates(100, 1000, 5, NULL)); |
+ layers_.reset(new ScreenshareLayers(2, 0)); |
+ ConfigureBitrates(); |
int flags = 0; |
uint32_t timestamp = 0; |
uint8_t expected_tl0_idx = 0; |
CodecSpecificInfoVP8 vp8_info; |
- SetEncodeExpectations(false, false, 1); |
EncodeFrame(timestamp, false, &vp8_info, &flags); |
- EXPECT_EQ(kFlagsTL0, flags); |
+ EXPECT_EQ(ScreenshareLayers::kTl0Flags, flags); |
EXPECT_EQ(0, vp8_info.temporalIdx); |
EXPECT_FALSE(vp8_info.layerSync); |
++expected_tl0_idx; |
EXPECT_EQ(expected_tl0_idx, vp8_info.tl0PicIdx); |
- EXPECT_CALL(tl1_frame_dropper_, SetRates(1000, 1)) |
- .Times(1); |
- EXPECT_TRUE(layers_->ConfigureBitrates(100, 1000, -1, NULL)); |
- // Insert 5 frames at 30 fps. All should belong to TL0. |
+ // Insert 5 frames, cover grace period. All should be in TL0. |
for (int i = 0; i < 5; ++i) { |
- timestamp += kTimestampDelta30Fps; |
- // First iteration has a framerate based on a single frame, thus 1. |
- SetEncodeExpectations(false, false, 30); |
+ 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); |
} |
+ |
+ // First frame in TL0. |
+ timestamp += kTimestampDelta5Fps; |
+ EncodeFrame(timestamp, false, &vp8_info, &flags); |
+ EXPECT_EQ(ScreenshareLayers::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 += kTimestampDelta30Fps; |
- SetEncodeExpectations(true, false, 30); |
+ timestamp += kTimestampDelta5Fps; |
EncodeFrame(timestamp, false, &vp8_info, &flags); |
- EXPECT_EQ(kFlagsTL1Sync, flags); |
+ // First frame is sync frame. |
+ EXPECT_EQ(ScreenshareLayers::kTl1SyncFlags, flags); |
EXPECT_EQ(1, vp8_info.temporalIdx); |
EXPECT_TRUE(vp8_info.layerSync); |
EXPECT_EQ(expected_tl0_idx, vp8_info.tl0PicIdx); |
- timestamp += kTimestampDelta30Fps; |
- SetEncodeExpectations(true, false, 30); |
+ timestamp += kTimestampDelta5Fps; |
EncodeFrame(timestamp, false, &vp8_info, &flags); |
- EXPECT_EQ(kFlagsTL1, flags); |
+ EXPECT_EQ(ScreenshareLayers::kTl1Flags, flags); |
EXPECT_EQ(1, vp8_info.temporalIdx); |
EXPECT_FALSE(vp8_info.layerSync); |
EXPECT_EQ(expected_tl0_idx, vp8_info.tl0PicIdx); |
} |
TEST_F(ScreenshareLayerTest, 2LayersPeriodicSync) { |
- layers_.reset( |
- new ScreenshareLayersFT(2, 0, &tl0_frame_dropper_, &tl1_frame_dropper_)); |
- EXPECT_TRUE(layers_->ConfigureBitrates(100, 1000, 5, NULL)); |
+ layers_.reset(new ScreenshareLayers(2, 0)); |
+ ConfigureBitrates(); |
int flags = 0; |
uint32_t timestamp = 0; |
CodecSpecificInfoVP8 vp8_info; |
- const int kNumFrames = 10; |
- const bool kDrops[kNumFrames] = {false, true, true, true, true, |
- true, true, true, true, true}; |
- const int kExpectedFramerates[kNumFrames] = {1, 5, 5, 5, 5, 5, 5, 5, 5, 5}; |
- const bool kExpectedSyncs[kNumFrames] = {false, true, false, false, false, |
- false, false, true, false, false}; |
- const int kExpectedTemporalIdx[kNumFrames] = {0, 1, 1, 1, 1, 1, 1, 1, 1, 1}; |
+ std::vector<int> sync_times; |
+ |
+ const int kNumFrames = kSyncPeriodSeconds * kFrameRate * 2 - 1; |
for (int i = 0; i < kNumFrames; ++i) { |
timestamp += kTimestampDelta5Fps; |
- SetEncodeExpectations(kDrops[i], false, kExpectedFramerates[i]); |
EncodeFrame(timestamp, false, &vp8_info, &flags); |
- EXPECT_EQ(kExpectedTemporalIdx[i], vp8_info.temporalIdx); |
- EXPECT_EQ(kExpectedSyncs[i], vp8_info.layerSync) << "Iteration: " << i; |
- EXPECT_EQ(1, vp8_info.tl0PicIdx); |
+ if (vp8_info.temporalIdx == 1 && vp8_info.layerSync) { |
+ sync_times.push_back(timestamp); |
+ } |
} |
+ |
+ ASSERT_EQ(2u, sync_times.size()); |
+ EXPECT_GE(sync_times[1] - sync_times[0], 90000 * kSyncPeriodSeconds); |
} |
-TEST_F(ScreenshareLayerTest, 2LayersToggling) { |
- layers_.reset( |
- new ScreenshareLayersFT(2, 0, &tl0_frame_dropper_, &tl1_frame_dropper_)); |
- EXPECT_TRUE(layers_->ConfigureBitrates(100, 1000, 5, NULL)); |
- int flags = 0; |
+TEST_F(ScreenshareLayerTest, 2LayersSyncAfterTimeout) { |
+ layers_.reset(new ScreenshareLayers(2, 0)); |
+ 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; |
+ layers_->EncodeFlags(timestamp); |
+ layers_->PopulateCodecSpecific(false, &vp8_info, timestamp); |
+ |
+ // Simulate TL1 being at least 8 qp steps better. |
+ if (vp8_info.temporalIdx == 0) { |
+ layers_->FrameEncoded(frame_size_, timestamp, kDefaultQp); |
+ } else { |
+ layers_->FrameEncoded(frame_size_, timestamp, kDefaultQp - 8); |
+ } |
+ |
+ if (vp8_info.temporalIdx == 1 && vp8_info.layerSync) |
+ sync_times.push_back(timestamp); |
+ } |
+ |
+ ASSERT_EQ(2u, sync_times.size()); |
+ EXPECT_GE(sync_times[1] - sync_times[0], 90000 * kMaxSyncPeriodSeconds); |
+} |
+ |
+TEST_F(ScreenshareLayerTest, 2LayersSyncAfterSimilarQP) { |
+ layers_.reset(new ScreenshareLayers(2, 0)); |
+ ConfigureBitrates(); |
uint32_t timestamp = 0; |
CodecSpecificInfoVP8 vp8_info; |
- const int kNumFrames = 10; |
- const bool kDrops[kNumFrames] = {false, true, false, true, false, |
- true, false, true, false, true}; |
- const int kExpectedFramerates[kNumFrames] = {1, 5, 5, 5, 5, 5, 5, 5, 5, 5}; |
- const bool kExpectedSyncs[kNumFrames] = {false, true, false, false, false, |
- false, false, true, false, false}; |
- const int kExpectedTemporalIdx[kNumFrames] = {0, 1, 0, 1, 0, 1, 0, 1, 0, 1}; |
- const int kExpectedTl0Idx[kNumFrames] = {1, 1, 2, 2, 3, 3, 4, 4, 5, 5}; |
+ std::vector<int> sync_times; |
+ |
+ const int kNumFrames = (kSyncPeriodSeconds + |
+ ((kMaxSyncPeriodSeconds - kSyncPeriodSeconds) / 2)) * |
+ kFrameRate; |
for (int i = 0; i < kNumFrames; ++i) { |
timestamp += kTimestampDelta5Fps; |
- SetEncodeExpectations(kDrops[i], false, kExpectedFramerates[i]); |
+ layers_->EncodeFlags(timestamp); |
+ layers_->PopulateCodecSpecific(false, &vp8_info, timestamp); |
+ |
+ // Simulate TL1 being at least 8 qp steps better. |
+ if (vp8_info.temporalIdx == 0) { |
+ layers_->FrameEncoded(frame_size_, timestamp, kDefaultQp); |
+ } else { |
+ layers_->FrameEncoded(frame_size_, timestamp, kDefaultQp - 8); |
+ } |
+ |
+ if (vp8_info.temporalIdx == 1 && vp8_info.layerSync) |
+ sync_times.push_back(timestamp); |
+ } |
+ |
+ ASSERT_EQ(1u, sync_times.size()); |
+ |
+ bool bumped_tl0_quality = false; |
+ for (int i = 0; i < 3; ++i) { |
+ timestamp += kTimestampDelta5Fps; |
+ int flags = layers_->EncodeFlags(timestamp); |
+ layers_->PopulateCodecSpecific(false, &vp8_info, timestamp); |
+ |
+ if (vp8_info.temporalIdx == 0) { |
+ // Bump TL0 to same quality as TL1. |
+ layers_->FrameEncoded(frame_size_, timestamp, kDefaultQp - 8); |
+ bumped_tl0_quality = true; |
+ } else { |
+ layers_->FrameEncoded(frame_size_, timestamp, kDefaultQp - 8); |
+ if (bumped_tl0_quality) { |
+ EXPECT_TRUE(vp8_info.layerSync); |
+ EXPECT_EQ(ScreenshareLayers::kTl1SyncFlags, flags); |
+ return; |
+ } |
+ } |
+ } |
+ ADD_FAILURE() << "No TL1 frame arrived within time limit."; |
+} |
+ |
+TEST_F(ScreenshareLayerTest, 2LayersToggling) { |
+ layers_.reset(new ScreenshareLayers(2, 0)); |
+ ConfigureBitrates(); |
+ int flags = 0; |
+ CodecSpecificInfoVP8 vp8_info; |
+ uint32_t timestamp = 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); |
- EXPECT_EQ(kExpectedTemporalIdx[i], vp8_info.temporalIdx); |
- EXPECT_EQ(kExpectedSyncs[i], vp8_info.layerSync) << "Iteration: " << i; |
- EXPECT_EQ(kExpectedTl0Idx[i], vp8_info.tl0PicIdx); |
+ switch (vp8_info.temporalIdx) { |
+ case 0: |
+ ++tl0_frames; |
+ break; |
+ case 1: |
+ ++tl1_frames; |
+ break; |
+ default: |
+ abort(); |
+ } |
} |
+ EXPECT_EQ(20, tl0_frames); |
+ EXPECT_EQ(30, tl1_frames); |
} |
-TEST_F(ScreenshareLayerTest, 2LayersBothDrops) { |
- layers_.reset( |
- new ScreenshareLayersFT(2, 0, &tl0_frame_dropper_, &tl1_frame_dropper_)); |
- EXPECT_TRUE(layers_->ConfigureBitrates(100, 1000, 5, NULL)); |
+TEST_F(ScreenshareLayerTest, AllFitsLayer0) { |
+ layers_.reset(new ScreenshareLayers(2, 0)); |
+ ConfigureBitrates(); |
+ frame_size_ = ((kDefaultTl0BitrateKbps * 1000) / 8) / kFrameRate; |
+ |
int flags = 0; |
uint32_t timestamp = 0; |
- uint8_t expected_tl0_idx = 0; |
CodecSpecificInfoVP8 vp8_info; |
- SetEncodeExpectations(false, false, 1); |
- EncodeFrame(timestamp, false, &vp8_info, &flags); |
- EXPECT_EQ(kFlagsTL0, flags); |
- EXPECT_EQ(0, vp8_info.temporalIdx); |
- EXPECT_FALSE(vp8_info.layerSync); |
- ++expected_tl0_idx; |
- EXPECT_EQ(expected_tl0_idx, vp8_info.tl0PicIdx); |
+ // 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; |
+ EXPECT_EQ(ScreenshareLayers::kTl0Flags, flags); |
+ EXPECT_EQ(0, vp8_info.temporalIdx); |
+ } |
+} |
- timestamp += kTimestampDelta5Fps; |
- SetEncodeExpectations(true, false, 5); |
- EncodeFrame(timestamp, false, &vp8_info, &flags); |
- EXPECT_EQ(kFlagsTL1Sync, flags); |
- EXPECT_EQ(1, vp8_info.temporalIdx); |
- EXPECT_TRUE(vp8_info.layerSync); |
- EXPECT_EQ(expected_tl0_idx, vp8_info.tl0PicIdx); |
+TEST_F(ScreenshareLayerTest, TooHighBitrate) { |
+ layers_.reset(new ScreenshareLayers(2, 0)); |
+ ConfigureBitrates(); |
+ frame_size_ = 2 * ((kDefaultTl1BitrateKbps * 1000) / 8) / kFrameRate; |
+ int flags = 0; |
+ CodecSpecificInfoVP8 vp8_info; |
+ uint32_t timestamp = RunGracePeriod(); |
- timestamp += kTimestampDelta5Fps; |
- SetEncodeExpectations(true, true, 5); |
- flags = layers_->EncodeFlags(timestamp); |
- EXPECT_EQ(-1, flags); |
+ // 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); |
+ if (flags == -1) { |
+ ++dropped_frames; |
+ } else { |
+ switch (vp8_info.temporalIdx) { |
+ case 0: |
+ ++tl0_frames; |
+ break; |
+ case 1: |
+ ++tl1_frames; |
+ break; |
+ default: |
+ abort(); |
+ } |
+ } |
+ } |
+ |
+ EXPECT_EQ(5, tl0_frames); |
+ EXPECT_EQ(45, tl1_frames); |
+ EXPECT_EQ(50, dropped_frames); |
} |
TEST_F(ScreenshareLayerTest, TargetBitrateCappedByTL0) { |
- layers_.reset( |
- new ScreenshareLayersFT(2, 0, &tl0_frame_dropper_, &tl1_frame_dropper_)); |
+ layers_.reset(new ScreenshareLayers(2, 0)); |
vpx_codec_enc_cfg_t cfg; |
layers_->ConfigureBitrates(100, 1000, 5, &cfg); |
@@ -268,8 +371,7 @@ TEST_F(ScreenshareLayerTest, TargetBitrateCappedByTL0) { |
} |
TEST_F(ScreenshareLayerTest, TargetBitrateCappedByTL1) { |
- layers_.reset( |
- new ScreenshareLayersFT(2, 0, &tl0_frame_dropper_, &tl1_frame_dropper_)); |
+ layers_.reset(new ScreenshareLayers(2, 0)); |
vpx_codec_enc_cfg_t cfg; |
layers_->ConfigureBitrates(100, 450, 5, &cfg); |
@@ -279,12 +381,64 @@ TEST_F(ScreenshareLayerTest, TargetBitrateCappedByTL1) { |
} |
TEST_F(ScreenshareLayerTest, TargetBitrateBelowTL0) { |
- layers_.reset( |
- new ScreenshareLayersFT(2, 0, &tl0_frame_dropper_, &tl1_frame_dropper_)); |
+ layers_.reset(new ScreenshareLayers(2, 0)); |
vpx_codec_enc_cfg_t cfg; |
layers_->ConfigureBitrates(100, 100, 5, &cfg); |
EXPECT_EQ(100U, cfg.rc_target_bitrate); |
} |
+TEST_F(ScreenshareLayerTest, EncoderDrop) { |
+ layers_.reset(new ScreenshareLayers(2, 0)); |
+ ConfigureBitrates(); |
+ CodecSpecificInfoVP8 vp8_info; |
+ vpx_codec_enc_cfg_t cfg; |
+ cfg.rc_max_quantizer = kDefaultQp; |
+ |
+ uint32_t timestamp = RunGracePeriod(); |
+ timestamp = SkipUntilTl(0, timestamp); |
+ |
+ // Size 0 indicates dropped frame. |
+ layers_->FrameEncoded(0, timestamp, kDefaultQp); |
+ timestamp += kTimestampDelta5Fps; |
+ EXPECT_FALSE(layers_->UpdateConfiguration(&cfg)); |
+ EXPECT_EQ(ScreenshareLayers::kTl0Flags, layers_->EncodeFlags(timestamp)); |
+ layers_->PopulateCodecSpecific(false, &vp8_info, timestamp); |
+ layers_->FrameEncoded(frame_size_, timestamp, kDefaultQp); |
+ |
+ timestamp = SkipUntilTl(0, timestamp); |
+ EXPECT_TRUE(layers_->UpdateConfiguration(&cfg)); |
+ EXPECT_LT(cfg.rc_max_quantizer, static_cast<unsigned int>(kDefaultQp)); |
+ layers_->FrameEncoded(frame_size_, timestamp, kDefaultQp); |
+ |
+ layers_->EncodeFlags(timestamp); |
+ timestamp += kTimestampDelta5Fps; |
+ EXPECT_TRUE(layers_->UpdateConfiguration(&cfg)); |
+ layers_->PopulateCodecSpecific(false, &vp8_info, timestamp); |
+ EXPECT_EQ(cfg.rc_max_quantizer, static_cast<unsigned int>(kDefaultQp)); |
+ layers_->FrameEncoded(frame_size_, timestamp, kDefaultQp); |
+ |
+ // Next drop in TL1. |
+ |
+ timestamp = SkipUntilTl(1, timestamp); |
+ layers_->FrameEncoded(0, timestamp, kDefaultQp); |
+ timestamp += kTimestampDelta5Fps; |
+ EXPECT_FALSE(layers_->UpdateConfiguration(&cfg)); |
+ EXPECT_EQ(ScreenshareLayers::kTl1Flags, layers_->EncodeFlags(timestamp)); |
+ layers_->PopulateCodecSpecific(false, &vp8_info, timestamp); |
+ layers_->FrameEncoded(frame_size_, timestamp, kDefaultQp); |
+ |
+ timestamp = SkipUntilTl(1, timestamp); |
+ EXPECT_TRUE(layers_->UpdateConfiguration(&cfg)); |
+ EXPECT_LT(cfg.rc_max_quantizer, static_cast<unsigned int>(kDefaultQp)); |
+ layers_->FrameEncoded(frame_size_, timestamp, kDefaultQp); |
+ |
+ layers_->EncodeFlags(timestamp); |
+ timestamp += kTimestampDelta5Fps; |
+ EXPECT_TRUE(layers_->UpdateConfiguration(&cfg)); |
+ layers_->PopulateCodecSpecific(false, &vp8_info, timestamp); |
+ EXPECT_EQ(cfg.rc_max_quantizer, static_cast<unsigned int>(kDefaultQp)); |
+ layers_->FrameEncoded(frame_size_, timestamp, kDefaultQp); |
+} |
+ |
} // namespace webrtc |