OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "base/environment.h" | 5 #include "base/environment.h" |
6 #include "base/file_util.h" | 6 #include "base/file_util.h" |
7 #include "base/path_service.h" | 7 #include "base/path_service.h" |
8 #include "base/process/launch.h" | 8 #include "base/process/launch.h" |
9 #include "base/strings/string_split.h" | 9 #include "base/strings/string_split.h" |
10 #include "base/strings/stringprintf.h" | 10 #include "base/strings/stringprintf.h" |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
54 static const char kHomeEnvName[] = | 54 static const char kHomeEnvName[] = |
55 #if defined(OS_WIN) | 55 #if defined(OS_WIN) |
56 "HOMEPATH"; | 56 "HOMEPATH"; |
57 #else | 57 #else |
58 "HOME"; | 58 "HOME"; |
59 #endif | 59 #endif |
60 | 60 |
61 // The working dir should be in the user's home folder. | 61 // The working dir should be in the user's home folder. |
62 static const base::FilePath::CharType kWorkingDirName[] = | 62 static const base::FilePath::CharType kWorkingDirName[] = |
63 FILE_PATH_LITERAL("webrtc_video_quality"); | 63 FILE_PATH_LITERAL("webrtc_video_quality"); |
| 64 static const base::FilePath::CharType kReferenceVideosDirName[] = |
| 65 FILE_PATH_LITERAL("webrtc.DEPS/webrtc_videos"); |
| 66 static const base::FilePath::CharType kReferenceFileName360p[] = |
| 67 FILE_PATH_LITERAL("reference_video_640x360_30fps"); |
| 68 static const base::FilePath::CharType kYuvFileExtension[] = |
| 69 FILE_PATH_LITERAL("yuv"); |
| 70 static const base::FilePath::CharType kY4mFileExtension[] = |
| 71 FILE_PATH_LITERAL("y4m"); |
64 static const base::FilePath::CharType kCapturedYuvFileName[] = | 72 static const base::FilePath::CharType kCapturedYuvFileName[] = |
65 FILE_PATH_LITERAL("captured_video.yuv"); | 73 FILE_PATH_LITERAL("captured_video.yuv"); |
66 static const base::FilePath::CharType kStatsFileName[] = | 74 static const base::FilePath::CharType kStatsFileName[] = |
67 FILE_PATH_LITERAL("stats.txt"); | 75 FILE_PATH_LITERAL("stats.txt"); |
68 static const char kMainWebrtcTestHtmlPage[] = | 76 static const char kMainWebrtcTestHtmlPage[] = |
69 "/webrtc/webrtc_jsep01_test.html"; | 77 "/webrtc/webrtc_jsep01_test.html"; |
70 static const char kCapturingWebrtcHtmlPage[] = | 78 static const char kCapturingWebrtcHtmlPage[] = |
71 "/webrtc/webrtc_video_quality_test.html"; | 79 "/webrtc/webrtc_video_quality_test.html"; |
72 static const int k360pWidth = 640; | 80 static const int k360pWidth = 640; |
73 static const int k360pHeight = 360; | 81 static const int k360pHeight = 360; |
74 | 82 |
75 // If you change the port number, don't forget to modify video_extraction.js | 83 // If you change the port number, don't forget to modify video_extraction.js |
76 // too! | 84 // too! |
77 static const char kPyWebSocketPortNumber[] = "12221"; | 85 static const char kPyWebSocketPortNumber[] = "12221"; |
78 | 86 |
| 87 const char kAdviseOnGclientSolution[] = |
| 88 "You need to add this solution to your .gclient to run this test:\n" |
| 89 "{\n" |
| 90 " \"name\" : \"webrtc.DEPS\",\n" |
| 91 " \"url\" : \"svn://svn.chromium.org/chrome/trunk/deps/" |
| 92 "third_party/webrtc/webrtc.DEPS\",\n" |
| 93 "}"; |
| 94 |
79 // Test the video quality of the WebRTC output. | 95 // Test the video quality of the WebRTC output. |
80 // | 96 // |
81 // Prerequisites: This test case must run on a machine with a chrome playing | 97 // Prerequisites: This test case must run on a machine with a chrome playing |
82 // the video from the reference files located int GetReferenceVideosDir(). | 98 // the video from the reference files located int GetReferenceVideosDir(). |
83 // The file kReferenceY4mFileName.kY4mFileExtension is played using a | 99 // The file kReferenceY4mFileName.kY4mFileExtension is played using a |
84 // FileVideoCaptureDevice and its sibling with kYuvFileExtension is used for | 100 // FileVideoCaptureDevice and its sibling with kYuvFileExtension is used for |
85 // comparison. | 101 // comparison. |
86 // | 102 // |
87 // You must also compile the chromium_builder_webrtc target before you run this | 103 // You must also compile the chromium_builder_webrtc target before you run this |
88 // test to get all the tools built. | 104 // test to get all the tools built. |
(...skipping 10 matching lines...) Expand all Loading... |
99 // frame_analyzer. Both tools can be found under third_party/webrtc/tools. The | 115 // frame_analyzer. Both tools can be found under third_party/webrtc/tools. The |
100 // test also runs a stand alone Python implementation of a WebSocket server | 116 // test also runs a stand alone Python implementation of a WebSocket server |
101 // (pywebsocket) and a barcode_decoder script. | 117 // (pywebsocket) and a barcode_decoder script. |
102 class WebRtcVideoQualityBrowserTest : public WebRtcTestBase { | 118 class WebRtcVideoQualityBrowserTest : public WebRtcTestBase { |
103 public: | 119 public: |
104 WebRtcVideoQualityBrowserTest() | 120 WebRtcVideoQualityBrowserTest() |
105 : pywebsocket_server_(0), | 121 : pywebsocket_server_(0), |
106 environment_(base::Environment::Create()) {} | 122 environment_(base::Environment::Create()) {} |
107 | 123 |
108 virtual void SetUpInProcessBrowserTestFixture() OVERRIDE { | 124 virtual void SetUpInProcessBrowserTestFixture() OVERRIDE { |
109 test::PeerConnectionServerRunner::KillAllPeerConnectionServers(); | 125 PeerConnectionServerRunner::KillAllPeerConnectionServersOnCurrentSystem(); |
110 DetectErrorsInJavaScript(); // Look for errors in our rather complex js. | 126 DetectErrorsInJavaScript(); // Look for errors in our rather complex js. |
111 } | 127 } |
112 | 128 |
113 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE { | 129 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE { |
114 // Set up the command line option with the expected file name. We will check | 130 // Set up the command line option with the expected file name. We will check |
115 // its existence in HasAllRequiredResources(). | 131 // its existence in HasAllRequiredResources(). |
116 webrtc_reference_video_y4m_ = test::GetReferenceVideosDir() | 132 webrtc_reference_video_y4m_ = GetReferenceVideosDir() |
117 .Append(test::kReferenceFileName360p) | 133 .Append(kReferenceFileName360p).AddExtension(kY4mFileExtension); |
118 .AddExtension(test::kY4mFileExtension); | |
119 command_line->AppendSwitchPath(switches::kUseFileForFakeVideoCapture, | 134 command_line->AppendSwitchPath(switches::kUseFileForFakeVideoCapture, |
120 webrtc_reference_video_y4m_); | 135 webrtc_reference_video_y4m_); |
121 command_line->AppendSwitch(switches::kUseFakeDeviceForMediaStream); | 136 command_line->AppendSwitch(switches::kUseFakeDeviceForMediaStream); |
122 | 137 |
123 // The video playback will not work without a GPU, so force its use here. | 138 // The video playback will not work without a GPU, so force its use here. |
124 command_line->AppendSwitch(switches::kUseGpuInTests); | 139 command_line->AppendSwitch(switches::kUseGpuInTests); |
125 } | 140 } |
126 | 141 |
127 bool HasAllRequiredResources() { | 142 bool HasAllRequiredResources() { |
128 if (!base::PathExists(GetWorkingDir())) { | 143 if (!base::PathExists(GetWorkingDir())) { |
129 LOG(ERROR) << "Cannot find the working directory for the temporary " | 144 LOG(ERROR) << "Cannot find the working directory for the temporary " |
130 "files:" << GetWorkingDir().value(); | 145 "files:" << GetWorkingDir().value(); |
131 return false; | 146 return false; |
132 } | 147 } |
133 | 148 if (!base::PathExists(GetReferenceVideosDir())) { |
134 // Ensure we have the required input files. | 149 LOG(ERROR) << "Cannot find the working directory for the reference video " |
135 return test::HasReferenceFilesInCheckout(); | 150 "files, expected at " << GetReferenceVideosDir().value() << ". " << |
| 151 kAdviseOnGclientSolution; |
| 152 return false; |
| 153 } |
| 154 base::FilePath webrtc_reference_video_yuv = GetReferenceVideosDir() |
| 155 .Append(kReferenceFileName360p).AddExtension(kYuvFileExtension); |
| 156 if (!base::PathExists(webrtc_reference_video_yuv)) { |
| 157 LOG(ERROR) << "Missing YUV reference video to be used for quality" |
| 158 << " comparison, expected at " << webrtc_reference_video_yuv.value() |
| 159 << ". " << kAdviseOnGclientSolution; |
| 160 return false; |
| 161 } |
| 162 if (!base::PathExists(webrtc_reference_video_y4m_)) { |
| 163 LOG(ERROR) << "Missing Y4M reference video to be used for quality" |
| 164 << " comparison, expected at "<< webrtc_reference_video_y4m_.value() |
| 165 << ". " << kAdviseOnGclientSolution; |
| 166 return false; |
| 167 } |
| 168 return true; |
136 } | 169 } |
137 | 170 |
138 bool StartPyWebSocketServer() { | 171 bool StartPyWebSocketServer() { |
139 base::FilePath path_pywebsocket_dir = | 172 base::FilePath path_pywebsocket_dir = |
140 GetSourceDir().Append(FILE_PATH_LITERAL("third_party/pywebsocket/src")); | 173 GetSourceDir().Append(FILE_PATH_LITERAL("third_party/pywebsocket/src")); |
141 base::FilePath pywebsocket_server = path_pywebsocket_dir.Append( | 174 base::FilePath pywebsocket_server = path_pywebsocket_dir.Append( |
142 FILE_PATH_LITERAL("mod_pywebsocket/standalone.py")); | 175 FILE_PATH_LITERAL("mod_pywebsocket/standalone.py")); |
143 base::FilePath path_to_data_handler = | 176 base::FilePath path_to_data_handler = |
144 GetSourceDir().Append(FILE_PATH_LITERAL("chrome/test/functional")); | 177 GetSourceDir().Append(FILE_PATH_LITERAL("chrome/test/functional")); |
145 | 178 |
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
271 } | 304 } |
272 | 305 |
273 base::FilePath GetWorkingDir() { | 306 base::FilePath GetWorkingDir() { |
274 std::string home_dir; | 307 std::string home_dir; |
275 environment_->GetVar(kHomeEnvName, &home_dir); | 308 environment_->GetVar(kHomeEnvName, &home_dir); |
276 base::FilePath::StringType native_home_dir(home_dir.begin(), | 309 base::FilePath::StringType native_home_dir(home_dir.begin(), |
277 home_dir.end()); | 310 home_dir.end()); |
278 return base::FilePath(native_home_dir).Append(kWorkingDirName); | 311 return base::FilePath(native_home_dir).Append(kWorkingDirName); |
279 } | 312 } |
280 | 313 |
281 test::PeerConnectionServerRunner peerconnection_server_; | 314 base::FilePath GetReferenceVideosDir() { |
| 315 // FilePath does not tolerate relative paths, and we want to hang the |
| 316 // kReferenceVideosDirName at the same level as Chromium codebase, so we |
| 317 // need to subtract the trailing .../src manually from the path. |
| 318 const size_t src_token_length = 3u; |
| 319 const base::FilePath::StringType src_token(FILE_PATH_LITERAL("src")); |
| 320 base::FilePath::StringType path = GetSourceDir().value(); |
| 321 DCHECK_GT(path.size(), src_token_length); |
| 322 std::size_t found = path.rfind(src_token); |
| 323 if (found != std::string::npos) |
| 324 path.replace(found, |
| 325 src_token_length, |
| 326 base::FilePath::StringType(FILE_PATH_LITERAL(""))); |
| 327 return base::FilePath(path).Append(kReferenceVideosDirName); |
| 328 } |
| 329 |
| 330 PeerConnectionServerRunner peerconnection_server_; |
282 | 331 |
283 private: | 332 private: |
284 base::FilePath GetSourceDir() { | 333 base::FilePath GetSourceDir() { |
285 base::FilePath source_dir; | 334 base::FilePath source_dir; |
286 PathService::Get(base::DIR_SOURCE_ROOT, &source_dir); | 335 PathService::Get(base::DIR_SOURCE_ROOT, &source_dir); |
287 return source_dir; | 336 return source_dir; |
288 } | 337 } |
289 | 338 |
290 base::FilePath GetBrowserDir() { | 339 base::FilePath GetBrowserDir() { |
291 base::FilePath browser_dir; | 340 base::FilePath browser_dir; |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
323 OpenPageAndGetUserMediaInNewTabWithConstraints( | 372 OpenPageAndGetUserMediaInNewTabWithConstraints( |
324 embedded_test_server()->GetURL(kCapturingWebrtcHtmlPage), | 373 embedded_test_server()->GetURL(kCapturingWebrtcHtmlPage), |
325 kAudioVideoCallConstraints360p); | 374 kAudioVideoCallConstraints360p); |
326 | 375 |
327 EstablishCall(left_tab, right_tab); | 376 EstablishCall(left_tab, right_tab); |
328 | 377 |
329 // Poll slower here to avoid flooding the log with messages: capturing and | 378 // Poll slower here to avoid flooding the log with messages: capturing and |
330 // sending frames take quite a bit of time. | 379 // sending frames take quite a bit of time. |
331 int polling_interval_msec = 1000; | 380 int polling_interval_msec = 1000; |
332 | 381 |
333 EXPECT_TRUE(test::PollingWaitUntil( | 382 EXPECT_TRUE(PollingWaitUntil( |
334 "doneFrameCapturing()", "done-capturing", right_tab, | 383 "doneFrameCapturing()", "done-capturing", right_tab, |
335 polling_interval_msec)); | 384 polling_interval_msec)); |
336 | 385 |
337 HangUp(left_tab); | 386 HangUp(left_tab); |
338 WaitUntilHangupVerified(left_tab); | 387 WaitUntilHangupVerified(left_tab); |
339 WaitUntilHangupVerified(right_tab); | 388 WaitUntilHangupVerified(right_tab); |
340 | 389 |
341 EXPECT_TRUE(test::PollingWaitUntil( | 390 EXPECT_TRUE(PollingWaitUntil( |
342 "haveMoreFramesToSend()", "no-more-frames", right_tab, | 391 "haveMoreFramesToSend()", "no-more-frames", right_tab, |
343 polling_interval_msec)); | 392 polling_interval_msec)); |
344 | 393 |
345 // Shut everything down to avoid having the javascript race with the analysis | 394 // Shut everything down to avoid having the javascript race with the analysis |
346 // tools. For instance, dont have console log printouts interleave with the | 395 // tools. For instance, dont have console log printouts interleave with the |
347 // RESULT lines from the analysis tools (crbug.com/323200). | 396 // RESULT lines from the analysis tools (crbug.com/323200). |
348 ASSERT_TRUE(peerconnection_server_.Stop()); | 397 ASSERT_TRUE(peerconnection_server_.Stop()); |
349 ASSERT_TRUE(ShutdownPyWebSocketServer()); | 398 ASSERT_TRUE(ShutdownPyWebSocketServer()); |
350 | 399 |
351 chrome::CloseWebContents(browser(), left_tab, false); | 400 chrome::CloseWebContents(browser(), left_tab, false); |
352 chrome::CloseWebContents(browser(), right_tab, false); | 401 chrome::CloseWebContents(browser(), right_tab, false); |
353 | 402 |
354 RunARGBtoI420Converter( | 403 RunARGBtoI420Converter( |
355 k360pWidth, k360pHeight, GetWorkingDir().Append(kCapturedYuvFileName)); | 404 k360pWidth, k360pHeight, GetWorkingDir().Append(kCapturedYuvFileName)); |
356 ASSERT_TRUE(CompareVideosAndPrintResult( | 405 ASSERT_TRUE(CompareVideosAndPrintResult( |
357 k360pWidth, | 406 k360pWidth, |
358 k360pHeight, | 407 k360pHeight, |
359 GetWorkingDir().Append(kCapturedYuvFileName), | 408 GetWorkingDir().Append(kCapturedYuvFileName), |
360 test::GetReferenceVideosDir() | 409 GetReferenceVideosDir().Append(kReferenceFileName360p).AddExtension( |
361 .Append(test::kReferenceFileName360p) | 410 kYuvFileExtension), |
362 .AddExtension(test::kYuvFileExtension), | |
363 GetWorkingDir().Append(kStatsFileName))); | 411 GetWorkingDir().Append(kStatsFileName))); |
364 } | 412 } |
OLD | NEW |