Home | History | Annotate | Download | only in camera
      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    */
    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    */
    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    */
    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    */
    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    */
    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 
    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   }
    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   }
    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    */
    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:
    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 
    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      */
    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. */
    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. */
    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