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