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_QEMU_CLIENT_H
     18 #define HW_EMULATOR_CAMERA_QEMU_CLIENT_H
     19 
     20 /*
     21  * Contains declaration of classes that encapsulate connection to camera
     22  * services in the emulator via qemu pipe.
     23  */
     24 
     25 #include <hardware/qemud.h>
     26 
     27 namespace android {
     28 
     29 /****************************************************************************
     30  * Qemu query
     31  ***************************************************************************/
     32 
     33 /* Encapsulates a query to the emulator.
     34  * Guest exchanges data with the emulator via queries sent over the qemu pipe.
     35  * The queries as well as replies to the queries are all strings (except for the
     36  * 'frame' query where reply is a framebuffer).
     37  * Each query is formatted as such:
     38  *
     39  *      "<query name>[ <parameters>]",
     40  *
     41  * where <query name> is a string representing query name, and <parameters> are
     42  * optional parameters for the query. If parameters are present, they must be
     43  * separated from the query name with a single space, and they must be formatted
     44  * as such:
     45  *
     46  *      "<name1>=<value1> <name2>=<value2> ... <nameN>=<valueN>"
     47  *
     48  * I.e.:
     49  *  - Every parameter must have a name, and a value.
     50  *  - Name and value must be separated with '='.
     51  *  - No spaces are allowed around '=' separating name and value.
     52  *  - Parameters must be separated with a single space character.
     53  *  - No '=' character is allowed in name and in value.
     54  *
     55  * There are certain restrictions on strings used in the query:
     56  *  - Spaces are allowed only as separators.
     57  *  - '=' are allowed only to divide parameter names from parameter values.
     58  *
     59  * Emulator replies to each query in two chunks:
     60  * - 8 bytes encoding the payload size as a string containing hexadecimal
     61  *   representation of the payload size value. This is done in order to simplify
     62  *   dealing with different endianness on the host, and on the guest.
     63  * - Payload, whose size is defined by the first chunk.
     64  *
     65  * Every payload always begins with two characters, encoding the result of the
     66  * query:
     67  *  - 'ok' Encoding the success
     68  *  - 'ko' Encoding a failure.
     69  * After that payload may have optional data. If payload has more data following
     70  * the query result, there is a ':' character separating them. If payload
     71  * carries only the result, it always ends with a zero-terminator. So, payload
     72  * 'ok'/'ko' prefix is always 3 bytes long: it either includes a
     73  * zero-terminator, if there is no data, or a ':' separator.
     74  */
     75 class QemuQuery {
     76  public:
     77   /* Constructs an uninitialized QemuQuery instance. */
     78   QemuQuery();
     79 
     80   /* Constructs and initializes QemuQuery instance for a query.
     81    * Param:
     82    *  query_string - Query string. This constructor can also be used to
     83    *      construct a query that doesn't have parameters. In this case query
     84    *      name can be passed as a parameter here.
     85    */
     86   explicit QemuQuery(const char* query_string);
     87 
     88   /* Constructs and initializes QemuQuery instance for a query with parameters.
     89    * Param:
     90    *  query_name - Query name.
     91    *  query_param - Query parameters. Can be NULL.
     92    */
     93   QemuQuery(const char* query_name, const char* query_param);
     94 
     95   /* Destructs QemuQuery instance. */
     96   ~QemuQuery();
     97 
     98   /****************************************************************************
     99    * Public API
    100    ***************************************************************************/
    101 
    102   /* Creates new query.
    103    * Note: this method will reset this instance prior to creating a new query
    104    * in order to discard possible "leftovers" from the previous query.
    105    * Param:
    106    *  query_name - Query name.
    107    *  query_param - Query parameters. Can be NULL.
    108    * Return:
    109    *  NO_ERROR on success, or an appropriate error status.
    110    */
    111   status_t createQuery(const char* name, const char* param);
    112 
    113   /* Completes the query after a reply from the emulator.
    114    * This method will parse the reply buffer, and calculate the final query
    115    * status, which depends not only on the transport success / failure, but
    116    * also on 'ok' / 'ko' in the reply buffer.
    117    * Param:
    118    *  status - Query delivery status. This status doesn't necessarily reflects
    119    *      the final query status (which is defined by 'ok'/'ko' prefix in the
    120    *      reply buffer). This status simply states whether or not the query has
    121    *      been sent, and a reply has been received successfuly. However, if
    122    *      this status indicates a failure, it means that the entire query has
    123    *      failed.
    124    * Return:
    125    *  NO_ERROR on success, or an appropriate error status on failure. Note that
    126    *  status returned here just signals whether or not the method has succeeded.
    127    *  Use isQuerySucceeded() / getCompletionStatus() methods of this class to
    128    *  check the final query status.
    129    */
    130   status_t completeQuery(status_t status);
    131 
    132   /* Resets the query from a previous use. */
    133   void resetQuery();
    134 
    135   /* Checks if query has succeeded.
    136    * Note that this method must be called after completeQuery() method of this
    137    * class has been executed.
    138    */
    139   inline bool isQuerySucceeded() const {
    140     return mQueryDeliveryStatus == NO_ERROR && mReplyStatus != 0;
    141   }
    142 
    143   /* Gets final completion status of the query.
    144    * Note that this method must be called after completeQuery() method of this
    145    * class has been executed.
    146    * Return:
    147    *  NO_ERROR if query has succeeded, or an appropriate error status on query
    148    *  failure.
    149    */
    150   inline status_t getCompletionStatus() const {
    151     if (mQueryDeliveryStatus == NO_ERROR) {
    152       if (mReplyStatus) {
    153         return NO_ERROR;
    154       } else {
    155         return EINVAL;
    156       }
    157     } else {
    158       return mQueryDeliveryStatus;
    159     }
    160   }
    161 
    162   /****************************************************************************
    163    * Public data memebers
    164    ***************************************************************************/
    165 
    166  public:
    167   /* Query string. */
    168   char* mQuery;
    169   /* Query delivery status. */
    170   status_t mQueryDeliveryStatus;
    171   /* Reply buffer */
    172   char* mReplyBuffer;
    173   /* Reply data (past 'ok'/'ko'). If NULL, there were no data in reply. */
    174   char* mReplyData;
    175   /* Reply buffer size. */
    176   size_t mReplySize;
    177   /* Reply data size. */
    178   size_t mReplyDataSize;
    179   /* Reply status: 1 - ok, 0 - ko. */
    180   int mReplyStatus;
    181 
    182   /****************************************************************************
    183    * Private data memebers
    184    ***************************************************************************/
    185 
    186  protected:
    187   /* Preallocated buffer for small queries. */
    188   char mQueryPrealloc[256];
    189 };
    190 
    191 /****************************************************************************
    192  * Qemu client base
    193  ***************************************************************************/
    194 
    195 /* Encapsulates a connection to the 'camera' service in the emulator via qemu
    196  * pipe.
    197  */
    198 class QemuClient {
    199  public:
    200   /* Constructs QemuClient instance. */
    201   QemuClient();
    202 
    203   /* Destructs QemuClient instance. */
    204   virtual ~QemuClient();
    205 
    206   /****************************************************************************
    207    * Qemu client API
    208    ***************************************************************************/
    209 
    210  public:
    211   /* Connects to the 'camera' service in the emulator via qemu pipe.
    212    * Param:
    213    *  param - Parameters to pass to the camera service. There are two types of
    214    *      camera services implemented by the emulator. The first one is a
    215    *      'camera factory' type of service that provides list of cameras
    216    *      connected to the host. Another one is an 'emulated camera' type of
    217    *      service that provides interface to a camera connected to the host. At
    218    *      the connection time emulator makes distinction between the two by
    219    *      looking at connection parameters: no parameters means connection to
    220    *      the 'factory' service, while connection with parameters means
    221    *      connection to an 'emulated camera' service, where camera is identified
    222    *      by one of the connection parameters. So, passing NULL, or an empty
    223    *      string to this method will establish a connection with the 'factory'
    224    *      service, while not empty string passed here will establish connection
    225    *      with an 'emulated camera' service. Parameters defining the emulated
    226    *      camera must be formatted as such:
    227    *
    228    *          "name=<device name> [inp_channel=<input channel #>]",
    229    *
    230    *      where 'device name' is a required parameter defining name of the
    231    *      camera device, and 'input channel' is an optional parameter (positive
    232    *      integer), defining the input channel to use on the camera device.
    233    *      Note that device name passed here must have been previously obtained
    234    *      from the factory service using 'list' query.
    235    * Return:
    236    *  NO_ERROR on success, or an appropriate error status.
    237    */
    238   virtual status_t connectClient(const char* param);
    239 
    240   /* Disconnects from the service. */
    241   virtual void disconnectClient();
    242 
    243   /* Sends data to the service.
    244    * Param:
    245    *  data, data_size - Data to send.
    246    * Return:
    247    *  NO_ERROR on success, or an appropriate error status on failure.
    248    */
    249   virtual status_t sendMessage(const void* data, size_t data_size);
    250 
    251   /* Receives data from the service.
    252    * This method assumes that data to receive will come in two chunks: 8
    253    * characters encoding the payload size in hexadecimal string, followed by
    254    * the paylod (if any).
    255    * This method will allocate data buffer where to receive the response.
    256    * Param:
    257    *  data - Upon success contains address of the allocated data buffer with
    258    *      the data received from the service. The caller is responsible for
    259    *      freeing allocated data buffer.
    260    *  data_size - Upon success contains size of the data received from the
    261    *      service.
    262    * Return:
    263    *  NO_ERROR on success, or an appropriate error status on failure.
    264    */
    265   virtual status_t receiveMessage(void** data, size_t* data_size);
    266 
    267   /* Sends a query, and receives a response from the service.
    268    * Param:
    269    *  query - Query to send to the service. When this method returns, the query
    270    *  is completed, and all its relevant data members are properly initialized.
    271    * Return:
    272    *  NO_ERROR on success, or an appropriate error status on failure. Note that
    273    *  status returned here is not the final query status. Use
    274    * isQuerySucceeded(), or getCompletionStatus() method on the query object to
    275    * see if it has succeeded. However, if this method returns a failure, it
    276    * means that the query has failed, and there is no guarantee that its data
    277    * members are properly initialized (except for the 'mQueryDeliveryStatus',
    278    * which is always in the proper state).
    279    */
    280   virtual status_t doQuery(QemuQuery* query);
    281 
    282   /****************************************************************************
    283    * Data members
    284    ***************************************************************************/
    285 
    286  protected:
    287   /* Qemu pipe handle. */
    288   int mPipeFD;
    289 
    290  private:
    291   /* Camera service name. */
    292   static const char mCameraServiceName[];
    293 };
    294 
    295 /****************************************************************************
    296  * Qemu client for the 'factory' service.
    297  ***************************************************************************/
    298 
    299 /* Encapsulates QemuClient for the 'factory' service. */
    300 class FactoryQemuClient : public QemuClient {
    301  public:
    302   /* Constructs FactoryQemuClient instance. */
    303   FactoryQemuClient();
    304 
    305   /* Destructs FactoryQemuClient instance. */
    306   ~FactoryQemuClient();
    307 
    308   /****************************************************************************
    309    * Public API
    310    ***************************************************************************/
    311 
    312  public:
    313   /* Lists camera devices connected to the host.
    314    * Param:
    315    *  list - Upon success contains a list of cameras connected to the host. The
    316    *      list returned here is represented as a string, containing multiple
    317    *      lines separated with '\n', where each line represents a camera. Each
    318    *      camera line is formatted as such:
    319    *
    320    *          "name=<device name> channel=<num> pix=<num>
    321    * framedims=<dimensions>\n"
    322    *
    323    *      Where:
    324    *      - 'name' is the name of the camera device attached to the host. This
    325    *        name must be used for subsequent connection to the 'emulated camera'
    326    *        service for that camera.
    327    *      - 'channel' - input channel number (positive int) to use to
    328    * communicate with the camera.
    329    *      - 'pix' - pixel format (a "fourcc" uint), chosen for the video frames
    330    *        by the camera service.
    331    *      - 'framedims' contains a list of frame dimensions supported by the
    332    *        camera for the chosen pixel format. Each etry in the list is in form
    333    *        '<width>x<height>', where 'width' and 'height' are numeric values
    334    *        for width and height of a supported frame dimension. Entries in
    335    *        this list are separated with ',' with no spaces between the entries.
    336    * Return:
    337    *  NO_ERROR on success, or an appropriate error status on failure.
    338    */
    339   status_t listCameras(char** list);
    340 
    341   /****************************************************************************
    342    * Names of the queries available for the emulated camera factory.
    343    ***************************************************************************/
    344 
    345  private:
    346   /* List cameras connected to the host. */
    347   static const char mQueryList[];
    348 };
    349 
    350 /****************************************************************************
    351  * Qemu client for an 'emulated camera' service.
    352  ***************************************************************************/
    353 
    354 /* Encapsulates QemuClient for an 'emulated camera' service.
    355  */
    356 class CameraQemuClient : public QemuClient {
    357  public:
    358   /* Constructs CameraQemuClient instance. */
    359   CameraQemuClient();
    360 
    361   /* Destructs CameraQemuClient instance. */
    362   ~CameraQemuClient();
    363 
    364   /****************************************************************************
    365    * Public API
    366    ***************************************************************************/
    367 
    368  public:
    369   /* Queries camera connection.
    370    * Return:
    371    *  NO_ERROR on success, or an appropriate error status on failure.
    372    */
    373   status_t queryConnect();
    374 
    375   /* Queries camera disconnection.
    376    * Return:
    377    *  NO_ERROR on success, or an appropriate error status on failure.
    378    */
    379   status_t queryDisconnect();
    380 
    381   /* Queries camera to start capturing video.
    382    * Param:
    383    *  pixel_format - Pixel format that is used by the client to push video
    384    *      frames to the camera framework.
    385    *  width, height - Frame dimensions, requested by the framework.
    386    * Return:
    387    *  NO_ERROR on success, or an appropriate error status on failure.
    388    */
    389   status_t queryStart(uint32_t pixel_format, int width, int height);
    390 
    391   /* Queries camera to stop capturing video.
    392    * Return:
    393    *  NO_ERROR on success, or an appropriate error status on failure.
    394    */
    395   status_t queryStop();
    396 
    397   /* Queries camera for the next video frame.
    398    * Param:
    399    *  vframe, vframe_size - Define buffer, allocated to receive a video frame.
    400    *      Any of these parameters can be 0, indicating that the caller is
    401    *      interested only in preview frame.
    402    *  pframe, pframe_size - Define buffer, allocated to receive a preview frame.
    403    *      Any of these parameters can be 0, indicating that the caller is
    404    *      interested only in video frame.
    405    *  r_scale, g_scale, b_scale - White balance scale.
    406    *  exposure_comp - Expsoure compensation.
    407    * Return:
    408    *  NO_ERROR on success, or an appropriate error status on failure.
    409    */
    410   status_t queryFrame(void* vframe, void* pframe, size_t vframe_size,
    411                       size_t pframe_size, float r_scale, float g_scale,
    412                       float b_scale, float exposure_comp);
    413 
    414   /****************************************************************************
    415    * Names of the queries available for the emulated camera.
    416    ***************************************************************************/
    417 
    418  private:
    419   /* Connect to the camera. */
    420   static const char mQueryConnect[];
    421   /* Disconnect from the camera. */
    422   static const char mQueryDisconnect[];
    423   /* Start video capturing. */
    424   static const char mQueryStart[];
    425   /* Stop video capturing. */
    426   static const char mQueryStop[];
    427   /* Query frame(s). */
    428   static const char mQueryFrame[];
    429 };
    430 
    431 }; /* namespace android */
    432 
    433 #endif /* HW_EMULATOR_CAMERA_QEMU_CLIENT_H */
    434