Home | History | Annotate | Download | only in login
      1 // Copyright (c) 2011 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 CHROME_BROWSER_CHROMEOS_LOGIN_CAMERA_H_
      6 #define CHROME_BROWSER_CHROMEOS_LOGIN_CAMERA_H_
      7 #pragma once
      8 
      9 #include <string>
     10 #include <vector>
     11 
     12 #include "base/memory/ref_counted.h"
     13 #include "base/synchronization/lock.h"
     14 #include "base/threading/thread.h"
     15 #include "third_party/skia/include/core/SkBitmap.h"
     16 
     17 class Task;
     18 namespace base {
     19 class Thread;
     20 }  // namespace base
     21 
     22 namespace chromeos {
     23 
     24 // Class that wraps interaction with video capturing device. Returns
     25 // frames captured with specified intervals of time via delegate interface.
     26 // All communication with camera driver is performed on a separate camera
     27 // thread. Delegate's callback are called on UI thread.
     28 class Camera : public base::RefCountedThreadSafe<Camera> {
     29  public:
     30   class Delegate {
     31    public:
     32     virtual ~Delegate() {}
     33 
     34     // Callbacks that notify of the initialization status.
     35     virtual void OnInitializeSuccess() = 0;
     36     virtual void OnInitializeFailure() = 0;
     37 
     38     // Callbacks that notify if video capturing was started successfully or
     39     // not.
     40     virtual void OnStartCapturingSuccess() = 0;
     41     virtual void OnStartCapturingFailure() = 0;
     42 
     43     // Notifies the delegate that new frame was captured.
     44     // The frame can be obtained via GetFrame() method.
     45     virtual void OnCaptureSuccess() = 0;
     46 
     47     // Notifies the delegate that we failed to capture the next frame.
     48     virtual void OnCaptureFailure() = 0;
     49   };
     50 
     51   // Initializes object members. |delegate| is object that will receive
     52   // notifications about success of async method calls. |thread| is a thread
     53   // to post blocking tasks to. |mirrored| determines if the returned video
     54   // image is mirrored horizontally.
     55   Camera(Delegate* delegate, base::Thread* thread, bool mirrored);
     56 
     57   // Initializes camera device on camera thread. Corresponding delegate's
     58   // callback is called on UI thread to notify about success or failure. Does
     59   // nothing if camera is successfully initialized already. Sets the desired
     60   // width and height of the frame to receive from camera.
     61   void Initialize(int desired_width, int desired_height);
     62 
     63   // Uninitializes the camera on camera thread. Can be called anytime, any
     64   // number of times.
     65   void Uninitialize();
     66 
     67   // Starts capturing video frames on camera thread. Frames can be retrieved
     68   // by calling GetFrame method.
     69   void StartCapturing();
     70 
     71   // Stops capturing video frames. Can be called anytime, any number of
     72   // times.
     73   void StopCapturing();
     74 
     75   // Setter for delegate: allows to set it to NULL when delegate is about to
     76   // be destroyed.
     77   void set_delegate(Delegate* delegate) { delegate_ = delegate; }
     78 
     79   // Returns the last successful frame in the member passed.
     80   void GetFrame(SkBitmap* frame);
     81 
     82  private:
     83   // Destructor is private so only its base class can delete Camera objects.
     84   ~Camera();
     85   friend class base::RefCountedThreadSafe<Camera>;
     86 
     87   // Tries to open the device with specified name. Returns opened device
     88   // descriptor if succeeds, -1 otherwise.
     89   int OpenDevice(const char* device_name) const;
     90 
     91   // Initializes reading mode for the device. Returns true on success, false
     92   // otherwise.
     93   bool InitializeReadingMode(int fd);
     94 
     95   // Unmaps video buffers stored in |buffers_|.
     96   void UnmapVideoBuffers();
     97 
     98   // Task for camera thread that queries camera about the next frame and
     99   // saves it to |frame_image| buffer for UI thread to pick up. Schedules the
    100   // next task for itself if capturing still takes place.
    101   void OnCapture();
    102 
    103   // Reads a frame from the video device. If retry is needed, returns false.
    104   // Otherwise, returns true despite of success status.
    105   bool ReadFrame();
    106 
    107   // Transforms raw data received from camera into SkBitmap with desired
    108   // size and notifies the delegate that the image is ready.
    109   void ProcessImage(void* data);
    110 
    111   // Actual routines that run on camera thread and call delegate's callbacks.
    112   // See the corresponding methods without Do prefix for details.
    113   void DoInitialize(int desired_width, int desired_height);
    114   void DoStartCapturing();
    115   void DoUninitialize();
    116   void DoStopCapturing();
    117 
    118   // Helper method that reports failure to the delegate via method
    119   // corresponding to the current state of the object.
    120   void ReportFailure();
    121 
    122   // Methods called on UI thread to call delegate.
    123   void OnInitializeSuccess();
    124   void OnInitializeFailure();
    125   void OnStartCapturingSuccess();
    126   void OnStartCapturingFailure();
    127   void OnCaptureSuccess();
    128   void OnCaptureFailure();
    129 
    130   // Returns true if the code is executed on camera thread right now, false
    131   // otherwise.
    132   bool IsOnCameraThread() const;
    133 
    134   // Posts task to camera thread.
    135   void PostCameraTask(const tracked_objects::Location& from_here,
    136                       Task* task);
    137 
    138   // Defines a buffer in memory where one frame from the camera is stored.
    139   struct VideoBuffer {
    140     void* start;
    141     size_t length;
    142   };
    143 
    144   // Delegate that receives the frames from the camera.
    145   // Delegate is accessed only on UI thread.
    146   Delegate* delegate_;
    147 
    148   // Thread where all work with the device is going on.
    149   base::Thread* thread_;
    150 
    151   // All the members below are accessed only on camera thread.
    152   // Name of the device file, i.e. "/dev/video0".
    153   std::string device_name_;
    154 
    155   // File descriptor of the opened device.
    156   int device_descriptor_;
    157 
    158   // Vector of buffers where to store video frames from camera.
    159   std::vector<VideoBuffer> buffers_;
    160 
    161   // Indicates if capturing has been started.
    162   bool is_capturing_;
    163 
    164   // Desired size of the frame to get from camera. If it doesn't match
    165   // camera's supported resolution, higher resolution is selected (if
    166   // available) and frame is cropped. If higher resolution is not available,
    167   // the highest is selected and resized.
    168   int desired_width_;
    169   int desired_height_;
    170 
    171   // Size of the frame that camera will give to us. It may not match the
    172   // desired size.
    173   int frame_width_;
    174   int frame_height_;
    175 
    176   // If set to true, the returned image will be reflected from the Y axis to
    177   // mimic mirror behavior.
    178   bool mirrored_;
    179 
    180   // Image where camera frames are stored for UI thread to pick up.
    181   SkBitmap frame_image_;
    182 
    183   // Lock that guards references to |frame_image_|.
    184   mutable base::Lock image_lock_;
    185 
    186   // Lock that guards references to |camera_thread_|.
    187   mutable base::Lock thread_lock_;
    188 
    189   DISALLOW_COPY_AND_ASSIGN(Camera);
    190 };
    191 
    192 }  // namespace chromeos
    193 
    194 #endif  // CHROME_BROWSER_CHROMEOS_LOGIN_CAMERA_H_
    195