summaryrefslogtreecommitdiffstats
path: root/chrome/browser/chromeos/login/camera.h
blob: c30f2dfbec1646b38197c6055cb808410c4b48ca (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
// 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 <string>
#include <vector>

#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<Camera> {
 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<Camera>;

  // 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<VideoBuffer> 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_