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