| // Copyright 2018 The Chromium Authors | 
 | // Use of this source code is governed by a BSD-style license that can be | 
 | // found in the LICENSE file. | 
 |  | 
 | #include "base/command_line.h" | 
 | #include "base/strings/stringprintf.h" | 
 | #include "base/test/test_timeouts.h" | 
 | #include "base/time/time.h" | 
 | #include "chrome/browser/media/webrtc/test_stats_dictionary.h" | 
 | #include "chrome/browser/media/webrtc/webrtc_browsertest_base.h" | 
 | #include "chrome/browser/media/webrtc/webrtc_browsertest_common.h" | 
 | #include "content/public/browser/web_contents.h" | 
 | #include "content/public/common/content_switches.h" | 
 | #include "content/public/test/browser_test.h" | 
 | #include "media/base/media_switches.h" | 
 | #include "testing/perf/perf_test.h" | 
 | #include "ui/gl/gl_switches.h" | 
 |  | 
 | namespace { | 
 |  | 
 | static const char kMainWebrtcTestHtmlPage[] = | 
 |     "/webrtc/webrtc_video_display_perf_test.html"; | 
 | static const char kInboundRtp[] = "inbound-rtp"; | 
 | static const char kOutboundRtp[] = "outbound-rtp"; | 
 |  | 
 | // Sums up "RTC[In/Out]boundRTPStreamStats.bytes_[received/sent]" values. | 
 | double GetTotalRTPStreamBytes(content::TestStatsReportDictionary* report, | 
 |                               const char* type, | 
 |                               const char* media_type) { | 
 |   DCHECK(type == kInboundRtp || type == kOutboundRtp); | 
 |   const char* bytes_name = | 
 |       (type == kInboundRtp) ? "bytesReceived" : "bytesSent"; | 
 |   double total_bytes = 0.0; | 
 |   report->ForEach([&type, &bytes_name, &media_type, | 
 |                    &total_bytes](const content::TestStatsDictionary& stats) { | 
 |     if (stats.GetString("type") == type && | 
 |         stats.GetString("mediaType") == media_type) { | 
 |       total_bytes += stats.GetNumber(bytes_name); | 
 |     } | 
 |   }); | 
 |   return total_bytes; | 
 | } | 
 |  | 
 | double GetVideoBytesSent(content::TestStatsReportDictionary* report) { | 
 |   return GetTotalRTPStreamBytes(report, kOutboundRtp, "video"); | 
 | } | 
 |  | 
 | double GetVideoBytesReceived(content::TestStatsReportDictionary* report) { | 
 |   return GetTotalRTPStreamBytes(report, kInboundRtp, "video"); | 
 | } | 
 |  | 
 | }  // anonymous namespace | 
 |  | 
 | namespace content { | 
 |  | 
 | // Tests the performance of WebRTC peer connection with high bitrate | 
 | // | 
 | // This test creates a WebRTC peer connection between two tabs and sets a very | 
 | // high target bitrate to observe any perf regressions/improvements for such | 
 | // cases. In order to achieve this, we use a fake codec that creates a dummy | 
 | // output for the given bitrate. | 
 | class WebRtcVideoHighBitrateBrowserTest : public WebRtcTestBase { | 
 |  public: | 
 |   void SetUpInProcessBrowserTestFixture() override { | 
 |     DetectErrorsInJavaScript(); | 
 |   } | 
 |  | 
 |   void SetUpCommandLine(base::CommandLine* command_line) override { | 
 |     command_line->AppendSwitch(switches::kUseFakeCodecForPeerConnection); | 
 |     command_line->AppendSwitch(switches::kUseFakeUIForMediaStream); | 
 |     command_line->AppendSwitch(switches::kUseGpuInTests); | 
 |   } | 
 |  | 
 |  protected: | 
 |   void SetDefaultVideoTargetBitrate(content::WebContents* tab, | 
 |                                     int bits_per_second) { | 
 |     EXPECT_EQ("ok", ExecuteJavascript( | 
 |                         base::StringPrintf("setDefaultVideoTargetBitrate(%d)", | 
 |                                            bits_per_second), | 
 |                         tab)); | 
 |   } | 
 | }; | 
 |  | 
 | IN_PROC_BROWSER_TEST_F(WebRtcVideoHighBitrateBrowserTest, | 
 |                        MANUAL_HighBitrateEncodeDecode) { | 
 |   ASSERT_TRUE(embedded_test_server()->Start()); | 
 |   ASSERT_GE(TestTimeouts::test_launcher_timeout().InSeconds(), 30) | 
 |       << "This is a long-running test; you must specify " | 
 |          "--test-launcher-timeout to have a value of at least 30000."; | 
 |   ASSERT_GE(TestTimeouts::action_max_timeout().InSeconds(), 30) | 
 |       << "This is a long-running test; you must specify " | 
 |          "--ui-test-action-max-timeout to have a value of at least 30000."; | 
 |   ASSERT_LT(TestTimeouts::action_max_timeout(), | 
 |             TestTimeouts::test_launcher_timeout()) | 
 |       << "action_max_timeout needs to be strictly-less-than " | 
 |          "test_launcher_timeout"; | 
 |  | 
 |   content::WebContents* left_tab = | 
 |       OpenPageAndGetUserMediaInNewTabWithConstraints( | 
 |           embedded_test_server()->GetURL(kMainWebrtcTestHtmlPage), | 
 |           "{audio: true, video: true}"); | 
 |   content::WebContents* right_tab = | 
 |       OpenPageAndGetUserMediaInNewTabWithConstraints( | 
 |           embedded_test_server()->GetURL(kMainWebrtcTestHtmlPage), | 
 |           "{audio: true, video: false}"); | 
 |   SetupPeerconnectionWithLocalStream(left_tab); | 
 |   SetupPeerconnectionWithLocalStream(right_tab); | 
 |   const int target_bits_per_second = 80000; | 
 |   SetDefaultVideoTargetBitrate(left_tab, target_bits_per_second); | 
 |   SetDefaultVideoTargetBitrate(right_tab, target_bits_per_second); | 
 |   NegotiateCall(left_tab, right_tab); | 
 |  | 
 |   // Run the connection a bit to ramp up. | 
 |   test::SleepInJavascript(left_tab, 10000); | 
 |  | 
 |   scoped_refptr<TestStatsReportDictionary> sender_report = | 
 |       GetStatsReportDictionary(left_tab); | 
 |   const double video_bytes_sent_before = GetVideoBytesSent(sender_report.get()); | 
 |   scoped_refptr<TestStatsReportDictionary> receiver_report = | 
 |       GetStatsReportDictionary(right_tab); | 
 |   const double video_bytes_received_before = | 
 |       GetVideoBytesReceived(receiver_report.get()); | 
 |  | 
 |   // Collect stats. | 
 |   const double duration_in_seconds = 5.0; | 
 |   test::SleepInJavascript( | 
 |       left_tab, duration_in_seconds * base::Time::kMillisecondsPerSecond); | 
 |  | 
 |   sender_report = GetStatsReportDictionary(left_tab); | 
 |   const double video_bytes_sent_after = GetVideoBytesSent(sender_report.get()); | 
 |   receiver_report = GetStatsReportDictionary(right_tab); | 
 |   const double video_bytes_received_after = | 
 |       GetVideoBytesReceived(receiver_report.get()); | 
 |  | 
 |   const double video_send_rate = | 
 |       (video_bytes_sent_after - video_bytes_sent_before) / duration_in_seconds; | 
 |   const double video_receive_rate = | 
 |       (video_bytes_received_after - video_bytes_received_before) / | 
 |       duration_in_seconds; | 
 |  | 
 |   perf_test::PrintResult("video", "", "send_rate", video_send_rate, | 
 |                          "bytes/second", false); | 
 |   perf_test::PrintResult("video", "", "receive_rate", video_receive_rate, | 
 |                          "bytes/second", false); | 
 |  | 
 |   HangUp(left_tab); | 
 |   HangUp(right_tab); | 
 | } | 
 |  | 
 | }  // namespace content |