Offline screenshare quality test, plus loopback.

BUG=4171
R=mflodman@webrtc.org, pbos@webrtc.org, stefan@webrtc.org

Review URL: https://webrtc-codereview.appspot.com/34109004

Cr-Commit-Position: refs/heads/master@{#8408}
git-svn-id: http://webrtc.googlecode.com/svn/trunk@8408 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/webrtc/test/frame_generator.cc b/webrtc/test/frame_generator.cc
index 4dd76ae..b7eada9 100644
--- a/webrtc/test/frame_generator.cc
+++ b/webrtc/test/frame_generator.cc
@@ -13,6 +13,7 @@
 #include <stdio.h>
 #include <string.h>
 
+#include "webrtc/base/checks.h"
 #include "webrtc/common_video/libyuv/include/webrtc_libyuv.h"
 
 namespace webrtc {
@@ -52,66 +53,98 @@
 
 class YuvFileGenerator : public FrameGenerator {
  public:
-  YuvFileGenerator(FILE* file, size_t width, size_t height)
-      : file_(file), width_(width), height_(height) {
-    assert(file);
+  YuvFileGenerator(std::vector<FILE*> files,
+                   size_t width,
+                   size_t height,
+                   int frame_repeat_count)
+      : file_index_(0),
+        files_(files),
+        width_(width),
+        height_(height),
+        frame_size_(CalcBufferSize(kI420,
+                                   static_cast<int>(width_),
+                                   static_cast<int>(height_))),
+        frame_buffer_(new uint8_t[frame_size_]),
+        frame_display_count_(frame_repeat_count),
+        current_display_count_(0) {
     assert(width > 0);
     assert(height > 0);
-    frame_size_ = CalcBufferSize(
-        kI420, static_cast<int>(width_), static_cast<int>(height_));
-    frame_buffer_ = new uint8_t[frame_size_];
+    ReadNextFrame();
   }
 
   virtual ~YuvFileGenerator() {
-    fclose(file_);
-    delete[] frame_buffer_;
+    for (FILE* file : files_)
+      fclose(file);
   }
 
   virtual I420VideoFrame* NextFrame() OVERRIDE {
-    size_t count = fread(frame_buffer_, 1, frame_size_, file_);
-    if (count < frame_size_) {
-      rewind(file_);
-      return NextFrame();
+    if (frame_display_count_ > 0) {
+      if (current_display_count_ < frame_display_count_) {
+        ++current_display_count_;
+      } else {
+        ReadNextFrame();
+        current_display_count_ = 0;
+      }
     }
 
-    frame_.CreateEmptyFrame(static_cast<int>(width_),
-                            static_cast<int>(height_),
-                            static_cast<int>(width_),
-                            static_cast<int>((width_ + 1) / 2),
-                            static_cast<int>((width_ + 1) / 2));
+    current_frame_.CopyFrame(last_read_frame_);
+    return &current_frame_;
+  }
 
-    ConvertToI420(kI420,
-                  frame_buffer_,
-                  0,
-                  0,
-                  static_cast<int>(width_),
-                  static_cast<int>(height_),
-                  0,
-                  kRotateNone,
-                  &frame_);
-    return &frame_;
+  void ReadNextFrame() {
+    size_t bytes_read =
+        fread(frame_buffer_.get(), 1, frame_size_, files_[file_index_]);
+    if (bytes_read < frame_size_) {
+      // No more frames to read in this file, rewind and move to next file.
+      rewind(files_[file_index_]);
+      file_index_ = (file_index_ + 1) % files_.size();
+      bytes_read = fread(frame_buffer_.get(), 1, frame_size_,
+          files_[file_index_]);
+      assert(bytes_read >= frame_size_);
+    }
+
+    last_read_frame_.CreateEmptyFrame(
+        static_cast<int>(width_), static_cast<int>(height_),
+        static_cast<int>(width_), static_cast<int>((width_ + 1) / 2),
+        static_cast<int>((width_ + 1) / 2));
+
+    ConvertToI420(kI420, frame_buffer_.get(), 0, 0, static_cast<int>(width_),
+                  static_cast<int>(height_), 0, kRotateNone, &last_read_frame_);
   }
 
  private:
-  FILE* file_;
-  size_t width_;
-  size_t height_;
-  size_t frame_size_;
-  uint8_t* frame_buffer_;
-  I420VideoFrame frame_;
+  size_t file_index_;
+  const std::vector<FILE*> files_;
+  const size_t width_;
+  const size_t height_;
+  const size_t frame_size_;
+  const scoped_ptr<uint8_t[]> frame_buffer_;
+  const int frame_display_count_;
+  int current_display_count_;
+  I420VideoFrame current_frame_;
+  I420VideoFrame last_read_frame_;
 };
 }  // namespace
 
-FrameGenerator* FrameGenerator::Create(size_t width, size_t height) {
+FrameGenerator* FrameGenerator::CreateChromaGenerator(size_t width,
+                                                      size_t height) {
   return new ChromaGenerator(width, height);
 }
 
-FrameGenerator* FrameGenerator::CreateFromYuvFile(const char* file,
-                                                  size_t width,
-                                                  size_t height) {
-  FILE* file_handle = fopen(file, "rb");
-  assert(file_handle);
-  return new YuvFileGenerator(file_handle, width, height);
+FrameGenerator* FrameGenerator::CreateFromYuvFile(
+    std::vector<std::string> filenames,
+    size_t width,
+    size_t height,
+    int frame_repeat_count) {
+  assert(!filenames.empty());
+  std::vector<FILE*> files;
+  for (const std::string& filename : filenames) {
+    FILE* file = fopen(filename.c_str(), "rb");
+    DCHECK(file != nullptr);
+    files.push_back(file);
+  }
+
+  return new YuvFileGenerator(files, width, height, frame_repeat_count);
 }
 
 }  // namespace test
diff --git a/webrtc/test/frame_generator.h b/webrtc/test/frame_generator.h
index fe10612..4598de8 100644
--- a/webrtc/test/frame_generator.h
+++ b/webrtc/test/frame_generator.h
@@ -10,6 +10,9 @@
 #ifndef WEBRTC_COMMON_VIDEO_TEST_FRAME_GENERATOR_H_
 #define WEBRTC_COMMON_VIDEO_TEST_FRAME_GENERATOR_H_
 
+#include <string>
+#include <vector>
+
 #include "webrtc/common_video/interface/i420_video_frame.h"
 #include "webrtc/typedefs.h"
 
@@ -24,10 +27,17 @@
   // Returns video frame that remains valid until next call.
   virtual I420VideoFrame* NextFrame() = 0;
 
-  static FrameGenerator* Create(size_t width, size_t height);
-  static FrameGenerator* CreateFromYuvFile(const char* file,
+  // Creates a test frame generator that creates fully saturated frames with
+  // varying U, V values over time.
+  static FrameGenerator* CreateChromaGenerator(size_t width, size_t height);
+
+  // Creates a frame generator that repeatedly plays a set of yuv files.
+  // The frame_repeat_count determines how many times each frame is shown,
+  // with 0 = show the first frame indefinitely, 1 = show each frame once, etc.
+  static FrameGenerator* CreateFromYuvFile(std::vector<std::string> files,
                                            size_t width,
-                                           size_t height);
+                                           size_t height,
+                                           int frame_repeat_count);
 };
 }  // namespace test
 }  // namespace webrtc
diff --git a/webrtc/test/frame_generator_capturer.cc b/webrtc/test/frame_generator_capturer.cc
index d1c17c7..721c29a 100644
--- a/webrtc/test/frame_generator_capturer.cc
+++ b/webrtc/test/frame_generator_capturer.cc
@@ -28,7 +28,8 @@
     int target_fps,
     Clock* clock) {
   FrameGeneratorCapturer* capturer = new FrameGeneratorCapturer(
-      clock, input, FrameGenerator::Create(width, height), target_fps);
+      clock, input, FrameGenerator::CreateChromaGenerator(width, height),
+      target_fps);
   if (!capturer->Init()) {
     delete capturer;
     return NULL;
@@ -39,15 +40,15 @@
 
 FrameGeneratorCapturer* FrameGeneratorCapturer::CreateFromYuvFile(
     VideoSendStreamInput* input,
-    const char* file_name,
+    const std::string& file_name,
     size_t width,
     size_t height,
     int target_fps,
     Clock* clock) {
   FrameGeneratorCapturer* capturer = new FrameGeneratorCapturer(
-      clock,
-      input,
-      FrameGenerator::CreateFromYuvFile(file_name, width, height),
+      clock, input,
+      FrameGenerator::CreateFromYuvFile(std::vector<std::string>(1, file_name),
+                                        width, height, 1),
       target_fps);
   if (!capturer->Init()) {
     delete capturer;
diff --git a/webrtc/test/frame_generator_capturer.h b/webrtc/test/frame_generator_capturer.h
index ee3f0e0..de2874e 100644
--- a/webrtc/test/frame_generator_capturer.h
+++ b/webrtc/test/frame_generator_capturer.h
@@ -10,6 +10,8 @@
 #ifndef WEBRTC_VIDEO_ENGINE_TEST_COMMON_FRAME_GENERATOR_CAPTURER_H_
 #define WEBRTC_VIDEO_ENGINE_TEST_COMMON_FRAME_GENERATOR_CAPTURER_H_
 
+#include <string>
+
 #include "webrtc/system_wrappers/interface/scoped_ptr.h"
 #include "webrtc/test/video_capturer.h"
 #include "webrtc/typedefs.h"
@@ -33,7 +35,7 @@
                                         Clock* clock);
 
   static FrameGeneratorCapturer* CreateFromYuvFile(VideoSendStreamInput* input,
-                                                   const char* file_name,
+                                                   const std::string& file_name,
                                                    size_t width,
                                                    size_t height,
                                                    int target_fps,
@@ -45,12 +47,13 @@
 
   int64_t first_frame_capture_time() const { return first_frame_capture_time_; }
 
- private:
   FrameGeneratorCapturer(Clock* clock,
                          VideoSendStreamInput* input,
                          FrameGenerator* frame_generator,
                          int target_fps);
   bool Init();
+
+ private:
   void InsertFrame();
   static bool Run(void* obj);