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