• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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:
~Delegate()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.
set_delegate(Delegate * delegate)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