Fixed bug in ExtractFrameFromY4mFile API which was not extracting the frames correctly.

Issue: This API was calculating the file_header and frame_header offset only for the first frame which is not the right logic. We need to skip the file and frame header every time we extract a new frame.

Also added a unit test case which compares the extracted frame with the frame stored in text file.

BUG=webrtc:6761

NOPRESUBMIT=true
NOTRY=true

Review-Url: https://codereview.webrtc.org/2529923002
Cr-Commit-Position: refs/heads/master@{#15260}
diff --git a/resources/reference_less_video_test_file.y4m.sha1 b/resources/reference_less_video_test_file.y4m.sha1
new file mode 100644
index 0000000..f9e3048
--- /dev/null
+++ b/resources/reference_less_video_test_file.y4m.sha1
@@ -0,0 +1 @@
+5a1620516daf59870158a66230d7bafd9fe9afa1
\ No newline at end of file
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/webrtc/tools/BUILD.gn b/webrtc/tools/BUILD.gn
index ace0b51..565a0a2 100644
--- a/webrtc/tools/BUILD.gn
+++ b/webrtc/tools/BUILD.gn
@@ -234,7 +234,11 @@
     ]
   }
 
-  tools_unittests_resources = [ "//resources/foreman_cif.yuv" ]
+  tools_unittests_resources = [
+    "//resources/foreman_cif.yuv",
+    "//resources/reference_less_video_test_file.y4m",
+    "//resources/video_quality_analysis_frame.txt",
+  ]
 
   if (is_ios) {
     bundle_data("tools_unittests_bundle_data") {
diff --git a/webrtc/tools/frame_analyzer/video_quality_analysis.cc b/webrtc/tools/frame_analyzer/video_quality_analysis.cc
index b28a5d2..ca78cc0 100644
--- a/webrtc/tools/frame_analyzer/video_quality_analysis.cc
+++ b/webrtc/tools/frame_analyzer/video_quality_analysis.cc
@@ -13,7 +13,6 @@
 #include <assert.h>
 #include <stdio.h>
 #include <stdlib.h>
-
 #include <string>
 
 #define STATS_LINE_LENGTH 32
@@ -126,8 +125,8 @@
                              int frame_number,
                              uint8_t* result_frame) {
   int frame_size = GetI420FrameSize(width, height);
-  int frame_offset = frame_number * frame_size;
-  bool errors = false;
+  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) {
@@ -138,41 +137,43 @@
 
   // 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".
-  // Skip the header if this is the first frame of the file.
-  if (frame_number == 0) {
-    char frame_header[Y4M_FILE_HEADER_MAX_SIZE];
-    size_t bytes_read =
-        fread(frame_header, 1, Y4M_FILE_HEADER_MAX_SIZE, input_file);
-    if (bytes_read != static_cast<size_t>(frame_size) && ferror(input_file)) {
-      fprintf(stdout, "Error while reading first frame from file %s\n",
-          y4m_file_name);
-      fclose(input_file);
-      return false;
-    }
-    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);
+  char frame_header[Y4M_FILE_HEADER_MAX_SIZE];
+  size_t bytes_read =
+      fread(frame_header, 1, Y4M_FILE_HEADER_MAX_SIZE, 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;
   }
+  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, frame_offset + Y4M_FRAME_HEADER_SIZE, SEEK_SET);
+  fseek(input_file, inital_offset + frame_offset + Y4M_FRAME_HEADER_SIZE,
+        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)) {
+  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);
-    errors = true;
+    fclose(input_file);
+    return false;
   }
 
   fclose(input_file);
-  return !errors;
+  return true;
 }
 
 double CalculateMetrics(VideoAnalysisMetricsType video_metrics_type,
diff --git a/webrtc/tools/frame_analyzer/video_quality_analysis_unittest.cc b/webrtc/tools/frame_analyzer/video_quality_analysis_unittest.cc
index f8a4b69..85c4181 100644
--- a/webrtc/tools/frame_analyzer/video_quality_analysis_unittest.cc
+++ b/webrtc/tools/frame_analyzer/video_quality_analysis_unittest.cc
@@ -11,6 +11,7 @@
 // This test doesn't actually verify the output since it's just printed
 // to stdout by void functions, but it's still useful as it executes the code.
 
+#include <stdio.h>
 #include <fstream>
 #include <string>
 
@@ -38,6 +39,31 @@
 };
 FILE* VideoQualityAnalysisTest::logfile_ = NULL;
 
+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);
+  delete[] result_frame;
+  delete[] expected_frame;
+}
+
 TEST_F(VideoQualityAnalysisTest, PrintAnalysisResultsEmpty) {
   ResultsContainer result;
   PrintAnalysisResults(logfile_, "Empty", &result);