summaryrefslogtreecommitdiff
path: root/v3/EmulatedCameraDevice.h (plain)
blob: b7cdcb7a4a64cdce15e9ae8b4e5ddae139d1a22a
1/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef HW_EMULATOR_CAMERA_EMULATED_CAMERA_DEVICE_H
18#define HW_EMULATOR_CAMERA_EMULATED_CAMERA_DEVICE_H
19
20/*
21 * Contains declaration of an abstract class EmulatedCameraDevice that defines
22 * functionality expected from an emulated physical camera device:
23 * - Obtaining and setting camera device parameters
24 * - Capturing frames
25 * - Streaming video
26 * - etc.
27 */
28
29#include <utils/threads.h>
30#include <utils/KeyedVector.h>
31#include <utils/String8.h>
32#include "EmulatedCameraCommon.h"
33#include "Converters.h"
34
35namespace android {
36
37class EmulatedCamera;
38
39/* Encapsulates an abstract class EmulatedCameraDevice that defines
40 * functionality expected from an emulated physical camera device:
41 * - Obtaining and setting camera device parameters
42 * - Capturing frames
43 * - Streaming video
44 * - etc.
45 */
46class EmulatedCameraDevice {
47public:
48 /* Constructs EmulatedCameraDevice instance.
49 * Param:
50 * camera_hal - Emulated camera that implements the camera HAL API, and
51 * manages (contains) this object.
52 */
53 explicit EmulatedCameraDevice(EmulatedCamera* camera_hal);
54
55 /* Destructs EmulatedCameraDevice instance. */
56 virtual ~EmulatedCameraDevice();
57
58 /***************************************************************************
59 * Emulated camera device abstract interface
60 **************************************************************************/
61
62public:
63 /* Connects to the camera device.
64 * This method must be called on an initialized instance of this class.
65 * Return:
66 * NO_ERROR on success, or an appropriate error status.
67 */
68 virtual status_t connectDevice() = 0;
69
70 /* Disconnects from the camera device.
71 * Return:
72 * NO_ERROR on success, or an appropriate error status. If this method is
73 * called for already disconnected, or uninitialized instance of this class,
74 * a successful status must be returned from this method. If this method is
75 * called for an instance that is in the "started" state, this method must
76 * return a failure.
77 */
78 virtual status_t disconnectDevice() = 0;
79
80 /* Starts the camera device.
81 * This method tells the camera device to start capturing frames of the given
82 * dimensions for the given pixel format. Note that this method doesn't start
83 * the delivery of the captured frames to the emulated camera. Call
84 * startDeliveringFrames method to start delivering frames. This method must
85 * be called on a connected instance of this class. If it is called on a
86 * disconnected instance, this method must return a failure.
87 * Param:
88 * width, height - Frame dimensions to use when capturing video frames.
89 * pix_fmt - Pixel format to use when capturing video frames.
90 * Return:
91 * NO_ERROR on success, or an appropriate error status.
92 */
93 virtual status_t startDevice(int width, int height, uint32_t pix_fmt) = 0;
94
95 /* Stops the camera device.
96 * This method tells the camera device to stop capturing frames. Note that
97 * this method doesn't stop delivering frames to the emulated camera. Always
98 * call stopDeliveringFrames prior to calling this method.
99 * Return:
100 * NO_ERROR on success, or an appropriate error status. If this method is
101 * called for an object that is not capturing frames, or is disconnected,
102 * or is uninitialized, a successful status must be returned from this
103 * method.
104 */
105 virtual status_t stopDevice() = 0;
106
107 /***************************************************************************
108 * Emulated camera device public API
109 **************************************************************************/
110
111public:
112 /* Initializes EmulatedCameraDevice instance.
113 * Derived classes should override this method in order to cache static
114 * properties of the physical device (list of supported pixel formats, frame
115 * sizes, etc.) If this method is called on an already initialized instance,
116 * it must return a successful status.
117 * Return:
118 * NO_ERROR on success, or an appropriate error status.
119 */
120 virtual status_t Initialize();
121
122 /* Initializes the white balance modes parameters.
123 * The parameters are passed by each individual derived camera API to
124 * represent that different camera manufacturers may have different
125 * preferences on the white balance parameters. Green channel in the RGB
126 * color space is fixed to keep the luminance to be reasonably constant.
127 *
128 * Param:
129 * mode the text describing the current white balance mode
130 * r_scale the scale factor for the R channel in RGB space
131 * b_scale the scale factor for the B channel in RGB space.
132 */
133 void initializeWhiteBalanceModes(const char* mode,
134 const float r_scale,
135 const float b_scale);
136
137 /* Starts delivering frames captured from the camera device.
138 * This method will start the worker thread that would be pulling frames from
139 * the camera device, and will deliver the pulled frames back to the emulated
140 * camera via onNextFrameAvailable callback. This method must be called on a
141 * connected instance of this class with a started camera device. If it is
142 * called on a disconnected instance, or camera device has not been started,
143 * this method must return a failure.
144 * Param:
145 * one_burst - Controls how many frames should be delivered. If this
146 * parameter is 'true', only one captured frame will be delivered to the
147 * emulated camera. If this parameter is 'false', frames will keep
148 * coming until stopDeliveringFrames method is called. Typically, this
149 * parameter is set to 'true' only in order to obtain a single frame
150 * that will be used as a "picture" in takePicture method of the
151 * emulated camera.
152 * Return:
153 * NO_ERROR on success, or an appropriate error status.
154 */
155 virtual status_t startDeliveringFrames(bool one_burst);
156
157 /* Stops delivering frames captured from the camera device.
158 * This method will stop the worker thread started by startDeliveringFrames.
159 * Return:
160 * NO_ERROR on success, or an appropriate error status.
161 */
162 virtual status_t stopDeliveringFrames();
163
164 /* Sets the exposure compensation for the camera device.
165 */
166 void setExposureCompensation(const float ev);
167
168 /* Sets the white balance mode for the device.
169 */
170 void setWhiteBalanceMode(const char* mode);
171
172 /* Gets current framebuffer, converted into preview frame format.
173 * This method must be called on a connected instance of this class with a
174 * started camera device. If it is called on a disconnected instance, or
175 * camera device has not been started, this method must return a failure.
176 * Note that this method should be called only after at least one frame has
177 * been captured and delivered. Otherwise it will return garbage in the
178 * preview frame buffer. Typically, this method shuld be called from
179 * onNextFrameAvailable callback.
180 * Param:
181 * buffer - Buffer, large enough to contain the entire preview frame.
182 * Return:
183 * NO_ERROR on success, or an appropriate error status.
184 */
185 virtual status_t getCurrentPreviewFrame(void* buffer);
186
187 /* Gets width of the frame obtained from the physical device.
188 * Return:
189 * Width of the frame obtained from the physical device. Note that value
190 * returned from this method is valid only in case if camera device has been
191 * started.
192 */
193 inline int getFrameWidth() const
194 {
195 ALOGE_IF(!isStarted(), "%s: Device is not started", __FUNCTION__);
196 return mFrameWidth;
197 }
198
199 /* Gets height of the frame obtained from the physical device.
200 * Return:
201 * Height of the frame obtained from the physical device. Note that value
202 * returned from this method is valid only in case if camera device has been
203 * started.
204 */
205 inline int getFrameHeight() const
206 {
207 ALOGE_IF(!isStarted(), "%s: Device is not started", __FUNCTION__);
208 return mFrameHeight;
209 }
210
211 /* Gets byte size of the current frame buffer.
212 * Return:
213 * Byte size of the frame buffer. Note that value returned from this method
214 * is valid only in case if camera device has been started.
215 */
216 inline size_t getFrameBufferSize() const
217 {
218 ALOGE_IF(!isStarted(), "%s: Device is not started", __FUNCTION__);
219 return mFrameBufferSize;
220 }
221
222 /* Gets number of pixels in the current frame buffer.
223 * Return:
224 * Number of pixels in the frame buffer. Note that value returned from this
225 * method is valid only in case if camera device has been started.
226 */
227 inline int getPixelNum() const
228 {
229 ALOGE_IF(!isStarted(), "%s: Device is not started", __FUNCTION__);
230 return mTotalPixels;
231 }
232
233 /* Gets pixel format of the frame that camera device streams to this class.
234 * Throughout camera framework, there are three different forms of pixel
235 * format representation:
236 * - Original format, as reported by the actual camera device. Values for
237 * this format are declared in bionic/libc/kernel/common/linux/videodev2.h
238 * - String representation as defined in CameraParameters::PIXEL_FORMAT_XXX
239 * strings in frameworks/base/include/camera/CameraParameters.h
240 * - HAL_PIXEL_FORMAT_XXX format, as defined in system/core/include/system/graphics.h
241 * Since emulated camera device gets its data from the actual device, it gets
242 * pixel format in the original form. And that's the pixel format
243 * representation that will be returned from this method. HAL components will
244 * need to translate value returned from this method to the appropriate form.
245 * This method must be called only on started instance of this class, since
246 * it's applicable only when camera device is ready to stream frames.
247 * Param:
248 * pix_fmt - Upon success contains the original pixel format.
249 * Return:
250 * Current framebuffer's pixel format. Note that value returned from this
251 * method is valid only in case if camera device has been started.
252 */
253 inline uint32_t getOriginalPixelFormat() const
254 {
255 ALOGE_IF(!isStarted(), "%s: Device is not started", __FUNCTION__);
256 return mPixelFormat;
257 }
258
259 /*
260 * State checkers.
261 */
262
263 inline bool isInitialized() const {
264 /* Instance is initialized when the worker thread has been successfuly
265 * created (but not necessarily started). */
266 return mWorkerThread.get() != NULL && mState != ECDS_CONSTRUCTED;
267 }
268 inline bool isConnected() const {
269 /* Instance is connected when its status is either"connected", or
270 * "started". */
271 return mState == ECDS_CONNECTED || mState == ECDS_STARTED;
272 }
273 inline bool isStarted() const {
274 return mState == ECDS_STARTED;
275 }
276
277 /****************************************************************************
278 * Emulated camera device private API
279 ***************************************************************************/
280protected:
281 /* Performs common validation and calculation of startDevice parameters.
282 * Param:
283 * width, height, pix_fmt - Parameters passed to the startDevice method.
284 * Return:
285 * NO_ERROR on success, or an appropriate error status.
286 */
287 virtual status_t commonStartDevice(int width, int height, uint32_t pix_fmt);
288
289 /* Performs common cleanup on stopDevice.
290 * This method will undo what commonStartDevice had done.
291 */
292 virtual void commonStopDevice();
293
294 /** Computes a luminance value after taking the exposure compensation.
295 * value into account.
296 *
297 * Param:
298 * inputY - The input luminance value.
299 * Return:
300 * The luminance value after adjusting the exposure compensation.
301 */
302 inline uint8_t changeExposure(const uint8_t& inputY) const {
303 return static_cast<uint8_t>(clamp(static_cast<float>(inputY) *
304 mExposureCompensation));
305 }
306
307 /** Computes the pixel value in YUV space after adjusting to the current
308 * white balance mode.
309 */
310 void changeWhiteBalance(uint8_t& y, uint8_t& u, uint8_t& v) const;
311
312 /****************************************************************************
313 * Worker thread management.
314 * Typicaly when emulated camera device starts capturing frames from the
315 * actual device, it does that in a worker thread created in StartCapturing,
316 * and terminated in StopCapturing. Since this is such a typical scenario,
317 * it makes sence to encapsulate worker thread management in the base class
318 * for all emulated camera devices.
319 ***************************************************************************/
320
321protected:
322 /* Starts the worker thread.
323 * Typically, worker thread is started from startDeliveringFrames method of
324 * this class.
325 * Param:
326 * one_burst - Controls how many times thread loop should run. If this
327 * parameter is 'true', thread routine will run only once If this
328 * parameter is 'false', thread routine will run until stopWorkerThread
329 * method is called. See startDeliveringFrames for more info.
330 * Return:
331 * NO_ERROR on success, or an appropriate error status.
332 */
333 virtual status_t startWorkerThread(bool one_burst);
334
335 /* Stops the worker thread.
336 * Note that this method will always wait for the worker thread to terminate.
337 * Typically, worker thread is started from stopDeliveringFrames method of
338 * this class.
339 * Return:
340 * NO_ERROR on success, or an appropriate error status.
341 */
342 virtual status_t stopWorkerThread();
343
344 /* Implementation of the worker thread routine.
345 * In the default implementation of the worker thread routine we simply
346 * return 'false' forcing the thread loop to exit, and the thread to
347 * terminate. Derived class should override that method to provide there the
348 * actual frame delivery.
349 * Return:
350 * true To continue thread loop (this method will be called again), or false
351 * to exit the thread loop and to terminate the thread.
352 */
353 virtual bool inWorkerThread();
354
355 /* Encapsulates a worker thread used by the emulated camera device.
356 */
357 friend class WorkerThread;
358 class WorkerThread : public Thread {
359
360 /****************************************************************************
361 * Public API
362 ***************************************************************************/
363
364 public:
365 inline explicit WorkerThread(EmulatedCameraDevice* camera_dev)
366 : Thread(true), // Callbacks may involve Java calls.
367 mCameraDevice(camera_dev),
368 mThreadControl(-1),
369 mControlFD(-1)
370 {
371 }
372
373 inline ~WorkerThread()
374 {
375 ALOGW_IF(mThreadControl >= 0 || mControlFD >= 0,
376 "%s: Control FDs are opened in the destructor",
377 __FUNCTION__);
378 if (mThreadControl >= 0) {
379 close(mThreadControl);
380 }
381 if (mControlFD >= 0) {
382 close(mControlFD);
383 }
384 }
385
386 /* Starts the thread
387 * Param:
388 * one_burst - Controls how many times thread loop should run. If
389 * this parameter is 'true', thread routine will run only once
390 * If this parameter is 'false', thread routine will run until
391 * stopThread method is called. See startWorkerThread for more
392 * info.
393 * Return:
394 * NO_ERROR on success, or an appropriate error status.
395 */
396 inline status_t startThread(bool one_burst)
397 {
398 mOneBurst = one_burst;
399 return run(NULL, ANDROID_PRIORITY_URGENT_DISPLAY, 0);
400 }
401
402 /* Overriden base class method.
403 * It is overriden in order to provide one-time initialization just
404 * prior to starting the thread routine.
405 */
406 status_t readyToRun();
407
408 /* Stops the thread. */
409 status_t stopThread();
410
411 /* Values returned from the Select method of this class. */
412 enum SelectRes {
413 /* A timeout has occurred. */
414 TIMEOUT,
415 /* Data are available for read on the provided FD. */
416 READY,
417 /* Thread exit request has been received. */
418 EXIT_THREAD,
419 /* An error has occurred. */
420 ERROR
421 };
422
423 /* Select on an FD event, keeping in mind thread exit message.
424 * Param:
425 * fd - File descriptor on which to wait for an event. This
426 * parameter may be negative. If it is negative this method will
427 * only wait on a control message to the thread.
428 * timeout - Timeout in microseconds. 0 indicates no timeout (wait
429 * forever).
430 * Return:
431 * See SelectRes enum comments.
432 */
433 SelectRes Select(int fd, int timeout);
434
435 /****************************************************************************
436 * Private API
437 ***************************************************************************/
438
439 private:
440 /* Implements abstract method of the base Thread class. */
441 bool threadLoop()
442 {
443 /* Simply dispatch the call to the containing camera device. */
444 if (mCameraDevice->inWorkerThread()) {
445 /* Respect "one burst" parameter (see startThread). */
446 return !mOneBurst;
447 } else {
448 return false;
449 }
450 }
451
452 /* Containing camera device object. */
453 EmulatedCameraDevice* mCameraDevice;
454
455 /* FD that is used to send control messages into the thread. */
456 int mThreadControl;
457
458 /* FD that thread uses to receive control messages. */
459 int mControlFD;
460
461 /* Controls number of times the thread loop runs.
462 * See startThread for more information. */
463 bool mOneBurst;
464
465 /* Enumerates control messages that can be sent into the thread. */
466 enum ControlMessage {
467 /* Stop the thread. */
468 THREAD_STOP
469 };
470 };
471
472 /* Worker thread accessor. */
473 inline WorkerThread* getWorkerThread() const
474 {
475 return mWorkerThread.get();
476 }
477
478 /****************************************************************************
479 * Data members
480 ***************************************************************************/
481
482protected:
483 /* Locks this instance for parameters, state, etc. change. */
484 Mutex mObjectLock;
485
486 /* Worker thread that is used in frame capturing. */
487 sp<WorkerThread> mWorkerThread;
488
489 /* Timestamp of the current frame. */
490 nsecs_t mCurFrameTimestamp;
491
492 /* Emulated camera object containing this instance. */
493 EmulatedCamera* mCameraHAL;
494
495 /* Framebuffer containing the current frame. */
496 uint8_t* mCurrentFrame;
497
498 /*
499 * Framebuffer properties.
500 */
501
502 /* Byte size of the framebuffer. */
503 size_t mFrameBufferSize;
504
505 /* Original pixel format (one of the V4L2_PIX_FMT_XXX values, as defined in
506 * bionic/libc/kernel/common/linux/videodev2.h */
507 uint32_t mPixelFormat;
508
509 /* Frame width */
510 int mFrameWidth;
511
512 /* Frame height */
513 int mFrameHeight;
514
515 /* Total number of pixels */
516 int mTotalPixels;
517
518 /* Exposure compensation value */
519 float mExposureCompensation;
520
521 float* mWhiteBalanceScale;
522
523 DefaultKeyedVector<String8, float*> mSupportedWhiteBalanceScale;
524
525 /* Defines possible states of the emulated camera device object.
526 */
527 enum EmulatedCameraDeviceState {
528 /* Object has been constructed. */
529 ECDS_CONSTRUCTED,
530 /* Object has been initialized. */
531 ECDS_INITIALIZED,
532 /* Object has been connected to the physical device. */
533 ECDS_CONNECTED,
534 /* Camera device has been started. */
535 ECDS_STARTED,
536 };
537
538 /* Object state. */
539 EmulatedCameraDeviceState mState;
540};
541
542}; /* namespace android */
543
544#endif /* HW_EMULATOR_CAMERA_EMULATED_CAMERA_DEVICE_H */
545