1 /*
2 * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11 #include "modules/video_coding/codecs/vp8/screenshare_layers.h"
12
13 #include <stdlib.h>
14 #include <string.h>
15
16 #include <cstdint>
17 #include <memory>
18 #include <vector>
19
20 #include "api/video_codecs/vp8_frame_config.h"
21 #include "modules/video_coding/codecs/interface/common_constants.h"
22 #include "modules/video_coding/codecs/vp8/libvpx_vp8_encoder.h"
23 #include "modules/video_coding/include/video_codec_interface.h"
24 #include "rtc_base/checks.h"
25 #include "rtc_base/fake_clock.h"
26 #include "system_wrappers/include/metrics.h"
27 #include "test/gmock.h"
28 #include "test/gtest.h"
29 #include "vpx/vp8cx.h"
30
31 using ::testing::_;
32 using ::testing::ElementsAre;
33 using ::testing::NiceMock;
34
35 namespace webrtc {
36 namespace {
37 // 5 frames per second at 90 kHz.
38 const uint32_t kTimestampDelta5Fps = 90000 / 5;
39 const int kDefaultQp = 54;
40 const int kDefaultTl0BitrateKbps = 200;
41 const int kDefaultTl1BitrateKbps = 2000;
42 const int kFrameRate = 5;
43 const int kSyncPeriodSeconds = 2;
44 const int kMaxSyncPeriodSeconds = 4;
45
46 // Expected flags for corresponding temporal layers.
47 const int kTl0Flags = VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF |
48 VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF;
49 const int kTl1Flags =
50 VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST;
51 const int kTl1SyncFlags = VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_REF_GF |
52 VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST;
53 const std::vector<uint32_t> kDefault2TlBitratesBps = {
54 kDefaultTl0BitrateKbps * 1000,
55 (kDefaultTl1BitrateKbps - kDefaultTl0BitrateKbps) * 1000};
56
57 } // namespace
58
59 class ScreenshareLayerTest : public ::testing::Test {
60 protected:
ScreenshareLayerTest()61 ScreenshareLayerTest()
62 : min_qp_(2),
63 max_qp_(kDefaultQp),
64 frame_size_(-1),
65 timestamp_(90),
66 config_updated_(false) {}
~ScreenshareLayerTest()67 virtual ~ScreenshareLayerTest() {}
68
SetUp()69 void SetUp() override {
70 layers_.reset(new ScreenshareLayers(2));
71 cfg_ = ConfigureBitrates();
72 }
73
EncodeFrame(bool base_sync,CodecSpecificInfo * info=nullptr)74 int EncodeFrame(bool base_sync, CodecSpecificInfo* info = nullptr) {
75 CodecSpecificInfo ignored_info;
76 if (!info) {
77 info = &ignored_info;
78 }
79
80 int flags = ConfigureFrame(base_sync);
81 if (flags != -1)
82 layers_->OnEncodeDone(0, timestamp_, frame_size_, base_sync, kDefaultQp,
83 info);
84 return flags;
85 }
86
ConfigureFrame(bool key_frame)87 int ConfigureFrame(bool key_frame) {
88 tl_config_ = NextFrameConfig(0, timestamp_);
89 EXPECT_EQ(0, tl_config_.encoder_layer_id)
90 << "ScreenshareLayers always encodes using the bitrate allocator for "
91 "layer 0, but may reference different buffers and packetize "
92 "differently.";
93 if (tl_config_.drop_frame) {
94 return -1;
95 }
96 const uint32_t prev_rc_target_bitrate = cfg_.rc_target_bitrate.value_or(-1);
97 const uint32_t prev_rc_max_quantizer = cfg_.rc_max_quantizer.value_or(-1);
98
99 cfg_ = layers_->UpdateConfiguration(0);
100
101 config_updated_ =
102 cfg_.temporal_layer_config.has_value() ||
103 (cfg_.rc_target_bitrate.has_value() &&
104 cfg_.rc_target_bitrate.value() != prev_rc_target_bitrate) ||
105 (cfg_.rc_max_quantizer.has_value() &&
106 cfg_.rc_max_quantizer.value() != prev_rc_max_quantizer) ||
107 cfg_.g_error_resilient.has_value();
108
109 int flags = LibvpxVp8Encoder::EncodeFlags(tl_config_);
110 EXPECT_NE(-1, frame_size_);
111 return flags;
112 }
113
NextFrameConfig(size_t stream_index,uint32_t timestamp)114 Vp8FrameConfig NextFrameConfig(size_t stream_index, uint32_t timestamp) {
115 int64_t timestamp_ms = timestamp / 90;
116 clock_.AdvanceTime(TimeDelta::Millis(timestamp_ms - rtc::TimeMillis()));
117 return layers_->NextFrameConfig(stream_index, timestamp);
118 }
119
FrameSizeForBitrate(int bitrate_kbps)120 int FrameSizeForBitrate(int bitrate_kbps) {
121 return ((bitrate_kbps * 1000) / 8) / kFrameRate;
122 }
123
ConfigureBitrates()124 Vp8EncoderConfig ConfigureBitrates() {
125 layers_->SetQpLimits(0, min_qp_, max_qp_);
126 layers_->OnRatesUpdated(0, kDefault2TlBitratesBps, kFrameRate);
127 const Vp8EncoderConfig vp8_cfg = layers_->UpdateConfiguration(0);
128 EXPECT_TRUE(vp8_cfg.rc_target_bitrate.has_value());
129 frame_size_ = FrameSizeForBitrate(vp8_cfg.rc_target_bitrate.value());
130 return vp8_cfg;
131 }
132
WithQpLimits(int min_qp,int max_qp)133 void WithQpLimits(int min_qp, int max_qp) {
134 min_qp_ = min_qp;
135 max_qp_ = max_qp;
136 }
137
138 // Runs a few initial frames and makes sure we have seen frames on both
139 // temporal layers, including sync and non-sync frames.
RunGracePeriod()140 bool RunGracePeriod() {
141 bool got_tl0 = false;
142 bool got_tl1 = false;
143 bool got_tl1_sync = false;
144 for (int i = 0; i < 10; ++i) {
145 CodecSpecificInfo info;
146 EXPECT_NE(-1, EncodeFrame(false, &info));
147 timestamp_ += kTimestampDelta5Fps;
148 if (info.codecSpecific.VP8.temporalIdx == 0) {
149 got_tl0 = true;
150 } else if (info.codecSpecific.VP8.layerSync) {
151 got_tl1_sync = true;
152 } else {
153 got_tl1 = true;
154 }
155 if (got_tl0 && got_tl1 && got_tl1_sync)
156 return true;
157 }
158 return false;
159 }
160
161 // Adds frames until we get one in the specified temporal layer. The last
162 // FrameEncoded() call will be omitted and needs to be done by the caller.
163 // Returns the flags for the last frame.
SkipUntilTl(int layer)164 int SkipUntilTl(int layer) {
165 return SkipUntilTlAndSync(layer, absl::nullopt);
166 }
167
168 // Same as SkipUntilTl, but also waits until the sync bit condition is met.
SkipUntilTlAndSync(int layer,absl::optional<bool> sync)169 int SkipUntilTlAndSync(int layer, absl::optional<bool> sync) {
170 int flags = 0;
171 const int kMaxFramesToSkip =
172 1 + (sync.value_or(false) ? kMaxSyncPeriodSeconds : 1) * kFrameRate;
173 for (int i = 0; i < kMaxFramesToSkip; ++i) {
174 flags = ConfigureFrame(false);
175 if (tl_config_.packetizer_temporal_idx != layer ||
176 (sync && *sync != tl_config_.layer_sync)) {
177 if (flags != -1) {
178 // If flags do not request a frame drop, report some default values
179 // for frame size etc.
180 CodecSpecificInfo info;
181 layers_->OnEncodeDone(0, timestamp_, frame_size_, false, kDefaultQp,
182 &info);
183 }
184 timestamp_ += kTimestampDelta5Fps;
185 } else {
186 // Found frame from sought after layer.
187 return flags;
188 }
189 }
190 ADD_FAILURE() << "Did not get a frame of TL" << layer << " in time.";
191 return -1;
192 }
193
194 int min_qp_;
195 uint32_t max_qp_;
196 int frame_size_;
197 rtc::ScopedFakeClock clock_;
198 std::unique_ptr<ScreenshareLayers> layers_;
199
200 uint32_t timestamp_;
201 Vp8FrameConfig tl_config_;
202 Vp8EncoderConfig cfg_;
203 bool config_updated_;
204
IgnoredCodecSpecificInfo()205 CodecSpecificInfo* IgnoredCodecSpecificInfo() {
206 ignored_codec_specific_info_ = std::make_unique<CodecSpecificInfo>();
207 return ignored_codec_specific_info_.get();
208 }
209
210 private:
211 std::unique_ptr<CodecSpecificInfo> ignored_codec_specific_info_;
212 };
213
214 TEST_F(ScreenshareLayerTest, 1Layer) {
215 layers_.reset(new ScreenshareLayers(1));
216 ConfigureBitrates();
217 // One layer screenshare should not use the frame dropper as all frames will
218 // belong to the base layer.
219 const int kSingleLayerFlags = 0;
220 auto info = std::make_unique<CodecSpecificInfo>();
221 int flags = EncodeFrame(/*base_sync=*/false, info.get());
222 timestamp_ += kTimestampDelta5Fps;
223 EXPECT_EQ(static_cast<uint8_t>(kNoTemporalIdx),
224 info->codecSpecific.VP8.temporalIdx);
225 EXPECT_FALSE(info->codecSpecific.VP8.layerSync);
226 EXPECT_EQ(info->generic_frame_info->temporal_id, 0);
227
228 info = std::make_unique<CodecSpecificInfo>();
229 flags = EncodeFrame(/*base_sync=*/false, info.get());
230 EXPECT_EQ(kSingleLayerFlags, flags);
231 EXPECT_EQ(static_cast<uint8_t>(kNoTemporalIdx),
232 info->codecSpecific.VP8.temporalIdx);
233 EXPECT_FALSE(info->codecSpecific.VP8.layerSync);
234 EXPECT_EQ(info->generic_frame_info->temporal_id, 0);
235 }
236
237 TEST_F(ScreenshareLayerTest, 2LayersPeriodicSync) {
238 std::vector<int> sync_times;
239 const int kNumFrames = kSyncPeriodSeconds * kFrameRate * 2 - 1;
240 for (int i = 0; i < kNumFrames; ++i) {
241 CodecSpecificInfo info;
242 EncodeFrame(false, &info);
243 timestamp_ += kTimestampDelta5Fps;
244 if (info.codecSpecific.VP8.temporalIdx == 1 &&
245 info.codecSpecific.VP8.layerSync) {
246 sync_times.push_back(timestamp_);
247 }
248 }
249
250 ASSERT_EQ(2u, sync_times.size());
251 EXPECT_GE(sync_times[1] - sync_times[0], 90000 * kSyncPeriodSeconds);
252 }
253
254 TEST_F(ScreenshareLayerTest, 2LayersSyncAfterTimeout) {
255 std::vector<int> sync_times;
256 const int kNumFrames = kMaxSyncPeriodSeconds * kFrameRate * 2 - 1;
257 for (int i = 0; i < kNumFrames; ++i) {
258 CodecSpecificInfo info;
259
260 tl_config_ = NextFrameConfig(0, timestamp_);
261 cfg_ = layers_->UpdateConfiguration(0);
262
263 // Simulate TL1 being at least 8 qp steps better.
264 if (tl_config_.packetizer_temporal_idx == 0) {
265 layers_->OnEncodeDone(0, timestamp_, frame_size_, false, kDefaultQp,
266 &info);
267 } else {
268 layers_->OnEncodeDone(0, timestamp_, frame_size_, false, kDefaultQp - 8,
269 &info);
270 }
271
272 if (info.codecSpecific.VP8.temporalIdx == 1 &&
273 info.codecSpecific.VP8.layerSync)
274 sync_times.push_back(timestamp_);
275
276 timestamp_ += kTimestampDelta5Fps;
277 }
278
279 ASSERT_EQ(2u, sync_times.size());
280 EXPECT_GE(sync_times[1] - sync_times[0], 90000 * kMaxSyncPeriodSeconds);
281 }
282
283 TEST_F(ScreenshareLayerTest, 2LayersSyncAfterSimilarQP) {
284 std::vector<int> sync_times;
285
286 const int kNumFrames = (kSyncPeriodSeconds +
287 ((kMaxSyncPeriodSeconds - kSyncPeriodSeconds) / 2)) *
288 kFrameRate;
289 for (int i = 0; i < kNumFrames; ++i) {
290 CodecSpecificInfo info;
291
292 ConfigureFrame(false);
293
294 // Simulate TL1 being at least 8 qp steps better.
295 if (tl_config_.packetizer_temporal_idx == 0) {
296 layers_->OnEncodeDone(0, timestamp_, frame_size_, false, kDefaultQp,
297 &info);
298 } else {
299 layers_->OnEncodeDone(0, timestamp_, frame_size_, false, kDefaultQp - 8,
300 &info);
301 }
302
303 if (info.codecSpecific.VP8.temporalIdx == 1 &&
304 info.codecSpecific.VP8.layerSync)
305 sync_times.push_back(timestamp_);
306
307 timestamp_ += kTimestampDelta5Fps;
308 }
309
310 ASSERT_EQ(1u, sync_times.size());
311
312 bool bumped_tl0_quality = false;
313 for (int i = 0; i < 3; ++i) {
314 CodecSpecificInfo info;
315
316 int flags = ConfigureFrame(false);
317 layers_->OnEncodeDone(0, timestamp_, frame_size_, false, kDefaultQp - 8,
318 &info);
319 if (info.codecSpecific.VP8.temporalIdx == 0) {
320 // Bump TL0 to same quality as TL1.
321 bumped_tl0_quality = true;
322 } else {
323 if (bumped_tl0_quality) {
324 EXPECT_TRUE(info.codecSpecific.VP8.layerSync);
325 EXPECT_EQ(kTl1SyncFlags, flags);
326 return;
327 }
328 }
329 timestamp_ += kTimestampDelta5Fps;
330 }
331 ADD_FAILURE() << "No TL1 frame arrived within time limit.";
332 }
333
334 TEST_F(ScreenshareLayerTest, 2LayersToggling) {
335 EXPECT_TRUE(RunGracePeriod());
336
337 // Insert 50 frames. 2/5 should be TL0.
338 int tl0_frames = 0;
339 int tl1_frames = 0;
340 for (int i = 0; i < 50; ++i) {
341 CodecSpecificInfo info;
342 EncodeFrame(/*base_sync=*/false, &info);
343 EXPECT_EQ(info.codecSpecific.VP8.temporalIdx,
344 info.generic_frame_info->temporal_id);
345 timestamp_ += kTimestampDelta5Fps;
346 switch (info.codecSpecific.VP8.temporalIdx) {
347 case 0:
348 ++tl0_frames;
349 break;
350 case 1:
351 ++tl1_frames;
352 break;
353 default:
354 abort();
355 }
356 }
357 EXPECT_EQ(20, tl0_frames);
358 EXPECT_EQ(30, tl1_frames);
359 }
360
TEST_F(ScreenshareLayerTest,AllFitsLayer0)361 TEST_F(ScreenshareLayerTest, AllFitsLayer0) {
362 frame_size_ = FrameSizeForBitrate(kDefaultTl0BitrateKbps);
363
364 // Insert 50 frames, small enough that all fits in TL0.
365 for (int i = 0; i < 50; ++i) {
366 CodecSpecificInfo info;
367 int flags = EncodeFrame(false, &info);
368 timestamp_ += kTimestampDelta5Fps;
369 EXPECT_EQ(kTl0Flags, flags);
370 EXPECT_EQ(0, info.codecSpecific.VP8.temporalIdx);
371 }
372 }
373
TEST_F(ScreenshareLayerTest,TooHighBitrate)374 TEST_F(ScreenshareLayerTest, TooHighBitrate) {
375 frame_size_ = 2 * FrameSizeForBitrate(kDefaultTl1BitrateKbps);
376
377 // Insert 100 frames. Half should be dropped.
378 int tl0_frames = 0;
379 int tl1_frames = 0;
380 int dropped_frames = 0;
381 for (int i = 0; i < 100; ++i) {
382 CodecSpecificInfo info;
383 int flags = EncodeFrame(false, &info);
384 timestamp_ += kTimestampDelta5Fps;
385 if (flags == -1) {
386 ++dropped_frames;
387 } else {
388 switch (info.codecSpecific.VP8.temporalIdx) {
389 case 0:
390 ++tl0_frames;
391 break;
392 case 1:
393 ++tl1_frames;
394 break;
395 default:
396 ADD_FAILURE() << "Unexpected temporal id";
397 }
398 }
399 }
400
401 EXPECT_NEAR(50, tl0_frames + tl1_frames, 1);
402 EXPECT_NEAR(50, dropped_frames, 1);
403 }
404
TEST_F(ScreenshareLayerTest,TargetBitrateCappedByTL0)405 TEST_F(ScreenshareLayerTest, TargetBitrateCappedByTL0) {
406 const int kTl0_kbps = 100;
407 const int kTl1_kbps = 1000;
408 const std::vector<uint32_t> layer_rates = {kTl0_kbps * 1000,
409 (kTl1_kbps - kTl0_kbps) * 1000};
410 layers_->OnRatesUpdated(0, layer_rates, kFrameRate);
411 cfg_ = layers_->UpdateConfiguration(0);
412
413 EXPECT_EQ(static_cast<unsigned int>(
414 ScreenshareLayers::kMaxTL0FpsReduction * kTl0_kbps + 0.5),
415 cfg_.rc_target_bitrate);
416 }
417
TEST_F(ScreenshareLayerTest,TargetBitrateCappedByTL1)418 TEST_F(ScreenshareLayerTest, TargetBitrateCappedByTL1) {
419 const int kTl0_kbps = 100;
420 const int kTl1_kbps = 450;
421 const std::vector<uint32_t> layer_rates = {kTl0_kbps * 1000,
422 (kTl1_kbps - kTl0_kbps) * 1000};
423 layers_->OnRatesUpdated(0, layer_rates, kFrameRate);
424 cfg_ = layers_->UpdateConfiguration(0);
425
426 EXPECT_EQ(static_cast<unsigned int>(
427 kTl1_kbps / ScreenshareLayers::kAcceptableTargetOvershoot),
428 cfg_.rc_target_bitrate);
429 }
430
TEST_F(ScreenshareLayerTest,TargetBitrateBelowTL0)431 TEST_F(ScreenshareLayerTest, TargetBitrateBelowTL0) {
432 const int kTl0_kbps = 100;
433 const std::vector<uint32_t> layer_rates = {kTl0_kbps * 1000};
434 layers_->OnRatesUpdated(0, layer_rates, kFrameRate);
435 cfg_ = layers_->UpdateConfiguration(0);
436
437 EXPECT_EQ(static_cast<uint32_t>(kTl0_kbps), cfg_.rc_target_bitrate);
438 }
439
TEST_F(ScreenshareLayerTest,EncoderDrop)440 TEST_F(ScreenshareLayerTest, EncoderDrop) {
441 EXPECT_TRUE(RunGracePeriod());
442 SkipUntilTl(0);
443
444 // Size 0 indicates dropped frame.
445 layers_->OnEncodeDone(0, timestamp_, 0, false, 0, IgnoredCodecSpecificInfo());
446
447 // Re-encode frame (so don't advance timestamp).
448 int flags = EncodeFrame(false);
449 timestamp_ += kTimestampDelta5Fps;
450 EXPECT_FALSE(config_updated_);
451 EXPECT_EQ(kTl0Flags, flags);
452
453 // Next frame should have boosted quality...
454 SkipUntilTl(0);
455 EXPECT_TRUE(config_updated_);
456 EXPECT_LT(cfg_.rc_max_quantizer, static_cast<unsigned int>(kDefaultQp));
457 layers_->OnEncodeDone(0, timestamp_, frame_size_, false, kDefaultQp,
458 IgnoredCodecSpecificInfo());
459 timestamp_ += kTimestampDelta5Fps;
460
461 // ...then back to standard setup.
462 SkipUntilTl(0);
463 layers_->OnEncodeDone(0, timestamp_, frame_size_, false, kDefaultQp,
464 IgnoredCodecSpecificInfo());
465 timestamp_ += kTimestampDelta5Fps;
466 EXPECT_EQ(cfg_.rc_max_quantizer, static_cast<unsigned int>(kDefaultQp));
467
468 // Next drop in TL1.
469 SkipUntilTl(1);
470 layers_->OnEncodeDone(0, timestamp_, 0, false, 0, IgnoredCodecSpecificInfo());
471
472 // Re-encode frame (so don't advance timestamp).
473 flags = EncodeFrame(false);
474 timestamp_ += kTimestampDelta5Fps;
475 EXPECT_FALSE(config_updated_);
476 EXPECT_EQ(kTl1Flags, flags);
477
478 // Next frame should have boosted QP.
479 SkipUntilTl(1);
480 EXPECT_TRUE(config_updated_);
481 EXPECT_LT(cfg_.rc_max_quantizer, static_cast<unsigned int>(kDefaultQp));
482 layers_->OnEncodeDone(0, timestamp_, frame_size_, false, kDefaultQp,
483 IgnoredCodecSpecificInfo());
484 timestamp_ += kTimestampDelta5Fps;
485
486 // ...and back to normal.
487 SkipUntilTl(1);
488 EXPECT_EQ(cfg_.rc_max_quantizer, static_cast<unsigned int>(kDefaultQp));
489 layers_->OnEncodeDone(0, timestamp_, frame_size_, false, kDefaultQp,
490 IgnoredCodecSpecificInfo());
491 timestamp_ += kTimestampDelta5Fps;
492 }
493
TEST_F(ScreenshareLayerTest,RespectsMaxIntervalBetweenFrames)494 TEST_F(ScreenshareLayerTest, RespectsMaxIntervalBetweenFrames) {
495 const int kLowBitrateKbps = 50;
496 const int kLargeFrameSizeBytes = 100000;
497 const uint32_t kStartTimestamp = 1234;
498
499 const std::vector<uint32_t> layer_rates = {kLowBitrateKbps * 1000};
500 layers_->OnRatesUpdated(0, layer_rates, kFrameRate);
501 cfg_ = layers_->UpdateConfiguration(0);
502
503 EXPECT_EQ(kTl0Flags,
504 LibvpxVp8Encoder::EncodeFlags(NextFrameConfig(0, kStartTimestamp)));
505 layers_->OnEncodeDone(0, kStartTimestamp, kLargeFrameSizeBytes, false,
506 kDefaultQp, IgnoredCodecSpecificInfo());
507
508 const uint32_t kTwoSecondsLater =
509 kStartTimestamp + (ScreenshareLayers::kMaxFrameIntervalMs * 90);
510
511 // Sanity check, repayment time should exceed kMaxFrameIntervalMs.
512 ASSERT_GT(kStartTimestamp + 90 * (kLargeFrameSizeBytes * 8) / kLowBitrateKbps,
513 kStartTimestamp + (ScreenshareLayers::kMaxFrameIntervalMs * 90));
514
515 // Expect drop one frame interval before the two second timeout. If we try
516 // any later, the frame will be dropped anyway by the frame rate throttling
517 // logic.
518 EXPECT_TRUE(
519 NextFrameConfig(0, kTwoSecondsLater - kTimestampDelta5Fps).drop_frame);
520
521 // More than two seconds has passed since last frame, one should be emitted
522 // even if bitrate target is then exceeded.
523 EXPECT_EQ(kTl0Flags, LibvpxVp8Encoder::EncodeFlags(
524 NextFrameConfig(0, kTwoSecondsLater + 90)));
525 }
526
TEST_F(ScreenshareLayerTest,UpdatesHistograms)527 TEST_F(ScreenshareLayerTest, UpdatesHistograms) {
528 metrics::Reset();
529 bool trigger_drop = false;
530 bool dropped_frame = false;
531 bool overshoot = false;
532 const int kTl0Qp = 35;
533 const int kTl1Qp = 30;
534 for (int64_t timestamp = 0;
535 timestamp < kTimestampDelta5Fps * 5 * metrics::kMinRunTimeInSeconds;
536 timestamp += kTimestampDelta5Fps) {
537 tl_config_ = NextFrameConfig(0, timestamp);
538 if (tl_config_.drop_frame) {
539 dropped_frame = true;
540 continue;
541 }
542 int flags = LibvpxVp8Encoder::EncodeFlags(tl_config_);
543 if (flags != -1)
544 cfg_ = layers_->UpdateConfiguration(0);
545
546 if (timestamp >= kTimestampDelta5Fps * 5 && !overshoot && flags != -1) {
547 // Simulate one overshoot.
548 layers_->OnEncodeDone(0, timestamp, 0, false, 0, nullptr);
549 overshoot = true;
550 }
551
552 if (flags == kTl0Flags) {
553 if (timestamp >= kTimestampDelta5Fps * 20 && !trigger_drop) {
554 // Simulate a too large frame, to cause frame drop.
555 layers_->OnEncodeDone(0, timestamp, frame_size_ * 10, false, kTl0Qp,
556 IgnoredCodecSpecificInfo());
557 trigger_drop = true;
558 } else {
559 layers_->OnEncodeDone(0, timestamp, frame_size_, false, kTl0Qp,
560 IgnoredCodecSpecificInfo());
561 }
562 } else if (flags == kTl1Flags || flags == kTl1SyncFlags) {
563 layers_->OnEncodeDone(0, timestamp, frame_size_, false, kTl1Qp,
564 IgnoredCodecSpecificInfo());
565 } else if (flags == -1) {
566 dropped_frame = true;
567 } else {
568 RTC_DCHECK_NOTREACHED() << "Unexpected flags";
569 }
570 clock_.AdvanceTime(TimeDelta::Millis(1000 / 5));
571 }
572
573 EXPECT_TRUE(overshoot);
574 EXPECT_TRUE(dropped_frame);
575
576 layers_.reset(); // Histograms are reported on destruction.
577
578 EXPECT_METRIC_EQ(
579 1, metrics::NumSamples("WebRTC.Video.Screenshare.Layer0.FrameRate"));
580 EXPECT_METRIC_EQ(
581 1, metrics::NumSamples("WebRTC.Video.Screenshare.Layer1.FrameRate"));
582 EXPECT_METRIC_EQ(
583 1, metrics::NumSamples("WebRTC.Video.Screenshare.FramesPerDrop"));
584 EXPECT_METRIC_EQ(
585 1, metrics::NumSamples("WebRTC.Video.Screenshare.FramesPerOvershoot"));
586 EXPECT_METRIC_EQ(1,
587 metrics::NumSamples("WebRTC.Video.Screenshare.Layer0.Qp"));
588 EXPECT_METRIC_EQ(1,
589 metrics::NumSamples("WebRTC.Video.Screenshare.Layer1.Qp"));
590 EXPECT_METRIC_EQ(
591 1, metrics::NumSamples("WebRTC.Video.Screenshare.Layer0.TargetBitrate"));
592 EXPECT_METRIC_EQ(
593 1, metrics::NumSamples("WebRTC.Video.Screenshare.Layer1.TargetBitrate"));
594
595 EXPECT_METRIC_GT(
596 metrics::MinSample("WebRTC.Video.Screenshare.Layer0.FrameRate"), 1);
597 EXPECT_METRIC_GT(
598 metrics::MinSample("WebRTC.Video.Screenshare.Layer1.FrameRate"), 1);
599 EXPECT_METRIC_GT(metrics::MinSample("WebRTC.Video.Screenshare.FramesPerDrop"),
600 1);
601 EXPECT_METRIC_GT(
602 metrics::MinSample("WebRTC.Video.Screenshare.FramesPerOvershoot"), 1);
603 EXPECT_METRIC_EQ(
604 1, metrics::NumEvents("WebRTC.Video.Screenshare.Layer0.Qp", kTl0Qp));
605 EXPECT_METRIC_EQ(
606 1, metrics::NumEvents("WebRTC.Video.Screenshare.Layer1.Qp", kTl1Qp));
607 EXPECT_METRIC_EQ(
608 1, metrics::NumEvents("WebRTC.Video.Screenshare.Layer0.TargetBitrate",
609 kDefaultTl0BitrateKbps));
610 EXPECT_METRIC_EQ(
611 1, metrics::NumEvents("WebRTC.Video.Screenshare.Layer1.TargetBitrate",
612 kDefaultTl1BitrateKbps));
613 }
614
TEST_F(ScreenshareLayerTest,RespectsConfiguredFramerate)615 TEST_F(ScreenshareLayerTest, RespectsConfiguredFramerate) {
616 int64_t kTestSpanMs = 2000;
617 int64_t kFrameIntervalsMs = 1000 / kFrameRate;
618
619 uint32_t timestamp = 1234;
620 int num_input_frames = 0;
621 int num_discarded_frames = 0;
622
623 // Send at regular rate - no drops expected.
624 for (int64_t i = 0; i < kTestSpanMs; i += kFrameIntervalsMs) {
625 if (NextFrameConfig(0, timestamp).drop_frame) {
626 ++num_discarded_frames;
627 } else {
628 size_t frame_size_bytes = kDefaultTl0BitrateKbps * kFrameIntervalsMs / 8;
629 layers_->OnEncodeDone(0, timestamp, frame_size_bytes, false, kDefaultQp,
630 IgnoredCodecSpecificInfo());
631 }
632 timestamp += kFrameIntervalsMs * 90;
633 clock_.AdvanceTime(TimeDelta::Millis(kFrameIntervalsMs));
634
635 ++num_input_frames;
636 }
637 EXPECT_EQ(0, num_discarded_frames);
638
639 // Send at twice the configured rate - drop every other frame.
640 num_input_frames = 0;
641 num_discarded_frames = 0;
642 for (int64_t i = 0; i < kTestSpanMs; i += kFrameIntervalsMs / 2) {
643 if (NextFrameConfig(0, timestamp).drop_frame) {
644 ++num_discarded_frames;
645 } else {
646 size_t frame_size_bytes = kDefaultTl0BitrateKbps * kFrameIntervalsMs / 8;
647 layers_->OnEncodeDone(0, timestamp, frame_size_bytes, false, kDefaultQp,
648 IgnoredCodecSpecificInfo());
649 }
650 timestamp += kFrameIntervalsMs * 90 / 2;
651 clock_.AdvanceTime(TimeDelta::Millis(kFrameIntervalsMs));
652 ++num_input_frames;
653 }
654
655 // Allow for some rounding errors in the measurements.
656 EXPECT_NEAR(num_discarded_frames, num_input_frames / 2, 2);
657 }
658
659 TEST_F(ScreenshareLayerTest, 2LayersSyncAtOvershootDrop) {
660 // Run grace period so we have existing frames in both TL0 and Tl1.
661 EXPECT_TRUE(RunGracePeriod());
662
663 // Move ahead until we have a sync frame in TL1.
664 EXPECT_EQ(kTl1SyncFlags, SkipUntilTlAndSync(1, true));
665 ASSERT_TRUE(tl_config_.layer_sync);
666
667 // Simulate overshoot of this frame.
668 layers_->OnEncodeDone(0, timestamp_, 0, false, 0, nullptr);
669
670 cfg_ = layers_->UpdateConfiguration(0);
671 EXPECT_EQ(kTl1SyncFlags, LibvpxVp8Encoder::EncodeFlags(tl_config_));
672
673 CodecSpecificInfo new_info;
674 layers_->OnEncodeDone(0, timestamp_, frame_size_, false, kDefaultQp,
675 &new_info);
676 EXPECT_TRUE(new_info.codecSpecific.VP8.layerSync);
677 }
678
TEST_F(ScreenshareLayerTest,DropOnTooShortFrameInterval)679 TEST_F(ScreenshareLayerTest, DropOnTooShortFrameInterval) {
680 // Run grace period so we have existing frames in both TL0 and Tl1.
681 EXPECT_TRUE(RunGracePeriod());
682
683 // Add a large gap, so there's plenty of room in the rate tracker.
684 timestamp_ += kTimestampDelta5Fps * 3;
685 EXPECT_FALSE(NextFrameConfig(0, timestamp_).drop_frame);
686 layers_->OnEncodeDone(0, timestamp_, frame_size_, false, kDefaultQp,
687 IgnoredCodecSpecificInfo());
688
689 // Frame interval below 90% if desired time is not allowed, try inserting
690 // frame just before this limit.
691 const int64_t kMinFrameInterval = (kTimestampDelta5Fps * 85) / 100;
692 timestamp_ += kMinFrameInterval - 90;
693 EXPECT_TRUE(NextFrameConfig(0, timestamp_).drop_frame);
694
695 // Try again at the limit, now it should pass.
696 timestamp_ += 90;
697 EXPECT_FALSE(NextFrameConfig(0, timestamp_).drop_frame);
698 }
699
TEST_F(ScreenshareLayerTest,AdjustsBitrateWhenDroppingFrames)700 TEST_F(ScreenshareLayerTest, AdjustsBitrateWhenDroppingFrames) {
701 const uint32_t kTimestampDelta10Fps = kTimestampDelta5Fps / 2;
702 const int kNumFrames = 30;
703 ASSERT_TRUE(cfg_.rc_target_bitrate.has_value());
704 const uint32_t default_bitrate = cfg_.rc_target_bitrate.value();
705 layers_->OnRatesUpdated(0, kDefault2TlBitratesBps, 10);
706
707 int num_dropped_frames = 0;
708 for (int i = 0; i < kNumFrames; ++i) {
709 if (EncodeFrame(false) == -1)
710 ++num_dropped_frames;
711 timestamp_ += kTimestampDelta10Fps;
712 }
713 cfg_ = layers_->UpdateConfiguration(0);
714
715 EXPECT_EQ(num_dropped_frames, kNumFrames / 2);
716 EXPECT_EQ(cfg_.rc_target_bitrate, default_bitrate * 2);
717 }
718
TEST_F(ScreenshareLayerTest,UpdatesConfigurationAfterRateChange)719 TEST_F(ScreenshareLayerTest, UpdatesConfigurationAfterRateChange) {
720 // Set inital rate again, no need to update configuration.
721 layers_->OnRatesUpdated(0, kDefault2TlBitratesBps, kFrameRate);
722 cfg_ = layers_->UpdateConfiguration(0);
723
724 // Rate changed, now update config.
725 std::vector<uint32_t> bitrates = kDefault2TlBitratesBps;
726 bitrates[1] -= 100000;
727 layers_->OnRatesUpdated(0, bitrates, 5);
728 cfg_ = layers_->UpdateConfiguration(0);
729
730 // Changed rate, but then set changed rate again before trying to update
731 // configuration, update should still apply.
732 bitrates[1] -= 100000;
733 layers_->OnRatesUpdated(0, bitrates, 5);
734 layers_->OnRatesUpdated(0, bitrates, 5);
735 cfg_ = layers_->UpdateConfiguration(0);
736 }
737
TEST_F(ScreenshareLayerTest,MaxQpRestoredAfterDoubleDrop)738 TEST_F(ScreenshareLayerTest, MaxQpRestoredAfterDoubleDrop) {
739 // Run grace period so we have existing frames in both TL0 and Tl1.
740 EXPECT_TRUE(RunGracePeriod());
741
742 // Move ahead until we have a sync frame in TL1.
743 EXPECT_EQ(kTl1SyncFlags, SkipUntilTlAndSync(1, true));
744 ASSERT_TRUE(tl_config_.layer_sync);
745
746 // Simulate overshoot of this frame.
747 layers_->OnEncodeDone(0, timestamp_, 0, false, -1, nullptr);
748
749 // Simulate re-encoded frame.
750 layers_->OnEncodeDone(0, timestamp_, 1, false, max_qp_,
751 IgnoredCodecSpecificInfo());
752
753 // Next frame, expect boosted quality.
754 // Slightly alter bitrate between each frame.
755 std::vector<uint32_t> kDefault2TlBitratesBpsAlt = kDefault2TlBitratesBps;
756 kDefault2TlBitratesBpsAlt[1] += 4000;
757 layers_->OnRatesUpdated(0, kDefault2TlBitratesBpsAlt, kFrameRate);
758 EXPECT_EQ(kTl1Flags, SkipUntilTlAndSync(1, false));
759 EXPECT_TRUE(config_updated_);
760 EXPECT_LT(cfg_.rc_max_quantizer, max_qp_);
761 ASSERT_TRUE(cfg_.rc_max_quantizer.has_value());
762 const uint32_t adjusted_qp = cfg_.rc_max_quantizer.value();
763
764 // Simulate overshoot of this frame.
765 layers_->OnEncodeDone(0, timestamp_, 0, false, -1, nullptr);
766
767 // Simulate re-encoded frame.
768 layers_->OnEncodeDone(0, timestamp_, frame_size_, false, max_qp_,
769 IgnoredCodecSpecificInfo());
770
771 // A third frame, expect boosted quality.
772 layers_->OnRatesUpdated(0, kDefault2TlBitratesBps, kFrameRate);
773 EXPECT_EQ(kTl1Flags, SkipUntilTlAndSync(1, false));
774 EXPECT_TRUE(config_updated_);
775 EXPECT_LT(cfg_.rc_max_quantizer, max_qp_);
776 EXPECT_EQ(adjusted_qp, cfg_.rc_max_quantizer);
777
778 // Frame encoded.
779 layers_->OnEncodeDone(0, timestamp_, frame_size_, false, max_qp_,
780 IgnoredCodecSpecificInfo());
781
782 // A fourth frame, max qp should be restored.
783 layers_->OnRatesUpdated(0, kDefault2TlBitratesBpsAlt, kFrameRate);
784 EXPECT_EQ(kTl1Flags, SkipUntilTlAndSync(1, false));
785 EXPECT_EQ(cfg_.rc_max_quantizer, max_qp_);
786 }
787
788 } // namespace webrtc
789