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

Side by Side Diff: webrtc/tools/frame_analyzer/video_quality_analysis.cc

Issue 2666333003: Better comparison for frame analyzer (Closed)
Patch Set: Better handling of decoding errors Created 3 years, 10 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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698