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 246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
257 LOG(INFO) << "Output was:\n\n" << result; | 257 LOG(INFO) << "Output was:\n\n" << result; |
258 return ok; | 258 return ok; |
259 } | 259 } |
260 | 260 |
261 // Compares the |captured_video_filename| with the |reference_video_filename|. | 261 // Compares the |captured_video_filename| with the |reference_video_filename|. |
262 // | 262 // |
263 // The barcode decoder decodes the captured video containing barcodes overlaid | 263 // The barcode decoder decodes the captured video containing barcodes overlaid |
264 // into every frame of the video (produced by rgba_to_i420_converter). It | 264 // into every frame of the video (produced by rgba_to_i420_converter). It |
265 // produces a set of PNG images and a |stats_file| that maps each captured | 265 // produces a set of PNG images and a |stats_file| that maps each captured |
266 // frame to a frame in the reference video. The frames should be of size | 266 // frame to a frame in the reference video. The frames should be of size |
267 // |width| x |height|. The output of compare_videos.py is returned. | 267 // |width| x |height|. |
268 bool CompareVideos(int width, | 268 // All measurements calculated are printed as perf parsable numbers to stdout. |
269 int height, | 269 bool CompareVideosAndPrintResult( |
270 const base::FilePath& captured_video_filename, | 270 int width, |
271 const base::FilePath& reference_video_filename, | 271 int height, |
272 const base::FilePath& stats_file, | 272 const base::FilePath& captured_video_filename, |
273 std::string* result) { | 273 const base::FilePath& reference_video_filename, |
274 const base::FilePath& stats_file) { | |
274 | 275 |
275 base::FilePath path_to_analyzer = base::MakeAbsoluteFilePath( | 276 base::FilePath path_to_analyzer = base::MakeAbsoluteFilePath( |
276 GetBrowserDir().Append(kFrameAnalyzerExecutable)); | 277 GetBrowserDir().Append(kFrameAnalyzerExecutable)); |
277 base::FilePath path_to_compare_script = GetSourceDir().Append( | 278 base::FilePath path_to_compare_script = GetSourceDir().Append( |
278 FILE_PATH_LITERAL("third_party/webrtc/tools/compare_videos.py")); | 279 FILE_PATH_LITERAL("third_party/webrtc/tools/compare_videos.py")); |
279 | 280 |
280 if (!base::PathExists(path_to_analyzer)) { | 281 if (!base::PathExists(path_to_analyzer)) { |
281 LOG(ERROR) << "Missing frame analyzer: should be in " | 282 LOG(ERROR) << "Missing frame analyzer: should be in " |
282 << path_to_analyzer.value(); | 283 << path_to_analyzer.value(); |
283 return false; | 284 return false; |
284 } | 285 } |
285 if (!base::PathExists(path_to_compare_script)) { | 286 if (!base::PathExists(path_to_compare_script)) { |
286 LOG(ERROR) << "Missing video compare script: should be in " | 287 LOG(ERROR) << "Missing video compare script: should be in " |
287 << path_to_compare_script.value(); | 288 << path_to_compare_script.value(); |
288 return false; | 289 return false; |
289 } | 290 } |
290 | 291 |
291 // Note: don't append switches to this command since it will mess up the | 292 // Note: don't append switches to this command since it will mess up the |
292 // -u in the python invocation! | 293 // -u in the python invocation! |
293 CommandLine compare_command(CommandLine::NO_PROGRAM); | 294 CommandLine compare_command(CommandLine::NO_PROGRAM); |
294 EXPECT_TRUE(GetPythonCommand(&compare_command)); | 295 EXPECT_TRUE(GetPythonCommand(&compare_command)); |
295 | 296 |
296 compare_command.AppendArgPath(path_to_compare_script); | 297 compare_command.AppendArgPath(path_to_compare_script); |
298 compare_command.AppendArg("--label=VGA"); | |
297 compare_command.AppendArg("--ref_video"); | 299 compare_command.AppendArg("--ref_video"); |
298 compare_command.AppendArgPath(reference_video_filename); | 300 compare_command.AppendArgPath(reference_video_filename); |
299 compare_command.AppendArg("--test_video"); | 301 compare_command.AppendArg("--test_video"); |
300 compare_command.AppendArgPath(captured_video_filename); | 302 compare_command.AppendArgPath(captured_video_filename); |
301 compare_command.AppendArg("--frame_analyzer"); | 303 compare_command.AppendArg("--frame_analyzer"); |
302 compare_command.AppendArgPath(path_to_analyzer); | 304 compare_command.AppendArgPath(path_to_analyzer); |
303 compare_command.AppendArg("--yuv_frame_width"); | 305 compare_command.AppendArg("--yuv_frame_width"); |
304 compare_command.AppendArg(base::StringPrintf("%d", width)); | 306 compare_command.AppendArg(base::StringPrintf("%d", width)); |
305 compare_command.AppendArg("--yuv_frame_height"); | 307 compare_command.AppendArg("--yuv_frame_height"); |
306 compare_command.AppendArg(base::StringPrintf("%d", height)); | 308 compare_command.AppendArg(base::StringPrintf("%d", height)); |
307 compare_command.AppendArg("--stats_file"); | 309 compare_command.AppendArg("--stats_file"); |
308 compare_command.AppendArgPath(stats_file); | 310 compare_command.AppendArgPath(stats_file); |
309 | 311 |
310 LOG(INFO) << "Running " << compare_command.GetCommandLineString(); | 312 LOG(INFO) << "Running " << compare_command.GetCommandLineString(); |
311 bool ok = base::GetAppOutput(compare_command, result); | 313 std::string output; |
312 LOG(INFO) << "Output was:\n\n" << *result; | 314 bool ok = base::GetAppOutput(compare_command, &output); |
315 // Print to stdout to ensure the perf numbers are parsed properly. | |
phoglund_chromium
2013/09/12 09:17:59
... by the buildbot step.
kjellander_chromium
2013/09/12 11:10:52
Done.
| |
316 std::cout << "Output was:\n\n" << output; | |
phoglund_chromium
2013/09/12 09:17:59
Style guide says: use fprintf or printf here.
kjellander_chromium
2013/09/12 11:10:52
Done.
| |
313 return ok; | 317 return ok; |
314 } | 318 } |
315 | 319 |
316 // Processes the |frame_analyzer_output| for the different frame counts. | |
317 // | |
318 // The frame analyzer outputs additional information about the number of | |
319 // unique frames captured, The max number of repeated frames in a sequence and | |
320 // the max number of skipped frames. These values are then written to the Perf | |
321 // Graph. (Note: Some of the repeated or skipped frames will probably be due | |
322 // to the imperfection of JavaScript timers). | |
323 void PrintFramesCountPerfResults(std::string frame_analyzer_output) { | |
324 size_t unique_frames_pos = | |
325 frame_analyzer_output.rfind("Unique_frames_count"); | |
326 EXPECT_NE(unique_frames_pos, std::string::npos) | |
327 << "Missing Unique_frames_count in frame analyzer output:\n" | |
328 << frame_analyzer_output; | |
329 | |
330 std::string unique_frame_counts = | |
331 frame_analyzer_output.substr(unique_frames_pos); | |
332 // TODO(phoglund): Fix ESTATS result to not have this silly newline. | |
333 std::replace( | |
334 unique_frame_counts.begin(), unique_frame_counts.end(), '\n', ' '); | |
335 | |
336 std::vector<std::pair<std::string, std::string> > key_values; | |
337 base::SplitStringIntoKeyValuePairs( | |
338 unique_frame_counts, ':', ' ', &key_values); | |
339 std::vector<std::pair<std::string, std::string> >::const_iterator iter; | |
340 for (iter = key_values.begin(); iter != key_values.end(); ++iter) { | |
341 const std::pair<std::string, std::string>& key_value = *iter; | |
342 perf_test::PrintResult( | |
343 key_value.first, "", "VGA", key_value.second, "", false); | |
344 } | |
345 } | |
346 | |
347 // Processes the |frame_analyzer_output| to extract the PSNR and SSIM values. | |
348 // | |
349 // The frame analyzer produces PSNR and SSIM results for every unique frame | |
350 // that has been captured. This method forms a list of all the psnr and ssim | |
351 // values and passes it to PrintResultList() for printing on the Perf Graph. | |
352 void PrintPsnrAndSsimPerfResults(std::string frame_analyzer_output) { | |
353 size_t stats_start = frame_analyzer_output.find("BSTATS"); | |
354 EXPECT_NE(stats_start, std::string::npos) | |
355 << "Missing BSTATS in frame analyzer output:\n" | |
356 << frame_analyzer_output; | |
357 size_t stats_end = frame_analyzer_output.find("ESTATS"); | |
358 EXPECT_NE(stats_end, std::string::npos) | |
359 << "Missing ESTATS in frame analyzer output:\n" | |
360 << frame_analyzer_output; | |
361 | |
362 stats_start += std::string("BSTATS").size(); | |
363 std::string psnr_ssim_stats = | |
364 frame_analyzer_output.substr(stats_start, stats_end - stats_start); | |
365 | |
366 // PSNR and SSIM values aren't really key-value pairs but it is convenient | |
367 // to parse them as such. | |
368 // TODO(phoglund): make the format more convenient so we need less | |
369 // processing here. | |
370 std::vector<std::pair<std::string, std::string> > psnr_ssim_entries; | |
371 base::SplitStringIntoKeyValuePairs( | |
372 psnr_ssim_stats, ' ', ';', &psnr_ssim_entries); | |
373 | |
374 std::string psnr_value_list; | |
375 std::string ssim_value_list; | |
376 std::vector<std::pair<std::string, std::string> >::const_iterator iter; | |
377 for (iter = psnr_ssim_entries.begin(); iter != psnr_ssim_entries.end(); | |
378 ++iter) { | |
379 const std::pair<std::string, std::string>& psnr_and_ssim = *iter; | |
380 psnr_value_list.append(psnr_and_ssim.first).append(","); | |
381 ssim_value_list.append(psnr_and_ssim.second).append(","); | |
382 } | |
383 | |
384 // Nuke last comma. | |
385 ASSERT_GT(psnr_value_list.size(), 0u) << "Received no valid PSNR values."; | |
386 ASSERT_GT(ssim_value_list.size(), 0u) << "Received no valid SSIM values."; | |
387 psnr_value_list.erase(psnr_value_list.size() - 1); | |
388 ssim_value_list.erase(ssim_value_list.size() - 1); | |
389 | |
390 perf_test::PrintResultList("PSNR", "", "VGA", psnr_value_list, "dB", false); | |
391 perf_test::PrintResultList("SSIM", "", "VGA", ssim_value_list, "", false); | |
392 } | |
393 | |
394 base::FilePath GetWorkingDir() { | 320 base::FilePath GetWorkingDir() { |
395 std::string home_dir; | 321 std::string home_dir; |
396 environment_->GetVar(kHomeEnvName, &home_dir); | 322 environment_->GetVar(kHomeEnvName, &home_dir); |
397 base::FilePath::StringType native_home_dir(home_dir.begin(), | 323 base::FilePath::StringType native_home_dir(home_dir.begin(), |
398 home_dir.end()); | 324 home_dir.end()); |
399 return base::FilePath(native_home_dir).Append(kWorkingDirName); | 325 return base::FilePath(native_home_dir).Append(kWorkingDirName); |
400 } | 326 } |
401 | 327 |
402 PeerConnectionServerRunner peerconnection_server_; | 328 PeerConnectionServerRunner peerconnection_server_; |
403 | 329 |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
460 | 386 |
461 AssertNoAsynchronousErrors(left_tab); | 387 AssertNoAsynchronousErrors(left_tab); |
462 AssertNoAsynchronousErrors(right_tab); | 388 AssertNoAsynchronousErrors(right_tab); |
463 | 389 |
464 EXPECT_TRUE(PollingWaitUntil( | 390 EXPECT_TRUE(PollingWaitUntil( |
465 "haveMoreFramesToSend()", "no-more-frames", right_tab, | 391 "haveMoreFramesToSend()", "no-more-frames", right_tab, |
466 polling_interval_msec)); | 392 polling_interval_msec)); |
467 | 393 |
468 RunARGBtoI420Converter( | 394 RunARGBtoI420Converter( |
469 kVgaWidth, kVgaHeight, GetWorkingDir().Append(kCapturedYuvFileName)); | 395 kVgaWidth, kVgaHeight, GetWorkingDir().Append(kCapturedYuvFileName)); |
470 std::string output; | |
471 ASSERT_TRUE( | 396 ASSERT_TRUE( |
472 CompareVideos(kVgaWidth, | 397 CompareVideosAndPrintResult(kVgaWidth, |
473 kVgaHeight, | 398 kVgaHeight, |
474 GetWorkingDir().Append(kCapturedYuvFileName), | 399 GetWorkingDir().Append(kCapturedYuvFileName), |
475 GetWorkingDir().Append(kReferenceYuvFileName), | 400 GetWorkingDir().Append(kReferenceYuvFileName), |
476 GetWorkingDir().Append(kStatsFileName), | 401 GetWorkingDir().Append(kStatsFileName))); |
477 &output)); | |
478 | |
479 PrintFramesCountPerfResults(output); | |
480 PrintPsnrAndSsimPerfResults(output); | |
481 | 402 |
482 ASSERT_TRUE(peerconnection_server_.Stop()); | 403 ASSERT_TRUE(peerconnection_server_.Stop()); |
483 ASSERT_TRUE(ShutdownPyWebSocketServer()); | 404 ASSERT_TRUE(ShutdownPyWebSocketServer()); |
484 } | 405 } |
OLD | NEW |