Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(67)

Side by Side Diff: chrome/browser/media/chrome_webrtc_video_quality_browsertest.cc

Issue 1762413002: Cleanup: remove prefix chrome_ of chrome/browser/media/chrome* files (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: reran the commands Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #include <stddef.h>
6
7 #include "base/base64.h"
8 #include "base/command_line.h"
9 #include "base/environment.h"
10 #include "base/files/file.h"
11 #include "base/files/file_util.h"
12 #include "base/files/scoped_temp_dir.h"
13 #include "base/path_service.h"
14 #include "base/process/launch.h"
15 #include "base/strings/string_number_conversions.h"
16 #include "base/strings/string_split.h"
17 #include "base/strings/stringprintf.h"
18 #include "base/test/test_timeouts.h"
19 #include "base/time/time.h"
20 #include "build/build_config.h"
21 #include "chrome/browser/chrome_notification_types.h"
22 #include "chrome/browser/infobars/infobar_service.h"
23 #include "chrome/browser/media/webrtc_browsertest_base.h"
24 #include "chrome/browser/media/webrtc_browsertest_common.h"
25 #include "chrome/browser/profiles/profile.h"
26 #include "chrome/browser/ui/browser.h"
27 #include "chrome/browser/ui/browser_tabstrip.h"
28 #include "chrome/browser/ui/tabs/tab_strip_model.h"
29 #include "chrome/common/chrome_switches.h"
30 #include "chrome/test/base/in_process_browser_test.h"
31 #include "components/infobars/core/infobar.h"
32 #include "content/public/browser/notification_service.h"
33 #include "content/public/common/feature_h264_with_openh264_ffmpeg.h"
34 #include "content/public/common/features.h"
35 #include "content/public/test/browser_test_utils.h"
36 #include "media/base/media_switches.h"
37 #include "net/test/embedded_test_server/embedded_test_server.h"
38 #include "net/test/python_utils.h"
39 #include "testing/perf/perf_test.h"
40 #include "ui/gl/gl_switches.h"
41
42 namespace {
43 std::string MakeLabel(const char* test_name, const std::string& video_codec) {
44 std::string codec_label = video_codec.empty() ? "" : "_" + video_codec;
45 return base::StringPrintf("%s%s", test_name, codec_label.c_str());
46 }
47 } // namespace
48
49 static const base::FilePath::CharType kFrameAnalyzerExecutable[] =
50 #if defined(OS_WIN)
51 FILE_PATH_LITERAL("frame_analyzer.exe");
52 #else
53 FILE_PATH_LITERAL("frame_analyzer");
54 #endif
55
56 static const base::FilePath::CharType kArgbToI420ConverterExecutable[] =
57 #if defined(OS_WIN)
58 FILE_PATH_LITERAL("rgba_to_i420_converter.exe");
59 #else
60 FILE_PATH_LITERAL("rgba_to_i420_converter");
61 #endif
62
63 static const base::FilePath::CharType kCapturedYuvFileName[] =
64 FILE_PATH_LITERAL("captured_video.yuv");
65 static const base::FilePath::CharType kStatsFileName[] =
66 FILE_PATH_LITERAL("stats.txt");
67 static const char kMainWebrtcTestHtmlPage[] =
68 "/webrtc/webrtc_jsep01_test.html";
69 static const char kCapturingWebrtcHtmlPage[] =
70 "/webrtc/webrtc_video_quality_test.html";
71
72 static const struct VideoQualityTestConfig {
73 const char* test_name;
74 int width;
75 int height;
76 const base::FilePath::CharType* reference_video;
77 const char* constraints;
78 } kVideoConfigurations[] = {
79 { "360p", 640, 360,
80 test::kReferenceFileName360p,
81 WebRtcTestBase::kAudioVideoCallConstraints360p },
82 { "720p", 1280, 720,
83 test::kReferenceFileName720p,
84 WebRtcTestBase::kAudioVideoCallConstraints720p },
85 };
86
87 // Test the video quality of the WebRTC output.
88 //
89 // Prerequisites: This test case must run on a machine with a chrome playing
90 // the video from the reference files located in GetReferenceFilesDir().
91 // The file kReferenceY4mFileName.kY4mFileExtension is played using a
92 // FileVideoCaptureDevice and its sibling with kYuvFileExtension is used for
93 // comparison.
94 //
95 // You must also compile the chromium_builder_webrtc target before you run this
96 // test to get all the tools built.
97 //
98 // The external compare_videos.py script also depends on two external
99 // executables which must be located in the PATH when running this test.
100 // * zxing (see the CPP version at https://code.google.com/p/zxing)
101 // * ffmpeg 0.11.1 or compatible version (see http://www.ffmpeg.org)
102 //
103 // The test runs several custom binaries - rgba_to_i420 converter and
104 // frame_analyzer. Both tools can be found under third_party/webrtc/tools. The
105 // test also runs a stand alone Python implementation of a WebSocket server
106 // (pywebsocket) and a barcode_decoder script.
107 class WebRtcVideoQualityBrowserTest : public WebRtcTestBase,
108 public testing::WithParamInterface<VideoQualityTestConfig> {
109 public:
110 WebRtcVideoQualityBrowserTest()
111 : environment_(base::Environment::Create()) {
112 test_config_ = GetParam();
113 }
114
115 void SetUpInProcessBrowserTestFixture() override {
116 DetectErrorsInJavaScript(); // Look for errors in our rather complex js.
117
118 ASSERT_TRUE(temp_working_dir_.CreateUniqueTempDir());
119 }
120
121 void SetUpCommandLine(base::CommandLine* command_line) override {
122 // Set up the command line option with the expected file name. We will check
123 // its existence in HasAllRequiredResources().
124 webrtc_reference_video_y4m_ = test::GetReferenceFilesDir()
125 .Append(test_config_.reference_video)
126 .AddExtension(test::kY4mFileExtension);
127 command_line->AppendSwitchPath(switches::kUseFileForFakeVideoCapture,
128 webrtc_reference_video_y4m_);
129 command_line->AppendSwitch(switches::kUseFakeDeviceForMediaStream);
130
131 // The video playback will not work without a GPU, so force its use here.
132 command_line->AppendSwitch(switches::kUseGpuInTests);
133 }
134
135 // Writes all frames we've captured so far by grabbing them from the
136 // javascript and writing them to the temporary work directory.
137 void WriteCapturedFramesToWorkingDir(content::WebContents* capturing_tab) {
138 int num_frames = 0;
139 std::string response =
140 ExecuteJavascript("getTotalNumberCapturedFrames()", capturing_tab);
141 ASSERT_TRUE(base::StringToInt(response, &num_frames)) <<
142 "Failed to retrieve frame count: got " << response;
143 ASSERT_NE(0, num_frames) << "Failed to capture any frames.";
144
145 for (int i = 0; i < num_frames; i++) {
146 std::string base64_encoded_frame =
147 ExecuteJavascript(base::StringPrintf("getOneCapturedFrame(%d)", i),
148 capturing_tab);
149 std::string decoded_frame;
150 ASSERT_TRUE(base::Base64Decode(base64_encoded_frame, &decoded_frame))
151 << "Failed to decode frame data '" << base64_encoded_frame << "'.";
152
153 std::string file_name = base::StringPrintf("frame_%04d", i);
154 base::File frame_file(GetWorkingDir().AppendASCII(file_name),
155 base::File::FLAG_CREATE | base::File::FLAG_WRITE);
156 size_t written = frame_file.Write(0, decoded_frame.c_str(),
157 decoded_frame.length());
158 ASSERT_EQ(decoded_frame.length(), written);
159 }
160 }
161
162 // Runs the RGBA to I420 converter on the video in |capture_video_filename|,
163 // which should contain frames of size |width| x |height|.
164 //
165 // The rgba_to_i420_converter is part of the webrtc_test_tools target which
166 // should be build prior to running this test. The resulting binary should
167 // live next to Chrome.
168 bool RunARGBtoI420Converter(int width,
169 int height,
170 const base::FilePath& captured_video_filename) {
171 base::FilePath path_to_converter =
172 GetBrowserDir().Append(kArgbToI420ConverterExecutable);
173
174 if (!base::PathExists(path_to_converter)) {
175 LOG(ERROR) << "Missing ARGB->I420 converter: should be in "
176 << path_to_converter.value()
177 << ". Try building the chromium_builder_webrtc target.";
178 return false;
179 }
180
181 base::CommandLine converter_command(path_to_converter);
182 converter_command.AppendSwitchPath("--frames_dir", GetWorkingDir());
183 converter_command.AppendSwitchPath("--output_file",
184 captured_video_filename);
185 converter_command.AppendSwitchASCII("--width", base::IntToString(width));
186 converter_command.AppendSwitchASCII("--height", base::IntToString(height));
187 converter_command.AppendSwitchASCII("--delete_frames", "true");
188
189 // We produce an output file that will later be used as an input to the
190 // barcode decoder and frame analyzer tools.
191 DVLOG(0) << "Running " << converter_command.GetCommandLineString();
192 std::string result;
193 bool ok = base::GetAppOutput(converter_command, &result);
194 DVLOG(0) << "Output was:\n\n" << result;
195 return ok;
196 }
197
198 // Compares the |captured_video_filename| with the |reference_video_filename|.
199 //
200 // The barcode decoder decodes the captured video containing barcodes overlaid
201 // into every frame of the video (produced by rgba_to_i420_converter). It
202 // produces a set of PNG images and a |stats_file| that maps each captured
203 // frame to a frame in the reference video. The frames should be of size
204 // |width| x |height|.
205 // All measurements calculated are printed as perf parsable numbers to stdout.
206 bool CompareVideosAndPrintResult(
207 const std::string& test_label,
208 int width,
209 int height,
210 const base::FilePath& captured_video_filename,
211 const base::FilePath& reference_video_filename,
212 const base::FilePath& stats_file) {
213
214 base::FilePath path_to_analyzer = base::MakeAbsoluteFilePath(
215 GetBrowserDir().Append(kFrameAnalyzerExecutable));
216 base::FilePath path_to_compare_script = GetSourceDir().Append(
217 FILE_PATH_LITERAL("third_party/webrtc/tools/compare_videos.py"));
218
219 if (!base::PathExists(path_to_analyzer)) {
220 LOG(ERROR) << "Missing frame analyzer: should be in "
221 << path_to_analyzer.value()
222 << ". Try building the chromium_builder_webrtc target.";
223 return false;
224 }
225 if (!base::PathExists(path_to_compare_script)) {
226 LOG(ERROR) << "Missing video compare script: should be in "
227 << path_to_compare_script.value();
228 return false;
229 }
230
231 base::FilePath path_to_zxing = test::GetToolForPlatform("zxing");
232 if (!base::PathExists(path_to_zxing)) {
233 LOG(ERROR) << "Missing zxing: should be in " << path_to_zxing.value();
234 return false;
235 }
236 base::FilePath path_to_ffmpeg = test::GetToolForPlatform("ffmpeg");
237 if (!base::PathExists(path_to_ffmpeg)) {
238 LOG(ERROR) << "Missing ffmpeg: should be in " << path_to_ffmpeg.value();
239 return false;
240 }
241
242 // Note: don't append switches to this command since it will mess up the
243 // -u in the python invocation!
244 base::CommandLine compare_command(base::CommandLine::NO_PROGRAM);
245 EXPECT_TRUE(GetPythonCommand(&compare_command));
246
247 compare_command.AppendArgPath(path_to_compare_script);
248 compare_command.AppendArg("--label=" + test_label);
249 compare_command.AppendArg("--ref_video");
250 compare_command.AppendArgPath(reference_video_filename);
251 compare_command.AppendArg("--test_video");
252 compare_command.AppendArgPath(captured_video_filename);
253 compare_command.AppendArg("--frame_analyzer");
254 compare_command.AppendArgPath(path_to_analyzer);
255 compare_command.AppendArg("--yuv_frame_width");
256 compare_command.AppendArg(base::IntToString(width));
257 compare_command.AppendArg("--yuv_frame_height");
258 compare_command.AppendArg(base::IntToString(height));
259 compare_command.AppendArg("--zxing_path");
260 compare_command.AppendArgPath(path_to_zxing);
261 compare_command.AppendArg("--ffmpeg_path");
262 compare_command.AppendArgPath(path_to_ffmpeg);
263 compare_command.AppendArg("--stats_file");
264 compare_command.AppendArgPath(stats_file);
265
266 DVLOG(0) << "Running " << compare_command.GetCommandLineString();
267 std::string output;
268 bool ok = base::GetAppOutput(compare_command, &output);
269
270 // Print to stdout to ensure the perf numbers are parsed properly by the
271 // buildbot step. The tool should print a handful RESULT lines.
272 printf("Output was:\n\n%s\n", output.c_str());
273 bool has_result_lines = output.find("RESULT") != std::string::npos;
274 if (!ok || !has_result_lines) {
275 LOG(ERROR) << "Failed to compare videos; see output above to see what "
276 << "the error was.";
277 return false;
278 }
279 return true;
280 }
281
282 void TestVideoQuality(const std::string& video_codec) {
283 ASSERT_GE(TestTimeouts::action_max_timeout().InSeconds(), 150)
284 << "This is a long-running test; you must specify "
285 "--ui-test-action-max-timeout to have a value of at least 150000.";
286 ASSERT_TRUE(test::HasReferenceFilesInCheckout());
287 ASSERT_TRUE(embedded_test_server()->Start());
288
289 content::WebContents* left_tab =
290 OpenPageAndGetUserMediaInNewTabWithConstraints(
291 embedded_test_server()->GetURL(kMainWebrtcTestHtmlPage),
292 test_config_.constraints);
293 content::WebContents* right_tab =
294 OpenPageAndGetUserMediaInNewTabWithConstraints(
295 embedded_test_server()->GetURL(kCapturingWebrtcHtmlPage),
296 test_config_.constraints);
297
298 SetupPeerconnectionWithLocalStream(left_tab);
299 SetupPeerconnectionWithLocalStream(right_tab);
300
301 NegotiateCall(left_tab, right_tab, video_codec);
302
303 // Poll slower here to avoid flooding the log with messages: capturing and
304 // sending frames take quite a bit of time.
305 int polling_interval_msec = 1000;
306
307 EXPECT_TRUE(test::PollingWaitUntil("doneFrameCapturing()", "done-capturing",
308 right_tab, polling_interval_msec));
309
310 HangUp(left_tab);
311
312 WriteCapturedFramesToWorkingDir(right_tab);
313
314 // Shut everything down to avoid having the javascript race with the
315 // analysis tools. For instance, dont have console log printouts interleave
316 // with the RESULT lines from the analysis tools (crbug.com/323200).
317 chrome::CloseWebContents(browser(), left_tab, false);
318 chrome::CloseWebContents(browser(), right_tab, false);
319
320 ASSERT_TRUE(
321 RunARGBtoI420Converter(test_config_.width, test_config_.height,
322 GetWorkingDir().Append(kCapturedYuvFileName)));
323
324 ASSERT_TRUE(CompareVideosAndPrintResult(
325 MakeLabel(test_config_.test_name, video_codec), test_config_.width,
326 test_config_.height, GetWorkingDir().Append(kCapturedYuvFileName),
327 test::GetReferenceFilesDir()
328 .Append(test_config_.reference_video)
329 .AddExtension(test::kYuvFileExtension),
330 GetWorkingDir().Append(kStatsFileName)));
331 }
332
333 protected:
334 VideoQualityTestConfig test_config_;
335
336 base::FilePath GetWorkingDir() { return temp_working_dir_.path(); }
337
338 private:
339 base::FilePath GetSourceDir() {
340 base::FilePath source_dir;
341 PathService::Get(base::DIR_SOURCE_ROOT, &source_dir);
342 return source_dir;
343 }
344
345 base::FilePath GetBrowserDir() {
346 base::FilePath browser_dir;
347 EXPECT_TRUE(PathService::Get(base::DIR_MODULE, &browser_dir));
348 return browser_dir;
349 }
350
351 scoped_ptr<base::Environment> environment_;
352 base::FilePath webrtc_reference_video_y4m_;
353 base::ScopedTempDir temp_working_dir_;
354 };
355
356 INSTANTIATE_TEST_CASE_P(
357 WebRtcVideoQualityBrowserTests,
358 WebRtcVideoQualityBrowserTest,
359 testing::ValuesIn(kVideoConfigurations));
360
361 // The video codec name is now appended to the test label (e.g. '720p_VP8').
362 // TODO(asapersson): Keep test below using the default video codec (which do
363 // not have the codec name appended ('720p')) until new tests have been
364 // running for some time.
365 IN_PROC_BROWSER_TEST_P(WebRtcVideoQualityBrowserTest,
366 MANUAL_TestVideoQualityDefault) {
367 TestVideoQuality("");
368 }
369
370 IN_PROC_BROWSER_TEST_P(WebRtcVideoQualityBrowserTest,
371 MANUAL_TestVideoQualityVp8) {
372 TestVideoQuality("VP8");
373 }
374
375 IN_PROC_BROWSER_TEST_P(WebRtcVideoQualityBrowserTest,
376 MANUAL_TestVideoQualityVp9) {
377 TestVideoQuality("VP9");
378 }
379
380 #if BUILDFLAG(RTC_USE_H264)
381
382 IN_PROC_BROWSER_TEST_P(WebRtcVideoQualityBrowserTest,
383 MANUAL_TestVideoQualityH264) {
384 // Only run test if run-time feature corresponding to |rtc_use_h264| is on.
385 if (!base::FeatureList::IsEnabled(content::kWebRtcH264WithOpenH264FFmpeg)) {
386 LOG(WARNING) << "Run-time feature WebRTC-H264WithOpenH264FFmpeg disabled. "
387 "Skipping WebRtcVideoQualityBrowserTest.MANUAL_TestVideoQualityH264 "
388 "(test \"OK\")";
389 return;
390 }
391 TestVideoQuality("H264");
392 }
393
394 #endif // BUILDFLAG(RTC_USE_H264)
OLDNEW
« no previous file with comments | « chrome/browser/media/chrome_webrtc_simulcast_browsertest.cc ('k') | chrome/browser/media/chrome_webrtc_webcam_browsertest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698