Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license | 4 * Use of this source code is governed by a BSD-style license |
| 5 * that can be found in the LICENSE file in the root of the source | 5 * that can be found in the LICENSE file in the root of the source |
| 6 * tree. An additional intellectual property rights grant can be found | 6 * tree. An additional intellectual property rights grant can be found |
| 7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
| 8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
| 9 */ | 9 */ |
| 10 | 10 |
| (...skipping 310 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 321 } | 321 } |
| 322 | 322 |
| 323 void PrintMaxRepeatedAndSkippedFrames(const std::string& label, | 323 void PrintMaxRepeatedAndSkippedFrames(const std::string& label, |
| 324 const std::string& stats_file_ref_name, | 324 const std::string& stats_file_ref_name, |
| 325 const std::string& stats_file_test_name) { | 325 const std::string& stats_file_test_name) { |
| 326 PrintMaxRepeatedAndSkippedFrames(stdout, label, stats_file_ref_name, | 326 PrintMaxRepeatedAndSkippedFrames(stdout, label, stats_file_ref_name, |
| 327 stats_file_test_name); | 327 stats_file_test_name); |
| 328 } | 328 } |
| 329 | 329 |
| 330 namespace { | 330 namespace { |
| 331 // The barcode number that means that the barcode could not be decoded. | |
| 332 const int DECODE_ERROR = -1; | |
| 333 | |
| 331 // Clusters the frames in the file. First in the pair is the frame number and | 334 // Clusters the frames in the file. First in the pair is the frame number and |
| 332 // second is the number | 335 // second is the number |
| 333 // of frames in that cluster. So if first frame in video has number 100 and it | 336 // of frames in that cluster. So if first frame in video has number 100 and it |
| 334 // is repeated 3 after | 337 // is repeated 3 after |
| 335 // each other, then the first entry in the returned vector has first set to 100 | 338 // each other, then the first entry in the returned vector has first set to 100 |
| 336 // and second set | 339 // and second set |
| 337 // to 3. | 340 // to 3. |
|
kjellander_webrtc
2017/02/08 12:39:34
Can you explain in the comment what happens if the
mandermo
2017/02/13 17:04:11
Added comment. Should I move CalculateFrameCluster
kjellander_webrtc
2017/02/14 20:55:58
Please do, I think that'll be very useful in the f
mandermo
2017/02/15 11:52:15
Done. Found I missed +1 when there are decode erro
| |
| 338 std::vector<std::pair<int, int> > CalculateFrameClusters(FILE* file) { | 341 std::vector<std::pair<int, int> > CalculateFrameClusters( |
| 342 FILE* file, | |
| 343 int* num_decode_errors) { | |
| 344 if (num_decode_errors) { | |
| 345 *num_decode_errors = 0; | |
| 346 } | |
| 339 std::vector<std::pair<int, int> > frame_cnt; | 347 std::vector<std::pair<int, int> > frame_cnt; |
| 340 char line[STATS_LINE_LENGTH]; | 348 char line[STATS_LINE_LENGTH]; |
| 341 while (GetNextStatsLine(file, line)) { | 349 while (GetNextStatsLine(file, line)) { |
| 342 int decoded_frame_number = ExtractDecodedFrameNumber(line); | 350 int decoded_frame_number; |
| 343 if (decoded_frame_number == -1) { | 351 if (IsThereBarcodeError(line)) { |
| 344 continue; | 352 decoded_frame_number = DECODE_ERROR; |
| 353 if (num_decode_errors) { | |
| 354 ++*num_decode_errors; | |
| 355 } | |
| 356 } else { | |
| 357 decoded_frame_number = ExtractDecodedFrameNumber(line); | |
| 345 } | 358 } |
| 346 if (frame_cnt.empty() || frame_cnt.back().first != decoded_frame_number) { | 359 if (frame_cnt.size() >= 2 && decoded_frame_number != DECODE_ERROR && |
| 360 frame_cnt.back().first == DECODE_ERROR && | |
| 361 frame_cnt[frame_cnt.size() - 2].first == decoded_frame_number) { | |
| 362 // Handle when there is a decoding error inside a cluster of frames. | |
| 363 frame_cnt[frame_cnt.size() - 2].second += frame_cnt.back().second; | |
| 364 frame_cnt.pop_back(); | |
| 365 } else if (frame_cnt.empty() || | |
| 366 frame_cnt.back().first != decoded_frame_number) { | |
| 347 frame_cnt.push_back(std::make_pair(decoded_frame_number, 1)); | 367 frame_cnt.push_back(std::make_pair(decoded_frame_number, 1)); |
| 348 } else { | 368 } else { |
| 349 ++frame_cnt.back().second; | 369 ++frame_cnt.back().second; |
| 350 } | 370 } |
| 351 } | 371 } |
| 352 return frame_cnt; | 372 return frame_cnt; |
| 353 } | 373 } |
| 354 } // namespace | 374 } // namespace |
| 355 | 375 |
| 356 void PrintMaxRepeatedAndSkippedFrames(FILE* output, | 376 void PrintMaxRepeatedAndSkippedFrames(FILE* output, |
| 357 const std::string& label, | 377 const std::string& label, |
| 358 const std::string& stats_file_ref_name, | 378 const std::string& stats_file_ref_name, |
| 359 const std::string& stats_file_test_name) { | 379 const std::string& stats_file_test_name) { |
| 360 FILE* stats_file_ref = fopen(stats_file_ref_name.c_str(), "r"); | 380 FILE* stats_file_ref = fopen(stats_file_ref_name.c_str(), "r"); |
| 361 FILE* stats_file_test = fopen(stats_file_test_name.c_str(), "r"); | 381 FILE* stats_file_test = fopen(stats_file_test_name.c_str(), "r"); |
| 362 if (stats_file_ref == NULL) { | 382 if (stats_file_ref == NULL) { |
| 363 fprintf(stderr, "Couldn't open reference stats file for reading: %s\n", | 383 fprintf(stderr, "Couldn't open reference stats file for reading: %s\n", |
| 364 stats_file_ref_name.c_str()); | 384 stats_file_ref_name.c_str()); |
| 365 return; | 385 return; |
| 366 } | 386 } |
| 367 if (stats_file_test == NULL) { | 387 if (stats_file_test == NULL) { |
| 368 fprintf(stderr, "Couldn't open test stats file for reading: %s\n", | 388 fprintf(stderr, "Couldn't open test stats file for reading: %s\n", |
| 369 stats_file_test_name.c_str()); | 389 stats_file_test_name.c_str()); |
| 370 fclose(stats_file_ref); | 390 fclose(stats_file_ref); |
| 371 return; | 391 return; |
| 372 } | 392 } |
| 373 | 393 |
| 374 int max_repeated_frames = 1; | 394 int max_repeated_frames = 1; |
|
kjellander_webrtc
2017/02/08 12:39:33
Does max_repeated_frames = 1 as a starting value m
mandermo
2017/02/13 17:04:11
You have a point. Fixing it will change the old be
| |
| 375 int max_skipped_frames = 1; | 395 int max_skipped_frames = 0; |
| 396 | |
| 397 int decode_errors_ref = 0; | |
| 398 int decode_errors_test = 0; | |
| 376 | 399 |
| 377 std::vector<std::pair<int, int> > frame_cnt_ref = | 400 std::vector<std::pair<int, int> > frame_cnt_ref = |
| 378 CalculateFrameClusters(stats_file_ref); | 401 CalculateFrameClusters(stats_file_ref, &decode_errors_ref); |
| 379 | 402 |
| 380 std::vector<std::pair<int, int> > frame_cnt_test = | 403 std::vector<std::pair<int, int> > frame_cnt_test = |
| 381 CalculateFrameClusters(stats_file_test); | 404 CalculateFrameClusters(stats_file_test, &decode_errors_test); |
| 382 | 405 |
| 383 fclose(stats_file_ref); | 406 fclose(stats_file_ref); |
| 384 fclose(stats_file_test); | 407 fclose(stats_file_test); |
| 385 | 408 |
| 386 auto it_ref = frame_cnt_ref.begin(); | 409 auto it_ref = frame_cnt_ref.begin(); |
| 387 auto it_test = frame_cnt_test.begin(); | 410 auto it_test = frame_cnt_test.begin(); |
| 388 auto end_ref = frame_cnt_ref.end(); | 411 auto end_ref = frame_cnt_ref.end(); |
| 389 auto end_test = frame_cnt_test.end(); | 412 auto end_test = frame_cnt_test.end(); |
| 390 | 413 |
| 391 if (it_test == end_test || it_ref == end_ref) { | 414 if (it_test == end_test || it_ref == end_ref) { |
| 392 fprintf(stderr, "Either test or ref file is empty, nothing to print\n"); | 415 fprintf(stderr, "Either test or ref file is empty, nothing to print\n"); |
| 393 return; | 416 return; |
| 394 } | 417 } |
| 395 | 418 |
| 419 while (it_test != end_test && it_test->first == DECODE_ERROR) { | |
| 420 ++it_test; | |
| 421 } | |
| 422 | |
| 423 if (it_test == end_test) { | |
| 424 fprintf(stderr, "Test video only has barcode decode errors\n"); | |
| 425 return; | |
| 426 } | |
| 427 | |
| 396 // Find the first frame in the reference video that match the first frame in | 428 // Find the first frame in the reference video that match the first frame in |
| 397 // the test video. | 429 // the test video. |
| 398 while (it_ref != end_ref && it_ref->first != it_test->first) { | 430 while (it_ref != end_ref && |
| 431 (it_ref->first == DECODE_ERROR || it_ref->first != it_test->first)) { | |
| 399 ++it_ref; | 432 ++it_ref; |
| 400 } | 433 } |
| 401 if (it_ref == end_ref) { | 434 if (it_ref == end_ref) { |
| 402 fprintf(stderr, | 435 fprintf(stderr, |
| 403 "The barcode in the test video's first frame is not in the " | 436 "The barcode in the test video's first frame is not in the " |
| 404 "reference video.\n"); | 437 "reference video.\n"); |
| 405 return; | 438 return; |
| 406 } | 439 } |
| 407 | 440 |
| 441 // The test frames that does not have corresponding barcode in the reference | |
|
kjellander_webrtc
2017/02/08 12:39:33
Do we have proof that this ever happens? If not I
mandermo
2017/02/13 17:04:11
Have removed that code and print an error instead
| |
| 442 // video. | |
| 443 std::vector<int> no_match_in_ref; | |
| 444 | |
| 445 int total_skipped = 0; | |
| 408 for (;;) { | 446 for (;;) { |
| 409 max_repeated_frames = | 447 max_repeated_frames = |
| 410 std::max(max_repeated_frames, it_test->second - it_ref->second + 1); | 448 std::max(max_repeated_frames, it_test->second - it_ref->second + 1); |
| 449 | |
| 450 bool passed_error = false; | |
| 451 | |
| 411 ++it_test; | 452 ++it_test; |
| 453 while (it_test != end_test && it_test->first == DECODE_ERROR) { | |
| 454 ++it_test; | |
| 455 passed_error = true; | |
| 456 } | |
| 412 if (it_test == end_test) { | 457 if (it_test == end_test) { |
| 413 break; | 458 break; |
| 414 } | 459 } |
| 460 | |
| 415 int skipped_frames = 0; | 461 int skipped_frames = 0; |
| 416 ++it_ref; | 462 ++it_ref; |
| 417 while (it_ref != end_ref && it_ref->first != it_test->first) { | 463 for (; it_ref != end_ref; ++it_ref) { |
| 418 skipped_frames += it_ref->second; | 464 if (it_ref->first != DECODE_ERROR && it_ref->first >= it_test->first) { |
| 419 ++it_ref; | 465 break; |
| 466 } | |
| 467 ++skipped_frames; | |
| 420 } | 468 } |
| 469 if (passed_error) { | |
| 470 // If we pass an error in the test video, then we are conservative | |
| 471 // and will not calculate skipped frames for that part. | |
| 472 skipped_frames = 0; | |
| 473 } | |
| 474 if (it_ref != end_ref && it_ref->first == it_test->first) { | |
| 475 total_skipped += skipped_frames; | |
| 476 if (skipped_frames > max_skipped_frames) { | |
| 477 max_skipped_frames = skipped_frames; | |
| 478 } | |
| 479 continue; | |
| 480 } | |
| 481 no_match_in_ref.push_back(it_test->first); | |
| 421 if (it_ref == end_ref) { | 482 if (it_ref == end_ref) { |
| 422 fprintf(stderr, | 483 break; |
| 423 "The barcode in the test video is not in the reference video.\n"); | 484 } else { |
| 424 return; | 485 --it_ref; |
| 425 } | |
| 426 if (skipped_frames > max_skipped_frames) { | |
| 427 max_skipped_frames = skipped_frames; | |
| 428 } | 486 } |
| 429 } | 487 } |
| 430 | 488 |
| 431 fprintf(output, "RESULT Max_repeated: %s= %d\n", label.c_str(), | 489 fprintf(output, "RESULT Max_repeated: %s= %d\n", label.c_str(), |
| 432 max_repeated_frames); | 490 max_repeated_frames); |
| 433 fprintf(output, "RESULT Max_skipped: %s= %d\n", label.c_str(), | 491 fprintf(output, "RESULT Max_skipped: %s= %d\n", label.c_str(), |
| 434 max_skipped_frames); | 492 max_skipped_frames); |
| 493 fprintf(output, "RESULT Total_skipped: %s= %d\n", label.c_str(), | |
| 494 total_skipped); | |
|
kjellander_webrtc
2017/02/08 12:39:33
Seeing this, I'd like to have total_repeated_frame
kjellander_webrtc
2017/02/08 12:39:33
Name this variable total_skipped_frames to be cons
mandermo
2017/02/13 17:04:11
I don't think such a value provide any meaningful
mandermo
2017/02/13 17:04:11
Done.
kjellander_webrtc
2017/02/14 20:55:58
Why not? If we have periodic freezes, let's say ev
mandermo
2017/02/15 11:52:15
Lets fix it in a follow up CL where we initialize
| |
| 495 fprintf(output, "RESULT Decode_errors_reference: %s= %d\n", label.c_str(), | |
| 496 decode_errors_ref); | |
| 497 fprintf(output, "RESULT Decode_errors_test: %s= %d\n", label.c_str(), | |
| 498 decode_errors_test); | |
| 499 fprintf(output, "RESULT No_matched: ["); | |
|
kjellander_webrtc
2017/02/08 12:39:34
This is not suitable as a perf number. The perf da
mandermo
2017/02/13 17:04:11
Done.
| |
| 500 for (std::size_t i = 0; i < no_match_in_ref.size(); ++i) { | |
| 501 if (i > 0) { | |
| 502 fprintf(output, ", "); | |
| 503 } | |
| 504 fprintf(output, "%d", no_match_in_ref[i]); | |
| 505 } | |
| 506 fprintf(output, "]\n"); | |
| 435 } | 507 } |
| 436 | 508 |
| 437 void PrintAnalysisResults(const std::string& label, ResultsContainer* results) { | 509 void PrintAnalysisResults(const std::string& label, ResultsContainer* results) { |
| 438 PrintAnalysisResults(stdout, label, results); | 510 PrintAnalysisResults(stdout, label, results); |
| 439 } | 511 } |
| 440 | 512 |
| 441 void PrintAnalysisResults(FILE* output, const std::string& label, | 513 void PrintAnalysisResults(FILE* output, const std::string& label, |
| 442 ResultsContainer* results) { | 514 ResultsContainer* results) { |
| 443 std::vector<AnalysisResult>::iterator iter; | 515 std::vector<AnalysisResult>::iterator iter; |
| 444 | 516 |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 457 for (iter = results->frames.begin(); iter != results->frames.end() - 1; | 529 for (iter = results->frames.begin(); iter != results->frames.end() - 1; |
| 458 ++iter) { | 530 ++iter) { |
| 459 fprintf(output, "%f,", iter->ssim_value); | 531 fprintf(output, "%f,", iter->ssim_value); |
| 460 } | 532 } |
| 461 fprintf(output, "%f] score\n", iter->ssim_value); | 533 fprintf(output, "%f] score\n", iter->ssim_value); |
| 462 } | 534 } |
| 463 } | 535 } |
| 464 | 536 |
| 465 } // namespace test | 537 } // namespace test |
| 466 } // namespace webrtc | 538 } // namespace webrtc |
| OLD | NEW |