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(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
227 info = std::make_unique<CodecSpecificInfo>();
228 flags = EncodeFrame(false, info.get());
229 EXPECT_EQ(kSingleLayerFlags, flags);
230 EXPECT_EQ(static_cast<uint8_t>(kNoTemporalIdx),
231 info->codecSpecific.VP8.temporalIdx);
232 EXPECT_FALSE(info->codecSpecific.VP8.layerSync);
233 }
234
235 TEST_F(ScreenshareLayerTest, 2LayersPeriodicSync) {
236 std::vector<int> sync_times;
237 const int kNumFrames = kSyncPeriodSeconds * kFrameRate * 2 - 1;
238 for (int i = 0; i < kNumFrames; ++i) {
239 CodecSpecificInfo info;
240 EncodeFrame(false, &info);
241 timestamp_ += kTimestampDelta5Fps;
242 if (info.codecSpecific.VP8.temporalIdx == 1 &&
243 info.codecSpecific.VP8.layerSync) {
244 sync_times.push_back(timestamp_);
245 }
246 }
247
248 ASSERT_EQ(2u, sync_times.size());
249 EXPECT_GE(sync_times[1] - sync_times[0], 90000 * kSyncPeriodSeconds);
250 }
251
252 TEST_F(ScreenshareLayerTest, 2LayersSyncAfterTimeout) {
253 std::vector<int> sync_times;
254 const int kNumFrames = kMaxSyncPeriodSeconds * kFrameRate * 2 - 1;
255 for (int i = 0; i < kNumFrames; ++i) {
256 CodecSpecificInfo info;
257
258 tl_config_ = NextFrameConfig(0, timestamp_);
259 cfg_ = layers_->UpdateConfiguration(0);
260
261 // Simulate TL1 being at least 8 qp steps better.
262 if (tl_config_.packetizer_temporal_idx == 0) {
263 layers_->OnEncodeDone(0, timestamp_, frame_size_, false, kDefaultQp,
264 &info);
265 } else {
266 layers_->OnEncodeDone(0, timestamp_, frame_size_, false, kDefaultQp - 8,
267 &info);
268 }
269
270 if (info.codecSpecific.VP8.temporalIdx == 1 &&
271 info.codecSpecific.VP8.layerSync)
272 sync_times.push_back(timestamp_);
273
274 timestamp_ += kTimestampDelta5Fps;
275 }
276
277 ASSERT_EQ(2u, sync_times.size());
278 EXPECT_GE(sync_times[1] - sync_times[0], 90000 * kMaxSyncPeriodSeconds);
279 }
280
281 TEST_F(ScreenshareLayerTest, 2LayersSyncAfterSimilarQP) {
282 std::vector<int> sync_times;
283
284 const int kNumFrames = (kSyncPeriodSeconds +
285 ((kMaxSyncPeriodSeconds - kSyncPeriodSeconds) / 2)) *
286 kFrameRate;
287 for (int i = 0; i < kNumFrames; ++i) {
288 CodecSpecificInfo info;
289
290 ConfigureFrame(false);
291
292 // Simulate TL1 being at least 8 qp steps better.
293 if (tl_config_.packetizer_temporal_idx == 0) {
294 layers_->OnEncodeDone(0, timestamp_, frame_size_, false, kDefaultQp,
295 &info);
296 } else {
297 layers_->OnEncodeDone(0, timestamp_, frame_size_, false, kDefaultQp - 8,
298 &info);
299 }
300
301 if (info.codecSpecific.VP8.temporalIdx == 1 &&
302 info.codecSpecific.VP8.layerSync)
303 sync_times.push_back(timestamp_);
304
305 timestamp_ += kTimestampDelta5Fps;
306 }
307
308 ASSERT_EQ(1u, sync_times.size());
309
310 bool bumped_tl0_quality = false;
311 for (int i = 0; i < 3; ++i) {
312 CodecSpecificInfo info;
313
314 int flags = ConfigureFrame(false);
315 layers_->OnEncodeDone(0, timestamp_, frame_size_, false, kDefaultQp - 8,
316 &info);
317 if (info.codecSpecific.VP8.temporalIdx == 0) {
318 // Bump TL0 to same quality as TL1.
319 bumped_tl0_quality = true;
320 } else {
321 if (bumped_tl0_quality) {
322 EXPECT_TRUE(info.codecSpecific.VP8.layerSync);
323 EXPECT_EQ(kTl1SyncFlags, flags);
324 return;
325 }
326 }
327 timestamp_ += kTimestampDelta5Fps;
328 }
329 ADD_FAILURE() << "No TL1 frame arrived within time limit.";
330 }
331
332 TEST_F(ScreenshareLayerTest, 2LayersToggling) {
333 EXPECT_TRUE(RunGracePeriod());
334
335 // Insert 50 frames. 2/5 should be TL0.
336 int tl0_frames = 0;
337 int tl1_frames = 0;
338 for (int i = 0; i < 50; ++i) {
339 CodecSpecificInfo info;
340 EncodeFrame(false, &info);
341 timestamp_ += kTimestampDelta5Fps;
342 switch (info.codecSpecific.VP8.temporalIdx) {
343 case 0:
344 ++tl0_frames;
345 break;
346 case 1:
347 ++tl1_frames;
348 break;
349 default:
350 abort();
351 }
352 }
353 EXPECT_EQ(20, tl0_frames);
354 EXPECT_EQ(30, tl1_frames);
355 }
356
TEST_F(ScreenshareLayerTest,AllFitsLayer0)357 TEST_F(ScreenshareLayerTest, AllFitsLayer0) {
358 frame_size_ = FrameSizeForBitrate(kDefaultTl0BitrateKbps);
359
360 // Insert 50 frames, small enough that all fits in TL0.
361 for (int i = 0; i < 50; ++i) {
362 CodecSpecificInfo info;
363 int flags = EncodeFrame(false, &info);
364 timestamp_ += kTimestampDelta5Fps;
365 EXPECT_EQ(kTl0Flags, flags);
366 EXPECT_EQ(0, info.codecSpecific.VP8.temporalIdx);
367 }
368 }
369
TEST_F(ScreenshareLayerTest,TooHighBitrate)370 TEST_F(ScreenshareLayerTest, TooHighBitrate) {
371 frame_size_ = 2 * FrameSizeForBitrate(kDefaultTl1BitrateKbps);
372
373 // Insert 100 frames. Half should be dropped.
374 int tl0_frames = 0;
375 int tl1_frames = 0;
376 int dropped_frames = 0;
377 for (int i = 0; i < 100; ++i) {
378 CodecSpecificInfo info;
379 int flags = EncodeFrame(false, &info);
380 timestamp_ += kTimestampDelta5Fps;
381 if (flags == -1) {
382 ++dropped_frames;
383 } else {
384 switch (info.codecSpecific.VP8.temporalIdx) {
385 case 0:
386 ++tl0_frames;
387 break;
388 case 1:
389 ++tl1_frames;
390 break;
391 default:
392 ADD_FAILURE() << "Unexpected temporal id";
393 }
394 }
395 }
396
397 EXPECT_NEAR(50, tl0_frames + tl1_frames, 1);
398 EXPECT_NEAR(50, dropped_frames, 1);
399 }
400
TEST_F(ScreenshareLayerTest,TargetBitrateCappedByTL0)401 TEST_F(ScreenshareLayerTest, TargetBitrateCappedByTL0) {
402 const int kTl0_kbps = 100;
403 const int kTl1_kbps = 1000;
404 const std::vector<uint32_t> layer_rates = {kTl0_kbps * 1000,
405 (kTl1_kbps - kTl0_kbps) * 1000};
406 layers_->OnRatesUpdated(0, layer_rates, kFrameRate);
407 cfg_ = layers_->UpdateConfiguration(0);
408
409 EXPECT_EQ(static_cast<unsigned int>(
410 ScreenshareLayers::kMaxTL0FpsReduction * kTl0_kbps + 0.5),
411 cfg_.rc_target_bitrate);
412 }
413
TEST_F(ScreenshareLayerTest,TargetBitrateCappedByTL1)414 TEST_F(ScreenshareLayerTest, TargetBitrateCappedByTL1) {
415 const int kTl0_kbps = 100;
416 const int kTl1_kbps = 450;
417 const std::vector<uint32_t> layer_rates = {kTl0_kbps * 1000,
418 (kTl1_kbps - kTl0_kbps) * 1000};
419 layers_->OnRatesUpdated(0, layer_rates, kFrameRate);
420 cfg_ = layers_->UpdateConfiguration(0);
421
422 EXPECT_EQ(static_cast<unsigned int>(
423 kTl1_kbps / ScreenshareLayers::kAcceptableTargetOvershoot),
424 cfg_.rc_target_bitrate);
425 }
426
TEST_F(ScreenshareLayerTest,TargetBitrateBelowTL0)427 TEST_F(ScreenshareLayerTest, TargetBitrateBelowTL0) {
428 const int kTl0_kbps = 100;
429 const std::vector<uint32_t> layer_rates = {kTl0_kbps * 1000};
430 layers_->OnRatesUpdated(0, layer_rates, kFrameRate);
431 cfg_ = layers_->UpdateConfiguration(0);
432
433 EXPECT_EQ(static_cast<uint32_t>(kTl0_kbps), cfg_.rc_target_bitrate);
434 }
435
TEST_F(ScreenshareLayerTest,EncoderDrop)436 TEST_F(ScreenshareLayerTest, EncoderDrop) {
437 EXPECT_TRUE(RunGracePeriod());
438 SkipUntilTl(0);
439
440 // Size 0 indicates dropped frame.
441 layers_->OnEncodeDone(0, timestamp_, 0, false, 0, IgnoredCodecSpecificInfo());
442
443 // Re-encode frame (so don't advance timestamp).
444 int flags = EncodeFrame(false);
445 timestamp_ += kTimestampDelta5Fps;
446 EXPECT_FALSE(config_updated_);
447 EXPECT_EQ(kTl0Flags, flags);
448
449 // Next frame should have boosted quality...
450 SkipUntilTl(0);
451 EXPECT_TRUE(config_updated_);
452 EXPECT_LT(cfg_.rc_max_quantizer, static_cast<unsigned int>(kDefaultQp));
453 layers_->OnEncodeDone(0, timestamp_, frame_size_, false, kDefaultQp,
454 IgnoredCodecSpecificInfo());
455 timestamp_ += kTimestampDelta5Fps;
456
457 // ...then back to standard setup.
458 SkipUntilTl(0);
459 layers_->OnEncodeDone(0, timestamp_, frame_size_, false, kDefaultQp,
460 IgnoredCodecSpecificInfo());
461 timestamp_ += kTimestampDelta5Fps;
462 EXPECT_EQ(cfg_.rc_max_quantizer, static_cast<unsigned int>(kDefaultQp));
463
464 // Next drop in TL1.
465 SkipUntilTl(1);
466 layers_->OnEncodeDone(0, timestamp_, 0, false, 0, IgnoredCodecSpecificInfo());
467
468 // Re-encode frame (so don't advance timestamp).
469 flags = EncodeFrame(false);
470 timestamp_ += kTimestampDelta5Fps;
471 EXPECT_FALSE(config_updated_);
472 EXPECT_EQ(kTl1Flags, flags);
473
474 // Next frame should have boosted QP.
475 SkipUntilTl(1);
476 EXPECT_TRUE(config_updated_);
477 EXPECT_LT(cfg_.rc_max_quantizer, static_cast<unsigned int>(kDefaultQp));
478 layers_->OnEncodeDone(0, timestamp_, frame_size_, false, kDefaultQp,
479 IgnoredCodecSpecificInfo());
480 timestamp_ += kTimestampDelta5Fps;
481
482 // ...and back to normal.
483 SkipUntilTl(1);
484 EXPECT_EQ(cfg_.rc_max_quantizer, static_cast<unsigned int>(kDefaultQp));
485 layers_->OnEncodeDone(0, timestamp_, frame_size_, false, kDefaultQp,
486 IgnoredCodecSpecificInfo());
487 timestamp_ += kTimestampDelta5Fps;
488 }
489
TEST_F(ScreenshareLayerTest,RespectsMaxIntervalBetweenFrames)490 TEST_F(ScreenshareLayerTest, RespectsMaxIntervalBetweenFrames) {
491 const int kLowBitrateKbps = 50;
492 const int kLargeFrameSizeBytes = 100000;
493 const uint32_t kStartTimestamp = 1234;
494
495 const std::vector<uint32_t> layer_rates = {kLowBitrateKbps * 1000};
496 layers_->OnRatesUpdated(0, layer_rates, kFrameRate);
497 cfg_ = layers_->UpdateConfiguration(0);
498
499 EXPECT_EQ(kTl0Flags,
500 LibvpxVp8Encoder::EncodeFlags(NextFrameConfig(0, kStartTimestamp)));
501 layers_->OnEncodeDone(0, kStartTimestamp, kLargeFrameSizeBytes, false,
502 kDefaultQp, IgnoredCodecSpecificInfo());
503
504 const uint32_t kTwoSecondsLater =
505 kStartTimestamp + (ScreenshareLayers::kMaxFrameIntervalMs * 90);
506
507 // Sanity check, repayment time should exceed kMaxFrameIntervalMs.
508 ASSERT_GT(kStartTimestamp + 90 * (kLargeFrameSizeBytes * 8) / kLowBitrateKbps,
509 kStartTimestamp + (ScreenshareLayers::kMaxFrameIntervalMs * 90));
510
511 // Expect drop one frame interval before the two second timeout. If we try
512 // any later, the frame will be dropped anyway by the frame rate throttling
513 // logic.
514 EXPECT_TRUE(
515 NextFrameConfig(0, kTwoSecondsLater - kTimestampDelta5Fps).drop_frame);
516
517 // More than two seconds has passed since last frame, one should be emitted
518 // even if bitrate target is then exceeded.
519 EXPECT_EQ(kTl0Flags, LibvpxVp8Encoder::EncodeFlags(
520 NextFrameConfig(0, kTwoSecondsLater + 90)));
521 }
522
TEST_F(ScreenshareLayerTest,UpdatesHistograms)523 TEST_F(ScreenshareLayerTest, UpdatesHistograms) {
524 metrics::Reset();
525 bool trigger_drop = false;
526 bool dropped_frame = false;
527 bool overshoot = false;
528 const int kTl0Qp = 35;
529 const int kTl1Qp = 30;
530 for (int64_t timestamp = 0;
531 timestamp < kTimestampDelta5Fps * 5 * metrics::kMinRunTimeInSeconds;
532 timestamp += kTimestampDelta5Fps) {
533 tl_config_ = NextFrameConfig(0, timestamp);
534 if (tl_config_.drop_frame) {
535 dropped_frame = true;
536 continue;
537 }
538 int flags = LibvpxVp8Encoder::EncodeFlags(tl_config_);
539 if (flags != -1)
540 cfg_ = layers_->UpdateConfiguration(0);
541
542 if (timestamp >= kTimestampDelta5Fps * 5 && !overshoot && flags != -1) {
543 // Simulate one overshoot.
544 layers_->OnEncodeDone(0, timestamp, 0, false, 0, nullptr);
545 overshoot = true;
546 }
547
548 if (flags == kTl0Flags) {
549 if (timestamp >= kTimestampDelta5Fps * 20 && !trigger_drop) {
550 // Simulate a too large frame, to cause frame drop.
551 layers_->OnEncodeDone(0, timestamp, frame_size_ * 10, false, kTl0Qp,
552 IgnoredCodecSpecificInfo());
553 trigger_drop = true;
554 } else {
555 layers_->OnEncodeDone(0, timestamp, frame_size_, false, kTl0Qp,
556 IgnoredCodecSpecificInfo());
557 }
558 } else if (flags == kTl1Flags || flags == kTl1SyncFlags) {
559 layers_->OnEncodeDone(0, timestamp, frame_size_, false, kTl1Qp,
560 IgnoredCodecSpecificInfo());
561 } else if (flags == -1) {
562 dropped_frame = true;
563 } else {
564 RTC_NOTREACHED() << "Unexpected flags";
565 }
566 clock_.AdvanceTime(TimeDelta::Millis(1000 / 5));
567 }
568
569 EXPECT_TRUE(overshoot);
570 EXPECT_TRUE(dropped_frame);
571
572 layers_.reset(); // Histograms are reported on destruction.
573
574 EXPECT_METRIC_EQ(
575 1, metrics::NumSamples("WebRTC.Video.Screenshare.Layer0.FrameRate"));
576 EXPECT_METRIC_EQ(
577 1, metrics::NumSamples("WebRTC.Video.Screenshare.Layer1.FrameRate"));
578 EXPECT_METRIC_EQ(
579 1, metrics::NumSamples("WebRTC.Video.Screenshare.FramesPerDrop"));
580 EXPECT_METRIC_EQ(
581 1, metrics::NumSamples("WebRTC.Video.Screenshare.FramesPerOvershoot"));
582 EXPECT_METRIC_EQ(1,
583 metrics::NumSamples("WebRTC.Video.Screenshare.Layer0.Qp"));
584 EXPECT_METRIC_EQ(1,
585 metrics::NumSamples("WebRTC.Video.Screenshare.Layer1.Qp"));
586 EXPECT_METRIC_EQ(
587 1, metrics::NumSamples("WebRTC.Video.Screenshare.Layer0.TargetBitrate"));
588 EXPECT_METRIC_EQ(
589 1, metrics::NumSamples("WebRTC.Video.Screenshare.Layer1.TargetBitrate"));
590
591 EXPECT_METRIC_GT(
592 metrics::MinSample("WebRTC.Video.Screenshare.Layer0.FrameRate"), 1);
593 EXPECT_METRIC_GT(
594 metrics::MinSample("WebRTC.Video.Screenshare.Layer1.FrameRate"), 1);
595 EXPECT_METRIC_GT(metrics::MinSample("WebRTC.Video.Screenshare.FramesPerDrop"),
596 1);
597 EXPECT_METRIC_GT(
598 metrics::MinSample("WebRTC.Video.Screenshare.FramesPerOvershoot"), 1);
599 EXPECT_METRIC_EQ(
600 1, metrics::NumEvents("WebRTC.Video.Screenshare.Layer0.Qp", kTl0Qp));
601 EXPECT_METRIC_EQ(
602 1, metrics::NumEvents("WebRTC.Video.Screenshare.Layer1.Qp", kTl1Qp));
603 EXPECT_METRIC_EQ(
604 1, metrics::NumEvents("WebRTC.Video.Screenshare.Layer0.TargetBitrate",
605 kDefaultTl0BitrateKbps));
606 EXPECT_METRIC_EQ(
607 1, metrics::NumEvents("WebRTC.Video.Screenshare.Layer1.TargetBitrate",
608 kDefaultTl1BitrateKbps));
609 }
610
TEST_F(ScreenshareLayerTest,RespectsConfiguredFramerate)611 TEST_F(ScreenshareLayerTest, RespectsConfiguredFramerate) {
612 int64_t kTestSpanMs = 2000;
613 int64_t kFrameIntervalsMs = 1000 / kFrameRate;
614
615 uint32_t timestamp = 1234;
616 int num_input_frames = 0;
617 int num_discarded_frames = 0;
618
619 // Send at regular rate - no drops expected.
620 for (int64_t i = 0; i < kTestSpanMs; i += kFrameIntervalsMs) {
621 if (NextFrameConfig(0, timestamp).drop_frame) {
622 ++num_discarded_frames;
623 } else {
624 size_t frame_size_bytes = kDefaultTl0BitrateKbps * kFrameIntervalsMs / 8;
625 layers_->OnEncodeDone(0, timestamp, frame_size_bytes, false, kDefaultQp,
626 IgnoredCodecSpecificInfo());
627 }
628 timestamp += kFrameIntervalsMs * 90;
629 clock_.AdvanceTime(TimeDelta::Millis(kFrameIntervalsMs));
630
631 ++num_input_frames;
632 }
633 EXPECT_EQ(0, num_discarded_frames);
634
635 // Send at twice the configured rate - drop every other frame.
636 num_input_frames = 0;
637 num_discarded_frames = 0;
638 for (int64_t i = 0; i < kTestSpanMs; i += kFrameIntervalsMs / 2) {
639 if (NextFrameConfig(0, timestamp).drop_frame) {
640 ++num_discarded_frames;
641 } else {
642 size_t frame_size_bytes = kDefaultTl0BitrateKbps * kFrameIntervalsMs / 8;
643 layers_->OnEncodeDone(0, timestamp, frame_size_bytes, false, kDefaultQp,
644 IgnoredCodecSpecificInfo());
645 }
646 timestamp += kFrameIntervalsMs * 90 / 2;
647 clock_.AdvanceTime(TimeDelta::Millis(kFrameIntervalsMs));
648 ++num_input_frames;
649 }
650
651 // Allow for some rounding errors in the measurements.
652 EXPECT_NEAR(num_discarded_frames, num_input_frames / 2, 2);
653 }
654
655 TEST_F(ScreenshareLayerTest, 2LayersSyncAtOvershootDrop) {
656 // Run grace period so we have existing frames in both TL0 and Tl1.
657 EXPECT_TRUE(RunGracePeriod());
658
659 // Move ahead until we have a sync frame in TL1.
660 EXPECT_EQ(kTl1SyncFlags, SkipUntilTlAndSync(1, true));
661 ASSERT_TRUE(tl_config_.layer_sync);
662
663 // Simulate overshoot of this frame.
664 layers_->OnEncodeDone(0, timestamp_, 0, false, 0, nullptr);
665
666 cfg_ = layers_->UpdateConfiguration(0);
667 EXPECT_EQ(kTl1SyncFlags, LibvpxVp8Encoder::EncodeFlags(tl_config_));
668
669 CodecSpecificInfo new_info;
670 layers_->OnEncodeDone(0, timestamp_, frame_size_, false, kDefaultQp,
671 &new_info);
672 EXPECT_TRUE(new_info.codecSpecific.VP8.layerSync);
673 }
674
TEST_F(ScreenshareLayerTest,DropOnTooShortFrameInterval)675 TEST_F(ScreenshareLayerTest, DropOnTooShortFrameInterval) {
676 // Run grace period so we have existing frames in both TL0 and Tl1.
677 EXPECT_TRUE(RunGracePeriod());
678
679 // Add a large gap, so there's plenty of room in the rate tracker.
680 timestamp_ += kTimestampDelta5Fps * 3;
681 EXPECT_FALSE(NextFrameConfig(0, timestamp_).drop_frame);
682 layers_->OnEncodeDone(0, timestamp_, frame_size_, false, kDefaultQp,
683 IgnoredCodecSpecificInfo());
684
685 // Frame interval below 90% if desired time is not allowed, try inserting
686 // frame just before this limit.
687 const int64_t kMinFrameInterval = (kTimestampDelta5Fps * 85) / 100;
688 timestamp_ += kMinFrameInterval - 90;
689 EXPECT_TRUE(NextFrameConfig(0, timestamp_).drop_frame);
690
691 // Try again at the limit, now it should pass.
692 timestamp_ += 90;
693 EXPECT_FALSE(NextFrameConfig(0, timestamp_).drop_frame);
694 }
695
TEST_F(ScreenshareLayerTest,AdjustsBitrateWhenDroppingFrames)696 TEST_F(ScreenshareLayerTest, AdjustsBitrateWhenDroppingFrames) {
697 const uint32_t kTimestampDelta10Fps = kTimestampDelta5Fps / 2;
698 const int kNumFrames = 30;
699 ASSERT_TRUE(cfg_.rc_target_bitrate.has_value());
700 const uint32_t default_bitrate = cfg_.rc_target_bitrate.value();
701 layers_->OnRatesUpdated(0, kDefault2TlBitratesBps, 10);
702
703 int num_dropped_frames = 0;
704 for (int i = 0; i < kNumFrames; ++i) {
705 if (EncodeFrame(false) == -1)
706 ++num_dropped_frames;
707 timestamp_ += kTimestampDelta10Fps;
708 }
709 cfg_ = layers_->UpdateConfiguration(0);
710
711 EXPECT_EQ(num_dropped_frames, kNumFrames / 2);
712 EXPECT_EQ(cfg_.rc_target_bitrate, default_bitrate * 2);
713 }
714
TEST_F(ScreenshareLayerTest,UpdatesConfigurationAfterRateChange)715 TEST_F(ScreenshareLayerTest, UpdatesConfigurationAfterRateChange) {
716 // Set inital rate again, no need to update configuration.
717 layers_->OnRatesUpdated(0, kDefault2TlBitratesBps, kFrameRate);
718 cfg_ = layers_->UpdateConfiguration(0);
719
720 // Rate changed, now update config.
721 std::vector<uint32_t> bitrates = kDefault2TlBitratesBps;
722 bitrates[1] -= 100000;
723 layers_->OnRatesUpdated(0, bitrates, 5);
724 cfg_ = layers_->UpdateConfiguration(0);
725
726 // Changed rate, but then set changed rate again before trying to update
727 // configuration, update should still apply.
728 bitrates[1] -= 100000;
729 layers_->OnRatesUpdated(0, bitrates, 5);
730 layers_->OnRatesUpdated(0, bitrates, 5);
731 cfg_ = layers_->UpdateConfiguration(0);
732 }
733
TEST_F(ScreenshareLayerTest,MaxQpRestoredAfterDoubleDrop)734 TEST_F(ScreenshareLayerTest, MaxQpRestoredAfterDoubleDrop) {
735 // Run grace period so we have existing frames in both TL0 and Tl1.
736 EXPECT_TRUE(RunGracePeriod());
737
738 // Move ahead until we have a sync frame in TL1.
739 EXPECT_EQ(kTl1SyncFlags, SkipUntilTlAndSync(1, true));
740 ASSERT_TRUE(tl_config_.layer_sync);
741
742 // Simulate overshoot of this frame.
743 layers_->OnEncodeDone(0, timestamp_, 0, false, -1, nullptr);
744
745 // Simulate re-encoded frame.
746 layers_->OnEncodeDone(0, timestamp_, 1, false, max_qp_,
747 IgnoredCodecSpecificInfo());
748
749 // Next frame, expect boosted quality.
750 // Slightly alter bitrate between each frame.
751 std::vector<uint32_t> kDefault2TlBitratesBpsAlt = kDefault2TlBitratesBps;
752 kDefault2TlBitratesBpsAlt[1] += 4000;
753 layers_->OnRatesUpdated(0, kDefault2TlBitratesBpsAlt, kFrameRate);
754 EXPECT_EQ(kTl1Flags, SkipUntilTlAndSync(1, false));
755 EXPECT_TRUE(config_updated_);
756 EXPECT_LT(cfg_.rc_max_quantizer, max_qp_);
757 ASSERT_TRUE(cfg_.rc_max_quantizer.has_value());
758 const uint32_t adjusted_qp = cfg_.rc_max_quantizer.value();
759
760 // Simulate overshoot of this frame.
761 layers_->OnEncodeDone(0, timestamp_, 0, false, -1, nullptr);
762
763 // Simulate re-encoded frame.
764 layers_->OnEncodeDone(0, timestamp_, frame_size_, false, max_qp_,
765 IgnoredCodecSpecificInfo());
766
767 // A third frame, expect boosted quality.
768 layers_->OnRatesUpdated(0, kDefault2TlBitratesBps, kFrameRate);
769 EXPECT_EQ(kTl1Flags, SkipUntilTlAndSync(1, false));
770 EXPECT_TRUE(config_updated_);
771 EXPECT_LT(cfg_.rc_max_quantizer, max_qp_);
772 EXPECT_EQ(adjusted_qp, cfg_.rc_max_quantizer);
773
774 // Frame encoded.
775 layers_->OnEncodeDone(0, timestamp_, frame_size_, false, max_qp_,
776 IgnoredCodecSpecificInfo());
777
778 // A fourth frame, max qp should be restored.
779 layers_->OnRatesUpdated(0, kDefault2TlBitratesBpsAlt, kFrameRate);
780 EXPECT_EQ(kTl1Flags, SkipUntilTlAndSync(1, false));
781 EXPECT_EQ(cfg_.rc_max_quantizer, max_qp_);
782 }
783
784 } // namespace webrtc
785