| Index: webrtc/tools/frame_analyzer/video_quality_analysis.cc
 | 
| diff --git a/webrtc/tools/frame_analyzer/video_quality_analysis.cc b/webrtc/tools/frame_analyzer/video_quality_analysis.cc
 | 
| index c1911ca81c7033e3e063d11338f5d5461d674f18..dfb7d900657540ca87adc6e38e79b143a721abe6 100644
 | 
| --- a/webrtc/tools/frame_analyzer/video_quality_analysis.cc
 | 
| +++ b/webrtc/tools/frame_analyzer/video_quality_analysis.cc
 | 
| @@ -13,7 +13,10 @@
 | 
|  #include <assert.h>
 | 
|  #include <stdio.h>
 | 
|  #include <stdlib.h>
 | 
| +#include <algorithm>
 | 
|  #include <string>
 | 
| +#include <map>
 | 
| +#include <utility>
 | 
|  
 | 
|  #define STATS_LINE_LENGTH 32
 | 
|  #define Y4M_FILE_HEADER_MAX_SIZE 200
 | 
| @@ -224,8 +227,12 @@ double CalculateMetrics(VideoAnalysisMetricsType video_metrics_type,
 | 
|    return result;
 | 
|  }
 | 
|  
 | 
| -void RunAnalysis(const char* reference_file_name, const char* test_file_name,
 | 
| -                 const char* stats_file_name, int width, int height,
 | 
| +void RunAnalysis(const char* reference_file_name,
 | 
| +                 const char* test_file_name,
 | 
| +                 const char* stats_file_reference_name,
 | 
| +                 const char* stats_file_test_name,
 | 
| +                 int width,
 | 
| +                 int height,
 | 
|                   ResultsContainer* results) {
 | 
|    // Check if the reference_file_name ends with "y4m".
 | 
|    bool y4m_mode = false;
 | 
| @@ -234,7 +241,8 @@ void RunAnalysis(const char* reference_file_name, const char* test_file_name,
 | 
|    }
 | 
|  
 | 
|    int size = GetI420FrameSize(width, height);
 | 
| -  FILE* stats_file = fopen(stats_file_name, "r");
 | 
| +  FILE* stats_file_ref = fopen(stats_file_reference_name, "r");
 | 
| +  FILE* stats_file_test = fopen(stats_file_test_name, "r");
 | 
|  
 | 
|    // String buffer for the lines in the stats file.
 | 
|    char line[STATS_LINE_LENGTH];
 | 
| @@ -244,10 +252,29 @@ void RunAnalysis(const char* reference_file_name, const char* test_file_name,
 | 
|    uint8_t* reference_frame = new uint8_t[size];
 | 
|    int previous_frame_number = -1;
 | 
|  
 | 
| +  // Maps barcode id to the frame id for the reference video.
 | 
| +  // In case two frames have same id, then we only save the first one.
 | 
| +  std::map<int, int> ref_barcode_to_frame;
 | 
|    // While there are entries in the stats file.
 | 
| -  while (GetNextStatsLine(stats_file, line)) {
 | 
| +  while (GetNextStatsLine(stats_file_ref, line)) {
 | 
| +    int extracted_ref_frame = ExtractFrameSequenceNumber(line);
 | 
| +    int decoded_frame_number = ExtractDecodedFrameNumber(line);
 | 
| +
 | 
| +    // Insert will only add if it is not in map already.
 | 
| +    ref_barcode_to_frame.insert(
 | 
| +        std::make_pair(decoded_frame_number, extracted_ref_frame));
 | 
| +  }
 | 
| +
 | 
| +  while (GetNextStatsLine(stats_file_test, line)) {
 | 
|      int extracted_test_frame = ExtractFrameSequenceNumber(line);
 | 
|      int decoded_frame_number = ExtractDecodedFrameNumber(line);
 | 
| +    auto it = ref_barcode_to_frame.find(decoded_frame_number);
 | 
| +    if (it == ref_barcode_to_frame.end()) {
 | 
| +      // Not found in the reference video.
 | 
| +      // TODO(mandermo) print
 | 
| +      continue;
 | 
| +    }
 | 
| +    int extracted_ref_frame = it->second;
 | 
|  
 | 
|      // If there was problem decoding the barcode in this frame or the frame has
 | 
|      // been duplicated, continue.
 | 
| @@ -263,17 +290,17 @@ void RunAnalysis(const char* reference_file_name, const char* test_file_name,
 | 
|                              test_frame);
 | 
|      if (y4m_mode) {
 | 
|        ExtractFrameFromY4mFile(reference_file_name, width, height,
 | 
| -                              decoded_frame_number, reference_frame);
 | 
| +                              extracted_ref_frame, reference_frame);
 | 
|      } else {
 | 
|        ExtractFrameFromYuvFile(reference_file_name, width, height,
 | 
| -                              decoded_frame_number, reference_frame);
 | 
| +                              extracted_ref_frame, reference_frame);
 | 
|      }
 | 
|  
 | 
|      // Calculate the PSNR and SSIM.
 | 
| -    double result_psnr = CalculateMetrics(kPSNR, reference_frame, test_frame,
 | 
| -                                          width, height);
 | 
| -    double result_ssim = CalculateMetrics(kSSIM, reference_frame, test_frame,
 | 
| -                                          width, height);
 | 
| +    double result_psnr =
 | 
| +        CalculateMetrics(kPSNR, reference_frame, test_frame, width, height);
 | 
| +    double result_ssim =
 | 
| +        CalculateMetrics(kSSIM, reference_frame, test_frame, width, height);
 | 
|  
 | 
|      previous_frame_number = decoded_frame_number;
 | 
|  
 | 
| @@ -287,62 +314,124 @@ void RunAnalysis(const char* reference_file_name, const char* test_file_name,
 | 
|    }
 | 
|  
 | 
|    // Cleanup.
 | 
| -  fclose(stats_file);
 | 
| +  fclose(stats_file_ref);
 | 
| +  fclose(stats_file_test);
 | 
|    delete[] test_frame;
 | 
|    delete[] reference_frame;
 | 
|  }
 | 
|  
 | 
|  void PrintMaxRepeatedAndSkippedFrames(const std::string& label,
 | 
| -                                      const std::string& stats_file_name) {
 | 
| -  PrintMaxRepeatedAndSkippedFrames(stdout, label, stats_file_name);
 | 
| +                                      const std::string& stats_file_ref_name,
 | 
| +                                      const std::string& stats_file_test_name) {
 | 
| +  PrintMaxRepeatedAndSkippedFrames(stdout, label, stats_file_ref_name,
 | 
| +                                   stats_file_test_name);
 | 
|  }
 | 
|  
 | 
| -void PrintMaxRepeatedAndSkippedFrames(FILE* output, const std::string& label,
 | 
| -                                      const std::string& stats_file_name) {
 | 
| -  FILE* stats_file = fopen(stats_file_name.c_str(), "r");
 | 
| -  if (stats_file == NULL) {
 | 
| -    fprintf(stderr, "Couldn't open stats file for reading: %s\n",
 | 
| -            stats_file_name.c_str());
 | 
| +namespace {
 | 
| +// Clusters the frames in the file. First in the pair is the frame number and
 | 
| +// second is the number
 | 
| +// of frames in that cluster. So if first frame in video has number 100 and it
 | 
| +// is repeated 3 after
 | 
| +// each other, then the first entry in the returned vector has first set to 100
 | 
| +// and second set
 | 
| +// to 3.
 | 
| +std::vector<std::pair<int, int> > CalculateFrameClusters(FILE* file) {
 | 
| +  std::vector<std::pair<int, int> > frame_cnt;
 | 
| +  char line[STATS_LINE_LENGTH];
 | 
| +  while (GetNextStatsLine(file, line)) {
 | 
| +    int decoded_frame_number = ExtractDecodedFrameNumber(line);
 | 
| +    if (decoded_frame_number == -1) {
 | 
| +      continue;
 | 
| +    }
 | 
| +    if (frame_cnt.empty() || frame_cnt.back().first != decoded_frame_number) {
 | 
| +      frame_cnt.push_back(std::make_pair(decoded_frame_number, 1));
 | 
| +    } else {
 | 
| +      ++frame_cnt.back().second;
 | 
| +    }
 | 
| +  }
 | 
| +  return frame_cnt;
 | 
| +}
 | 
| +}  // namespace
 | 
| +
 | 
| +void PrintMaxRepeatedAndSkippedFrames(FILE* output,
 | 
| +                                      const std::string& label,
 | 
| +                                      const std::string& stats_file_ref_name,
 | 
| +                                      const std::string& stats_file_test_name) {
 | 
| +  FILE* stats_file_ref = fopen(stats_file_ref_name.c_str(), "r");
 | 
| +  FILE* stats_file_test = fopen(stats_file_test_name.c_str(), "r");
 | 
| +  if (stats_file_ref == NULL) {
 | 
| +    fprintf(stderr, "Couldn't open reference stats file for reading: %s\n",
 | 
| +            stats_file_ref_name.c_str());
 | 
| +    return;
 | 
| +  }
 | 
| +  if (stats_file_test == NULL) {
 | 
| +    fprintf(stderr, "Couldn't open test stats file for reading: %s\n",
 | 
| +            stats_file_test_name.c_str());
 | 
| +    fclose(stats_file_ref);
 | 
|      return;
 | 
|    }
 | 
| -  char line[STATS_LINE_LENGTH];
 | 
|  
 | 
| -  int repeated_frames = 1;
 | 
|    int max_repeated_frames = 1;
 | 
|    int max_skipped_frames = 1;
 | 
| -  int previous_frame_number = -1;
 | 
|  
 | 
| -  while (GetNextStatsLine(stats_file, line)) {
 | 
| -    int decoded_frame_number = ExtractDecodedFrameNumber(line);
 | 
| +  std::vector<std::pair<int, int> > frame_cnt_ref =
 | 
| +      CalculateFrameClusters(stats_file_ref);
 | 
|  
 | 
| -    if (decoded_frame_number == -1) {
 | 
| -      continue;
 | 
| -    }
 | 
| +  std::vector<std::pair<int, int> > frame_cnt_test =
 | 
| +      CalculateFrameClusters(stats_file_test);
 | 
|  
 | 
| -    // Calculate how many frames a cluster of repeated frames contains.
 | 
| -    if (decoded_frame_number == previous_frame_number) {
 | 
| -      ++repeated_frames;
 | 
| -      if (repeated_frames > max_repeated_frames) {
 | 
| -        max_repeated_frames = repeated_frames;
 | 
| -      }
 | 
| -    } else {
 | 
| -      repeated_frames = 1;
 | 
| -    }
 | 
| +  fclose(stats_file_ref);
 | 
| +  fclose(stats_file_test);
 | 
|  
 | 
| -    // Calculate how much frames have been skipped.
 | 
| -    if (decoded_frame_number != 0 && previous_frame_number != -1) {
 | 
| -      int skipped_frames = decoded_frame_number - previous_frame_number - 1;
 | 
| -      if (skipped_frames > max_skipped_frames) {
 | 
| -        max_skipped_frames = skipped_frames;
 | 
| -      }
 | 
| +  auto it_ref = frame_cnt_ref.begin();
 | 
| +  auto it_test = frame_cnt_test.begin();
 | 
| +  auto end_ref = frame_cnt_ref.end();
 | 
| +  auto end_test = frame_cnt_test.end();
 | 
| +
 | 
| +  if (it_test == end_test || it_ref == end_ref) {
 | 
| +    fprintf(stderr, "Either test or ref file is empty, nothing to print\n");
 | 
| +    return;
 | 
| +  }
 | 
| +
 | 
| +  // Find the first frame in the reference video that match the first frame in
 | 
| +  // the test video.
 | 
| +  while (it_ref != end_ref && it_ref->first != it_test->first) {
 | 
| +    ++it_ref;
 | 
| +  }
 | 
| +  if (it_ref == end_ref) {
 | 
| +    fprintf(stderr,
 | 
| +            "The barcode in the test video's first frame is not in the "
 | 
| +            "reference video.\n");
 | 
| +    return;
 | 
| +  }
 | 
| +
 | 
| +  for (;;) {
 | 
| +    max_repeated_frames =
 | 
| +        std::max(max_repeated_frames, it_test->second - it_ref->second + 1);
 | 
| +    ++it_test;
 | 
| +    if (it_test == end_test) {
 | 
| +      break;
 | 
| +    }
 | 
| +    int skipped_frames = 0;
 | 
| +    ++it_ref;
 | 
| +    while (it_ref != end_ref && it_ref->first != it_test->first) {
 | 
| +      skipped_frames += it_ref->second;
 | 
| +      ++it_ref;
 | 
| +    }
 | 
| +    if (it_ref == end_ref) {
 | 
| +      fprintf(stderr,
 | 
| +              "The barcode in the test video is not in the reference video.\n");
 | 
| +      return;
 | 
| +    }
 | 
| +    if (skipped_frames > max_skipped_frames) {
 | 
| +      max_skipped_frames = skipped_frames;
 | 
|      }
 | 
| -    previous_frame_number = decoded_frame_number;
 | 
|    }
 | 
| +
 | 
|    fprintf(output, "RESULT Max_repeated: %s= %d\n", label.c_str(),
 | 
|            max_repeated_frames);
 | 
|    fprintf(output, "RESULT Max_skipped: %s= %d\n", label.c_str(),
 | 
|            max_skipped_frames);
 | 
| -  fclose(stats_file);
 | 
|  }
 | 
|  
 | 
|  void PrintAnalysisResults(const std::string& label, ResultsContainer* results) {
 | 
| 
 |