OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license | 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 | 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 | 6 * tree. An additional intellectual property rights grant can be found |
7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
9 */ | 9 */ |
10 | 10 |
11 #include <limits> | 11 #include <limits> |
12 #include <utility> | 12 #include <utility> |
13 | 13 |
14 #include "webrtc/base/logging.h" | 14 #include "webrtc/base/logging.h" |
15 #include "webrtc/system_wrappers/include/metrics_default.h" | 15 #include "webrtc/system_wrappers/include/metrics_default.h" |
16 #include "webrtc/test/encoder_settings.h" | 16 #include "webrtc/test/encoder_settings.h" |
17 #include "webrtc/test/fake_encoder.h" | 17 #include "webrtc/test/fake_encoder.h" |
18 #include "webrtc/test/frame_generator.h" | 18 #include "webrtc/test/frame_generator.h" |
19 #include "webrtc/test/gtest.h" | 19 #include "webrtc/test/gtest.h" |
20 #include "webrtc/video/send_statistics_proxy.h" | 20 #include "webrtc/video/send_statistics_proxy.h" |
21 #include "webrtc/video/vie_encoder.h" | 21 #include "webrtc/video/vie_encoder.h" |
22 | 22 |
23 namespace webrtc { | 23 namespace webrtc { |
24 | 24 |
25 using DegredationPreference = VideoSendStream::DegradationPreference; | |
26 using ScaleReason = ScalingObserverInterface::ScaleReason; | |
27 | |
25 namespace { | 28 namespace { |
26 class TestBuffer : public webrtc::I420Buffer { | 29 class TestBuffer : public webrtc::I420Buffer { |
27 public: | 30 public: |
28 TestBuffer(rtc::Event* event, int width, int height) | 31 TestBuffer(rtc::Event* event, int width, int height) |
29 : I420Buffer(width, height), event_(event) {} | 32 : I420Buffer(width, height), event_(event) {} |
30 | 33 |
31 private: | 34 private: |
32 friend class rtc::RefCountedObject<TestBuffer>; | 35 friend class rtc::RefCountedObject<TestBuffer>; |
33 ~TestBuffer() override { | 36 ~TestBuffer() override { |
34 if (event_) | 37 if (event_) |
35 event_->Set(); | 38 event_->Set(); |
36 } | 39 } |
37 rtc::Event* const event_; | 40 rtc::Event* const event_; |
38 }; | 41 }; |
39 | 42 |
40 class ViEEncoderUnderTest : public ViEEncoder { | 43 class ViEEncoderUnderTest : public ViEEncoder { |
41 public: | 44 public: |
42 ViEEncoderUnderTest( | 45 ViEEncoderUnderTest(SendStatisticsProxy* stats_proxy, |
43 SendStatisticsProxy* stats_proxy, | 46 const VideoSendStream::Config::EncoderSettings& settings) |
44 const webrtc::VideoSendStream::Config::EncoderSettings& settings) | |
45 : ViEEncoder(1 /* number_of_cores */, | 47 : ViEEncoder(1 /* number_of_cores */, |
46 stats_proxy, | 48 stats_proxy, |
47 settings, | 49 settings, |
48 nullptr /* pre_encode_callback */, | 50 nullptr /* pre_encode_callback */, |
49 nullptr /* encoder_timing */) {} | 51 nullptr /* encoder_timing */) {} |
50 | 52 |
51 void TriggerCpuOveruse() { | 53 void PostTaskAndWait(bool down, ScaleReason reason) { |
52 rtc::Event event(false, false); | 54 rtc::Event event(false, false); |
53 encoder_queue()->PostTask([this, &event] { | 55 encoder_queue()->PostTask([this, &event, reason, down] { |
54 OveruseDetected(); | 56 down ? ScaleDown(reason) : ScaleUp(reason); |
55 event.Set(); | 57 event.Set(); |
56 }); | 58 }); |
57 event.Wait(rtc::Event::kForever); | 59 RTC_DCHECK(event.Wait(5000)); |
58 } | 60 } |
59 | 61 |
60 void TriggerCpuNormalUsage() { | 62 void TriggerCpuOveruse() { PostTaskAndWait(true, ScaleReason::kCpu); } |
61 rtc::Event event(false, false); | 63 |
62 encoder_queue()->PostTask([this, &event] { | 64 void TriggerCpuNormalUsage() { PostTaskAndWait(false, ScaleReason::kCpu); } |
63 NormalUsage(); | 65 |
64 event.Set(); | 66 void TriggerQualityLow() { PostTaskAndWait(true, ScaleReason::kQuality); } |
65 }); | 67 |
66 event.Wait(rtc::Event::kForever); | 68 void TriggerQualityHigh() { PostTaskAndWait(false, ScaleReason::kQuality); } |
67 } | |
68 }; | 69 }; |
69 | 70 |
70 } // namespace | 71 } // namespace |
71 | 72 |
72 class ViEEncoderTest : public ::testing::Test { | 73 class ViEEncoderTest : public ::testing::Test { |
73 public: | 74 public: |
74 static const int kDefaultTimeoutMs = 30 * 1000; | 75 static const int kDefaultTimeoutMs = 30 * 1000; |
75 | 76 |
76 ViEEncoderTest() | 77 ViEEncoderTest() |
77 : video_send_config_(VideoSendStream::Config(nullptr)), | 78 : video_send_config_(VideoSendStream::Config(nullptr)), |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
128 VideoCodec codec_config() { | 129 VideoCodec codec_config() { |
129 rtc::CritScope lock(&crit_); | 130 rtc::CritScope lock(&crit_); |
130 return config_; | 131 return config_; |
131 } | 132 } |
132 | 133 |
133 void BlockNextEncode() { | 134 void BlockNextEncode() { |
134 rtc::CritScope lock(&crit_); | 135 rtc::CritScope lock(&crit_); |
135 block_next_encode_ = true; | 136 block_next_encode_ = true; |
136 } | 137 } |
137 | 138 |
139 VideoEncoder::ScalingSettings GetScalingSettings() const override { | |
140 return VideoEncoder::ScalingSettings(true, 1, 2); | |
141 } | |
142 | |
138 void ContinueEncode() { continue_encode_event_.Set(); } | 143 void ContinueEncode() { continue_encode_event_.Set(); } |
139 | 144 |
140 void CheckLastTimeStampsMatch(int64_t ntp_time_ms, | 145 void CheckLastTimeStampsMatch(int64_t ntp_time_ms, |
141 uint32_t timestamp) const { | 146 uint32_t timestamp) const { |
142 rtc::CritScope lock(&crit_); | 147 rtc::CritScope lock(&crit_); |
143 EXPECT_EQ(timestamp_, timestamp); | 148 EXPECT_EQ(timestamp_, timestamp); |
144 EXPECT_EQ(ntp_time_ms_, ntp_time_ms); | 149 EXPECT_EQ(ntp_time_ms_, ntp_time_ms); |
145 } | 150 } |
146 | 151 |
147 private: | 152 private: |
(...skipping 274 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
422 | 427 |
423 EXPECT_LT(video_source_.sink_wants().max_pixel_count.value_or( | 428 EXPECT_LT(video_source_.sink_wants().max_pixel_count.value_or( |
424 std::numeric_limits<int>::max()), | 429 std::numeric_limits<int>::max()), |
425 frame_width * frame_height); | 430 frame_width * frame_height); |
426 EXPECT_FALSE(video_source_.sink_wants().max_pixel_count_step_up); | 431 EXPECT_FALSE(video_source_.sink_wants().max_pixel_count_step_up); |
427 | 432 |
428 frame_width /= 2; | 433 frame_width /= 2; |
429 frame_height /= 2; | 434 frame_height /= 2; |
430 } | 435 } |
431 | 436 |
432 // Trigger CPU overuse a one more time. This should not trigger request for | 437 // Trigger CPU overuse one more time. This should not trigger a request for |
433 // lower resolution. | 438 // lower resolution. |
434 rtc::VideoSinkWants current_wants = video_source_.sink_wants(); | 439 rtc::VideoSinkWants current_wants = video_source_.sink_wants(); |
435 video_source_.IncomingCapturedFrame(CreateFrame( | 440 video_source_.IncomingCapturedFrame(CreateFrame( |
436 ViEEncoder::kMaxCpuDowngrades + 1, frame_width, frame_height)); | 441 ViEEncoder::kMaxCpuDowngrades + 1, frame_width, frame_height)); |
437 sink_.WaitForEncodedFrame(ViEEncoder::kMaxCpuDowngrades + 1); | 442 sink_.WaitForEncodedFrame(ViEEncoder::kMaxCpuDowngrades + 1); |
438 vie_encoder_->TriggerCpuOveruse(); | 443 vie_encoder_->TriggerCpuOveruse(); |
439 EXPECT_EQ(video_source_.sink_wants().max_pixel_count, | 444 EXPECT_EQ(video_source_.sink_wants().max_pixel_count, |
440 current_wants.max_pixel_count); | 445 current_wants.max_pixel_count); |
441 EXPECT_EQ(video_source_.sink_wants().max_pixel_count_step_up, | 446 EXPECT_EQ(video_source_.sink_wants().max_pixel_count_step_up, |
442 current_wants.max_pixel_count_step_up); | 447 current_wants.max_pixel_count_step_up); |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
528 CreateFrame(3, frame_width, frame_height)); | 533 CreateFrame(3, frame_width, frame_height)); |
529 sink_.WaitForEncodedFrame(3); | 534 sink_.WaitForEncodedFrame(3); |
530 | 535 |
531 stats = stats_proxy_->GetStats(); | 536 stats = stats_proxy_->GetStats(); |
532 EXPECT_FALSE(stats.cpu_limited_resolution); | 537 EXPECT_FALSE(stats.cpu_limited_resolution); |
533 EXPECT_EQ(2, stats.number_of_cpu_adapt_changes); | 538 EXPECT_EQ(2, stats.number_of_cpu_adapt_changes); |
534 | 539 |
535 vie_encoder_->Stop(); | 540 vie_encoder_->Stop(); |
536 } | 541 } |
537 | 542 |
538 TEST_F(ViEEncoderTest, StatsTracksAdaptationStatsWhenSwitchingSource) { | 543 TEST_F(ViEEncoderTest, SwitchingSourceKeepsAdaptation) { |
539 const int kTargetBitrateBps = 100000; | 544 const int kTargetBitrateBps = 100000; |
540 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0); | 545 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0); |
541 | 546 |
542 // Trigger CPU overuse. | |
543 vie_encoder_->TriggerCpuOveruse(); | |
544 int frame_width = 1280; | 547 int frame_width = 1280; |
545 int frame_height = 720; | 548 int frame_height = 720; |
546 | |
547 video_source_.IncomingCapturedFrame( | 549 video_source_.IncomingCapturedFrame( |
548 CreateFrame(1, frame_width, frame_height)); | 550 CreateFrame(1, frame_width, frame_height)); |
549 sink_.WaitForEncodedFrame(1); | 551 sink_.WaitForEncodedFrame(1); |
550 | 552 |
551 VideoSendStream::Stats stats = stats_proxy_->GetStats(); | 553 VideoSendStream::Stats stats = stats_proxy_->GetStats(); |
552 EXPECT_TRUE(stats.cpu_limited_resolution); | 554 EXPECT_FALSE(stats.cpu_limited_resolution); |
perkj_webrtc
2016/11/17 21:23:38
Why these changes? Now you dont test that switchin
kthelgason
2016/11/21 13:06:53
Sorry, this must've gotten lost somewhere in the r
| |
553 EXPECT_EQ(1, stats.number_of_cpu_adapt_changes); | 555 EXPECT_FALSE(stats.bw_limited_resolution); |
556 EXPECT_EQ(0, stats.number_of_cpu_adapt_changes); | |
554 | 557 |
555 // Set new source with adaptation still enabled. | 558 // Set new source with adaptation still enabled. |
556 test::FrameForwarder new_video_source; | 559 test::FrameForwarder new_video_source; |
557 vie_encoder_->SetSource(&new_video_source, | 560 vie_encoder_->SetSource(&new_video_source, |
558 VideoSendStream::DegradationPreference::kBalanced); | 561 VideoSendStream::DegradationPreference::kBalanced); |
559 | 562 |
560 new_video_source.IncomingCapturedFrame( | 563 new_video_source.IncomingCapturedFrame( |
561 CreateFrame(2, frame_width, frame_height)); | 564 CreateFrame(2, frame_width, frame_height)); |
562 sink_.WaitForEncodedFrame(2); | 565 sink_.WaitForEncodedFrame(2); |
563 stats = stats_proxy_->GetStats(); | 566 stats = stats_proxy_->GetStats(); |
564 EXPECT_TRUE(stats.cpu_limited_resolution); | 567 EXPECT_FALSE(stats.cpu_limited_resolution); |
565 EXPECT_EQ(1, stats.number_of_cpu_adapt_changes); | 568 EXPECT_FALSE(stats.bw_limited_resolution); |
569 EXPECT_EQ(0, stats.number_of_cpu_adapt_changes); | |
570 | |
571 vie_encoder_->TriggerQualityLow(); | |
572 | |
573 new_video_source.IncomingCapturedFrame( | |
574 CreateFrame(3, frame_width, frame_height)); | |
575 sink_.WaitForEncodedFrame(3); | |
576 stats = stats_proxy_->GetStats(); | |
577 EXPECT_FALSE(stats.cpu_limited_resolution); | |
578 EXPECT_TRUE(stats.bw_limited_resolution); | |
579 | |
580 vie_encoder_->SetSource(&new_video_source, | |
581 VideoSendStream::DegradationPreference::kBalanced); | |
582 | |
583 new_video_source.IncomingCapturedFrame( | |
584 CreateFrame(4, frame_width, frame_height)); | |
585 sink_.WaitForEncodedFrame(4); | |
586 stats = stats_proxy_->GetStats(); | |
587 EXPECT_FALSE(stats.cpu_limited_resolution); | |
588 EXPECT_TRUE(stats.bw_limited_resolution); | |
566 | 589 |
567 // Set adaptation disabled. | 590 // Set adaptation disabled. |
568 vie_encoder_->SetSource( | 591 vie_encoder_->SetSource( |
569 &new_video_source, | 592 &new_video_source, |
570 VideoSendStream::DegradationPreference::kMaintainResolution); | 593 VideoSendStream::DegradationPreference::kMaintainResolution); |
594 | |
571 new_video_source.IncomingCapturedFrame( | 595 new_video_source.IncomingCapturedFrame( |
572 CreateFrame(3, frame_width, frame_height)); | |
573 sink_.WaitForEncodedFrame(3); | |
574 stats = stats_proxy_->GetStats(); | |
575 EXPECT_FALSE(stats.cpu_limited_resolution); | |
576 EXPECT_EQ(1, stats.number_of_cpu_adapt_changes); | |
577 | |
578 // Switch back the source with adaptation enabled. | |
579 vie_encoder_->SetSource(&video_source_, | |
perkj_webrtc
2016/11/17 21:23:38
and this?
kthelgason
2016/11/21 13:06:53
Done.
| |
580 VideoSendStream::DegradationPreference::kBalanced); | |
581 video_source_.IncomingCapturedFrame( | |
582 CreateFrame(4, frame_width, frame_height)); | |
583 sink_.WaitForEncodedFrame(4); | |
584 stats = stats_proxy_->GetStats(); | |
585 EXPECT_TRUE(stats.cpu_limited_resolution); | |
586 EXPECT_EQ(1, stats.number_of_cpu_adapt_changes); | |
587 | |
588 // Trigger CPU normal usage. | |
589 vie_encoder_->TriggerCpuNormalUsage(); | |
590 video_source_.IncomingCapturedFrame( | |
591 CreateFrame(5, frame_width, frame_height)); | 596 CreateFrame(5, frame_width, frame_height)); |
592 sink_.WaitForEncodedFrame(5); | 597 sink_.WaitForEncodedFrame(5); |
593 stats = stats_proxy_->GetStats(); | 598 stats = stats_proxy_->GetStats(); |
594 EXPECT_FALSE(stats.cpu_limited_resolution); | 599 EXPECT_FALSE(stats.cpu_limited_resolution); |
595 EXPECT_EQ(2, stats.number_of_cpu_adapt_changes); | 600 EXPECT_FALSE(stats.bw_limited_resolution); |
perkj_webrtc
2016/11/17 21:23:38
and this?
kthelgason
2016/11/21 13:06:53
Done.
| |
596 | 601 |
597 vie_encoder_->Stop(); | 602 vie_encoder_->Stop(); |
598 } | 603 } |
599 | 604 |
600 TEST_F(ViEEncoderTest, StatsTracksPreferredBitrate) { | 605 TEST_F(ViEEncoderTest, StatsTracksPreferredBitrate) { |
601 const int kTargetBitrateBps = 100000; | 606 const int kTargetBitrateBps = 100000; |
602 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0); | 607 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0); |
603 | 608 |
604 video_source_.IncomingCapturedFrame(CreateFrame(1, 1280, 720)); | 609 video_source_.IncomingCapturedFrame(CreateFrame(1, 1280, 720)); |
605 sink_.WaitForEncodedFrame(1); | 610 sink_.WaitForEncodedFrame(1); |
606 | 611 |
607 VideoSendStream::Stats stats = stats_proxy_->GetStats(); | 612 VideoSendStream::Stats stats = stats_proxy_->GetStats(); |
608 EXPECT_EQ(video_encoder_config_.max_bitrate_bps, | 613 EXPECT_EQ(video_encoder_config_.max_bitrate_bps, |
609 stats.preferred_media_bitrate_bps); | 614 stats.preferred_media_bitrate_bps); |
610 | 615 |
611 vie_encoder_->Stop(); | 616 vie_encoder_->Stop(); |
612 } | 617 } |
613 | 618 |
619 TEST_F(ViEEncoderTest, ScalingUpAndDownDoesNothingWithMaintainResolution) { | |
perkj_webrtc
2016/11/17 21:23:38
LowQualityWhenScalingDisabled?
kthelgason
2016/11/21 13:06:53
I think the current name better describes what thi
| |
620 const int kTargetBitrateBps = 100000; | |
621 int frame_width = 1280; | |
622 int frame_height = 720; | |
623 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0); | |
624 | |
625 // Expect no scaling to begin with | |
626 EXPECT_FALSE(video_source_.sink_wants().max_pixel_count); | |
627 EXPECT_FALSE(video_source_.sink_wants().max_pixel_count_step_up); | |
628 | |
629 // Trigger scale down | |
630 vie_encoder_->TriggerQualityLow(); | |
631 | |
632 video_source_.IncomingCapturedFrame( | |
633 CreateFrame(1, frame_width, frame_height)); | |
634 sink_.WaitForEncodedFrame(1); | |
635 // Expect a scale down. | |
636 EXPECT_TRUE(video_source_.sink_wants().max_pixel_count); | |
637 EXPECT_LT(*video_source_.sink_wants().max_pixel_count, | |
638 frame_width * frame_height); | |
639 const auto last_pixel_count = *video_source_.sink_wants().max_pixel_count; | |
perkj_webrtc
2016/11/17 21:23:38
nit const int last_pix...
kthelgason
2016/11/21 13:06:53
Done.
| |
640 | |
641 // Set adaptation disabled. | |
642 test::FrameForwarder new_video_source; | |
643 vie_encoder_->SetSource( | |
644 &new_video_source, | |
645 VideoSendStream::DegradationPreference::kMaintainResolution); | |
646 | |
647 // Trigger scale down | |
648 vie_encoder_->TriggerQualityLow(); | |
649 | |
650 new_video_source.IncomingCapturedFrame( | |
651 CreateFrame(2, frame_width, frame_height)); | |
652 sink_.WaitForEncodedFrame(2); | |
653 | |
654 // Expect nothing to change | |
655 EXPECT_EQ(video_source_.sink_wants().max_pixel_count, last_pixel_count); | |
656 | |
657 // Trigger scale up | |
658 vie_encoder_->TriggerQualityHigh(); | |
659 | |
660 new_video_source.IncomingCapturedFrame( | |
661 CreateFrame(3, frame_width, frame_height)); | |
662 sink_.WaitForEncodedFrame(3); | |
663 | |
664 // Expect nothing to change | |
665 EXPECT_EQ(video_source_.sink_wants().max_pixel_count, last_pixel_count); | |
666 | |
667 vie_encoder_->Stop(); | |
668 } | |
669 | |
614 TEST_F(ViEEncoderTest, UMACpuLimitedResolutionInPercent) { | 670 TEST_F(ViEEncoderTest, UMACpuLimitedResolutionInPercent) { |
615 const int kTargetBitrateBps = 100000; | 671 const int kTargetBitrateBps = 100000; |
616 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0); | 672 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0); |
617 | 673 |
618 int frame_width = 640; | 674 int frame_width = 640; |
619 int frame_height = 360; | 675 int frame_height = 360; |
620 | 676 |
621 for (int i = 1; i <= SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) { | 677 for (int i = 1; i <= SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) { |
622 video_source_.IncomingCapturedFrame( | 678 video_source_.IncomingCapturedFrame( |
623 CreateFrame(i, frame_width, frame_height)); | 679 CreateFrame(i, frame_width, frame_height)); |
(...skipping 12 matching lines...) Expand all Loading... | |
636 vie_encoder_->Stop(); | 692 vie_encoder_->Stop(); |
637 | 693 |
638 stats_proxy_.reset(); | 694 stats_proxy_.reset(); |
639 EXPECT_EQ(1, | 695 EXPECT_EQ(1, |
640 metrics::NumSamples("WebRTC.Video.CpuLimitedResolutionInPercent")); | 696 metrics::NumSamples("WebRTC.Video.CpuLimitedResolutionInPercent")); |
641 EXPECT_EQ( | 697 EXPECT_EQ( |
642 1, metrics::NumEvents("WebRTC.Video.CpuLimitedResolutionInPercent", 50)); | 698 1, metrics::NumEvents("WebRTC.Video.CpuLimitedResolutionInPercent", 50)); |
643 } | 699 } |
644 | 700 |
645 } // namespace webrtc | 701 } // namespace webrtc |
OLD | NEW |