Fake VideoCapturer based on FrameGenerator

BUG=1793
R=mflodman@webrtc.org

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

git-svn-id: http://webrtc.googlecode.com/svn/trunk/webrtc@4132 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/video_engine/test/common/frame_generator_capturer.cc b/video_engine/test/common/frame_generator_capturer.cc
new file mode 100644
index 0000000..4b481b9
--- /dev/null
+++ b/video_engine/test/common/frame_generator_capturer.cc
@@ -0,0 +1,116 @@
+/*
+ *  Copyright (c) 2013 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 "webrtc/video_engine/test/common/frame_generator_capturer.h"
+
+#include "webrtc/system_wrappers/interface/clock.h"
+#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
+#include "webrtc/system_wrappers/interface/sleep.h"
+#include "webrtc/system_wrappers/interface/thread_wrapper.h"
+#include "webrtc/video_engine/test/common/frame_generator.h"
+
+namespace webrtc {
+namespace test {
+
+FrameGeneratorCapturer* FrameGeneratorCapturer::Create(
+    newapi::VideoSendStreamInput* input,
+    FrameGenerator* frame_generator,
+    int target_fps,
+    Clock* clock) {
+  FrameGeneratorCapturer* capturer =
+      new FrameGeneratorCapturer(input, frame_generator, target_fps, clock);
+
+  if (!capturer->Init()) {
+    delete capturer;
+    return NULL;
+  }
+
+  return capturer;
+}
+
+FrameGeneratorCapturer::FrameGeneratorCapturer(
+    newapi::VideoSendStreamInput* input,
+    FrameGenerator* frame_generator,
+    int target_fps,
+    Clock* clock)
+    : VideoCapturer(input),
+      sending_(false),
+      clock_(clock),
+      lock_(CriticalSectionWrapper::CreateCriticalSection()),
+      thread_(NULL),
+      frame_generator_(frame_generator),
+      target_fps_(target_fps) {
+  assert(input != NULL);
+  assert(frame_generator != NULL);
+  assert(target_fps > 0);
+}
+
+FrameGeneratorCapturer::~FrameGeneratorCapturer() {
+  Stop();
+
+  if (thread_ != NULL) {
+    if (!thread_->Stop()) {
+      // TODO(pbos): Log a warning instead.
+      assert(!"Couldn't stop FrameGeneratorCapturer thread!");
+    }
+
+    delete thread_;
+  }
+}
+
+bool FrameGeneratorCapturer::Init() {
+  thread_ = ThreadWrapper::CreateThread(FrameGeneratorCapturer::Run,
+                                        this,
+                                        webrtc::kHighPriority,
+                                        "FrameGeneratorCapturer");
+  if (thread_ == NULL)
+    return false;
+  unsigned int thread_id;
+  if (!thread_->Start(thread_id)) {
+    delete thread_;
+    thread_ = NULL;
+    return false;
+  }
+  return true;
+}
+
+bool FrameGeneratorCapturer::Run(void* obj) {
+  static_cast<FrameGeneratorCapturer*>(obj)->InsertFrame();
+  return true;
+}
+
+void FrameGeneratorCapturer::InsertFrame() {
+  int64_t time_start = clock_->TimeInMilliseconds();
+
+  {
+    CriticalSectionScoped cs(lock_);
+    if (sending_)
+      frame_generator_->InsertFrame(input_);
+  }
+
+  int64_t remaining_sleep =
+      1000 / target_fps_ - (clock_->TimeInMilliseconds() - time_start);
+
+  if (remaining_sleep > 0) {
+    SleepMs(static_cast<int>(remaining_sleep));
+  }
+}
+
+void FrameGeneratorCapturer::Start() {
+  CriticalSectionScoped cs(lock_);
+  sending_ = true;
+}
+
+void FrameGeneratorCapturer::Stop() {
+  CriticalSectionScoped cs(lock_);
+  sending_ = false;
+}
+}  // test
+}  // webrtc
diff --git a/video_engine/test/common/frame_generator_capturer.h b/video_engine/test/common/frame_generator_capturer.h
new file mode 100644
index 0000000..383f724
--- /dev/null
+++ b/video_engine/test/common/frame_generator_capturer.h
@@ -0,0 +1,58 @@
+/*
+ *  Copyright (c) 2013 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 WEBRTC_VIDEO_ENGINE_TEST_COMMON_FRAME_GENERATOR_CAPTURER_H_
+#define WEBRTC_VIDEO_ENGINE_TEST_COMMON_FRAME_GENERATOR_CAPTURER_H_
+
+#include "webrtc/video_engine/test/common/video_capturer.h"
+#include "webrtc/typedefs.h"
+
+namespace webrtc {
+
+class Clock;
+class CriticalSectionWrapper;
+class ThreadWrapper;
+
+namespace test {
+
+class FrameGenerator;
+
+class FrameGeneratorCapturer : public VideoCapturer {
+ public:
+  static FrameGeneratorCapturer* Create(newapi::VideoSendStreamInput* input,
+                                        FrameGenerator* frame_generator,
+                                        int target_fps,
+                                        Clock* clock);
+  virtual ~FrameGeneratorCapturer();
+
+  virtual void Start() OVERRIDE;
+  virtual void Stop() OVERRIDE;
+
+ private:
+  FrameGeneratorCapturer(newapi::VideoSendStreamInput* input,
+                         FrameGenerator* frame_generator,
+                         int target_fps,
+                         Clock* clock);
+  bool Init();
+  void InsertFrame();
+  static bool Run(void* obj);
+
+  bool sending_;
+
+  Clock* clock_;
+  CriticalSectionWrapper* lock_;
+  ThreadWrapper* thread_;
+  FrameGenerator* frame_generator_;
+
+  int target_fps_;
+};
+}  // test
+}  // webrtc
+
+#endif  // WEBRTC_VIDEO_ENGINE_TEST_COMMON_FRAME_GENERATOR_CAPTURER_H_
diff --git a/video_engine/test/common/video_capturer.cc b/video_engine/test/common/video_capturer.cc
index af96d44..b90daaa 100644
--- a/video_engine/test/common/video_capturer.cc
+++ b/video_engine/test/common/video_capturer.cc
@@ -8,9 +8,12 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#include "webrtc/video_engine/test/common/vcm_capturer.h"
 #include "webrtc/video_engine/test/common/video_capturer.h"
 
+#include "webrtc/video_engine/test/common/frame_generator.h"
+#include "webrtc/video_engine/test/common/frame_generator_capturer.h"
+#include "webrtc/video_engine/test/common/vcm_capturer.h"
+
 namespace webrtc {
 namespace test {
 
@@ -29,7 +32,8 @@
 VideoCapturer* VideoCapturer::Create(newapi::VideoSendStreamInput* input,
                                      size_t width,
                                      size_t height,
-                                     size_t fps) {
+                                     size_t fps,
+                                     Clock* clock) {
   VcmCapturer* vcm_capturer = VcmCapturer::Create(input, width, height, fps);
 
   if (vcm_capturer != NULL) {
@@ -37,7 +41,13 @@
   }
   // TODO(pbos): Log a warning that this failed.
 
-  // TODO(pbos): Add a pseudocapturer which generates frames.
+  FrameGeneratorCapturer* frame_generator_capturer =
+      FrameGeneratorCapturer::Create(
+          input, FrameGenerator::Create(width, height, clock), fps, clock);
+  if (frame_generator_capturer != NULL) {
+    return frame_generator_capturer;
+  }
+  // TODO(pbos): Log a warning that this failed.
 
   return new NullCapturer();
 }
diff --git a/video_engine/test/common/video_capturer.h b/video_engine/test/common/video_capturer.h
index bfb9f41..1f8f680 100644
--- a/video_engine/test/common/video_capturer.h
+++ b/video_engine/test/common/video_capturer.h
@@ -10,8 +10,12 @@
 #ifndef WEBRTC_VIDEO_ENGINE_TEST_COMMON_VIDEO_CAPTURER_H_
 #define WEBRTC_VIDEO_ENGINE_TEST_COMMON_VIDEO_CAPTURER_H_
 
+#include <stddef.h>
+
 namespace webrtc {
 
+class Clock;
+
 namespace newapi {
 class VideoSendStreamInput;
 }  // newapi
@@ -23,7 +27,8 @@
   static VideoCapturer* Create(newapi::VideoSendStreamInput* input,
                                size_t width,
                                size_t height,
-                               size_t fps);
+                               size_t fps,
+                               Clock* clock);
   virtual ~VideoCapturer() {}
 
   virtual void Start() = 0;
diff --git a/video_engine/test/loopback.cc b/video_engine/test/loopback.cc
index 44ab50a..ba31937 100644
--- a/video_engine/test/loopback.cc
+++ b/video_engine/test/loopback.cc
@@ -13,6 +13,7 @@
 
 #include "testing/gtest/include/gtest/gtest.h"
 
+#include "webrtc/system_wrappers/interface/clock.h"
 #include "webrtc/typedefs.h"
 #include "webrtc/video_engine/new_include/video_engine.h"
 #include "webrtc/video_engine/test/common/direct_transport.h"
@@ -63,11 +64,14 @@
 
   newapi::VideoSendStream* send_stream = call->CreateSendStream(send_config);
 
+  Clock* test_clock = Clock::GetRealTimeClock();
+
   test::VideoCapturer* camera =
       test::VideoCapturer::Create(send_stream->Input(),
                                   test::flags::Width(),
                                   test::flags::Height(),
-                                  test::flags::Fps());
+                                  test::flags::Fps(),
+                                  test_clock);
 
   newapi::VideoReceiveStreamConfig receive_config;
   call->GetDefaultReceiveConfig(&receive_config);
diff --git a/video_engine/test/tests.gypi b/video_engine/test/tests.gypi
index 4ddd9b4..8b08fcb 100644
--- a/video_engine/test/tests.gypi
+++ b/video_engine/test/tests.gypi
@@ -19,6 +19,8 @@
         'common/flags.h',
         'common/frame_generator.cc',
         'common/frame_generator.h',
+        'common/frame_generator_capturer.cc',
+        'common/frame_generator_capturer.h',
         'common/generate_ssrcs.h',
         'common/gl/gl_renderer.cc',
         'common/gl/gl_renderer.h',