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