Chromium Code Reviews| 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|. |
|
phoglund_chromium
2013/09/12 07:32:10
Add a comment which describes how the output gets
kjellander_chromium
2013/09/12 09:02:36
I agree with both, updated.
| |
| 268 bool CompareVideos(int width, | 268 bool CompareVideos(int width, |
| 269 int height, | 269 int height, |
| 270 const base::FilePath& captured_video_filename, | 270 const base::FilePath& captured_video_filename, |
| 271 const base::FilePath& reference_video_filename, | 271 const base::FilePath& reference_video_filename, |
| 272 const base::FilePath& stats_file, | 272 const base::FilePath& stats_file) { |
| 273 std::string* result) { | |
| 274 | 273 |
| 275 base::FilePath path_to_analyzer = base::MakeAbsoluteFilePath( | 274 base::FilePath path_to_analyzer = base::MakeAbsoluteFilePath( |
| 276 GetBrowserDir().Append(kFrameAnalyzerExecutable)); | 275 GetBrowserDir().Append(kFrameAnalyzerExecutable)); |
| 277 base::FilePath path_to_compare_script = GetSourceDir().Append( | 276 base::FilePath path_to_compare_script = GetSourceDir().Append( |
| 278 FILE_PATH_LITERAL("third_party/webrtc/tools/compare_videos.py")); | 277 FILE_PATH_LITERAL("third_party/webrtc/tools/compare_videos.py")); |
| 279 | 278 |
| 280 if (!base::PathExists(path_to_analyzer)) { | 279 if (!base::PathExists(path_to_analyzer)) { |
| 281 LOG(ERROR) << "Missing frame analyzer: should be in " | 280 LOG(ERROR) << "Missing frame analyzer: should be in " |
| 282 << path_to_analyzer.value(); | 281 << path_to_analyzer.value(); |
| 283 return false; | 282 return false; |
| 284 } | 283 } |
| 285 if (!base::PathExists(path_to_compare_script)) { | 284 if (!base::PathExists(path_to_compare_script)) { |
| 286 LOG(ERROR) << "Missing video compare script: should be in " | 285 LOG(ERROR) << "Missing video compare script: should be in " |
| 287 << path_to_compare_script.value(); | 286 << path_to_compare_script.value(); |
| 288 return false; | 287 return false; |
| 289 } | 288 } |
| 290 | 289 |
| 291 // Note: don't append switches to this command since it will mess up the | 290 // Note: don't append switches to this command since it will mess up the |
| 292 // -u in the python invocation! | 291 // -u in the python invocation! |
| 293 CommandLine compare_command(CommandLine::NO_PROGRAM); | 292 CommandLine compare_command(CommandLine::NO_PROGRAM); |
| 294 EXPECT_TRUE(GetPythonCommand(&compare_command)); | 293 EXPECT_TRUE(GetPythonCommand(&compare_command)); |
| 295 | 294 |
| 296 compare_command.AppendArgPath(path_to_compare_script); | 295 compare_command.AppendArgPath(path_to_compare_script); |
| 296 compare_command.AppendArg("--label=VGA"); | |
|
kjellander_chromium
2013/09/11 15:30:58
This is a new argument for the script, preparing f
| |
| 297 compare_command.AppendArg("--ref_video"); | 297 compare_command.AppendArg("--ref_video"); |
| 298 compare_command.AppendArgPath(reference_video_filename); | 298 compare_command.AppendArgPath(reference_video_filename); |
| 299 compare_command.AppendArg("--test_video"); | 299 compare_command.AppendArg("--test_video"); |
| 300 compare_command.AppendArgPath(captured_video_filename); | 300 compare_command.AppendArgPath(captured_video_filename); |
| 301 compare_command.AppendArg("--frame_analyzer"); | 301 compare_command.AppendArg("--frame_analyzer"); |
| 302 compare_command.AppendArgPath(path_to_analyzer); | 302 compare_command.AppendArgPath(path_to_analyzer); |
| 303 compare_command.AppendArg("--yuv_frame_width"); | 303 compare_command.AppendArg("--yuv_frame_width"); |
| 304 compare_command.AppendArg(base::StringPrintf("%d", width)); | 304 compare_command.AppendArg(base::StringPrintf("%d", width)); |
| 305 compare_command.AppendArg("--yuv_frame_height"); | 305 compare_command.AppendArg("--yuv_frame_height"); |
| 306 compare_command.AppendArg(base::StringPrintf("%d", height)); | 306 compare_command.AppendArg(base::StringPrintf("%d", height)); |
| 307 compare_command.AppendArg("--stats_file"); | 307 compare_command.AppendArg("--stats_file"); |
| 308 compare_command.AppendArgPath(stats_file); | 308 compare_command.AppendArgPath(stats_file); |
| 309 | 309 |
| 310 LOG(INFO) << "Running " << compare_command.GetCommandLineString(); | 310 LOG(INFO) << "Running " << compare_command.GetCommandLineString(); |
| 311 bool ok = base::GetAppOutput(compare_command, result); | 311 std::string output; |
| 312 LOG(INFO) << "Output was:\n\n" << *result; | 312 bool ok = base::GetAppOutput(compare_command, &output); |
| 313 LOG(INFO) << "Output was:\n\n" << output; | |
|
phoglund_chromium
2013/09/12 07:32:10
Ok, so this LOG(INFO) is what really prints the ou
kjellander_chromium
2013/09/12 09:02:36
Right, there's a ton of other stuff printed before
| |
| 313 return ok; | 314 return ok; |
| 314 } | 315 } |
| 315 | 316 |
| 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() { | 317 base::FilePath GetWorkingDir() { |
| 395 std::string home_dir; | 318 std::string home_dir; |
| 396 environment_->GetVar(kHomeEnvName, &home_dir); | 319 environment_->GetVar(kHomeEnvName, &home_dir); |
| 397 base::FilePath::StringType native_home_dir(home_dir.begin(), | 320 base::FilePath::StringType native_home_dir(home_dir.begin(), |
| 398 home_dir.end()); | 321 home_dir.end()); |
| 399 return base::FilePath(native_home_dir).Append(kWorkingDirName); | 322 return base::FilePath(native_home_dir).Append(kWorkingDirName); |
| 400 } | 323 } |
| 401 | 324 |
| 402 PeerConnectionServerRunner peerconnection_server_; | 325 PeerConnectionServerRunner peerconnection_server_; |
| 403 | 326 |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 460 | 383 |
| 461 AssertNoAsynchronousErrors(left_tab); | 384 AssertNoAsynchronousErrors(left_tab); |
| 462 AssertNoAsynchronousErrors(right_tab); | 385 AssertNoAsynchronousErrors(right_tab); |
| 463 | 386 |
| 464 EXPECT_TRUE(PollingWaitUntil( | 387 EXPECT_TRUE(PollingWaitUntil( |
| 465 "haveMoreFramesToSend()", "no-more-frames", right_tab, | 388 "haveMoreFramesToSend()", "no-more-frames", right_tab, |
| 466 polling_interval_msec)); | 389 polling_interval_msec)); |
| 467 | 390 |
| 468 RunARGBtoI420Converter( | 391 RunARGBtoI420Converter( |
| 469 kVgaWidth, kVgaHeight, GetWorkingDir().Append(kCapturedYuvFileName)); | 392 kVgaWidth, kVgaHeight, GetWorkingDir().Append(kCapturedYuvFileName)); |
| 470 std::string output; | |
| 471 ASSERT_TRUE( | 393 ASSERT_TRUE( |
| 472 CompareVideos(kVgaWidth, | 394 CompareVideos(kVgaWidth, |
| 473 kVgaHeight, | 395 kVgaHeight, |
| 474 GetWorkingDir().Append(kCapturedYuvFileName), | 396 GetWorkingDir().Append(kCapturedYuvFileName), |
| 475 GetWorkingDir().Append(kReferenceYuvFileName), | 397 GetWorkingDir().Append(kReferenceYuvFileName), |
| 476 GetWorkingDir().Append(kStatsFileName), | 398 GetWorkingDir().Append(kStatsFileName))); |
| 477 &output)); | |
| 478 | |
| 479 PrintFramesCountPerfResults(output); | |
| 480 PrintPsnrAndSsimPerfResults(output); | |
| 481 | 399 |
| 482 ASSERT_TRUE(peerconnection_server_.Stop()); | 400 ASSERT_TRUE(peerconnection_server_.Stop()); |
| 483 ASSERT_TRUE(ShutdownPyWebSocketServer()); | 401 ASSERT_TRUE(ShutdownPyWebSocketServer()); |
| 484 } | 402 } |
| OLD | NEW |