// Copyright (c) 2010 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef CHROME_BROWSER_CHROMEOS_LOGIN_CAMERA_H_ #define CHROME_BROWSER_CHROMEOS_LOGIN_CAMERA_H_ #pragma once #include #include #include "base/lock.h" #include "base/ref_counted.h" #include "base/threading/thread.h" #include "third_party/skia/include/core/SkBitmap.h" class Task; namespace base { class Thread; } // namespace base namespace chromeos { // Class that wraps interaction with video capturing device. Returns // frames captured with specified intervals of time via delegate interface. // All communication with camera driver is performed on a separate camera // thread. Delegate's callback are called on UI thread. class Camera : public base::RefCountedThreadSafe { public: class Delegate { public: virtual ~Delegate() {} // Callbacks that notify of the initialization status. virtual void OnInitializeSuccess() = 0; virtual void OnInitializeFailure() = 0; // Callbacks that notify if video capturing was started successfully or // not. virtual void OnStartCapturingSuccess() = 0; virtual void OnStartCapturingFailure() = 0; // Notifies the delegate that new frame was captured. // The frame can be obtained via GetFrame() method. virtual void OnCaptureSuccess() = 0; // Notifies the delegate that we failed to capture the next frame. virtual void OnCaptureFailure() = 0; }; // Initializes object members. |delegate| is object that will receive // notifications about success of async method calls. |thread| is a thread // to post blocking tasks to. |mirrored| determines if the returned video // image is mirrored horizontally. Camera(Delegate* delegate, base::Thread* thread, bool mirrored); // Initializes camera device on camera thread. Corresponding delegate's // callback is called on UI thread to notify about success or failure. Does // nothing if camera is successfully initialized already. Sets the desired // width and height of the frame to receive from camera. void Initialize(int desired_width, int desired_height); // Uninitializes the camera on camera thread. Can be called anytime, any // number of times. void Uninitialize(); // Starts capturing video frames on camera thread. Frames can be retrieved // by calling GetFrame method. void StartCapturing(); // Stops capturing video frames. Can be called anytime, any number of // times. void StopCapturing(); // Setter for delegate: allows to set it to NULL when delegate is about to // be destroyed. void set_delegate(Delegate* delegate) { delegate_ = delegate; } // Returns the last successful frame in the member passed. void GetFrame(SkBitmap* frame); private: // Destructor is private so only its base class can delete Camera objects. ~Camera(); friend class base::RefCountedThreadSafe; // Tries to open the device with specified name. Returns opened device // descriptor if succeeds, -1 otherwise. int OpenDevice(const char* device_name) const; // Initializes reading mode for the device. Returns true on success, false // otherwise. bool InitializeReadingMode(int fd); // Unmaps video buffers stored in |buffers_|. void UnmapVideoBuffers(); // Task for camera thread that queries camera about the next frame and // saves it to |frame_image| buffer for UI thread to pick up. Schedules the // next task for itself if capturing still takes place. void OnCapture(); // Reads a frame from the video device. If retry is needed, returns false. // Otherwise, returns true despite of success status. bool ReadFrame(); // Transforms raw data received from camera into SkBitmap with desired // size and notifies the delegate that the image is ready. void ProcessImage(void* data); // Actual routines that run on camera thread and call delegate's callbacks. // See the corresponding methods without Do prefix for details. void DoInitialize(int desired_width, int desired_height); void DoStartCapturing(); void DoUninitialize(); void DoStopCapturing(); // Helper method that reports failure to the delegate via method // corresponding to the current state of the object. void ReportFailure(); // Methods called on UI thread to call delegate. void OnInitializeSuccess(); void OnInitializeFailure(); void OnStartCapturingSuccess(); void OnStartCapturingFailure(); void OnCaptureSuccess(); void OnCaptureFailure(); // Returns true if the code is executed on camera thread right now, false // otherwise. bool IsOnCameraThread() const; // Posts task to camera thread. void PostCameraTask(const tracked_objects::Location& from_here, Task* task); // Defines a buffer in memory where one frame from the camera is stored. struct VideoBuffer { void* start; size_t length; }; // Delegate that receives the frames from the camera. // Delegate is accessed only on UI thread. Delegate* delegate_; // Thread where all work with the device is going on. base::Thread* thread_; // All the members below are accessed only on camera thread. // Name of the device file, i.e. "/dev/video0". std::string device_name_; // File descriptor of the opened device. int device_descriptor_; // Vector of buffers where to store video frames from camera. std::vector buffers_; // Indicates if capturing has been started. bool is_capturing_; // Desired size of the frame to get from camera. If it doesn't match // camera's supported resolution, higher resolution is selected (if // available) and frame is cropped. If higher resolution is not available, // the highest is selected and resized. int desired_width_; int desired_height_; // Size of the frame that camera will give to us. It may not match the // desired size. int frame_width_; int frame_height_; // If set to true, the returned image will be reflected from the Y axis to // mimic mirror behavior. bool mirrored_; // Image where camera frames are stored for UI thread to pick up. SkBitmap frame_image_; // Lock that guards references to |frame_image_|. mutable Lock image_lock_; // Lock that guards references to |camera_thread_|. mutable Lock thread_lock_; DISALLOW_COPY_AND_ASSIGN(Camera); }; } // namespace chromeos #endif // CHROME_BROWSER_CHROMEOS_LOGIN_CAMERA_H_