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"); | |
72 static const base::FilePath::CharType kCapturedYuvFileName[] = | 64 static const base::FilePath::CharType kCapturedYuvFileName[] = |
73 FILE_PATH_LITERAL("captured_video.yuv"); | 65 FILE_PATH_LITERAL("captured_video.yuv"); |
74 static const base::FilePath::CharType kStatsFileName[] = | 66 static const base::FilePath::CharType kStatsFileName[] = |
75 FILE_PATH_LITERAL("stats.txt"); | 67 FILE_PATH_LITERAL("stats.txt"); |
76 static const char kMainWebrtcTestHtmlPage[] = | 68 static const char kMainWebrtcTestHtmlPage[] = |
77 "/webrtc/webrtc_jsep01_test.html"; | 69 "/webrtc/webrtc_jsep01_test.html"; |
78 static const char kCapturingWebrtcHtmlPage[] = | 70 static const char kCapturingWebrtcHtmlPage[] = |
79 "/webrtc/webrtc_video_quality_test.html"; | 71 "/webrtc/webrtc_video_quality_test.html"; |
80 static const int k360pWidth = 640; | 72 static const int k360pWidth = 640; |
81 static const int k360pHeight = 360; | 73 static const int k360pHeight = 360; |
82 | 74 |
83 // If you change the port number, don't forget to modify video_extraction.js | 75 // If you change the port number, don't forget to modify video_extraction.js |
84 // too! | 76 // too! |
85 static const char kPyWebSocketPortNumber[] = "12221"; | 77 static const char kPyWebSocketPortNumber[] = "12221"; |
86 | 78 |
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 | |
95 // Test the video quality of the WebRTC output. | 79 // Test the video quality of the WebRTC output. |
96 // | 80 // |
97 // Prerequisites: This test case must run on a machine with a chrome playing | 81 // Prerequisites: This test case must run on a machine with a chrome playing |
98 // the video from the reference files located int GetReferenceVideosDir(). | 82 // the video from the reference files located int GetReferenceVideosDir(). |
99 // The file kReferenceY4mFileName.kY4mFileExtension is played using a | 83 // The file kReferenceY4mFileName.kY4mFileExtension is played using a |
100 // FileVideoCaptureDevice and its sibling with kYuvFileExtension is used for | 84 // FileVideoCaptureDevice and its sibling with kYuvFileExtension is used for |
101 // comparison. | 85 // comparison. |
102 // | 86 // |
103 // You must also compile the chromium_builder_webrtc target before you run this | 87 // You must also compile the chromium_builder_webrtc target before you run this |
104 // test to get all the tools built. | 88 // test to get all the tools built. |
(...skipping 10 matching lines...) Expand all Loading... |
115 // frame_analyzer. Both tools can be found under third_party/webrtc/tools. The | 99 // frame_analyzer. Both tools can be found under third_party/webrtc/tools. The |
116 // test also runs a stand alone Python implementation of a WebSocket server | 100 // test also runs a stand alone Python implementation of a WebSocket server |
117 // (pywebsocket) and a barcode_decoder script. | 101 // (pywebsocket) and a barcode_decoder script. |
118 class WebRtcVideoQualityBrowserTest : public WebRtcTestBase { | 102 class WebRtcVideoQualityBrowserTest : public WebRtcTestBase { |
119 public: | 103 public: |
120 WebRtcVideoQualityBrowserTest() | 104 WebRtcVideoQualityBrowserTest() |
121 : pywebsocket_server_(0), | 105 : pywebsocket_server_(0), |
122 environment_(base::Environment::Create()) {} | 106 environment_(base::Environment::Create()) {} |
123 | 107 |
124 virtual void SetUpInProcessBrowserTestFixture() OVERRIDE { | 108 virtual void SetUpInProcessBrowserTestFixture() OVERRIDE { |
125 PeerConnectionServerRunner::KillAllPeerConnectionServersOnCurrentSystem(); | 109 test::PeerConnectionServerRunner::KillAllPeerConnectionServers(); |
126 DetectErrorsInJavaScript(); // Look for errors in our rather complex js. | 110 DetectErrorsInJavaScript(); // Look for errors in our rather complex js. |
127 } | 111 } |
128 | 112 |
129 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE { | 113 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE { |
130 // Set up the command line option with the expected file name. We will check | 114 // Set up the command line option with the expected file name. We will check |
131 // its existence in HasAllRequiredResources(). | 115 // its existence in HasAllRequiredResources(). |
132 webrtc_reference_video_y4m_ = GetReferenceVideosDir() | 116 webrtc_reference_video_y4m_ = test::GetReferenceVideosDir() |
133 .Append(kReferenceFileName360p).AddExtension(kY4mFileExtension); | 117 .Append(test::kReferenceFileName360p) |
| 118 .AddExtension(test::kY4mFileExtension); |
134 command_line->AppendSwitchPath(switches::kUseFileForFakeVideoCapture, | 119 command_line->AppendSwitchPath(switches::kUseFileForFakeVideoCapture, |
135 webrtc_reference_video_y4m_); | 120 webrtc_reference_video_y4m_); |
136 command_line->AppendSwitch(switches::kUseFakeDeviceForMediaStream); | 121 command_line->AppendSwitch(switches::kUseFakeDeviceForMediaStream); |
137 | 122 |
138 // The video playback will not work without a GPU, so force its use here. | 123 // The video playback will not work without a GPU, so force its use here. |
139 command_line->AppendSwitch(switches::kUseGpuInTests); | 124 command_line->AppendSwitch(switches::kUseGpuInTests); |
140 } | 125 } |
141 | 126 |
142 bool HasAllRequiredResources() { | 127 bool HasAllRequiredResources() { |
143 if (!base::PathExists(GetWorkingDir())) { | 128 if (!base::PathExists(GetWorkingDir())) { |
144 LOG(ERROR) << "Cannot find the working directory for the temporary " | 129 LOG(ERROR) << "Cannot find the working directory for the temporary " |
145 "files:" << GetWorkingDir().value(); | 130 "files:" << GetWorkingDir().value(); |
146 return false; | 131 return false; |
147 } | 132 } |
148 if (!base::PathExists(GetReferenceVideosDir())) { | 133 |
149 LOG(ERROR) << "Cannot find the working directory for the reference video " | 134 // Ensure we have the required input files. |
150 "files, expected at " << GetReferenceVideosDir().value() << ". " << | 135 return test::HasReferenceFilesInCheckout(); |
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; | |
169 } | 136 } |
170 | 137 |
171 bool StartPyWebSocketServer() { | 138 bool StartPyWebSocketServer() { |
172 base::FilePath path_pywebsocket_dir = | 139 base::FilePath path_pywebsocket_dir = |
173 GetSourceDir().Append(FILE_PATH_LITERAL("third_party/pywebsocket/src")); | 140 GetSourceDir().Append(FILE_PATH_LITERAL("third_party/pywebsocket/src")); |
174 base::FilePath pywebsocket_server = path_pywebsocket_dir.Append( | 141 base::FilePath pywebsocket_server = path_pywebsocket_dir.Append( |
175 FILE_PATH_LITERAL("mod_pywebsocket/standalone.py")); | 142 FILE_PATH_LITERAL("mod_pywebsocket/standalone.py")); |
176 base::FilePath path_to_data_handler = | 143 base::FilePath path_to_data_handler = |
177 GetSourceDir().Append(FILE_PATH_LITERAL("chrome/test/functional")); | 144 GetSourceDir().Append(FILE_PATH_LITERAL("chrome/test/functional")); |
178 | 145 |
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
304 } | 271 } |
305 | 272 |
306 base::FilePath GetWorkingDir() { | 273 base::FilePath GetWorkingDir() { |
307 std::string home_dir; | 274 std::string home_dir; |
308 environment_->GetVar(kHomeEnvName, &home_dir); | 275 environment_->GetVar(kHomeEnvName, &home_dir); |
309 base::FilePath::StringType native_home_dir(home_dir.begin(), | 276 base::FilePath::StringType native_home_dir(home_dir.begin(), |
310 home_dir.end()); | 277 home_dir.end()); |
311 return base::FilePath(native_home_dir).Append(kWorkingDirName); | 278 return base::FilePath(native_home_dir).Append(kWorkingDirName); |
312 } | 279 } |
313 | 280 |
314 base::FilePath GetReferenceVideosDir() { | 281 test::PeerConnectionServerRunner peerconnection_server_; |
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_; | |
331 | 282 |
332 private: | 283 private: |
333 base::FilePath GetSourceDir() { | 284 base::FilePath GetSourceDir() { |
334 base::FilePath source_dir; | 285 base::FilePath source_dir; |
335 PathService::Get(base::DIR_SOURCE_ROOT, &source_dir); | 286 PathService::Get(base::DIR_SOURCE_ROOT, &source_dir); |
336 return source_dir; | 287 return source_dir; |
337 } | 288 } |
338 | 289 |
339 base::FilePath GetBrowserDir() { | 290 base::FilePath GetBrowserDir() { |
340 base::FilePath browser_dir; | 291 base::FilePath browser_dir; |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
372 OpenPageAndGetUserMediaInNewTabWithConstraints( | 323 OpenPageAndGetUserMediaInNewTabWithConstraints( |
373 embedded_test_server()->GetURL(kCapturingWebrtcHtmlPage), | 324 embedded_test_server()->GetURL(kCapturingWebrtcHtmlPage), |
374 kAudioVideoCallConstraints360p); | 325 kAudioVideoCallConstraints360p); |
375 | 326 |
376 EstablishCall(left_tab, right_tab); | 327 EstablishCall(left_tab, right_tab); |
377 | 328 |
378 // Poll slower here to avoid flooding the log with messages: capturing and | 329 // Poll slower here to avoid flooding the log with messages: capturing and |
379 // sending frames take quite a bit of time. | 330 // sending frames take quite a bit of time. |
380 int polling_interval_msec = 1000; | 331 int polling_interval_msec = 1000; |
381 | 332 |
382 EXPECT_TRUE(PollingWaitUntil( | 333 EXPECT_TRUE(test::PollingWaitUntil( |
383 "doneFrameCapturing()", "done-capturing", right_tab, | 334 "doneFrameCapturing()", "done-capturing", right_tab, |
384 polling_interval_msec)); | 335 polling_interval_msec)); |
385 | 336 |
386 HangUp(left_tab); | 337 HangUp(left_tab); |
387 WaitUntilHangupVerified(left_tab); | 338 WaitUntilHangupVerified(left_tab); |
388 WaitUntilHangupVerified(right_tab); | 339 WaitUntilHangupVerified(right_tab); |
389 | 340 |
390 EXPECT_TRUE(PollingWaitUntil( | 341 EXPECT_TRUE(test::PollingWaitUntil( |
391 "haveMoreFramesToSend()", "no-more-frames", right_tab, | 342 "haveMoreFramesToSend()", "no-more-frames", right_tab, |
392 polling_interval_msec)); | 343 polling_interval_msec)); |
393 | 344 |
394 // Shut everything down to avoid having the javascript race with the analysis | 345 // Shut everything down to avoid having the javascript race with the analysis |
395 // tools. For instance, dont have console log printouts interleave with the | 346 // tools. For instance, dont have console log printouts interleave with the |
396 // RESULT lines from the analysis tools (crbug.com/323200). | 347 // RESULT lines from the analysis tools (crbug.com/323200). |
397 ASSERT_TRUE(peerconnection_server_.Stop()); | 348 ASSERT_TRUE(peerconnection_server_.Stop()); |
398 ASSERT_TRUE(ShutdownPyWebSocketServer()); | 349 ASSERT_TRUE(ShutdownPyWebSocketServer()); |
399 | 350 |
400 chrome::CloseWebContents(browser(), left_tab, false); | 351 chrome::CloseWebContents(browser(), left_tab, false); |
401 chrome::CloseWebContents(browser(), right_tab, false); | 352 chrome::CloseWebContents(browser(), right_tab, false); |
402 | 353 |
403 RunARGBtoI420Converter( | 354 RunARGBtoI420Converter( |
404 k360pWidth, k360pHeight, GetWorkingDir().Append(kCapturedYuvFileName)); | 355 k360pWidth, k360pHeight, GetWorkingDir().Append(kCapturedYuvFileName)); |
405 ASSERT_TRUE(CompareVideosAndPrintResult( | 356 ASSERT_TRUE(CompareVideosAndPrintResult( |
406 k360pWidth, | 357 k360pWidth, |
407 k360pHeight, | 358 k360pHeight, |
408 GetWorkingDir().Append(kCapturedYuvFileName), | 359 GetWorkingDir().Append(kCapturedYuvFileName), |
409 GetReferenceVideosDir().Append(kReferenceFileName360p).AddExtension( | 360 test::GetReferenceVideosDir() |
410 kYuvFileExtension), | 361 .Append(test::kReferenceFileName360p) |
| 362 .AddExtension(test::kYuvFileExtension), |
411 GetWorkingDir().Append(kStatsFileName))); | 363 GetWorkingDir().Append(kStatsFileName))); |
412 } | 364 } |
OLD | NEW |