| 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 by the |
| 316 // buildbot step. |
| 317 printf("Output was:\n\n%s\n", output.c_str()); |
| 313 return ok; | 318 return ok; |
| 314 } | 319 } |
| 315 | 320 |
| 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() { | 321 base::FilePath GetWorkingDir() { |
| 395 std::string home_dir; | 322 std::string home_dir; |
| 396 environment_->GetVar(kHomeEnvName, &home_dir); | 323 environment_->GetVar(kHomeEnvName, &home_dir); |
| 397 base::FilePath::StringType native_home_dir(home_dir.begin(), | 324 base::FilePath::StringType native_home_dir(home_dir.begin(), |
| 398 home_dir.end()); | 325 home_dir.end()); |
| 399 return base::FilePath(native_home_dir).Append(kWorkingDirName); | 326 return base::FilePath(native_home_dir).Append(kWorkingDirName); |
| 400 } | 327 } |
| 401 | 328 |
| 402 PeerConnectionServerRunner peerconnection_server_; | 329 PeerConnectionServerRunner peerconnection_server_; |
| 403 | 330 |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 460 | 387 |
| 461 AssertNoAsynchronousErrors(left_tab); | 388 AssertNoAsynchronousErrors(left_tab); |
| 462 AssertNoAsynchronousErrors(right_tab); | 389 AssertNoAsynchronousErrors(right_tab); |
| 463 | 390 |
| 464 EXPECT_TRUE(PollingWaitUntil( | 391 EXPECT_TRUE(PollingWaitUntil( |
| 465 "haveMoreFramesToSend()", "no-more-frames", right_tab, | 392 "haveMoreFramesToSend()", "no-more-frames", right_tab, |
| 466 polling_interval_msec)); | 393 polling_interval_msec)); |
| 467 | 394 |
| 468 RunARGBtoI420Converter( | 395 RunARGBtoI420Converter( |
| 469 kVgaWidth, kVgaHeight, GetWorkingDir().Append(kCapturedYuvFileName)); | 396 kVgaWidth, kVgaHeight, GetWorkingDir().Append(kCapturedYuvFileName)); |
| 470 std::string output; | |
| 471 ASSERT_TRUE( | 397 ASSERT_TRUE( |
| 472 CompareVideos(kVgaWidth, | 398 CompareVideosAndPrintResult(kVgaWidth, |
| 473 kVgaHeight, | 399 kVgaHeight, |
| 474 GetWorkingDir().Append(kCapturedYuvFileName), | 400 GetWorkingDir().Append(kCapturedYuvFileName), |
| 475 GetWorkingDir().Append(kReferenceYuvFileName), | 401 GetWorkingDir().Append(kReferenceYuvFileName), |
| 476 GetWorkingDir().Append(kStatsFileName), | 402 GetWorkingDir().Append(kStatsFileName))); |
| 477 &output)); | |
| 478 | |
| 479 PrintFramesCountPerfResults(output); | |
| 480 PrintPsnrAndSsimPerfResults(output); | |
| 481 | 403 |
| 482 ASSERT_TRUE(peerconnection_server_.Stop()); | 404 ASSERT_TRUE(peerconnection_server_.Stop()); |
| 483 ASSERT_TRUE(ShutdownPyWebSocketServer()); | 405 ASSERT_TRUE(ShutdownPyWebSocketServer()); |
| 484 } | 406 } |
| OLD | NEW |