1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file.
4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
5c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#ifndef CHROME_BROWSER_CHROMEOS_LOGIN_CAMERA_H_
6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#define CHROME_BROWSER_CHROMEOS_LOGIN_CAMERA_H_
73345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#pragma once
8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
9c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <string>
10c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <vector>
11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
12ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/memory/ref_counted.h"
1372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "base/synchronization/lock.h"
143f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#include "base/threading/thread.h"
15513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include "third_party/skia/include/core/SkBitmap.h"
16c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
17513209b27ff55e2841eac0e4120199c23acce758Ben Murdochclass Task;
18c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace base {
19513209b27ff55e2841eac0e4120199c23acce758Ben Murdochclass Thread;
20c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}  // namespace base
21c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace chromeos {
23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Class that wraps interaction with video capturing device. Returns
25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// frames captured with specified intervals of time via delegate interface.
26513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// All communication with camera driver is performed on a separate camera
27513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// thread. Delegate's callback are called on UI thread.
28731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickclass Camera : public base::RefCountedThreadSafe<Camera> {
29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public:
30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  class Delegate {
31c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch   public:
32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    virtual ~Delegate() {}
33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
34731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    // Callbacks that notify of the initialization status.
35731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    virtual void OnInitializeSuccess() = 0;
36731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    virtual void OnInitializeFailure() = 0;
37731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
38731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    // Callbacks that notify if video capturing was started successfully or
39731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    // not.
40731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    virtual void OnStartCapturingSuccess() = 0;
41731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    virtual void OnStartCapturingFailure() = 0;
42731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
43513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    // Notifies the delegate that new frame was captured.
44513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    // The frame can be obtained via GetFrame() method.
45513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    virtual void OnCaptureSuccess() = 0;
46513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
47513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    // Notifies the delegate that we failed to capture the next frame.
48731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    virtual void OnCaptureFailure() = 0;
49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
51731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // Initializes object members. |delegate| is object that will receive
52513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // notifications about success of async method calls. |thread| is a thread
53513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // to post blocking tasks to. |mirrored| determines if the returned video
54513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // image is mirrored horizontally.
55513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  Camera(Delegate* delegate, base::Thread* thread, bool mirrored);
56513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
57513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // Initializes camera device on camera thread. Corresponding delegate's
58513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // callback is called on UI thread to notify about success or failure. Does
59513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // nothing if camera is successfully initialized already. Sets the desired
60513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // width and height of the frame to receive from camera.
61731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  void Initialize(int desired_width, int desired_height);
62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
63513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // Uninitializes the camera on camera thread. Can be called anytime, any
64513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // number of times.
65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void Uninitialize();
66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
67513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // Starts capturing video frames on camera thread. Frames can be retrieved
68513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // by calling GetFrame method.
69513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  void StartCapturing();
70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Stops capturing video frames. Can be called anytime, any number of
72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // times.
73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void StopCapturing();
74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
75731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // Setter for delegate: allows to set it to NULL when delegate is about to
76731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // be destroyed.
77731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  void set_delegate(Delegate* delegate) { delegate_ = delegate; }
78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
79513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // Returns the last successful frame in the member passed.
80513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  void GetFrame(SkBitmap* frame);
81513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private:
83731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // Destructor is private so only its base class can delete Camera objects.
84731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  ~Camera();
85731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  friend class base::RefCountedThreadSafe<Camera>;
86731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Tries to open the device with specified name. Returns opened device
88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // descriptor if succeeds, -1 otherwise.
89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int OpenDevice(const char* device_name) const;
90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Initializes reading mode for the device. Returns true on success, false
92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // otherwise.
93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool InitializeReadingMode(int fd);
94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Unmaps video buffers stored in |buffers_|.
96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void UnmapVideoBuffers();
97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
98513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // Task for camera thread that queries camera about the next frame and
99513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // saves it to |frame_image| buffer for UI thread to pick up. Schedules the
100513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // next task for itself if capturing still takes place.
101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void OnCapture();
102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Reads a frame from the video device. If retry is needed, returns false.
104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Otherwise, returns true despite of success status.
105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool ReadFrame();
106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Transforms raw data received from camera into SkBitmap with desired
108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // size and notifies the delegate that the image is ready.
109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void ProcessImage(void* data);
110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
111513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // Actual routines that run on camera thread and call delegate's callbacks.
112513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // See the corresponding methods without Do prefix for details.
113731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  void DoInitialize(int desired_width, int desired_height);
114513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  void DoStartCapturing();
115513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  void DoUninitialize();
116513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  void DoStopCapturing();
117731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
118731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // Helper method that reports failure to the delegate via method
119731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // corresponding to the current state of the object.
120731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  void ReportFailure();
121731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
122731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // Methods called on UI thread to call delegate.
123731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  void OnInitializeSuccess();
124731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  void OnInitializeFailure();
125731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  void OnStartCapturingSuccess();
126731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  void OnStartCapturingFailure();
127513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  void OnCaptureSuccess();
128731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  void OnCaptureFailure();
129731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
130513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // Returns true if the code is executed on camera thread right now, false
131513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // otherwise.
132513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  bool IsOnCameraThread() const;
133513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
134513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // Posts task to camera thread.
135513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  void PostCameraTask(const tracked_objects::Location& from_here,
136513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch                      Task* task);
137731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Defines a buffer in memory where one frame from the camera is stored.
139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  struct VideoBuffer {
140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    void* start;
141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    size_t length;
142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Delegate that receives the frames from the camera.
145731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // Delegate is accessed only on UI thread.
146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  Delegate* delegate_;
147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
148513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // Thread where all work with the device is going on.
149513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  base::Thread* thread_;
150513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
151513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // All the members below are accessed only on camera thread.
152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Name of the device file, i.e. "/dev/video0".
153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string device_name_;
154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // File descriptor of the opened device.
156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int device_descriptor_;
157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Vector of buffers where to store video frames from camera.
159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::vector<VideoBuffer> buffers_;
160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
161731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // Indicates if capturing has been started.
162731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  bool is_capturing_;
163731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Desired size of the frame to get from camera. If it doesn't match
165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // camera's supported resolution, higher resolution is selected (if
166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // available) and frame is cropped. If higher resolution is not available,
167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // the highest is selected and resized.
168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int desired_width_;
169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int desired_height_;
170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Size of the frame that camera will give to us. It may not match the
172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // desired size.
173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int frame_width_;
174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int frame_height_;
175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // If set to true, the returned image will be reflected from the Y axis to
177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // mimic mirror behavior.
178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool mirrored_;
179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
180513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // Image where camera frames are stored for UI thread to pick up.
181513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  SkBitmap frame_image_;
182513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
183513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // Lock that guards references to |frame_image_|.
18472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  mutable base::Lock image_lock_;
185513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
186513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // Lock that guards references to |camera_thread_|.
18772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  mutable base::Lock thread_lock_;
188513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DISALLOW_COPY_AND_ASSIGN(Camera);
190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch};
191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}  // namespace chromeos
193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif  // CHROME_BROWSER_CHROMEOS_LOGIN_CAMERA_H_
195