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/threads.h>
     30 #include <utils/KeyedVector.h>
     31 #include <utils/String8.h>
     32 #include "EmulatedCameraCommon.h"
     33 #include "Converters.h"
     34 
     35 namespace android {
     36 
     37 class 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  */
     46 class EmulatedCameraDevice {
     47 public:
     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 
     62 public:
     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 
    111 public:
    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      ***************************************************************************/
    280 protected:
    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 
    321 protected:
    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 
    482 protected:
    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