Revert CLs affecting video quality toolchain.

Speculatively fixes Chromium test for cut: crbug.com/877968

Reverts CLs:
https://webrtc-review.googlesource.com/c/src/+/94772
https://webrtc-review.googlesource.com/c/src/+/95648
https://webrtc-review.googlesource.com/c/src/+/94773
https://webrtc-review.googlesource.com/c/src/+/96000
https://webrtc-review.googlesource.com/c/src/+/95949

Revert "Add Y4mFileReader"

This reverts commit 404be7f302358e6be16aadeba8bc8f8aba348c0f.

Revert "Remove SequencedTaskChecker from Y4mFileReader"

This reverts commit 1b5e5db842971340eb9128985ddbaf0225a9d0b1.

Revert "Add tool for aliging video files"

This reverts commit b2c0e8f60fad10e2786e5e131136a0da1299d883.

Revert "Reland "Update video_quality_analysis to align videos instead of using barcodes""

This reverts commit 9bb55fc09b6bfa00cba7779c37ad6c39b4206f7a.

Revert "Fix a bug in barcode_decoder.py"

This reverts commit 5c2de6b3ce079cff52c411a2c02ce6553a38dc79.

TBR=magjed@webrtc.org, phoglund@webrtc.org, phensman@webrtc.org

Bug: chromium:877968, webrtc:9642
Change-Id: I784d0598fd0370eec38d758b9fa0b38e4b3423be
Reviewed-on: https://webrtc-review.googlesource.com/96320
Reviewed-by: Sami Kalliomäki <sakal@webrtc.org>
Commit-Queue: Sami Kalliomäki <sakal@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#24458}
diff --git a/examples/androidtests/video_quality_loopback_test.py b/examples/androidtests/video_quality_loopback_test.py
index 52ae3b1..225f885 100755
--- a/examples/androidtests/video_quality_loopback_test.py
+++ b/examples/androidtests/video_quality_loopback_test.py
@@ -165,6 +165,8 @@
 def RunTest(android_device, adb_path, build_dir, temp_dir, num_retries,
             chartjson_result_file):
   ffmpeg_path = os.path.join(TOOLCHAIN_DIR, 'ffmpeg')
+  def ConvertVideo(input_video, output_video):
+    _RunCommand([ffmpeg_path, '-y', '-i', input_video, output_video])
 
   # Start loopback call and record video.
   test_script = os.path.join(
@@ -181,6 +183,13 @@
   reference_video = os.path.join(SRC_DIR,
       'resources', 'reference_video_640x360_30fps.y4m')
 
+  test_video_yuv = os.path.join(temp_dir, 'test_video.yuv')
+  reference_video_yuv = os.path.join(
+      temp_dir, 'reference_video_640x360_30fps.yuv')
+
+  ConvertVideo(test_video, test_video_yuv)
+  ConvertVideo(reference_video, reference_video_yuv)
+
   # Run comparison script.
   compare_script = os.path.join(SRC_DIR, 'rtc_tools', 'compare_videos.py')
   frame_analyzer = os.path.join(TOOLCHAIN_DIR, 'frame_analyzer')
@@ -189,8 +198,8 @@
   stats_file_test = os.path.join(temp_dir, 'stats_test.txt')
 
   args = [
-      '--ref_video', reference_video,
-      '--test_video', test_video,
+      '--ref_video', reference_video_yuv,
+      '--test_video', test_video_yuv,
       '--yuv_frame_width', '640',
       '--yuv_frame_height', '360',
       '--stats_file_ref', stats_file_ref,
diff --git a/resources/video_quality_analysis_frame.txt.sha1 b/resources/video_quality_analysis_frame.txt.sha1
new file mode 100644
index 0000000..e4a7c73
--- /dev/null
+++ b/resources/video_quality_analysis_frame.txt.sha1
@@ -0,0 +1 @@
+4d1ac894f1743af8059e8d8ae2465f6eaa1790b0
\ No newline at end of file
diff --git a/rtc_tools/BUILD.gn b/rtc_tools/BUILD.gn
index 4eb292a..99f1ae6 100644
--- a/rtc_tools/BUILD.gn
+++ b/rtc_tools/BUILD.gn
@@ -17,7 +17,6 @@
     ":command_line_parser",
     ":frame_analyzer",
     ":video_quality_analysis",
-    ":y4m_file_reader",
   ]
   if (!build_with_chromium) {
     deps += [
@@ -60,34 +59,14 @@
   ]
 }
 
-rtc_static_library("y4m_file_reader") {
-  sources = [
-    "y4m_file_reader.cc",
-    "y4m_file_reader.h",
-  ]
-  deps = [
-    "../api/video:video_frame",
-    "../api/video:video_frame_i420",
-    "../rtc_base:rtc_base_approved",
-    "//third_party/abseil-cpp/absl/types:optional",
-  ]
-}
-
 rtc_static_library("video_quality_analysis") {
   sources = [
     "frame_analyzer/video_quality_analysis.cc",
     "frame_analyzer/video_quality_analysis.h",
-    "frame_analyzer/video_temporal_aligner.cc",
-    "frame_analyzer/video_temporal_aligner.h",
   ]
   deps = [
-    ":y4m_file_reader",
-    "../api/video:video_frame_i420",
     "../common_video",
-    "../rtc_base:checks",
-    "../rtc_base:rtc_base_approved",
     "../test:perf_test",
-    "//third_party/abseil-cpp/absl/types:optional",
     "//third_party/libyuv",
   ]
 }
@@ -101,7 +80,6 @@
   deps = [
     ":command_line_parser",
     ":video_quality_analysis",
-    ":y4m_file_reader",
     "../test:perf_test",
     "//build/win:default_exe_manifest",
   ]
@@ -118,7 +96,6 @@
     deps = [
       ":command_line_parser",
       ":video_quality_analysis",
-      ":y4m_file_reader",
       "//build/win:default_exe_manifest",
     ]
   }
@@ -131,7 +108,6 @@
 
     deps = [
       ":video_quality_analysis",
-      ":y4m_file_reader",
     ]
   }
 
@@ -312,7 +288,7 @@
   tools_unittests_resources = [
     "../resources/foreman_cif.yuv",
     "../resources/reference_less_video_test_file.y4m",
-    "../resources/reference_video_640x360_30fps.y4m",
+    "../resources/video_quality_analysis_frame.txt",
   ]
 
   if (is_ios) {
@@ -331,11 +307,9 @@
     sources = [
       "frame_analyzer/reference_less_video_analysis_unittest.cc",
       "frame_analyzer/video_quality_analysis_unittest.cc",
-      "frame_analyzer/video_temporal_aligner_unittest.cc",
       "frame_editing/frame_editing_unittest.cc",
       "sanitizers_unittest.cc",
       "simple_command_line_parser_unittest.cc",
-      "y4m_file_reader_unittest.cc",
     ]
 
     if (!build_with_chromium && is_clang) {
@@ -348,7 +322,6 @@
       ":frame_editing_lib",
       ":reference_less_video_analysis_lib",
       ":video_quality_analysis",
-      ":y4m_file_reader",
       "../common_video:common_video",
       "../rtc_base",
       "../rtc_base:checks",
diff --git a/rtc_tools/barcode_tools/barcode_decoder.py b/rtc_tools/barcode_tools/barcode_decoder.py
index 6be0f5d..2abd677 100755
--- a/rtc_tools/barcode_tools/barcode_decoder.py
+++ b/rtc_tools/barcode_tools/barcode_decoder.py
@@ -44,13 +44,9 @@
   output_files_pattern = os.path.join(output_directory, 'frame_%04d.png')
   if not ffmpeg_path:
     ffmpeg_path = 'ffmpeg.exe' if sys.platform == 'win32' else 'ffmpeg'
-  if yuv_file_name.endswith('.yuv'):
-    command = [ffmpeg_path, '-s', '%s' % size_string, '-i', '%s'
-               % yuv_file_name, '-f', 'image2', '-vcodec', 'png',
-               '%s' % output_files_pattern]
-  else:
-    command = [ffmpeg_path, '-i', '%s' % yuv_file_name, '-f', 'image2',
-               '-vcodec', 'png', '%s' % output_files_pattern]
+  command = [ffmpeg_path, '-s', '%s' % size_string, '-i', '%s'
+             % yuv_file_name, '-f', 'image2', '-vcodec', 'png',
+             '%s' % output_files_pattern]
   try:
     print 'Converting YUV file to PNG images (may take a while)...'
     print ' '.join(command)
diff --git a/rtc_tools/frame_analyzer/frame_analyzer.cc b/rtc_tools/frame_analyzer/frame_analyzer.cc
index 443a868..b3d9b94 100644
--- a/rtc_tools/frame_analyzer/frame_analyzer.cc
+++ b/rtc_tools/frame_analyzer/frame_analyzer.cc
@@ -16,16 +16,19 @@
 #include <vector>
 
 #include "rtc_tools/frame_analyzer/video_quality_analysis.h"
-#include "rtc_tools/frame_analyzer/video_temporal_aligner.h"
 #include "rtc_tools/simple_command_line_parser.h"
-#include "rtc_tools/y4m_file_reader.h"
 #include "test/testsupport/perf_test.h"
 
 /*
  * A command line tool running PSNR and SSIM on a reference video and a test
  * video. The test video is a record of the reference video which can start at
  * an arbitrary point. It is possible that there will be repeated frames or
- * skipped frames as well. The video files should be 1420 Y4M videos.
+ * skipped frames as well. In order to have a way to compare corresponding
+ * frames from the two videos, two stats files should be provided. One for the
+ * reference video and one for the test video. The stats file
+ * is a text file assumed to be in the format:
+ * frame_xxxx yyyy where xxxx is the frame number in and yyyy is the
+ * corresponding barcode. The video files should be 1420 YUV videos.
  * The tool prints the result to standard output in the Chromium perf format:
  * RESULT <metric>:<label>= <values>
  *
@@ -33,7 +36,9 @@
  *
  * Usage:
  * frame_analyzer --label=<test_label> --reference_file=<name_of_file>
- * --test_file_ref=<name_of_file>
+ * --test_file_ref=<name_of_file> --stats_file_test=<name_of_file>
+ * --stats_file=<name_of_file> --width=<frame_width>
+ * --height=<frame_height>
  */
 int main(int argc, char* argv[]) {
   std::string program_name = argv[0];
@@ -41,13 +46,24 @@
       "Compares the output video with the initially sent video."
       "\nExample usage:\n" +
       program_name +
-      " --reference_file=ref.y4m --test_file=test.y4m\n"
+      " --reference_file=ref.yuv --test_file=test.yuv --width=320 "
+      "--height=240\n"
       "Command line flags:\n"
+      "  - width(int): The width of the reference and test files. Default: -1\n"
+      "  - height(int): The height of the reference and test files. "
+      " Default: -1\n"
       "  - label(string): The label to use for the perf output."
       " Default: MY_TEST\n"
-      " Default: ref.y4m\n"
+      "  - stats_file_ref(string): The path to the stats file that will be"
+      " produced for the reference video file."
+      " Default: stats_ref.txt\n"
+      "  - stats_file_test(string): The path to the stats file that will be"
+      " produced for the test video file."
+      " Default: stats_test.txt\n"
+      "  - reference_file(string): The reference YUV file to compare against."
+      " Default: ref.yuv\n"
       "  - test_file(string): The test YUV file to run the analysis for."
-      " Default: test_file.y4m\n"
+      " Default: test_file.yuv\n"
       "  - chartjson_result_file: Where to store perf result in chartjson"
       " format. If not present, no perf result will be stored."
       " Default: None\n";
@@ -58,9 +74,13 @@
   parser.Init(argc, argv);
   parser.SetUsageMessage(usage);
 
+  parser.SetFlag("width", "-1");
+  parser.SetFlag("height", "-1");
   parser.SetFlag("label", "MY_TEST");
-  parser.SetFlag("reference_file", "ref.y4m");
-  parser.SetFlag("test_file", "test.y4m");
+  parser.SetFlag("stats_file_ref", "stats_ref.txt");
+  parser.SetFlag("stats_file_test", "stats_test.txt");
+  parser.SetFlag("reference_file", "ref.yuv");
+  parser.SetFlag("test_file", "test.yuv");
   parser.SetFlag("chartjson_result_file", "");
   parser.SetFlag("help", "false");
 
@@ -71,32 +91,24 @@
   }
   parser.PrintEnteredFlags();
 
-  webrtc::test::ResultsContainer results;
+  int width = strtol((parser.GetFlag("width")).c_str(), NULL, 10);
+  int height = strtol((parser.GetFlag("height")).c_str(), NULL, 10);
 
-  rtc::scoped_refptr<webrtc::test::Y4mFile> reference_video =
-      webrtc::test::Y4mFile::Open(parser.GetFlag("reference_file"));
-  rtc::scoped_refptr<webrtc::test::Y4mFile> test_video =
-      webrtc::test::Y4mFile::Open(parser.GetFlag("test_file"));
-
-  if (!reference_video || !test_video) {
-    fprintf(stderr, "Error opening video files\n");
-    return 0;
+  if (width <= 0 || height <= 0) {
+    fprintf(stderr, "Error: width or height cannot be <= 0!\n");
+    return -1;
   }
 
-  const std::vector<size_t> matching_indices =
-      webrtc::test::FindMatchingFrameIndices(reference_video, test_video);
+  webrtc::test::ResultsContainer results;
 
-  results.frames =
-      webrtc::test::RunAnalysis(reference_video, test_video, matching_indices);
-
-  const std::vector<webrtc::test::Cluster> clusters =
-      webrtc::test::CalculateFrameClusters(matching_indices);
-  results.max_repeated_frames = webrtc::test::GetMaxRepeatedFrames(clusters);
-  results.max_skipped_frames = webrtc::test::GetMaxSkippedFrames(clusters);
-  results.total_skipped_frames =
-      webrtc::test::GetTotalNumberOfSkippedFrames(clusters);
-  results.decode_errors_ref = 0;
-  results.decode_errors_test = 0;
+  webrtc::test::RunAnalysis(parser.GetFlag("reference_file").c_str(),
+                            parser.GetFlag("test_file").c_str(),
+                            parser.GetFlag("stats_file_ref").c_str(),
+                            parser.GetFlag("stats_file_test").c_str(), width,
+                            height, &results);
+  webrtc::test::GetMaxRepeatedAndSkippedFrames(
+      parser.GetFlag("stats_file_ref"), parser.GetFlag("stats_file_test"),
+      &results);
 
   webrtc::test::PrintAnalysisResults(parser.GetFlag("label"), &results);
 
diff --git a/rtc_tools/frame_analyzer/reference_less_video_analysis_lib.cc b/rtc_tools/frame_analyzer/reference_less_video_analysis_lib.cc
index 96e0ef4..9a7535b 100644
--- a/rtc_tools/frame_analyzer/reference_less_video_analysis_lib.cc
+++ b/rtc_tools/frame_analyzer/reference_less_video_analysis_lib.cc
@@ -25,6 +25,36 @@
 #define strtok_r strtok_s
 #endif
 
+void get_height_width_fps(int* height,
+                          int* width,
+                          int* fps,
+                          const std::string& video_file) {
+  // File header looks like :
+  //  YUV4MPEG2 W1280 H720 F25:1 Ip A0:0 C420mpeg2 XYSCSS=420MPEG2.
+  char frame_header[STATS_LINE_LENGTH];
+  FILE* input_file = fopen(video_file.c_str(), "rb");
+
+  size_t bytes_read = fread(frame_header, 1, STATS_LINE_LENGTH - 1, input_file);
+
+  frame_header[bytes_read] = '\0';
+  std::string file_header_stats[5];
+  int no_of_stats = 0;
+  char* save_ptr;
+  char* token = strtok_r(frame_header, " ", &save_ptr);
+
+  while (token != NULL) {
+    file_header_stats[no_of_stats++] = token;
+    token = strtok_r(NULL, " ", &save_ptr);
+  }
+
+  *width = std::stoi(file_header_stats[1].erase(0, 1));
+  *height = std::stoi(file_header_stats[2].erase(0, 1));
+  *fps = std::stoi(file_header_stats[3].erase(0, 1));
+
+  printf("Height: %d Width: %d fps:%d \n", *height, *width, *fps);
+  fclose(input_file);
+}
+
 bool frozen_frame(std::vector<double> psnr_per_frame,
                   std::vector<double> ssim_per_frame,
                   size_t frame) {
@@ -105,29 +135,60 @@
   printf("\n");
 }
 
-void compute_metrics(const rtc::scoped_refptr<webrtc::test::Y4mFile>& video,
+void compute_metrics(const std::string& video_file_name,
                      std::vector<double>* psnr_per_frame,
                      std::vector<double>* ssim_per_frame) {
-  for (size_t i = 0; i < video->number_of_frames() - 1; ++i) {
-    const rtc::scoped_refptr<webrtc::I420BufferInterface> current_frame =
-        video->GetFrame(i);
-    const rtc::scoped_refptr<webrtc::I420BufferInterface> next_frame =
-        video->GetFrame(i + 1);
-    double result_psnr = webrtc::test::Psnr(current_frame, next_frame);
-    double result_ssim = webrtc::test::Ssim(current_frame, next_frame);
+  int height = 0, width = 0, fps = 0;
+  get_height_width_fps(&height, &width, &fps, video_file_name);
+
+  int no_of_frames = 0;
+  int size = webrtc::test::GetI420FrameSize(width, height);
+
+  // Allocate buffers for test and reference frames.
+  uint8_t* current_frame = new uint8_t[size];
+  uint8_t* next_frame = new uint8_t[size];
+
+  while (true) {
+    if (!(webrtc::test::ExtractFrameFromY4mFile(video_file_name.c_str(), width,
+                                                height, no_of_frames,
+                                                current_frame))) {
+      break;
+    }
+
+    if (!(webrtc::test::ExtractFrameFromY4mFile(video_file_name.c_str(), width,
+                                                height, no_of_frames + 1,
+                                                next_frame))) {
+      break;
+    }
+
+    double result_psnr = webrtc::test::CalculateMetrics(
+        webrtc::test::kPSNR, current_frame, next_frame, width, height);
+    double result_ssim = webrtc::test::CalculateMetrics(
+        webrtc::test::kSSIM, current_frame, next_frame, width, height);
 
     psnr_per_frame->push_back(result_psnr);
     ssim_per_frame->push_back(result_ssim);
+    no_of_frames++;
   }
+  // Cleanup.
+  delete[] current_frame;
+  delete[] next_frame;
+}
+
+bool check_file_extension(const std::string& video_file_name) {
+  if (video_file_name.substr(video_file_name.length() - 3, 3) != "y4m") {
+    printf("Only y4m video file format is supported. Given: %s\n",
+           video_file_name.c_str());
+    return false;
+  }
+  return true;
 }
 
 int run_analysis(const std::string& video_file) {
   std::vector<double> psnr_per_frame;
   std::vector<double> ssim_per_frame;
-  rtc::scoped_refptr<webrtc::test::Y4mFile> video =
-      webrtc::test::Y4mFile::Open(video_file);
-  if (video) {
-    compute_metrics(video, &psnr_per_frame, &ssim_per_frame);
+  if (check_file_extension(video_file)) {
+    compute_metrics(video_file, &psnr_per_frame, &ssim_per_frame);
   } else {
     return -1;
   }
diff --git a/rtc_tools/frame_analyzer/reference_less_video_analysis_lib.h b/rtc_tools/frame_analyzer/reference_less_video_analysis_lib.h
index 6da9f4e..a1de03b 100644
--- a/rtc_tools/frame_analyzer/reference_less_video_analysis_lib.h
+++ b/rtc_tools/frame_analyzer/reference_less_video_analysis_lib.h
@@ -14,7 +14,12 @@
 #include <string>
 #include <vector>
 
-#include "rtc_tools/y4m_file_reader.h"
+// Parse the file header to extract height, width and fps
+// for a given video file.
+void get_height_width_fps(int* height,
+                          int* width,
+                          int* fps,
+                          const std::string& video_file);
 
 // Returns true if the frame is frozen based on psnr and ssim freezing
 // threshold values.
@@ -34,10 +39,13 @@
 
 // Compute the metrics like freezing score based on PSNR and SSIM values for a
 // given video file.
-void compute_metrics(const rtc::scoped_refptr<webrtc::test::Y4mFile>& video,
+void compute_metrics(const std::string& video_file_name,
                      std::vector<double>* psnr_per_frame,
                      std::vector<double>* ssim_per_frame);
 
+// Checks the file extension and return true if it is y4m.
+bool check_file_extension(const std::string& video_file_name);
+
 // Compute freezing score metrics and prints the metrics
 // for a list of video files.
 int run_analysis(const std::string& video_file);
diff --git a/rtc_tools/frame_analyzer/reference_less_video_analysis_unittest.cc b/rtc_tools/frame_analyzer/reference_less_video_analysis_unittest.cc
index 2c3cf3a..4e20532 100644
--- a/rtc_tools/frame_analyzer/reference_less_video_analysis_unittest.cc
+++ b/rtc_tools/frame_analyzer/reference_less_video_analysis_unittest.cc
@@ -20,18 +20,16 @@
 class ReferenceLessVideoAnalysisTest : public ::testing::Test {
  public:
   void SetUp() override {
-    video = webrtc::test::Y4mFile::Open(
-        webrtc::test::ResourcePath("reference_less_video_test_file", "y4m"));
-    ASSERT_TRUE(video);
+    video_file =
+        webrtc::test::ResourcePath("reference_less_video_test_file", "y4m");
   }
-
-  rtc::scoped_refptr<webrtc::test::Y4mFile> video;
+  std::string video_file;
   std::vector<double> psnr_per_frame;
   std::vector<double> ssim_per_frame;
 };
 
 TEST_F(ReferenceLessVideoAnalysisTest, MatchComputedMetrics) {
-  compute_metrics(video, &psnr_per_frame, &ssim_per_frame);
+  compute_metrics(video_file, &psnr_per_frame, &ssim_per_frame);
   EXPECT_EQ(74, (int)psnr_per_frame.size());
 
   ASSERT_NEAR(27.2f, psnr_per_frame[1], 0.1f);
@@ -41,11 +39,26 @@
   ASSERT_NEAR(0.9f, ssim_per_frame[5], 0.1f);
 }
 
+TEST_F(ReferenceLessVideoAnalysisTest, MatchHeightWidthFps) {
+  int height = 0, width = 0, fps = 0;
+  get_height_width_fps(&height, &width, &fps, video_file.c_str());
+  EXPECT_EQ(height, 720);
+  EXPECT_EQ(width, 1280);
+  EXPECT_EQ(fps, 25);
+}
+
 TEST_F(ReferenceLessVideoAnalysisTest, MatchIdenticalFrameClusters) {
-  compute_metrics(video, &psnr_per_frame, &ssim_per_frame);
+  compute_metrics(video_file, &psnr_per_frame, &ssim_per_frame);
   std::vector<int> identical_frame_clusters =
       find_frame_clusters(psnr_per_frame, ssim_per_frame);
   EXPECT_EQ(5, (int)identical_frame_clusters.size());
   EXPECT_EQ(1, identical_frame_clusters[0]);
   EXPECT_EQ(1, identical_frame_clusters[4]);
 }
+
+TEST_F(ReferenceLessVideoAnalysisTest, CheckFileExtension) {
+  EXPECT_TRUE(check_file_extension(video_file));
+  std::string txt_file =
+      webrtc::test::ResourcePath("video_quality_analysis_frame", "txt");
+  EXPECT_FALSE(check_file_extension(txt_file));
+}
diff --git a/rtc_tools/frame_analyzer/video_quality_analysis.cc b/rtc_tools/frame_analyzer/video_quality_analysis.cc
index 6f687f5..60a4a01 100644
--- a/rtc_tools/frame_analyzer/video_quality_analysis.cc
+++ b/rtc_tools/frame_analyzer/video_quality_analysis.cc
@@ -10,12 +10,20 @@
 
 #include "rtc_tools/frame_analyzer/video_quality_analysis.h"
 
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
 #include <algorithm>
-#include <numeric>
+#include <map>
+#include <string>
+#include <utility>
 
 #include "test/testsupport/perf_test.h"
-#include "third_party/libyuv/include/libyuv/compare.h"
-#include "third_party/libyuv/include/libyuv/convert.h"
+
+#define STATS_LINE_LENGTH 32
+#define Y4M_FILE_HEADER_MAX_SIZE 200
+#define Y4M_FRAME_DELIMITER "FRAME"
+#define Y4M_FRAME_HEADER_SIZE 6
 
 namespace webrtc {
 namespace test {
@@ -23,97 +31,436 @@
 ResultsContainer::ResultsContainer() {}
 ResultsContainer::~ResultsContainer() {}
 
-template <typename FrameMetricFunction>
-static double CalculateMetric(
-    const FrameMetricFunction& frame_metric_function,
-    const rtc::scoped_refptr<I420BufferInterface>& ref_buffer,
-    const rtc::scoped_refptr<I420BufferInterface>& test_buffer) {
-  RTC_CHECK_EQ(ref_buffer->width(), test_buffer->width());
-  RTC_CHECK_EQ(ref_buffer->height(), test_buffer->height());
-  return frame_metric_function(
-      ref_buffer->DataY(), ref_buffer->StrideY(), ref_buffer->DataU(),
-      ref_buffer->StrideU(), ref_buffer->DataV(), ref_buffer->StrideV(),
-      test_buffer->DataY(), test_buffer->StrideY(), test_buffer->DataU(),
-      test_buffer->StrideU(), test_buffer->DataV(), test_buffer->StrideV(),
-      test_buffer->width(), test_buffer->height());
+int GetI420FrameSize(int width, int height) {
+  int half_width = (width + 1) >> 1;
+  int half_height = (height + 1) >> 1;
+
+  int y_plane = width * height;            // I420 Y plane.
+  int u_plane = half_width * half_height;  // I420 U plane.
+  int v_plane = half_width * half_height;  // I420 V plane.
+
+  return y_plane + u_plane + v_plane;
 }
 
-double Psnr(const rtc::scoped_refptr<I420BufferInterface>& ref_buffer,
-            const rtc::scoped_refptr<I420BufferInterface>& test_buffer) {
-  // LibYuv sets the max psnr value to 128, we restrict it to 48.
-  // In case of 0 mse in one frame, 128 can skew the results significantly.
-  return std::min(48.0,
-                  CalculateMetric(&libyuv::I420Psnr, ref_buffer, test_buffer));
+int ExtractFrameSequenceNumber(std::string line) {
+  size_t space_position = line.find(' ');
+  if (space_position == std::string::npos) {
+    return -1;
+  }
+  std::string frame = line.substr(0, space_position);
+
+  size_t underscore_position = frame.find('_');
+  if (underscore_position == std::string::npos) {
+    return -1;
+  }
+  std::string frame_number = frame.substr(underscore_position + 1);
+
+  return strtol(frame_number.c_str(), NULL, 10);
 }
 
-double Ssim(const rtc::scoped_refptr<I420BufferInterface>& ref_buffer,
-            const rtc::scoped_refptr<I420BufferInterface>& test_buffer) {
-  return CalculateMetric(&libyuv::I420Ssim, ref_buffer, test_buffer);
+int ExtractDecodedFrameNumber(std::string line) {
+  size_t space_position = line.find(' ');
+  if (space_position == std::string::npos) {
+    return -1;
+  }
+  std::string decoded_number = line.substr(space_position + 1);
+
+  return strtol(decoded_number.c_str(), NULL, 10);
 }
 
-std::vector<AnalysisResult> RunAnalysis(
-    const rtc::scoped_refptr<webrtc::test::Video>& reference_video,
-    const rtc::scoped_refptr<webrtc::test::Video>& test_video,
-    const std::vector<size_t>& test_frame_indices) {
-  std::vector<AnalysisResult> results;
-  for (size_t i = 0; i < test_frame_indices.size(); ++i) {
-    // Ignore duplicated frames in the test video.
-    if (i > 0 && test_frame_indices[i] == test_frame_indices[i - 1])
+bool IsThereBarcodeError(std::string line) {
+  size_t barcode_error_position = line.find("Barcode error");
+  if (barcode_error_position != std::string::npos) {
+    return true;
+  }
+  return false;
+}
+
+bool GetNextStatsLine(FILE* stats_file, char* line) {
+  int chars = 0;
+  char buf = 0;
+
+  while (buf != '\n') {
+    size_t chars_read = fread(&buf, 1, 1, stats_file);
+    if (chars_read != 1 || feof(stats_file)) {
+      return false;
+    }
+    line[chars] = buf;
+    ++chars;
+  }
+  line[chars - 1] = '\0';  // Strip the trailing \n and put end of string.
+  return true;
+}
+
+bool ExtractFrameFromYuvFile(const char* i420_file_name,
+                             int width,
+                             int height,
+                             int frame_number,
+                             uint8_t* result_frame) {
+  int frame_size = GetI420FrameSize(width, height);
+  int offset = frame_number * frame_size;  // Calculate offset for the frame.
+  bool errors = false;
+
+  FILE* input_file = fopen(i420_file_name, "rb");
+  if (input_file == NULL) {
+    fprintf(stderr, "Couldn't open input file for reading: %s\n",
+            i420_file_name);
+    return false;
+  }
+
+  // Change stream pointer to new offset.
+  fseek(input_file, offset, SEEK_SET);
+
+  size_t bytes_read = fread(result_frame, 1, frame_size, input_file);
+  if (bytes_read != static_cast<size_t>(frame_size) && ferror(input_file)) {
+    fprintf(stdout, "Error while reading frame no %d from file %s\n",
+            frame_number, i420_file_name);
+    errors = true;
+  }
+  fclose(input_file);
+  return !errors;
+}
+
+bool ExtractFrameFromY4mFile(const char* y4m_file_name,
+                             int width,
+                             int height,
+                             int frame_number,
+                             uint8_t* result_frame) {
+  int frame_size = GetI420FrameSize(width, height);
+  int inital_offset = frame_number * (frame_size + Y4M_FRAME_HEADER_SIZE);
+  int frame_offset = 0;
+
+  FILE* input_file = fopen(y4m_file_name, "rb");
+  if (input_file == NULL) {
+    fprintf(stderr, "Couldn't open input file for reading: %s\n",
+            y4m_file_name);
+    return false;
+  }
+
+  // YUV4MPEG2, a.k.a. Y4M File format has a file header and a frame header. The
+  // file header has the aspect: "YUV4MPEG2 C420 W640 H360 Ip F30:1 A1:1".
+  char frame_header[Y4M_FILE_HEADER_MAX_SIZE];
+  size_t bytes_read =
+      fread(frame_header, 1, Y4M_FILE_HEADER_MAX_SIZE - 1, input_file);
+  if (bytes_read != static_cast<size_t>(frame_size) && ferror(input_file)) {
+    fprintf(stdout, "Error while reading frame from file %s\n", y4m_file_name);
+    fclose(input_file);
+    return false;
+  }
+  frame_header[bytes_read] = '\0';
+  std::string header_contents(frame_header);
+  std::size_t found = header_contents.find(Y4M_FRAME_DELIMITER);
+  if (found == std::string::npos) {
+    fprintf(stdout, "Corrupted Y4M header, could not find \"FRAME\" in %s\n",
+            header_contents.c_str());
+    fclose(input_file);
+    return false;
+  }
+  frame_offset = static_cast<int>(found);
+
+  // Change stream pointer to new offset, skipping the frame header as well.
+  fseek(input_file, inital_offset + frame_offset + Y4M_FRAME_HEADER_SIZE,
+        SEEK_SET);
+
+  bytes_read = fread(result_frame, 1, frame_size, input_file);
+  if (feof(input_file)) {
+    fclose(input_file);
+    return false;
+  }
+  if (bytes_read != static_cast<size_t>(frame_size) && ferror(input_file)) {
+    fprintf(stdout, "Error while reading frame no %d from file %s\n",
+            frame_number, y4m_file_name);
+    fclose(input_file);
+    return false;
+  }
+
+  fclose(input_file);
+  return true;
+}
+
+double CalculateMetrics(VideoAnalysisMetricsType video_metrics_type,
+                        const uint8_t* ref_frame,
+                        const uint8_t* test_frame,
+                        int width,
+                        int height) {
+  if (!ref_frame || !test_frame)
+    return -1;
+  else if (height < 0 || width < 0)
+    return -1;
+  int half_width = (width + 1) >> 1;
+  int half_height = (height + 1) >> 1;
+  const uint8_t* src_y_a = ref_frame;
+  const uint8_t* src_u_a = src_y_a + width * height;
+  const uint8_t* src_v_a = src_u_a + half_width * half_height;
+  const uint8_t* src_y_b = test_frame;
+  const uint8_t* src_u_b = src_y_b + width * height;
+  const uint8_t* src_v_b = src_u_b + half_width * half_height;
+
+  int stride_y = width;
+  int stride_uv = half_width;
+
+  double result = 0.0;
+
+  switch (video_metrics_type) {
+    case kPSNR:
+      // In the following: stride is determined by width.
+      result = libyuv::I420Psnr(src_y_a, width, src_u_a, half_width, src_v_a,
+                                half_width, src_y_b, width, src_u_b, half_width,
+                                src_v_b, half_width, width, height);
+      // LibYuv sets the max psnr value to 128, we restrict it to 48.
+      // In case of 0 mse in one frame, 128 can skew the results significantly.
+      result = (result > 48.0) ? 48.0 : result;
+      break;
+    case kSSIM:
+      result = libyuv::I420Ssim(src_y_a, stride_y, src_u_a, stride_uv, src_v_a,
+                                stride_uv, src_y_b, stride_y, src_u_b,
+                                stride_uv, src_v_b, stride_uv, width, height);
+      break;
+    default:
+      assert(false);
+  }
+
+  return result;
+}
+
+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;
+  if (std::string(reference_file_name).find("y4m") != std::string::npos) {
+    y4m_mode = true;
+  }
+
+  int size = GetI420FrameSize(width, height);
+  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];
+
+  // Allocate buffers for test and reference frames.
+  uint8_t* test_frame = new uint8_t[size];
+  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_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;
 
-    const rtc::scoped_refptr<I420BufferInterface>& test_frame =
-        test_video->GetFrame(i);
-    const rtc::scoped_refptr<I420BufferInterface>& reference_frame =
-        reference_video->GetFrame(test_frame_indices[i] %
-                                  reference_video->number_of_frames());
+    // If there was problem decoding the barcode in this frame or the frame has
+    // been duplicated, continue.
+    if (IsThereBarcodeError(line) ||
+        decoded_frame_number == previous_frame_number) {
+      continue;
+    }
+
+    assert(extracted_test_frame != -1);
+    assert(decoded_frame_number != -1);
+
+    ExtractFrameFromYuvFile(test_file_name, width, height, extracted_test_frame,
+                            test_frame);
+    if (y4m_mode) {
+      ExtractFrameFromY4mFile(reference_file_name, width, height,
+                              extracted_ref_frame, reference_frame);
+    } else {
+      ExtractFrameFromYuvFile(reference_file_name, width, height,
+                              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);
+
+    previous_frame_number = decoded_frame_number;
 
     // Fill in the result struct.
     AnalysisResult result;
-    result.frame_number = test_frame_indices[i];
-    result.psnr_value = Psnr(reference_frame, test_frame);
-    result.ssim_value = Ssim(reference_frame, test_frame);
-    results.push_back(result);
+    result.frame_number = decoded_frame_number;
+    result.psnr_value = result_psnr;
+    result.ssim_value = result_ssim;
+
+    results->frames.push_back(result);
   }
 
-  return results;
+  // Cleanup.
+  fclose(stats_file_ref);
+  fclose(stats_file_test);
+  delete[] test_frame;
+  delete[] reference_frame;
 }
 
-std::vector<Cluster> CalculateFrameClusters(
-    const std::vector<size_t>& indices) {
-  std::vector<Cluster> clusters;
-  for (size_t i = 0; i < indices.size(); ++i) {
-    const size_t start_index = i;
-    while (i < indices.size() && indices[i] == indices[start_index])
-      ++i;
-    const int number_of_repeated_frames = static_cast<int>(i - start_index);
-    clusters.push_back({indices[start_index], number_of_repeated_frames});
+std::vector<std::pair<int, int> > CalculateFrameClusters(
+    FILE* file,
+    int* num_decode_errors) {
+  if (num_decode_errors) {
+    *num_decode_errors = 0;
   }
-  return clusters;
-}
-
-int GetMaxRepeatedFrames(const std::vector<Cluster>& clusters) {
-  int max_number_of_repeated_frames = 0;
-  for (const Cluster& cluster : clusters) {
-    max_number_of_repeated_frames = std::max(max_number_of_repeated_frames,
-                                             cluster.number_of_repeated_frames);
+  std::vector<std::pair<int, int> > frame_cnt;
+  char line[STATS_LINE_LENGTH];
+  while (GetNextStatsLine(file, line)) {
+    int decoded_frame_number;
+    if (IsThereBarcodeError(line)) {
+      decoded_frame_number = DECODE_ERROR;
+      if (num_decode_errors) {
+        ++*num_decode_errors;
+      }
+    } else {
+      decoded_frame_number = ExtractDecodedFrameNumber(line);
+    }
+    if (frame_cnt.size() >= 2 && decoded_frame_number != DECODE_ERROR &&
+        frame_cnt.back().first == DECODE_ERROR &&
+        frame_cnt[frame_cnt.size() - 2].first == decoded_frame_number) {
+      // Handle when there is a decoding error inside a cluster of frames.
+      frame_cnt[frame_cnt.size() - 2].second += frame_cnt.back().second + 1;
+      frame_cnt.pop_back();
+    } else 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 max_number_of_repeated_frames;
+  return frame_cnt;
 }
 
-int GetMaxSkippedFrames(const std::vector<Cluster>& clusters) {
-  size_t max_skipped_frames = 0;
-  for (size_t i = 1; i < clusters.size(); ++i) {
-    const size_t skipped_frames = clusters[i].index - clusters[i - 1].index - 1;
-    max_skipped_frames = std::max(max_skipped_frames, skipped_frames);
+void GetMaxRepeatedAndSkippedFrames(const std::string& stats_file_ref_name,
+                                    const std::string& stats_file_test_name,
+                                    ResultsContainer* results) {
+  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;
   }
-  return static_cast<int>(max_skipped_frames);
-}
+  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;
+  }
 
-int GetTotalNumberOfSkippedFrames(const std::vector<Cluster>& clusters) {
-  // The number of reference frames the test video spans.
-  const size_t number_ref_frames =
-      clusters.empty() ? 0 : 1 + clusters.back().index - clusters.front().index;
-  return static_cast<int>(number_ref_frames - clusters.size());
+  int max_repeated_frames = 1;
+  int max_skipped_frames = 0;
+
+  int decode_errors_ref = 0;
+  int decode_errors_test = 0;
+
+  std::vector<std::pair<int, int> > frame_cnt_ref =
+      CalculateFrameClusters(stats_file_ref, &decode_errors_ref);
+
+  std::vector<std::pair<int, int> > frame_cnt_test =
+      CalculateFrameClusters(stats_file_test, &decode_errors_test);
+
+  fclose(stats_file_ref);
+  fclose(stats_file_test);
+
+  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;
+  }
+
+  while (it_test != end_test && it_test->first == DECODE_ERROR) {
+    ++it_test;
+  }
+
+  if (it_test == end_test) {
+    fprintf(stderr, "Test video only has barcode decode errors\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 == DECODE_ERROR || 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;
+  }
+
+  int total_skipped_frames = 0;
+  for (;;) {
+    max_repeated_frames =
+        std::max(max_repeated_frames, it_test->second - it_ref->second + 1);
+
+    bool passed_error = false;
+
+    ++it_test;
+    while (it_test != end_test && it_test->first == DECODE_ERROR) {
+      ++it_test;
+      passed_error = true;
+    }
+    if (it_test == end_test) {
+      break;
+    }
+
+    int skipped_frames = 0;
+    ++it_ref;
+    for (; it_ref != end_ref; ++it_ref) {
+      if (it_ref->first != DECODE_ERROR && it_ref->first >= it_test->first) {
+        break;
+      }
+      ++skipped_frames;
+    }
+    if (passed_error) {
+      // If we pass an error in the test video, then we are conservative
+      // and will not calculate skipped frames for that part.
+      skipped_frames = 0;
+    }
+    if (it_ref != end_ref && it_ref->first == it_test->first) {
+      total_skipped_frames += skipped_frames;
+      if (skipped_frames > max_skipped_frames) {
+        max_skipped_frames = skipped_frames;
+      }
+      continue;
+    }
+    fprintf(stdout,
+            "Found barcode %d in test video, which is not in reference video\n",
+            it_test->first);
+    break;
+  }
+
+  results->max_repeated_frames = max_repeated_frames;
+  results->max_skipped_frames = max_skipped_frames;
+  results->total_skipped_frames = total_skipped_frames;
+  results->decode_errors_ref = decode_errors_ref;
+  results->decode_errors_test = decode_errors_test;
 }
 
 void PrintAnalysisResults(const std::string& label, ResultsContainer* results) {
diff --git a/rtc_tools/frame_analyzer/video_quality_analysis.h b/rtc_tools/frame_analyzer/video_quality_analysis.h
index 81e0111..dca719d 100644
--- a/rtc_tools/frame_analyzer/video_quality_analysis.h
+++ b/rtc_tools/frame_analyzer/video_quality_analysis.h
@@ -15,8 +15,8 @@
 #include <utility>
 #include <vector>
 
-#include "api/video/i420_buffer.h"
-#include "rtc_tools/y4m_file_reader.h"
+#include "third_party/libyuv/include/libyuv/compare.h"
+#include "third_party/libyuv/include/libyuv/convert.h"
 
 namespace webrtc {
 namespace test {
@@ -44,25 +44,40 @@
   int decode_errors_test;
 };
 
+enum VideoAnalysisMetricsType { kPSNR, kSSIM };
+
 // A function to run the PSNR and SSIM analysis on the test file. The test file
 // comprises the frames that were captured during the quality measurement test.
 // There may be missing or duplicate frames. Also the frames start at a random
-// position in the original video. We also need to provide a map from test frame
-// indices to reference frame indices.
-std::vector<AnalysisResult> RunAnalysis(
-    const rtc::scoped_refptr<webrtc::test::Video>& reference_video,
-    const rtc::scoped_refptr<webrtc::test::Video>& test_video,
-    const std::vector<size_t>& test_frame_indices);
+// position in the original video. We should provide a statistics file along
+// with the test video. The stats file contains the connection between the
+// actual frames in the test file and their bar code number. There is one file
+// for the reference video and one for the test video. The stats file should
+// be in the form 'frame_xxxx yyyy', where xxxx is the consecutive
+// number of the frame in the test video, and yyyy is the barcode number.
+// The stats file could be produced by
+// tools/barcode_tools/barcode_decoder.py. This script decodes the barcodes
+// integrated in every video and generates the stats file. If three was some
+// problem with the decoding there would be 'Barcode error' instead of yyyy.
+// The stat files are used to compare the right frames with each other and
+// to calculate statistics.
+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);
 
-// Compute PSNR for an I420 buffer (all planes). The max return value (in the
-// case where the test and reference frames are exactly the same) will be 48.
-double Psnr(const rtc::scoped_refptr<I420BufferInterface>& ref_buffer,
-            const rtc::scoped_refptr<I420BufferInterface>& test_buffer);
-
-// Compute SSIM for an I420 buffer (all planes). The max return value (in the
-// case where the test and reference frames are exactly the same) will be 1.
-double Ssim(const rtc::scoped_refptr<I420BufferInterface>& ref_buffer,
-            const rtc::scoped_refptr<I420BufferInterface>& test_buffer);
+// Compute PSNR or SSIM for an I420 frame (all planes). When we are calculating
+// PSNR values, the max return value (in the case where the test and reference
+// frames are exactly the same) will be 48. In the case of SSIM the max return
+// value will be 1.
+double CalculateMetrics(VideoAnalysisMetricsType video_metrics_type,
+                        const uint8_t* ref_frame,
+                        const uint8_t* test_frame,
+                        int width,
+                        int height);
 
 // Prints the result from the analysis in Chromium performance
 // numbers compatible format to stdout. If the results object contains no frames
@@ -74,28 +89,60 @@
                           const std::string& label,
                           ResultsContainer* results);
 
-struct Cluster {
-  // Corresponding reference frame index for this cluster.
-  size_t index;
-  // The number of sequential frames that mapped to the same reference frame
-  // index.
-  int number_of_repeated_frames;
-};
+// The barcode number that means that the barcode could not be decoded.
+const int DECODE_ERROR = -1;
 
-// Clusters sequentially repeated frames. For example, the sequence {100, 102,
-// 102, 103} will be mapped to {{100, 1}, {102, 2}, {103, 1}}.
-std::vector<Cluster> CalculateFrameClusters(const std::vector<size_t>& indices);
+// 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.
+// Decode errors between two frames with same barcode, then it interprets
+// the frame with the decode error as having the same id as the two frames
+// around it. Eg. [400, DECODE_ERROR, DECODE_ERROR, 400] is becomes an entry
+// in return vector with first==400 and second==4. In other cases with decode
+// errors like [400, DECODE_ERROR, 401] becomes three entries, each with
+// second==1 and the middle has first==DECODE_ERROR.
+std::vector<std::pair<int, int> > CalculateFrameClusters(
+    FILE* file,
+    int* num_decode_errors);
 
-// Get number of max sequentially repeated frames in the test video. This number
-// will be one if we only store unique frames in the test video.
-int GetMaxRepeatedFrames(const std::vector<Cluster>& clusters);
+// Calculates max repeated and skipped frames and prints them to stdout in a
+// format that is compatible with Chromium performance numbers.
+void GetMaxRepeatedAndSkippedFrames(const std::string& stats_file_ref_name,
+                                    const std::string& stats_file_test_name,
+                                    ResultsContainer* results);
 
-// Get the longest sequence of skipped reference frames. This corresponds to the
-// longest freeze in the test video.
-int GetMaxSkippedFrames(const std::vector<Cluster>& clusters);
+// Gets the next line from an open stats file.
+bool GetNextStatsLine(FILE* stats_file, char* line);
 
-// Get total number of skipped frames in the test video.
-int GetTotalNumberOfSkippedFrames(const std::vector<Cluster>& clusters);
+// Calculates the size of a I420 frame if given the width and height.
+int GetI420FrameSize(int width, int height);
+
+// Extract the sequence of the frame in the video. I.e. if line is
+// frame_0023 0284, we will get 23.
+int ExtractFrameSequenceNumber(std::string line);
+
+// Checks if there is 'Barcode error' for the given line.
+bool IsThereBarcodeError(std::string line);
+
+// Extract the frame number in the reference video. I.e. if line is
+// frame_0023 0284, we will get 284.
+int ExtractDecodedFrameNumber(std::string line);
+
+// Extracts an I420 frame at position frame_number from the raw YUV file.
+bool ExtractFrameFromYuvFile(const char* i420_file_name,
+                             int width,
+                             int height,
+                             int frame_number,
+                             uint8_t* result_frame);
+
+// Extracts an I420 frame at position frame_number from the Y4M file. The first
+// frame has corresponded |frame_number| 0.
+bool ExtractFrameFromY4mFile(const char* i420_file_name,
+                             int width,
+                             int height,
+                             int frame_number,
+                             uint8_t* result_frame);
 
 }  // namespace test
 }  // namespace webrtc
diff --git a/rtc_tools/frame_analyzer/video_quality_analysis_unittest.cc b/rtc_tools/frame_analyzer/video_quality_analysis_unittest.cc
index dd4d4f0..d1edb30 100644
--- a/rtc_tools/frame_analyzer/video_quality_analysis_unittest.cc
+++ b/rtc_tools/frame_analyzer/video_quality_analysis_unittest.cc
@@ -31,11 +31,41 @@
                                             "VideoQualityAnalysisTest.log");
     logfile_ = fopen(log_filename.c_str(), "w");
     ASSERT_TRUE(logfile_ != NULL);
+
+    stats_filename_ref_ = TempFilename(OutputPath(), "stats-1.txt");
+    stats_filename_ = TempFilename(OutputPath(), "stats-2.txt");
   }
   void TearDown() { ASSERT_EQ(0, fclose(logfile_)); }
   FILE* logfile_;
+  std::string stats_filename_ref_;
+  std::string stats_filename_;
 };
 
+TEST_F(VideoQualityAnalysisTest, MatchExtractedY4mFrame) {
+  std::string video_file =
+      webrtc::test::ResourcePath("reference_less_video_test_file", "y4m");
+
+  std::string extracted_frame_from_video_file =
+      webrtc::test::ResourcePath("video_quality_analysis_frame", "txt");
+
+  int frame_height = 720, frame_width = 1280;
+  int frame_number = 2;
+  int size = GetI420FrameSize(frame_width, frame_height);
+  uint8_t* result_frame = new uint8_t[size];
+  uint8_t* expected_frame = new uint8_t[size];
+
+  FILE* input_file = fopen(extracted_frame_from_video_file.c_str(), "rb");
+  fread(expected_frame, 1, size, input_file);
+
+  ExtractFrameFromY4mFile(video_file.c_str(), frame_width, frame_height,
+                          frame_number, result_frame);
+
+  EXPECT_EQ(*expected_frame, *result_frame);
+  fclose(input_file);
+  delete[] result_frame;
+  delete[] expected_frame;
+}
+
 TEST_F(VideoQualityAnalysisTest, PrintAnalysisResultsEmpty) {
   ResultsContainer result;
   PrintAnalysisResults(logfile_, "Empty", &result);
@@ -55,6 +85,46 @@
   PrintAnalysisResults(logfile_, "ThreeFrames", &result);
 }
 
+TEST_F(VideoQualityAnalysisTest, GetMaxRepeatedAndSkippedFramesInvalidFile) {
+  ResultsContainer result;
+  remove(stats_filename_.c_str());
+  GetMaxRepeatedAndSkippedFrames(stats_filename_ref_, stats_filename_, &result);
+}
+
+TEST_F(VideoQualityAnalysisTest, GetMaxRepeatedAndSkippedFramesEmptyStatsFile) {
+  ResultsContainer result;
+  std::ofstream stats_file;
+  stats_file.open(stats_filename_ref_.c_str());
+  stats_file.close();
+  stats_file.open(stats_filename_.c_str());
+  stats_file.close();
+  GetMaxRepeatedAndSkippedFrames(stats_filename_ref_, stats_filename_, &result);
+}
+
+TEST_F(VideoQualityAnalysisTest, GetMaxRepeatedAndSkippedFramesNormalFile) {
+  ResultsContainer result;
+  std::ofstream stats_file;
+
+  stats_file.open(stats_filename_ref_.c_str());
+  stats_file << "frame_0001 0100\n";
+  stats_file << "frame_0002 0101\n";
+  stats_file << "frame_0003 0102\n";
+  stats_file << "frame_0004 0103\n";
+  stats_file << "frame_0005 0106\n";
+  stats_file << "frame_0006 0107\n";
+  stats_file << "frame_0007 0108\n";
+  stats_file.close();
+
+  stats_file.open(stats_filename_.c_str());
+  stats_file << "frame_0001 0100\n";
+  stats_file << "frame_0002 0101\n";
+  stats_file << "frame_0003 0101\n";
+  stats_file << "frame_0004 0106\n";
+  stats_file.close();
+
+  GetMaxRepeatedAndSkippedFrames(stats_filename_ref_, stats_filename_, &result);
+}
+
 namespace {
 void VerifyLogOutput(const std::string& log_filename,
                      const std::vector<std::string>& expected_out) {
@@ -72,18 +142,35 @@
 TEST_F(VideoQualityAnalysisTest,
        PrintMaxRepeatedAndSkippedFramesSkippedFrames) {
   ResultsContainer result;
+  std::ofstream stats_file;
 
   std::string log_filename =
       TempFilename(webrtc::test::OutputPath(), "log.log");
   FILE* logfile = fopen(log_filename.c_str(), "w");
   ASSERT_TRUE(logfile != NULL);
+  stats_file.open(stats_filename_ref_.c_str());
+  stats_file << "frame_0001 0100\n";
+  stats_file << "frame_0002 0101\n";
+  stats_file << "frame_0002 0101\n";
+  stats_file << "frame_0003 0103\n";
+  stats_file << "frame_0004 0103\n";
+  stats_file << "frame_0005 0106\n";
+  stats_file << "frame_0006 0106\n";
+  stats_file << "frame_0007 0108\n";
+  stats_file << "frame_0008 0110\n";
+  stats_file << "frame_0009 0112\n";
+  stats_file.close();
 
-  result.max_repeated_frames = 2;
-  result.max_skipped_frames = 2;
-  result.total_skipped_frames = 3;
-  result.decode_errors_ref = 0;
-  result.decode_errors_test = 0;
+  stats_file.open(stats_filename_.c_str());
+  stats_file << "frame_0001 0101\n";
+  stats_file << "frame_0002 0101\n";
+  stats_file << "frame_0003 0101\n";
+  stats_file << "frame_0004 0108\n";
+  stats_file << "frame_0005 0108\n";
+  stats_file << "frame_0006 0112\n";
+  stats_file.close();
 
+  GetMaxRepeatedAndSkippedFrames(stats_filename_ref_, stats_filename_, &result);
   PrintAnalysisResults(logfile, "NormalStatsFile", &result);
   ASSERT_EQ(0, fclose(logfile));
 
@@ -99,17 +186,35 @@
 TEST_F(VideoQualityAnalysisTest,
        PrintMaxRepeatedAndSkippedFramesDecodeErrorInTest) {
   ResultsContainer result;
+  std::ofstream stats_file;
 
   std::string log_filename =
       TempFilename(webrtc::test::OutputPath(), "log.log");
   FILE* logfile = fopen(log_filename.c_str(), "w");
   ASSERT_TRUE(logfile != NULL);
+  stats_file.open(stats_filename_ref_.c_str());
+  stats_file << "frame_0001 0100\n";
+  stats_file << "frame_0002 0100\n";
+  stats_file << "frame_0002 0101\n";
+  stats_file << "frame_0003 0103\n";
+  stats_file << "frame_0004 0103\n";
+  stats_file << "frame_0005 0106\n";
+  stats_file << "frame_0006 0107\n";
+  stats_file << "frame_0007 0107\n";
+  stats_file << "frame_0008 0110\n";
+  stats_file << "frame_0009 0112\n";
+  stats_file.close();
 
-  result.max_repeated_frames = 1;
-  result.max_skipped_frames = 0;
-  result.total_skipped_frames = 0;
-  result.decode_errors_ref = 0;
-  result.decode_errors_test = 3;
+  stats_file.open(stats_filename_.c_str());
+  stats_file << "frame_0001 0101\n";
+  stats_file << "frame_0002 Barcode error\n";
+  stats_file << "frame_0003 Barcode error\n";
+  stats_file << "frame_0004 Barcode error\n";
+  stats_file << "frame_0005 0107\n";
+  stats_file << "frame_0006 0110\n";
+  stats_file.close();
+
+  GetMaxRepeatedAndSkippedFrames(stats_filename_ref_, stats_filename_, &result);
   PrintAnalysisResults(logfile, "NormalStatsFile", &result);
   ASSERT_EQ(0, fclose(logfile));
 
@@ -122,42 +227,114 @@
   VerifyLogOutput(log_filename, expected_out);
 }
 
-TEST_F(VideoQualityAnalysisTest, GetMaxRepeatedFramesOneValue) {
-  EXPECT_EQ(1, GetMaxRepeatedFrames(CalculateFrameClusters({1})));
+TEST_F(VideoQualityAnalysisTest, CalculateFrameClustersOneValue) {
+  std::ofstream stats_file;
+
+  stats_file.open(stats_filename_.c_str());
+  stats_file << "frame_0001 0101\n";
+  stats_file.close();
+
+  FILE* stats_filef = fopen(stats_filename_.c_str(), "r");
+  ASSERT_TRUE(stats_filef != NULL);
+
+  auto clusters = CalculateFrameClusters(stats_filef, nullptr);
+  ASSERT_EQ(0, fclose(stats_filef));
+  decltype(clusters) expected = {std::make_pair(101, 1)};
+  ASSERT_EQ(expected, clusters);
 }
 
-TEST_F(VideoQualityAnalysisTest, GetMaxSkippedFramesOneValue) {
-  EXPECT_EQ(0, GetMaxSkippedFrames(CalculateFrameClusters({1})));
+TEST_F(VideoQualityAnalysisTest, CalculateFrameClustersOneOneTwo) {
+  std::ofstream stats_file;
+
+  stats_file.open(stats_filename_.c_str());
+  stats_file << "frame_0001 0101\n";
+  stats_file << "frame_0002 0101\n";
+  stats_file << "frame_0003 0102\n";
+  stats_file.close();
+
+  FILE* stats_filef = fopen(stats_filename_.c_str(), "r");
+  ASSERT_TRUE(stats_filef != NULL);
+
+  auto clusters = CalculateFrameClusters(stats_filef, nullptr);
+  ASSERT_EQ(0, fclose(stats_filef));
+  decltype(clusters) expected = {std::make_pair(101, 2),
+                                 std::make_pair(102, 1)};
+  ASSERT_EQ(expected, clusters);
 }
 
-TEST_F(VideoQualityAnalysisTest, GetTotalNumberOfSkippedFramesOneValue) {
-  EXPECT_EQ(0, GetTotalNumberOfSkippedFrames(CalculateFrameClusters({1})));
+TEST_F(VideoQualityAnalysisTest, CalculateFrameClustersOneOneErrErrThree) {
+  std::ofstream stats_file;
+
+  stats_file.open(stats_filename_.c_str());
+  stats_file << "frame_0001 0101\n";
+  stats_file << "frame_0002 0101\n";
+  stats_file << "frame_0003 Barcode error\n";
+  stats_file << "frame_0004 Barcode error\n";
+  stats_file << "frame_0005 0103\n";
+  stats_file.close();
+
+  FILE* stats_filef = fopen(stats_filename_.c_str(), "r");
+  ASSERT_TRUE(stats_filef != NULL);
+
+  auto clusters = CalculateFrameClusters(stats_filef, nullptr);
+  ASSERT_EQ(0, fclose(stats_filef));
+  decltype(clusters) expected = {std::make_pair(101, 2),
+                                 std::make_pair(DECODE_ERROR, 2),
+                                 std::make_pair(103, 1)};
+  ASSERT_EQ(expected, clusters);
 }
 
-TEST_F(VideoQualityAnalysisTest, GetMaxRepeatedFramesOneOneTwo) {
-  EXPECT_EQ(2, GetMaxRepeatedFrames(CalculateFrameClusters({1, 1, 2})));
+TEST_F(VideoQualityAnalysisTest, CalculateFrameClustersErrErr) {
+  std::ofstream stats_file;
+
+  stats_file.open(stats_filename_.c_str());
+  stats_file << "frame_0001 Barcode error\n";
+  stats_file << "frame_0002 Barcode error\n";
+  stats_file.close();
+
+  FILE* stats_filef = fopen(stats_filename_.c_str(), "r");
+  ASSERT_TRUE(stats_filef != NULL);
+
+  auto clusters = CalculateFrameClusters(stats_filef, nullptr);
+  ASSERT_EQ(0, fclose(stats_filef));
+  decltype(clusters) expected = {std::make_pair(DECODE_ERROR, 2)};
+  ASSERT_EQ(expected, clusters);
 }
 
-TEST_F(VideoQualityAnalysisTest, GetMaxSkippedFramesOneOneTwo) {
-  EXPECT_EQ(0, GetMaxSkippedFrames(CalculateFrameClusters({1, 1, 2})));
+TEST_F(VideoQualityAnalysisTest, CalculateFrameClustersOneOneErrErrOneOne) {
+  std::ofstream stats_file;
+
+  stats_file.open(stats_filename_.c_str());
+  stats_file << "frame_0001 0101\n";
+  stats_file << "frame_0002 0101\n";
+  stats_file << "frame_0003 Barcode error\n";
+  stats_file << "frame_0004 Barcode error\n";
+  stats_file << "frame_0005 0101\n";
+  stats_file << "frame_0006 0101\n";
+  stats_file.close();
+
+  FILE* stats_filef = fopen(stats_filename_.c_str(), "r");
+  ASSERT_TRUE(stats_filef != NULL);
+
+  auto clusters = CalculateFrameClusters(stats_filef, nullptr);
+  ASSERT_EQ(0, fclose(stats_filef));
+  decltype(clusters) expected = {std::make_pair(101, 6)};
+  ASSERT_EQ(expected, clusters);
 }
 
-TEST_F(VideoQualityAnalysisTest, GetTotalNumberOfSkippedFramesOneOneTwo) {
-  EXPECT_EQ(0,
-            GetTotalNumberOfSkippedFrames(CalculateFrameClusters({1, 1, 2})));
-}
+TEST_F(VideoQualityAnalysisTest, CalculateFrameClustersEmpty) {
+  std::ofstream stats_file;
 
-TEST_F(VideoQualityAnalysisTest, GetMaxRepeatedFramesEmpty) {
-  EXPECT_EQ(0, GetMaxRepeatedFrames({}));
-}
+  stats_file.open(stats_filename_.c_str());
+  stats_file.close();
 
-TEST_F(VideoQualityAnalysisTest, GetMaxSkippedFramesEmpty) {
-  EXPECT_EQ(0, GetMaxSkippedFrames({}));
-}
+  FILE* stats_filef = fopen(stats_filename_.c_str(), "r");
+  ASSERT_TRUE(stats_filef != NULL);
 
-TEST_F(VideoQualityAnalysisTest, GetTotalNumberOfSkippedFramesEmpty) {
-  EXPECT_EQ(0, GetTotalNumberOfSkippedFrames({}));
+  auto clusters = CalculateFrameClusters(stats_filef, nullptr);
+  ASSERT_EQ(0, fclose(stats_filef));
+  decltype(clusters) expected;
+  ASSERT_EQ(expected, clusters);
 }
-
 }  // namespace test
 }  // namespace webrtc
diff --git a/rtc_tools/frame_analyzer/video_temporal_aligner.cc b/rtc_tools/frame_analyzer/video_temporal_aligner.cc
deleted file mode 100644
index 85eece8..0000000
--- a/rtc_tools/frame_analyzer/video_temporal_aligner.cc
+++ /dev/null
@@ -1,217 +0,0 @@
-/*
- *  Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
- *
- *  Use of this source code is governed by a BSD-style license
- *  that can be found in the LICENSE file in the root of the source
- *  tree. An additional intellectual property rights grant can be found
- *  in the file PATENTS.  All contributing project authors may
- *  be found in the AUTHORS file in the root of the source tree.
- */
-
-#include "rtc_tools/frame_analyzer/video_temporal_aligner.h"
-
-#include <algorithm>
-#include <cmath>
-#include <deque>
-#include <limits>
-#include <vector>
-
-#include "api/video/i420_buffer.h"
-#include "rtc_base/checks.h"
-#include "rtc_base/refcountedobject.h"
-#include "rtc_tools/frame_analyzer/video_quality_analysis.h"
-#include "third_party/libyuv/include/libyuv/compare.h"
-
-namespace webrtc {
-namespace test {
-
-namespace {
-
-// This constant controls how many frames we look ahead while seeking for the
-// match for the next frame. Note that we may span bigger gaps than this number
-// since we reset the counter as soon as we find a better match. The seeking
-// will stop when there is no improvement in the next kNumberOfFramesLookAhead
-// frames. Typically, the SSIM will improve as we get closer and closer to the
-// real match.
-const int kNumberOfFramesLookAhead = 60;
-
-// Helper class that takes a video and generates an infinite looping video.
-class LoopingVideo : public rtc::RefCountedObject<Video> {
- public:
-  explicit LoopingVideo(const rtc::scoped_refptr<Video>& video)
-      : video_(video) {}
-
-  size_t number_of_frames() const override {
-    return std::numeric_limits<size_t>::max();
-  }
-
-  rtc::scoped_refptr<I420BufferInterface> GetFrame(
-      size_t index) const override {
-    return video_->GetFrame(index % video_->number_of_frames());
-  }
-
- private:
-  const rtc::scoped_refptr<Video> video_;
-};
-
-// Helper class that take a vector of frame indices and a video and produces a
-// new video where the frames have been reshuffled.
-class ReorderedVideo : public rtc::RefCountedObject<Video> {
- public:
-  ReorderedVideo(const rtc::scoped_refptr<Video>& video,
-                 const std::vector<size_t>& indices)
-      : video_(video), indices_(indices) {}
-
-  size_t number_of_frames() const override { return indices_.size(); }
-
-  rtc::scoped_refptr<I420BufferInterface> GetFrame(
-      size_t index) const override {
-    return video_->GetFrame(indices_.at(index));
-  }
-
- private:
-  const rtc::scoped_refptr<Video> video_;
-  const std::vector<size_t> indices_;
-};
-
-// Helper class that takes a video and produces a downscaled video.
-class DownscaledVideo : public rtc::RefCountedObject<Video> {
- public:
-  DownscaledVideo(float scale_factor, const rtc::scoped_refptr<Video>& video)
-      : scale_factor_(scale_factor), video_(video) {}
-
-  size_t number_of_frames() const override {
-    return video_->number_of_frames();
-  }
-
-  rtc::scoped_refptr<I420BufferInterface> GetFrame(
-      size_t index) const override {
-    const rtc::scoped_refptr<I420BufferInterface> frame =
-        video_->GetFrame(index);
-    rtc::scoped_refptr<I420Buffer> downscaled_frame = I420Buffer::Create(
-        static_cast<int>(round(scale_factor_ * frame->width())),
-        static_cast<int>(round(scale_factor_ * frame->height())));
-    downscaled_frame->ScaleFrom(*frame);
-    return downscaled_frame;
-  }
-
- private:
-  const float scale_factor_;
-  const rtc::scoped_refptr<Video> video_;
-};
-
-// Helper class that takes a video and caches the latest frame access. This
-// improves performance a lot since the original source is often from a file.
-class CachedVideo : public rtc::RefCountedObject<Video> {
- public:
-  CachedVideo(int max_cache_size, const rtc::scoped_refptr<Video>& video)
-      : max_cache_size_(max_cache_size), video_(video) {}
-
-  size_t number_of_frames() const override {
-    return video_->number_of_frames();
-  }
-
-  rtc::scoped_refptr<I420BufferInterface> GetFrame(
-      size_t index) const override {
-    for (const CachedFrame& cached_frame : cache_) {
-      if (cached_frame.index == index)
-        return cached_frame.frame;
-    }
-
-    rtc::scoped_refptr<I420BufferInterface> frame = video_->GetFrame(index);
-    cache_.push_front({index, frame});
-    if (cache_.size() > max_cache_size_)
-      cache_.pop_back();
-
-    return frame;
-  }
-
- private:
-  struct CachedFrame {
-    size_t index;
-    rtc::scoped_refptr<I420BufferInterface> frame;
-  };
-
-  const size_t max_cache_size_;
-  const rtc::scoped_refptr<Video> video_;
-  mutable std::deque<CachedFrame> cache_;
-};
-
-// Try matching the test frame against all frames in the reference video and
-// return the index of the best matching frame.
-size_t FindBestMatch(const rtc::scoped_refptr<I420BufferInterface>& test_frame,
-                     const Video& reference_video) {
-  std::vector<double> ssim;
-  for (const auto& ref_frame : reference_video)
-    ssim.push_back(Ssim(test_frame, ref_frame));
-  return std::distance(ssim.begin(),
-                       std::max_element(ssim.begin(), ssim.end()));
-}
-
-// Find and return the index of the frame matching the test frame. The search
-// starts at the starting index and continues until there is no better match
-// within the next kNumberOfFramesLookAhead frames.
-size_t FindNextMatch(const rtc::scoped_refptr<I420BufferInterface>& test_frame,
-                     const Video& reference_video,
-                     size_t start_index) {
-  const double start_ssim =
-      Ssim(test_frame, reference_video.GetFrame(start_index));
-  for (int i = 1; i < kNumberOfFramesLookAhead; ++i) {
-    const size_t next_index = start_index + i;
-    // If we find a better match, restart the search at that point.
-    if (start_ssim < Ssim(test_frame, reference_video.GetFrame(next_index)))
-      return FindNextMatch(test_frame, reference_video, next_index);
-  }
-  // The starting index was the best match.
-  return start_index;
-}
-
-}  // namespace
-
-std::vector<size_t> FindMatchingFrameIndices(
-    const rtc::scoped_refptr<Video>& reference_video,
-    const rtc::scoped_refptr<Video>& test_video) {
-  // This is done to get a 10x speedup. We don't need the full resolution in
-  // order to match frames, and we should limit file access and not read the
-  // same memory tens of times.
-  const float kScaleFactor = 0.25f;
-  const rtc::scoped_refptr<Video> cached_downscaled_reference_video =
-      new CachedVideo(kNumberOfFramesLookAhead,
-                      new DownscaledVideo(kScaleFactor, reference_video));
-  const rtc::scoped_refptr<Video> downscaled_test_video =
-      new DownscaledVideo(kScaleFactor, test_video);
-
-  // Assume the video is looping around.
-  const rtc::scoped_refptr<Video> looping_reference_video =
-      new LoopingVideo(cached_downscaled_reference_video);
-
-  std::vector<size_t> match_indices;
-  for (const rtc::scoped_refptr<I420BufferInterface>& test_frame :
-       *downscaled_test_video) {
-    if (match_indices.empty()) {
-      // First frame.
-      match_indices.push_back(
-          FindBestMatch(test_frame, *cached_downscaled_reference_video));
-    } else {
-      match_indices.push_back(FindNextMatch(
-          test_frame, *looping_reference_video, match_indices.back()));
-    }
-  }
-
-  return match_indices;
-}
-
-rtc::scoped_refptr<Video> ReorderVideo(const rtc::scoped_refptr<Video>& video,
-                                       const std::vector<size_t>& indices) {
-  return new ReorderedVideo(video, indices);
-}
-
-rtc::scoped_refptr<Video> GenerateAlignedReferenceVideo(
-    const rtc::scoped_refptr<Video>& reference_video,
-    const rtc::scoped_refptr<Video>& test_video) {
-  return ReorderVideo(new LoopingVideo(reference_video),
-                      FindMatchingFrameIndices(reference_video, test_video));
-}
-
-}  // namespace test
-}  // namespace webrtc
diff --git a/rtc_tools/frame_analyzer/video_temporal_aligner.h b/rtc_tools/frame_analyzer/video_temporal_aligner.h
deleted file mode 100644
index 6a64636..0000000
--- a/rtc_tools/frame_analyzer/video_temporal_aligner.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- *  Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
- *
- *  Use of this source code is governed by a BSD-style license
- *  that can be found in the LICENSE file in the root of the source
- *  tree. An additional intellectual property rights grant can be found
- *  in the file PATENTS.  All contributing project authors may
- *  be found in the AUTHORS file in the root of the source tree.
- */
-
-#ifndef RTC_TOOLS_FRAME_ANALYZER_VIDEO_TEMPORAL_ALIGNER_H_
-#define RTC_TOOLS_FRAME_ANALYZER_VIDEO_TEMPORAL_ALIGNER_H_
-
-#include <vector>
-
-#include "rtc_tools/y4m_file_reader.h"
-
-namespace webrtc {
-namespace test {
-
-// Returns a vector with the same size as the given test video. Each index
-// corresponds to what reference frame that test frame matches to. These
-// indices are strictly increasing and might loop around the reference video,
-// e.g. their values can be bigger than the number of frames in the reference
-// video and they should be interpreted modulo that size. The matching frames
-// will be determined by maximizing SSIM.
-std::vector<size_t> FindMatchingFrameIndices(
-    const rtc::scoped_refptr<Video>& reference_video,
-    const rtc::scoped_refptr<Video>& test_video);
-
-// Generate a new video using the frames from the original video. The returned
-// video will have the same number of frames as the size of |indices|, and
-// frame nr i in the returned video will point to frame nr indices[i] in the
-// original video.
-rtc::scoped_refptr<Video> ReorderVideo(const rtc::scoped_refptr<Video>& video,
-                                       const std::vector<size_t>& indices);
-
-// Returns a modified version of the reference video where the frames have
-// been aligned to the test video. The test video is assumed to be captured
-// during a quality measurement test where the reference video is the source.
-// The test video may start at an arbitrary position in the reference video
-// and there might be missing frames. The reference video is assumed to loop
-// over when it reaches the end. The returned result is a version of the
-// reference video where the missing frames are left out so it aligns to the
-// test video.
-rtc::scoped_refptr<Video> GenerateAlignedReferenceVideo(
-    const rtc::scoped_refptr<Video>& reference_video,
-    const rtc::scoped_refptr<Video>& test_video);
-
-}  // namespace test
-}  // namespace webrtc
-
-#endif  // RTC_TOOLS_FRAME_ANALYZER_VIDEO_TEMPORAL_ALIGNER_H_
diff --git a/rtc_tools/frame_analyzer/video_temporal_aligner_unittest.cc b/rtc_tools/frame_analyzer/video_temporal_aligner_unittest.cc
deleted file mode 100644
index 806fe90..0000000
--- a/rtc_tools/frame_analyzer/video_temporal_aligner_unittest.cc
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- *  Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
- *
- *  Use of this source code is governed by a BSD-style license
- *  that can be found in the LICENSE file in the root of the source
- *  tree. An additional intellectual property rights grant can be found
- *  in the file PATENTS.  All contributing project authors may
- *  be found in the AUTHORS file in the root of the source tree.
- */
-
-#include "rtc_tools/frame_analyzer/video_temporal_aligner.h"
-
-#include "rtc_tools/frame_analyzer/video_quality_analysis.h"
-#include "rtc_tools/y4m_file_reader.h"
-#include "test/gtest.h"
-#include "test/testsupport/fileutils.h"
-
-namespace webrtc {
-namespace test {
-
-class VideoTemporalAlignerTest : public ::testing::Test {
- protected:
-  void SetUp() {
-    reference_video =
-        Y4mFile::Open(ResourcePath("reference_video_640x360_30fps", "y4m"));
-    ASSERT_TRUE(reference_video);
-  }
-
-  rtc::scoped_refptr<Y4mFile> reference_video;
-};
-
-TEST_F(VideoTemporalAlignerTest, FindMatchingFrameIndicesEmpty) {
-  rtc::scoped_refptr<Video> empty_test_video =
-      ReorderVideo(reference_video, std::vector<size_t>());
-
-  const std::vector<size_t> matched_indices =
-      FindMatchingFrameIndices(reference_video, empty_test_video);
-
-  EXPECT_TRUE(matched_indices.empty());
-}
-
-TEST_F(VideoTemporalAlignerTest, FindMatchingFrameIndicesIdentity) {
-  const std::vector<size_t> indices =
-      FindMatchingFrameIndices(reference_video, reference_video);
-
-  EXPECT_EQ(indices.size(), reference_video->number_of_frames());
-  for (size_t i = 0; i < indices.size(); ++i)
-    EXPECT_EQ(i, indices[i]);
-}
-
-TEST_F(VideoTemporalAlignerTest, FindMatchingFrameIndicesDuplicateFrames) {
-  const std::vector<size_t> indices = {2, 2, 2, 2};
-
-  // Generate a test video based on this sequence.
-  rtc::scoped_refptr<Video> test_video = ReorderVideo(reference_video, indices);
-
-  const std::vector<size_t> matched_indices =
-      FindMatchingFrameIndices(reference_video, test_video);
-
-  EXPECT_EQ(indices, matched_indices);
-}
-
-TEST_F(VideoTemporalAlignerTest, FindMatchingFrameIndicesLoopAround) {
-  std::vector<size_t> indices;
-  for (size_t i = 0; i < reference_video->number_of_frames() * 2; ++i)
-    indices.push_back(i % reference_video->number_of_frames());
-
-  // Generate a test video based on this sequence.
-  rtc::scoped_refptr<Video> test_video = ReorderVideo(reference_video, indices);
-
-  const std::vector<size_t> matched_indices =
-      FindMatchingFrameIndices(reference_video, test_video);
-
-  for (size_t i = 0; i < matched_indices.size(); ++i)
-    EXPECT_EQ(i, matched_indices[i]);
-}
-
-TEST_F(VideoTemporalAlignerTest, FindMatchingFrameIndicesStressTest) {
-  std::vector<size_t> indices;
-  // Arbitrary start index.
-  const size_t start_index = 12345;
-  // Generate some generic sequence of frames.
-  indices.push_back(start_index % reference_video->number_of_frames());
-  indices.push_back((start_index + 1) % reference_video->number_of_frames());
-  indices.push_back((start_index + 2) % reference_video->number_of_frames());
-  indices.push_back((start_index + 5) % reference_video->number_of_frames());
-  indices.push_back((start_index + 10) % reference_video->number_of_frames());
-  indices.push_back((start_index + 20) % reference_video->number_of_frames());
-  indices.push_back((start_index + 20) % reference_video->number_of_frames());
-  indices.push_back((start_index + 22) % reference_video->number_of_frames());
-  indices.push_back((start_index + 32) % reference_video->number_of_frames());
-
-  // Generate a test video based on this sequence.
-  rtc::scoped_refptr<Video> test_video = ReorderVideo(reference_video, indices);
-
-  const std::vector<size_t> matched_indices =
-      FindMatchingFrameIndices(reference_video, test_video);
-
-  EXPECT_EQ(indices, matched_indices);
-}
-
-TEST_F(VideoTemporalAlignerTest, GenerateAlignedReferenceVideo) {
-  // Arbitrary start index.
-  const size_t start_index = 12345;
-  std::vector<size_t> indices;
-  const size_t frame_step = 10;
-  for (size_t i = 0; i < reference_video->number_of_frames() / frame_step;
-       ++i) {
-    indices.push_back((start_index + i * frame_step) %
-                      reference_video->number_of_frames());
-  }
-
-  // Generate a test video based on this sequence.
-  rtc::scoped_refptr<Video> test_video = ReorderVideo(reference_video, indices);
-
-  rtc::scoped_refptr<Video> aligned_reference_video =
-      GenerateAlignedReferenceVideo(reference_video, test_video);
-
-  // Assume perfect match, i.e. ssim == 1, for all frames.
-  for (size_t i = 0; i < test_video->number_of_frames(); ++i) {
-    EXPECT_EQ(1.0, Ssim(test_video->GetFrame(i),
-                        aligned_reference_video->GetFrame(i)));
-  }
-}
-
-}  // namespace test
-}  // namespace webrtc
diff --git a/rtc_tools/psnr_ssim_analyzer/psnr_ssim_analyzer.cc b/rtc_tools/psnr_ssim_analyzer/psnr_ssim_analyzer.cc
index b995f54..dc63aca 100644
--- a/rtc_tools/psnr_ssim_analyzer/psnr_ssim_analyzer.cc
+++ b/rtc_tools/psnr_ssim_analyzer/psnr_ssim_analyzer.cc
@@ -8,42 +8,70 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
+#include <limits.h>
 #include <stdio.h>
 #include <stdlib.h>
 
+#include <map>
 #include <string>
+#include <vector>
 
 #include "rtc_tools/frame_analyzer/video_quality_analysis.h"
 #include "rtc_tools/simple_command_line_parser.h"
-#include "rtc_tools/y4m_file_reader.h"
 
-void CompareFiles(
-    const rtc::scoped_refptr<webrtc::test::Video>& reference_video,
-    const rtc::scoped_refptr<webrtc::test::Video>& test_video,
-    const char* results_file_name) {
+#define MAX_NUM_FRAMES_PER_FILE INT_MAX
+
+void CompareFiles(const char* reference_file_name,
+                  const char* test_file_name,
+                  const char* results_file_name,
+                  int width,
+                  int height) {
+  // Check if the reference_file_name ends with "y4m".
+  bool y4m_mode = false;
+  if (std::string(reference_file_name).find("y4m") != std::string::npos) {
+    y4m_mode = true;
+  }
+
   FILE* results_file = fopen(results_file_name, "w");
 
-  const size_t num_frames = std::min(reference_video->number_of_frames(),
-                                     test_video->number_of_frames());
-  for (size_t i = 0; i < num_frames; ++i) {
-    const rtc::scoped_refptr<webrtc::I420BufferInterface> ref_buffer =
-        reference_video->GetFrame(i);
-    const rtc::scoped_refptr<webrtc::I420BufferInterface> test_buffer =
-        test_video->GetFrame(i);
+  int size = webrtc::test::GetI420FrameSize(width, height);
+
+  // Allocate buffers for test and reference frames.
+  uint8_t* test_frame = new uint8_t[size];
+  uint8_t* ref_frame = new uint8_t[size];
+
+  bool read_result = true;
+  for (int frame_counter = 0; frame_counter < MAX_NUM_FRAMES_PER_FILE;
+       ++frame_counter) {
+    read_result &=
+        (y4m_mode)
+            ? webrtc::test::ExtractFrameFromY4mFile(
+                  reference_file_name, width, height, frame_counter, ref_frame)
+            : webrtc::test::ExtractFrameFromYuvFile(
+                  reference_file_name, width, height, frame_counter, ref_frame);
+    read_result &= webrtc::test::ExtractFrameFromYuvFile(
+        test_file_name, width, height, frame_counter, test_frame);
+
+    if (!read_result)
+      break;
 
     // Calculate the PSNR and SSIM.
-    double result_psnr = webrtc::test::Psnr(ref_buffer, test_buffer);
-    double result_ssim = webrtc::test::Ssim(ref_buffer, test_buffer);
-    fprintf(results_file, "Frame: %zu, PSNR: %f, SSIM: %f\n", i, result_psnr,
-            result_ssim);
+    double result_psnr = webrtc::test::CalculateMetrics(
+        webrtc::test::kPSNR, ref_frame, test_frame, width, height);
+    double result_ssim = webrtc::test::CalculateMetrics(
+        webrtc::test::kSSIM, ref_frame, test_frame, width, height);
+    fprintf(results_file, "Frame: %d, PSNR: %f, SSIM: %f\n", frame_counter,
+            result_psnr, result_ssim);
   }
+  delete[] test_frame;
+  delete[] ref_frame;
 
   fclose(results_file);
 }
 
 /*
  * A tool running PSNR and SSIM analysis on two videos - a reference video and a
- * test video. The two videos should be I420 Y4M videos.
+ * test video. The two videos should be I420 YUV videos.
  * The tool just runs PSNR and SSIM on the corresponding frames in the test and
  * the reference videos until either the first or the second video runs out of
  * frames. The result is written in a results text file in the format:
@@ -54,7 +82,8 @@
  *
  * Usage:
  * psnr_ssim_analyzer --reference_file=<name_of_file> --test_file=<name_of_file>
- * --results_file=<name_of_file>
+ * --results_file=<name_of_file> --width=<width_of_frames>
+ * --height=<height_of_frames>
  */
 int main(int argc, char* argv[]) {
   std::string program_name = argv[0];
@@ -64,8 +93,12 @@
       "Example usage:\n" +
       program_name +
       " --reference_file=ref.yuv "
-      "--test_file=test.yuv --results_file=results.txt\n"
+      "--test_file=test.yuv --results_file=results.txt --width=320 "
+      "--height=240\n"
       "Command line flags:\n"
+      "  - width(int): The width of the reference and test files. Default: -1\n"
+      "  - height(int): The height of the reference and test files. "
+      " Default: -1\n"
       "  - reference_file(string): The reference YUV file to compare against."
       " Default: ref.yuv\n"
       "  - test_file(string): The test YUV file to run the analysis for."
@@ -79,6 +112,8 @@
   parser.Init(argc, argv);
   parser.SetUsageMessage(usage);
 
+  parser.SetFlag("width", "-1");
+  parser.SetFlag("height", "-1");
   parser.SetFlag("results_file", "results.txt");
   parser.SetFlag("reference_file", "ref.yuv");
   parser.SetFlag("test_file", "test.yuv");
@@ -92,26 +127,16 @@
   }
   parser.PrintEnteredFlags();
 
-  rtc::scoped_refptr<webrtc::test::Y4mFile> reference_video =
-      webrtc::test::Y4mFile::Open(parser.GetFlag("reference_file"));
-  rtc::scoped_refptr<webrtc::test::Y4mFile> test_video =
-      webrtc::test::Y4mFile::Open(parser.GetFlag("test_file"));
+  int width = strtol((parser.GetFlag("width")).c_str(), NULL, 10);
+  int height = strtol((parser.GetFlag("height")).c_str(), NULL, 10);
 
-  if (!reference_video || !test_video) {
-    fprintf(stderr, "Error opening video files\n");
-    return 0;
-  }
-  if (reference_video->width() != test_video->width() ||
-      reference_video->height() != test_video->height()) {
-    fprintf(stderr,
-            "Reference and test video files do not have same size: %dx%d "
-            "versus %dx%d\n",
-            reference_video->width(), reference_video->height(),
-            test_video->width(), test_video->height());
-    return 0;
+  if (width <= 0 || height <= 0) {
+    fprintf(stderr, "Error: width or height cannot be <= 0!\n");
+    return -1;
   }
 
-  CompareFiles(reference_video, test_video,
-               parser.GetFlag("results_file").c_str());
+  CompareFiles(parser.GetFlag("reference_file").c_str(),
+               parser.GetFlag("test_file").c_str(),
+               parser.GetFlag("results_file").c_str(), width, height);
   return 0;
 }
diff --git a/rtc_tools/y4m_file_reader.cc b/rtc_tools/y4m_file_reader.cc
deleted file mode 100644
index ea8a741..0000000
--- a/rtc_tools/y4m_file_reader.cc
+++ /dev/null
@@ -1,232 +0,0 @@
-/*
- *  Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
- *
- *  Use of this source code is governed by a BSD-style license
- *  that can be found in the LICENSE file in the root of the source
- *  tree. An additional intellectual property rights grant can be found
- *  in the file PATENTS.  All contributing project authors may
- *  be found in the AUTHORS file in the root of the source tree.
- */
-
-#include "rtc_tools/y4m_file_reader.h"
-
-#include <algorithm>
-#include <cmath>
-#include <cstdio>
-#include <string>
-#include <utility>
-
-#include "absl/types/optional.h"
-#include "api/video/i420_buffer.h"
-#include "rtc_base/logging.h"
-#include "rtc_base/refcountedobject.h"
-#include "rtc_base/string_to_number.h"
-#include "rtc_base/stringencode.h"
-#include "rtc_base/stringutils.h"
-
-namespace webrtc {
-namespace test {
-
-Video::Iterator::Iterator(const rtc::scoped_refptr<const Video>& video,
-                          size_t index)
-    : video_(video), index_(index) {}
-
-Video::Iterator::Iterator(const Video::Iterator& other) = default;
-Video::Iterator::Iterator(Video::Iterator&& other) = default;
-Video::Iterator& Video::Iterator::operator=(Video::Iterator&&) = default;
-Video::Iterator& Video::Iterator::operator=(const Video::Iterator&) = default;
-Video::Iterator::~Iterator() = default;
-
-rtc::scoped_refptr<I420BufferInterface> Video::Iterator::operator*() const {
-  return video_->GetFrame(index_);
-}
-bool Video::Iterator::operator==(const Video::Iterator& other) const {
-  return index_ == other.index_;
-}
-bool Video::Iterator::operator!=(const Video::Iterator& other) const {
-  return !(*this == other);
-}
-
-Video::Iterator Video::Iterator::operator++(int) {
-  const Iterator copy = *this;
-  ++*this;
-  return copy;
-}
-
-Video::Iterator& Video::Iterator::operator++() {
-  ++index_;
-  return *this;
-}
-
-Video::Iterator Video::begin() const {
-  return Iterator(this, 0);
-}
-
-Video::Iterator Video::end() const {
-  return Iterator(this, number_of_frames());
-}
-
-rtc::scoped_refptr<Y4mFile> Y4mFile::Open(const std::string& file_name) {
-  FILE* file = fopen(file_name.c_str(), "rb");
-  if (file == nullptr) {
-    RTC_LOG(LS_ERROR) << "Could not open input file for reading: " << file_name;
-    return nullptr;
-  }
-
-  int parse_file_header_result = -1;
-  fscanf(file, "YUV4MPEG2 %n", &parse_file_header_result);
-  if (parse_file_header_result == -1) {
-    RTC_LOG(LS_ERROR) << "File " << file_name
-                      << " does not start with YUV4MPEG2 header";
-    return nullptr;
-  }
-
-  std::string header_line;
-  while (true) {
-    const int c = fgetc(file);
-    if (c == EOF) {
-      RTC_LOG(LS_ERROR) << "Could not read header line";
-      return nullptr;
-    }
-    if (c == '\n')
-      break;
-    header_line.push_back(static_cast<char>(c));
-  }
-
-  absl::optional<int> width;
-  absl::optional<int> height;
-  absl::optional<float> fps;
-
-  std::vector<std::string> fields;
-  rtc::tokenize(header_line, ' ', &fields);
-  for (const std::string& field : fields) {
-    const char prefix = field.front();
-    const std::string suffix = field.substr(1);
-    switch (prefix) {
-      case 'W':
-        width = rtc::StringToNumber<int>(suffix);
-        break;
-      case 'H':
-        height = rtc::StringToNumber<int>(suffix);
-        break;
-      case 'C':
-        if (suffix != "420" && suffix != "420mpeg2") {
-          RTC_LOG(LS_ERROR)
-              << "Does not support any other color space than I420 or "
-                 "420mpeg2, but was: "
-              << suffix;
-          return nullptr;
-        }
-        break;
-      case 'F': {
-        std::vector<std::string> fraction;
-        rtc::tokenize(suffix, ':', &fraction);
-        if (fraction.size() == 2) {
-          const absl::optional<int> numerator =
-              rtc::StringToNumber<int>(fraction[0]);
-          const absl::optional<int> denominator =
-              rtc::StringToNumber<int>(fraction[1]);
-          if (numerator && denominator && *denominator != 0)
-            fps = *numerator / static_cast<float>(*denominator);
-          break;
-        }
-      }
-    }
-  }
-  if (!width || !height) {
-    RTC_LOG(LS_ERROR) << "Could not find width and height in file header";
-    return nullptr;
-  }
-  if (!fps) {
-    RTC_LOG(LS_ERROR) << "Could not find fps in file header";
-    return nullptr;
-  }
-  RTC_LOG(LS_INFO) << "Video has resolution: " << *width << "x" << *height
-                   << " " << *fps << " fps";
-  if (*width % 2 != 0 || *height % 2 != 0) {
-    RTC_LOG(LS_ERROR)
-        << "Only supports even width/height so that chroma size is a "
-           "whole number.";
-    return nullptr;
-  }
-
-  const int i420_frame_size = 3 * *width * *height / 2;
-  std::vector<fpos_t> frame_positions;
-  while (true) {
-    int parse_frame_header_result = -1;
-    fscanf(file, "FRAME\n%n", &parse_frame_header_result);
-    if (parse_frame_header_result == -1) {
-      if (!feof(file)) {
-        RTC_LOG(LS_ERROR) << "Did not find FRAME header, ignoring rest of file";
-      }
-      break;
-    }
-    fpos_t pos;
-    fgetpos(file, &pos);
-    frame_positions.push_back(pos);
-    // Skip over YUV pixel data.
-    fseek(file, i420_frame_size, SEEK_CUR);
-  }
-  if (frame_positions.empty()) {
-    RTC_LOG(LS_ERROR) << "Could not find any frames in the file";
-    return nullptr;
-  }
-  RTC_LOG(LS_INFO) << "Video has " << frame_positions.size() << " frames";
-
-  return new rtc::RefCountedObject<Y4mFile>(*width, *height, *fps,
-                                            frame_positions, file);
-}
-
-size_t Y4mFile::number_of_frames() const {
-  return frame_positions_.size();
-}
-
-rtc::scoped_refptr<I420BufferInterface> Y4mFile::GetFrame(
-    size_t frame_index) const {
-  RTC_CHECK_LT(frame_index, frame_positions_.size());
-
-  fsetpos(file_, &frame_positions_[frame_index]);
-  rtc::scoped_refptr<I420Buffer> buffer = I420Buffer::Create(width_, height_);
-  fread(reinterpret_cast<char*>(buffer->MutableDataY()), /* size= */ 1,
-        width_ * height_, file_);
-  fread(reinterpret_cast<char*>(buffer->MutableDataU()), /* size= */ 1,
-        buffer->ChromaWidth() * buffer->ChromaHeight(), file_);
-  fread(reinterpret_cast<char*>(buffer->MutableDataV()), /* size= */ 1,
-        buffer->ChromaWidth() * buffer->ChromaHeight(), file_);
-
-  if (ferror(file_) != 0) {
-    RTC_LOG(LS_ERROR) << "Could not read YUV data for frame " << frame_index;
-    return nullptr;
-  }
-  return buffer;
-}
-
-int Y4mFile::width() const {
-  return width_;
-}
-
-int Y4mFile::height() const {
-  return height_;
-}
-
-float Y4mFile::fps() const {
-  return fps_;
-}
-
-Y4mFile::Y4mFile(int width,
-                 int height,
-                 float fps,
-                 const std::vector<fpos_t>& frame_positions,
-                 FILE* file)
-    : width_(width),
-      height_(height),
-      fps_(fps),
-      frame_positions_(frame_positions),
-      file_(file) {}
-
-Y4mFile::~Y4mFile() {
-  fclose(file_);
-}
-
-}  // namespace test
-}  // namespace webrtc
diff --git a/rtc_tools/y4m_file_reader.h b/rtc_tools/y4m_file_reader.h
deleted file mode 100644
index cb86c9e..0000000
--- a/rtc_tools/y4m_file_reader.h
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- *  Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
- *
- *  Use of this source code is governed by a BSD-style license
- *  that can be found in the LICENSE file in the root of the source
- *  tree. An additional intellectual property rights grant can be found
- *  in the file PATENTS.  All contributing project authors may
- *  be found in the AUTHORS file in the root of the source tree.
- */
-#ifndef RTC_TOOLS_Y4M_FILE_READER_H_
-#define RTC_TOOLS_Y4M_FILE_READER_H_
-
-#include <cstdio>
-#include <iterator>
-#include <string>
-#include <vector>
-
-#include "api/video/video_frame.h"
-#include "rtc_base/refcount.h"
-
-namespace webrtc {
-namespace test {
-
-// Iterable class representing a sequence of I420 buffers. This class is not
-// thread safe because it is expected to be backed by a file.
-class Video : public rtc::RefCountInterface {
- public:
-  class Iterator {
-   public:
-    typedef int value_type;
-    typedef std::ptrdiff_t difference_type;
-    typedef int* pointer;
-    typedef int& reference;
-    typedef std::input_iterator_tag iterator_category;
-
-    Iterator(const rtc::scoped_refptr<const Video>& video, size_t index);
-    Iterator(const Iterator& other);
-    Iterator(Iterator&& other);
-    Iterator& operator=(Iterator&&);
-    Iterator& operator=(const Iterator&);
-    ~Iterator();
-
-    rtc::scoped_refptr<I420BufferInterface> operator*() const;
-    bool operator==(const Iterator& other) const;
-    bool operator!=(const Iterator& other) const;
-
-    Iterator operator++(int);
-    Iterator& operator++();
-
-   private:
-    rtc::scoped_refptr<const Video> video_;
-    size_t index_;
-  };
-
-  Iterator begin() const;
-  Iterator end() const;
-
-  virtual size_t number_of_frames() const = 0;
-  virtual rtc::scoped_refptr<I420BufferInterface> GetFrame(
-      size_t index) const = 0;
-};
-
-class Y4mFile : public Video {
- public:
-  // This function opens the file and reads it as an .y4m file. It returns null
-  // on failure. The file will be closed when the returned object is destroyed.
-  static rtc::scoped_refptr<Y4mFile> Open(const std::string& file_name);
-
-  size_t number_of_frames() const override;
-
-  rtc::scoped_refptr<I420BufferInterface> GetFrame(
-      size_t frame_index) const override;
-
-  int width() const;
-  int height() const;
-  float fps() const;
-
- protected:
-  Y4mFile(int width,
-          int height,
-          float fps,
-          const std::vector<fpos_t>& frame_positions,
-          FILE* file);
-  ~Y4mFile() override;
-
- private:
-  const int width_;
-  const int height_;
-  const float fps_;
-  const std::vector<fpos_t> frame_positions_;
-  FILE* const file_;
-};
-
-}  // namespace test
-}  // namespace webrtc
-
-#endif  // RTC_TOOLS_Y4M_FILE_READER_H_
diff --git a/rtc_tools/y4m_file_reader_unittest.cc b/rtc_tools/y4m_file_reader_unittest.cc
deleted file mode 100644
index 3c6c92f..0000000
--- a/rtc_tools/y4m_file_reader_unittest.cc
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- *  Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
- *
- *  Use of this source code is governed by a BSD-style license
- *  that can be found in the LICENSE file in the root of the source
- *  tree. An additional intellectual property rights grant can be found
- *  in the file PATENTS.  All contributing project authors may
- *  be found in the AUTHORS file in the root of the source tree.
- */
-
-#include "rtc_tools/y4m_file_reader.h"
-#include "test/gtest.h"
-#include "test/testsupport/fileutils.h"
-
-namespace webrtc {
-namespace test {
-
-class Y4mFileReaderTest : public ::testing::Test {
- public:
-  void SetUp() override {
-    const std::string filename =
-        TempFilename(webrtc::test::OutputPath(), "test_video_file.y4m");
-
-    // Create simple test video of size 6x4.
-    FILE* file = fopen(filename.c_str(), "wb");
-    ASSERT_TRUE(file != nullptr);
-    fprintf(file, "YUV4MPEG2 W6 H4 F57:10 C420 dummyParam\n");
-    fprintf(file, "FRAME\n");
-
-    const int width = 6;
-    const int height = 4;
-    const int i40_size = width * height * 3 / 2;
-    for (int i = 0; i < i40_size; ++i)
-      fputc(static_cast<char>(i), file);
-    fprintf(file, "FRAME\n");
-    for (int i = 0; i < i40_size; ++i)
-      fputc(static_cast<char>(i + i40_size), file);
-    fclose(file);
-
-    // Open the newly created file.
-    video = webrtc::test::Y4mFile::Open(filename);
-    ASSERT_TRUE(video);
-  }
-
-  rtc::scoped_refptr<webrtc::test::Y4mFile> video;
-};
-
-TEST_F(Y4mFileReaderTest, TestParsingFileHeader) {
-  EXPECT_EQ(6, video->width());
-  EXPECT_EQ(4, video->height());
-  EXPECT_EQ(5.7f, video->fps());
-}
-
-TEST_F(Y4mFileReaderTest, TestParsingNumberOfFrames) {
-  EXPECT_EQ(2u, video->number_of_frames());
-}
-
-TEST_F(Y4mFileReaderTest, TestPixelContent) {
-  int cnt = 0;
-  for (const rtc::scoped_refptr<I420BufferInterface> frame : *video) {
-    for (int i = 0; i < 6 * 4; ++i, ++cnt)
-      EXPECT_EQ(cnt, frame->DataY()[i]);
-    for (int i = 0; i < 3 * 2; ++i, ++cnt)
-      EXPECT_EQ(cnt, frame->DataU()[i]);
-    for (int i = 0; i < 3 * 2; ++i, ++cnt)
-      EXPECT_EQ(cnt, frame->DataV()[i]);
-  }
-}
-
-}  // namespace test
-}  // namespace webrtc