Home | History | Annotate | Download | only in media
      1 // Copyright 2013 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #ifndef CONTENT_BROWSER_RENDERER_HOST_VIDEO_CAPTURE_DEVICE_IMPL_H_
      6 #define CONTENT_BROWSER_RENDERER_HOST_VIDEO_CAPTURE_DEVICE_IMPL_H_
      7 
      8 #include <string>
      9 
     10 #include "base/memory/scoped_ptr.h"
     11 #include "base/memory/weak_ptr.h"
     12 #include "base/threading/thread.h"
     13 #include "base/threading/thread_checker.h"
     14 #include "content/browser/renderer_host/media/video_capture_oracle.h"
     15 #include "content/common/content_export.h"
     16 #include "media/video/capture/video_capture_device.h"
     17 
     18 namespace content {
     19 
     20 const int kMinFrameWidth = 2;
     21 const int kMinFrameHeight = 2;
     22 
     23 // Returns the nearest even integer closer to zero.
     24 template<typename IntType>
     25 IntType MakeEven(IntType x) {
     26   return x & static_cast<IntType>(-2);
     27 }
     28 
     29 // TODO(nick): Remove this once frame subscription is supported on Aura and
     30 // Linux.
     31 #if (defined(OS_WIN) || defined(OS_MACOSX)) || defined(USE_AURA)
     32 const bool kAcceleratedSubscriberIsSupported = true;
     33 #else
     34 const bool kAcceleratedSubscriberIsSupported = false;
     35 #endif
     36 
     37 class VideoCaptureMachine;
     38 
     39 // Thread-safe, refcounted proxy to the VideoCaptureOracle.  This proxy wraps
     40 // the VideoCaptureOracle, which decides which frames to capture, and a
     41 // VideoCaptureDevice::Client, which allocates and receives the captured
     42 // frames, in a lock to synchronize state between the two.
     43 class ThreadSafeCaptureOracle
     44     : public base::RefCountedThreadSafe<ThreadSafeCaptureOracle> {
     45  public:
     46   ThreadSafeCaptureOracle(scoped_ptr<media::VideoCaptureDevice::Client> client,
     47                           scoped_ptr<VideoCaptureOracle> oracle,
     48                           const media::VideoCaptureParams& params);
     49 
     50   // Called when a captured frame is available or an error has occurred.
     51   // If |success| is true then the frame provided is valid and |timestamp|
     52   // indicates when the frame was painted.
     53   // If |success| is false, both the frame provided and |timestamp| are invalid.
     54   typedef base::Callback<void(base::Time timestamp, bool success)>
     55       CaptureFrameCallback;
     56 
     57   bool ObserveEventAndDecideCapture(VideoCaptureOracle::Event event,
     58                                     base::Time event_time,
     59                                     scoped_refptr<media::VideoFrame>* storage,
     60                                     CaptureFrameCallback* callback);
     61 
     62   base::TimeDelta capture_period() const {
     63     return oracle_->capture_period();
     64   }
     65 
     66   // Updates capture resolution based on the supplied source size and the
     67   // maximum frame size.
     68   void UpdateCaptureSize(const gfx::Size& source_size);
     69 
     70   // Stop new captures from happening (but doesn't forget the client).
     71   void Stop();
     72 
     73   // Signal an error to the client.
     74   void ReportError();
     75 
     76  private:
     77   friend class base::RefCountedThreadSafe<ThreadSafeCaptureOracle>;
     78   virtual ~ThreadSafeCaptureOracle();
     79 
     80   // Callback invoked on completion of all captures.
     81   void DidCaptureFrame(
     82       scoped_refptr<media::VideoCaptureDevice::Client::Buffer> buffer,
     83       int frame_number,
     84       base::Time timestamp,
     85       bool success);
     86   // Protects everything below it.
     87   base::Lock lock_;
     88 
     89   // Recipient of our capture activity.
     90   scoped_ptr<media::VideoCaptureDevice::Client> client_;
     91 
     92   // Makes the decision to capture a frame.
     93   const scoped_ptr<VideoCaptureOracle> oracle_;
     94 
     95   // The video capture parameters used to construct the oracle proxy.
     96   const media::VideoCaptureParams params_;
     97 
     98   // Indicates if capture size has been updated after construction.
     99   bool capture_size_updated_;
    100 
    101   // The current capturing resolution and frame rate.
    102   gfx::Size capture_size_;
    103   int frame_rate_;
    104 };
    105 
    106 // Keeps track of the video capture source frames and executes copying on the
    107 // UI BrowserThread.
    108 class VideoCaptureMachine {
    109  public:
    110   VideoCaptureMachine() : started_(false) {}
    111   virtual ~VideoCaptureMachine() {}
    112 
    113   // This should only be checked on the UI thread.
    114   bool started() const { return started_; }
    115 
    116   // Starts capturing. Returns true if succeeded.
    117   // Must be run on the UI BrowserThread.
    118   virtual bool Start(
    119       const scoped_refptr<ThreadSafeCaptureOracle>& oracle_proxy) = 0;
    120 
    121   // Stops capturing. Must be run on the UI BrowserThread.
    122   virtual void Stop() = 0;
    123 
    124  protected:
    125   bool started_;
    126 
    127  private:
    128   DISALLOW_COPY_AND_ASSIGN(VideoCaptureMachine);
    129 };
    130 
    131 // The "meat" of the video capture implementation.
    132 //
    133 // Separating this from the "shell classes" WebContentsVideoCaptureDevice and
    134 // BrowserCompositorCaptureDevice allows safe destruction without needing to
    135 // block any threads (e.g., the IO BrowserThread), as well as code sharing.
    136 //
    137 // VideoCaptureDeviceImpl manages a simple state machine and the pipeline (see
    138 // notes at top of this file).  It times the start of successive
    139 // captures and facilitates the processing of each through the stages of the
    140 // pipeline.
    141 class CONTENT_EXPORT VideoCaptureDeviceImpl
    142     : public base::SupportsWeakPtr<VideoCaptureDeviceImpl> {
    143  public:
    144   VideoCaptureDeviceImpl(scoped_ptr<VideoCaptureMachine> capture_machine);
    145   virtual ~VideoCaptureDeviceImpl();
    146 
    147   // Asynchronous requests to change VideoCaptureDeviceImpl state.
    148   void AllocateAndStart(const media::VideoCaptureParams& params,
    149                         scoped_ptr<media::VideoCaptureDevice::Client> client);
    150   void StopAndDeAllocate();
    151 
    152  private:
    153   // Flag indicating current state.
    154   enum State {
    155     kIdle,
    156     kCapturing,
    157     kError
    158   };
    159 
    160   void TransitionStateTo(State next_state);
    161 
    162   // Called on the IO thread in response to StartCaptureMachine().
    163   // |success| is true if capture machine succeeded to start.
    164   void CaptureStarted(bool success);
    165 
    166   // Stops capturing and notifies client_ of an error state.
    167   void Error();
    168 
    169   // Tracks that all activity occurs on the media stream manager's thread.
    170   base::ThreadChecker thread_checker_;
    171 
    172   // Current lifecycle state.
    173   State state_;
    174 
    175   // Tracks the CaptureMachine that's doing work on our behalf on the UI thread.
    176   // This value should never be dereferenced by this class, other than to
    177   // create and destroy it on the UI thread.
    178   scoped_ptr<VideoCaptureMachine> capture_machine_;
    179 
    180   // Our thread-safe capture oracle which serves as the gateway to the video
    181   // capture pipeline. Besides the WCVCD itself, it is the only component of the
    182   // system with direct access to |client_|.
    183   scoped_refptr<ThreadSafeCaptureOracle> oracle_proxy_;
    184 
    185   DISALLOW_COPY_AND_ASSIGN(VideoCaptureDeviceImpl);
    186 };
    187 
    188 
    189 }  // namespace content
    190 
    191 #endif  // CONTENT_BROWSER_RENDERER_HOST_VIDEO_CAPTURE_DEVICE_IMPL_H_
    192