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