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 /*
     18  * Contains emulated camera service implementation.
     19  */
     20 
     21 #include "qemu-common.h"
     22 #include "android/globals.h"  /* for android_hw */
     23 #include "android/hw-qemud.h"
     24 #include "android/utils/misc.h"
     25 #include "android/utils/system.h"
     26 #include "android/utils/debug.h"
     27 #include "android/camera/camera-capture.h"
     28 #include "android/camera/camera-format-converters.h"
     29 #include "android/camera/camera-service.h"
     30 
     31 #define  E(...)    derror(__VA_ARGS__)
     32 #define  W(...)    dwarning(__VA_ARGS__)
     33 #define  D(...)    VERBOSE_PRINT(camera,__VA_ARGS__)
     34 #define  D_ACTIVE  VERBOSE_CHECK(camera)
     35 
     36 /* the T(...) macro is used to dump traffic */
     37 #define  T_ACTIVE   0
     38 
     39 #if T_ACTIVE
     40 #define  T(...)    VERBOSE_PRINT(camera,__VA_ARGS__)
     41 #else
     42 #define  T(...)    ((void)0)
     43 #endif
     44 
     45 /* Defines name of the camera service. */
     46 #define SERVICE_NAME    "camera"
     47 
     48 /* Maximum number of supported emulated cameras. */
     49 #define MAX_CAMERA      8
     50 
     51 /* Camera sevice descriptor. */
     52 typedef struct CameraServiceDesc CameraServiceDesc;
     53 struct CameraServiceDesc {
     54     /* Information about camera devices connected to the host.
     55      * Note that once initialized, entries in this array are considered to be
     56      * constant. */
     57     CameraInfo  camera_info[MAX_CAMERA];
     58     /* Number of camera devices connected to the host. */
     59     int         camera_count;
     60 };
     61 
     62 /* One and only one camera service. */
     63 static CameraServiceDesc    _camera_service_desc;
     64 
     65 /********************************************************************************
     66  * Helper routines
     67  *******************************************************************************/
     68 
     69 /* Extracts query name, and (optionally) query parameters from the query string.
     70  * Param:
     71  *  query - Query string. Query string in the camera service are formatted as such:
     72  *          "<query name>[ <parameters>]",
     73  *      where parameters are optional, and if present, must be separated from the
     74  *      query name with a single ' '. See comments to get_token_value routine
     75  *      for the format of the parameters string.
     76  *  query_name - Upon success contains query name extracted from the query
     77  *      string.
     78  *  query_name_size - Buffer size for 'query_name' string.
     79  *  query_param - Upon success contains a pointer to the beginning of the query
     80  *      parameters. If query has no parameters, NULL will be passed back with
     81  *      this parameter. This parameter is optional and can be NULL.
     82  * Return:
     83  *  0 on success, or number of bytes required for query name if 'query_name'
     84  *  string buffer was too small to contain it.
     85  */
     86 static int
     87 _parse_query(const char* query,
     88              char* query_name,
     89              int query_name_size,
     90              const char** query_param)
     91 {
     92     /* Extract query name. */
     93     const char* qend = strchr(query, ' ');
     94     if (qend == NULL) {
     95         qend = query + strlen(query);
     96     }
     97     if ((qend - query) >= query_name_size) {
     98         return qend - query + 1;
     99     }
    100     memcpy(query_name, query, qend - query);
    101     query_name[qend - query] = '\0';
    102 
    103     /* Calculate query parameters pointer (if needed) */
    104     if (query_param != NULL) {
    105         if (*qend == ' ') {
    106             qend++;
    107         }
    108         *query_param = (*qend == '\0') ? NULL : qend;
    109     }
    110 
    111     return 0;
    112 }
    113 
    114 /* Appends one string to another, growing the destination string buffer if
    115  * needed.
    116  * Param:
    117  *  str_buffer - Contains pointer to the destination string buffer. Content of
    118  *      this parameter can be NULL. Note that content of this parameter will
    119  *      change if string buffer has been reallocated.
    120  *  str_buf_size - Contains current buffer size of the string, addressed by
    121  *      'str_buffer' parameter. Note that content of this parameter will change
    122  *      if string buffer has been reallocated.
    123  *  str - String to append.
    124  * Return:
    125  *  0 on success, or -1 on failure (memory allocation).
    126  */
    127 static int
    128 _append_string(char** str_buf, size_t* str_buf_size, const char* str)
    129 {
    130     const size_t offset = (*str_buf != NULL) ? strlen(*str_buf) : 0;
    131     const size_t append_bytes = strlen(str) + 1;
    132 
    133     /* Make sure these two match. */
    134     if (*str_buf == NULL) {
    135         *str_buf_size = 0;
    136     }
    137 
    138     if ((offset + append_bytes) > *str_buf_size) {
    139         /* Reallocate string, so it can fit what's being append to it. Note that
    140          * we reallocate a bit bigger buffer than is needed in order to minimize
    141          * number of memory allocation calls in case there are more "appends"
    142          * coming. */
    143         const size_t required_mem = offset + append_bytes + 256;
    144         char* new_buf = (char*)realloc(*str_buf, required_mem);
    145         if (new_buf == NULL) {
    146             E("%s: Unable to allocate %d bytes for a string",
    147               __FUNCTION__, required_mem);
    148             return -1;
    149         }
    150         *str_buf = new_buf;
    151         *str_buf_size = required_mem;
    152     }
    153     memcpy(*str_buf + offset, str, append_bytes);
    154 
    155     return 0;
    156 }
    157 
    158 /* Represents camera information as a string formatted as follows:
    159  *  'name=<devname> channel=<num> pix=<format> facing=<direction> framedims=<widh1xheight1,...>\n'
    160  * Param:
    161  *  ci - Camera information descriptor to convert into a string.
    162  *  str - Pointer to the string buffer where to save the converted camera
    163  *      information descriptor. On entry, content of this parameter can be NULL.
    164  *      Note that string buffer addressed with this parameter may be reallocated
    165  *      in this routine, so (if not NULL) it must contain a buffer allocated with
    166  *      malloc.  The caller is responsible for freeing string buffer returned in
    167  *      this parameter.
    168  *  str_size - Contains byte size of the buffer addressed by 'str' parameter.
    169  * Return:
    170  *  0 on success, or != 0 on failure.
    171  */
    172 static int
    173 _camera_info_to_string(const CameraInfo* ci, char** str, size_t* str_size) {
    174     int res;
    175     int n;
    176     char tmp[128];
    177 
    178     /* Append device name. */
    179     snprintf(tmp, sizeof(tmp), "name=%s ", ci->device_name);
    180     res = _append_string(str, str_size, tmp);
    181     if (res) {
    182         return res;
    183     }
    184     /* Append input channel. */
    185     snprintf(tmp, sizeof(tmp), "channel=%d ", ci->inp_channel);
    186     res = _append_string(str, str_size, tmp);
    187     if (res) {
    188         return res;
    189     }
    190     /* Append pixel format. */
    191     snprintf(tmp, sizeof(tmp), "pix=%d ", ci->pixel_format);
    192     res = _append_string(str, str_size, tmp);
    193     if (res) {
    194         return res;
    195     }
    196     /* Append direction. */
    197     snprintf(tmp, sizeof(tmp), "dir=%s ", ci->direction);
    198     res = _append_string(str, str_size, tmp);
    199     if (res) {
    200         return res;
    201     }
    202     /* Append supported frame sizes. */
    203     snprintf(tmp, sizeof(tmp), "framedims=%dx%d",
    204              ci->frame_sizes[0].width, ci->frame_sizes[0].height);
    205     res = _append_string(str, str_size, tmp);
    206     if (res) {
    207         return res;
    208     }
    209     for (n = 1; n < ci->frame_sizes_num; n++) {
    210         snprintf(tmp, sizeof(tmp), ",%dx%d",
    211                  ci->frame_sizes[n].width, ci->frame_sizes[n].height);
    212         res = _append_string(str, str_size, tmp);
    213         if (res) {
    214             return res;
    215         }
    216     }
    217 
    218     /* Stringified camera properties should end with EOL. */
    219     return _append_string(str, str_size, "\n");
    220 }
    221 
    222 /* Gets camera information matching a display name.
    223  * Param:
    224  *  disp_name - Display name to match.
    225  *  arr - Array of camera informations.
    226  *  num - Number of elements in the array.
    227  * Return:
    228  *  Matching camera information, or NULL if matching camera information for the
    229  *  given display name has not been found in the array.
    230  */
    231 static CameraInfo*
    232 _camera_info_get_by_display_name(const char* disp_name, CameraInfo* arr, int num)
    233 {
    234     int n;
    235     for (n = 0; n < num; n++) {
    236         if (!arr[n].in_use && arr[n].display_name != NULL &&
    237             !strcmp(arr[n].display_name, disp_name)) {
    238             return &arr[n];
    239         }
    240     }
    241     return NULL;
    242 }
    243 
    244 /* Gets camera information matching a device name.
    245  * Param:
    246  *  device_name - Device name to match.
    247  *  arr - Array of camera informations.
    248  *  num - Number of elements in the array.
    249  * Return:
    250  *  Matching camera information, or NULL if matching camera information for the
    251  *  given device name has not been found in the array.
    252  */
    253 static CameraInfo*
    254 _camera_info_get_by_device_name(const char* device_name, CameraInfo* arr, int num)
    255 {
    256     int n;
    257     for (n = 0; n < num; n++) {
    258         if (arr[n].device_name != NULL && !strcmp(arr[n].device_name, device_name)) {
    259             return &arr[n];
    260         }
    261     }
    262     return NULL;
    263 }
    264 
    265 /********************************************************************************
    266  * CameraServiceDesc API
    267  *******************************************************************************/
    268 
    269 /* Initialized webcam emulation record in camera service descriptor.
    270  * Param:
    271  *  csd - Camera service descriptor to initialize a record in.
    272  *  disp_name - Display name of a web camera ('webcam<N>') to use for emulation.
    273  *  dir - Direction ('back', or 'front') that emulated camera is facing.
    274  *  ci, ci_cnt - Array of webcam information for enumerated web cameras connected
    275  *      to the host.
    276  */
    277 static void
    278 _wecam_setup(CameraServiceDesc* csd,
    279              const char* disp_name,
    280              const char* dir,
    281              CameraInfo* ci,
    282              int ci_cnt)
    283 {
    284     /* Find webcam record in the list of enumerated web cameras. */
    285     CameraInfo* found = _camera_info_get_by_display_name(disp_name, ci, ci_cnt);
    286     if (found == NULL) {
    287         W("Camera name '%s' is not found in the list of connected cameras.\n"
    288           "Use '-webcam-list' emulator option to obtain the list of connected camera names.\n",
    289           disp_name);
    290         return;
    291     }
    292 
    293     /* Save to the camera info array that will be used by the service. */
    294     memcpy(csd->camera_info + csd->camera_count, found, sizeof(CameraInfo));
    295     /* This camera is taken. */
    296     found->in_use = 1;
    297     /* Update direction parameter. */
    298     if (csd->camera_info[csd->camera_count].direction != NULL) {
    299         free(csd->camera_info[csd->camera_count].direction);
    300     }
    301     csd->camera_info[csd->camera_count].direction = ASTRDUP(dir);
    302     D("Camera %d '%s' connected to '%s' facing %s using %.4s pixel format",
    303       csd->camera_count, csd->camera_info[csd->camera_count].display_name,
    304       csd->camera_info[csd->camera_count].device_name,
    305       csd->camera_info[csd->camera_count].direction,
    306       (const char*)(&csd->camera_info[csd->camera_count].pixel_format));
    307       csd->camera_count++;
    308 }
    309 
    310 /* Initializes camera service descriptor.
    311  */
    312 static void
    313 _camera_service_init(CameraServiceDesc* csd)
    314 {
    315     CameraInfo ci[MAX_CAMERA];
    316     int connected_cnt;
    317 
    318     /* Enumerate camera devices connected to the host. */
    319     memset(ci, 0, sizeof(CameraInfo) * MAX_CAMERA);
    320     memset(csd->camera_info, 0, sizeof(CameraInfo) * MAX_CAMERA);
    321     csd->camera_count = 0;
    322 
    323     /* Lets see if HW config uses web cameras. */
    324     if (memcmp(android_hw->hw_camera_back, "webcam", 6) &&
    325         memcmp(android_hw->hw_camera_front, "webcam", 6)) {
    326         /* Web camera emulation is disabled. Skip enumeration of webcameras. */
    327         return;
    328     }
    329 
    330     /* Enumerate web cameras connected to the host. */
    331     connected_cnt = enumerate_camera_devices(ci, MAX_CAMERA);
    332     if (connected_cnt <= 0) {
    333         /* Nothing is connected - nothing to emulate. */
    334         return;
    335     }
    336 
    337     /* Set up back camera emulation. */
    338     if (!memcmp(android_hw->hw_camera_back, "webcam", 6)) {
    339         _wecam_setup(csd, android_hw->hw_camera_back, "back", ci, connected_cnt);
    340     }
    341 
    342     /* Set up front camera emulation. */
    343     if (!memcmp(android_hw->hw_camera_front, "webcam", 6)) {
    344         _wecam_setup(csd, android_hw->hw_camera_front, "front", ci, connected_cnt);
    345     }
    346 }
    347 
    348 /* Gets camera information for the given camera device name.
    349  * Param:
    350  *  cs - Initialized camera service descriptor.
    351  *  device_name - Camera's device name to look up the information for.
    352  * Return:
    353  *  Camera information pointer on success, or NULL if no camera information has
    354  *  been found for the given device name.
    355  */
    356 static CameraInfo*
    357 _camera_service_get_camera_info_by_device_name(CameraServiceDesc* cs,
    358                                                const char* device_name)
    359 {
    360     return _camera_info_get_by_device_name(device_name, cs->camera_info,
    361                                            cs->camera_count);
    362 }
    363 
    364 /********************************************************************************
    365  * Helpers for handling camera client queries
    366  *******************************************************************************/
    367 
    368 /* Formats paload size according to the protocol, and sends it to the client.
    369  * To simplify endianess handling we convert payload size to an eight characters
    370  * string, representing payload size value in hexadecimal format.
    371  * Param:
    372  *  qc - Qemu client to send the payload size to.
    373  *  payload_size - Payload size to report to the client.
    374  */
    375 static void
    376 _qemu_client_reply_payload(QemudClient* qc, size_t payload_size)
    377 {
    378     char payload_size_str[9];
    379     snprintf(payload_size_str, sizeof(payload_size_str), "%08zx", payload_size);
    380     qemud_client_send(qc, (const uint8_t*)payload_size_str, 8);
    381 }
    382 
    383 /*
    384  * Prefixes for replies to camera client queries.
    385  */
    386 
    387 /* Success, no data to send in reply. */
    388 #define OK_REPLY        "ok"
    389 /* Failure, no data to send in reply. */
    390 #define KO_REPLY        "ko"
    391 /* Success, there are data to send in reply. */
    392 #define OK_REPLY_DATA   OK_REPLY ":"
    393 /* Failure, there are data to send in reply. */
    394 #define KO_REPLY_DATA   KO_REPLY ":"
    395 
    396 /* Builds and sends a reply to a query.
    397  * All replies to a query in camera service have a prefix indicating whether the
    398  * query has succeeded ("ok"), or failed ("ko"). The prefix can be followed by
    399  * extra data, containing response to the query. In case there are extra data,
    400  * they are separated from the prefix with a ':' character.
    401  * Param:
    402  *  qc - Qemu client to send the reply to.
    403  *  ok_ko - An "ok", or "ko" selector, where 0 is for "ko", and !0 is for "ok".
    404  *  extra - Optional extra query data. Can be NULL.
    405  *  extra_size - Extra data size.
    406  */
    407 static void
    408 _qemu_client_query_reply(QemudClient* qc,
    409                          int ok_ko,
    410                          const void* extra,
    411                          size_t extra_size)
    412 {
    413     const char* ok_ko_str;
    414     size_t payload_size;
    415 
    416     /* Make sure extra_size is 0 if extra is NULL. */
    417     if (extra == NULL && extra_size != 0) {
    418         W("%s: 'extra' = NULL, while 'extra_size' = %d",
    419           __FUNCTION__, (int)extra_size);
    420         extra_size = 0;
    421     }
    422 
    423     /* Calculate total payload size, and select appropriate 'ok'/'ko' prefix */
    424     if (extra_size) {
    425         /* 'extra' size + 2 'ok'/'ko' bytes + 1 ':' separator byte. */
    426         payload_size = extra_size + 3;
    427         ok_ko_str = ok_ko ? OK_REPLY_DATA : KO_REPLY_DATA;
    428     } else {
    429         /* No extra data: just zero-terminated 'ok'/'ko'. */
    430         payload_size = 3;
    431         ok_ko_str = ok_ko ? OK_REPLY : KO_REPLY;
    432     }
    433 
    434     /* Send payload size first. */
    435     _qemu_client_reply_payload(qc, payload_size);
    436     /* Send 'ok[:]'/'ko[:]' next. Note that if there is no extra data, we still
    437      * need to send a zero-terminator for 'ok'/'ko' string instead of the ':'
    438      * separator. So, one way or another, the prefix is always 3 bytes. */
    439     qemud_client_send(qc, (const uint8_t*)ok_ko_str, 3);
    440     /* Send extra data (if present). */
    441     if (extra != NULL) {
    442         qemud_client_send(qc, (const uint8_t*)extra, extra_size);
    443     }
    444 }
    445 
    446 /* Replies query success ("OK") back to the client.
    447  * Param:
    448  *  qc - Qemu client to send the reply to.
    449  *  ok_str - An optional string containing query results. Can be NULL.
    450  */
    451 static void
    452 _qemu_client_reply_ok(QemudClient* qc, const char* ok_str)
    453 {
    454     _qemu_client_query_reply(qc, 1, ok_str,
    455                              (ok_str != NULL) ? (strlen(ok_str) + 1) : 0);
    456 }
    457 
    458 /* Replies query failure ("KO") back to the client.
    459  * Param:
    460  *  qc - Qemu client to send the reply to.
    461  *  ko_str - An optional string containing reason for failure. Can be NULL.
    462  */
    463 static void
    464 _qemu_client_reply_ko(QemudClient* qc, const char* ko_str)
    465 {
    466     _qemu_client_query_reply(qc, 0, ko_str,
    467                              (ko_str != NULL) ? (strlen(ko_str) + 1) : 0);
    468 }
    469 
    470 /********************************************************************************
    471  * Camera Factory API
    472  *******************************************************************************/
    473 
    474 /* Handles 'list' query received from the Factory client.
    475  * Response to this query is a string that represents each connected camera in
    476  * this format: 'name=devname framedims=widh1xheight1,widh2xheight2,widhNxheightN\n'
    477  * Strings, representing each camera are separated with EOL symbol.
    478  * Param:
    479  *  csd, client - Factory serivice, and client.
    480  * Return:
    481  *  0 on success, or != 0 on failure.
    482  */
    483 static int
    484 _factory_client_list_cameras(CameraServiceDesc* csd, QemudClient* client)
    485 {
    486     int n;
    487     size_t reply_size = 0;
    488     char* reply = NULL;
    489 
    490     /* Lets see if there was anything found... */
    491     if (csd->camera_count == 0) {
    492         /* No cameras connected to the host. Reply with "\n" */
    493         _qemu_client_reply_ok(client, "\n");
    494         return 0;
    495     }
    496 
    497     /* "Stringify" each camera information into the reply string. */
    498     for (n = 0; n < csd->camera_count; n++) {
    499         const int res =
    500             _camera_info_to_string(csd->camera_info + n, &reply, &reply_size);
    501         if (res) {
    502             if (reply != NULL) {
    503                 free(reply);
    504             }
    505             _qemu_client_reply_ko(client, "Memory allocation error");
    506             return res;
    507         }
    508     }
    509 
    510     D("%s Replied: %s", __FUNCTION__, reply);
    511     _qemu_client_reply_ok(client, reply);
    512     free(reply);
    513 
    514     return 0;
    515 }
    516 
    517 /* Handles a message received from the emulated camera factory client.
    518  * Queries received here are represented as strings:
    519  *  'list' - Queries list of cameras connected to the host.
    520  * Param:
    521  *  opaque - Camera service descriptor.
    522  *  msg, msglen - Message received from the camera factory client.
    523  *  client - Camera factory client pipe.
    524  */
    525 static void
    526 _factory_client_recv(void*         opaque,
    527                      uint8_t*      msg,
    528                      int           msglen,
    529                      QemudClient*  client)
    530 {
    531     /*
    532      * Emulated camera factory client queries.
    533      */
    534 
    535     /* List cameras connected to the host. */
    536     static const char _query_list[]     = "list";
    537 
    538     CameraServiceDesc* csd = (CameraServiceDesc*)opaque;
    539     char query_name[64];
    540     const char* query_param = NULL;
    541 
    542     /* Parse the query, extracting query name and parameters. */
    543     if (_parse_query((const char*)msg, query_name, sizeof(query_name),
    544                      &query_param)) {
    545         E("%s: Invalid format in query '%s'", __FUNCTION__, (const char*)msg);
    546         _qemu_client_reply_ko(client, "Invalid query format");
    547         return;
    548     }
    549 
    550     D("%s Camera factory query '%s'", __FUNCTION__, query_name);
    551 
    552     /* Dispatch the query to an appropriate handler. */
    553     if (!strcmp(query_name, _query_list)) {
    554         /* This is a "list" query. */
    555         _factory_client_list_cameras(csd, client);
    556     } else {
    557         E("%s: Unknown camera factory query name in '%s'",
    558           __FUNCTION__, (const char*)msg);
    559         _qemu_client_reply_ko(client, "Unknown query name");
    560     }
    561 }
    562 
    563 /* Emulated camera factory client has been disconnected from the service. */
    564 static void
    565 _factory_client_close(void*  opaque)
    566 {
    567     /* There is nothing to clean up here: factory service is just an alias for
    568      * the "root" camera service, that doesn't require anything more, than camera
    569      * dervice descriptor already provides. */
    570 }
    571 
    572 /********************************************************************************
    573  * Camera client API
    574  *******************************************************************************/
    575 
    576 /* Describes an emulated camera client.
    577  */
    578 typedef struct CameraClient CameraClient;
    579 struct CameraClient
    580 {
    581     /* Client name.
    582      *  On Linux this is the name of the camera device.
    583      *  On Windows this is the name of capturing window.
    584      */
    585     char*               device_name;
    586     /* Input channel to use to connect to the camera. */
    587     int                 inp_channel;
    588     /* Camera information. */
    589     const CameraInfo*   camera_info;
    590     /* Emulated camera device descriptor. */
    591     CameraDevice*       camera;
    592     /* Buffer allocated for video frames.
    593      * Note that memory allocated for this buffer
    594      * also contains preview framebuffer. */
    595     uint8_t*            video_frame;
    596     /* Preview frame buffer.
    597      * This address points inside the 'video_frame' buffer. */
    598     uint16_t*           preview_frame;
    599     /* Byte size of the videoframe buffer. */
    600     size_t              video_frame_size;
    601     /* Byte size of the preview frame buffer. */
    602     size_t              preview_frame_size;
    603     /* Pixel format required by the guest. */
    604     uint32_t            pixel_format;
    605     /* Frame width. */
    606     int                 width;
    607     /* Frame height. */
    608     int                 height;
    609     /* Number of pixels in a frame buffer. */
    610     int                 pixel_num;
    611     /* Status of video and preview frame cache. */
    612     int                 frames_cached;
    613 };
    614 
    615 /* Frees emulated camera client descriptor. */
    616 static void
    617 _camera_client_free(CameraClient* cc)
    618 {
    619     /* The only exception to the "read only" rule: we have to mark the camera
    620      * as being not used when we destroy a service for it. */
    621     if (cc->camera_info != NULL) {
    622         ((CameraInfo*)cc->camera_info)->in_use = 0;
    623     }
    624     if (cc->camera != NULL) {
    625         camera_device_close(cc->camera);
    626     }
    627     if (cc->video_frame != NULL) {
    628         free(cc->video_frame);
    629     }
    630     if (cc->device_name != NULL) {
    631         free(cc->device_name);
    632     }
    633 
    634     AFREE(cc);
    635 }
    636 
    637 /* Creates descriptor for a connecting emulated camera client.
    638  * Param:
    639  *  csd - Camera service descriptor.
    640  *  param - Client parameters. Must be formatted as described in comments to
    641  *      get_token_value routine, and must contain at least 'name' parameter,
    642  *      identifiying the camera device to create the service for. Also parameters
    643  *      may contain a decimal 'inp_channel' parameter, selecting the input
    644  *      channel to use when communicating with the camera device.
    645  * Return:
    646  *  Emulated camera client descriptor on success, or NULL on failure.
    647  */
    648 static CameraClient*
    649 _camera_client_create(CameraServiceDesc* csd, const char* param)
    650 {
    651     CameraClient* cc;
    652     CameraInfo* ci;
    653     int res;
    654     ANEW0(cc);
    655 
    656     /*
    657      * Parse parameter string, containing camera client properties.
    658      */
    659 
    660     /* Pull required device name. */
    661     if (get_token_value_alloc(param, "name", &cc->device_name)) {
    662         E("%s: Allocation failure, or required 'name' parameter is missing, or misformed in '%s'",
    663           __FUNCTION__, param);
    664         return NULL;
    665     }
    666 
    667     /* Pull optional input channel. */
    668     res = get_token_value_int(param, "inp_channel", &cc->inp_channel);
    669     if (res != 0) {
    670         if (res == -1) {
    671             /* 'inp_channel' parameter has been ommited. Use default input
    672              * channel, which is zero. */
    673             cc->inp_channel = 0;
    674         } else {
    675             E("%s: 'inp_channel' parameter is misformed in '%s'",
    676               __FUNCTION__, param);
    677             return NULL;
    678         }
    679     }
    680 
    681     /* Get camera info for the emulated camera represented with this service.
    682      * Array of camera information records has been created when the camera
    683      * service was enumerating camera devices during the service initialization.
    684      * By the camera service protocol, camera service clients must first obtain
    685      * list of enumerated cameras via the 'list' query to the camera service, and
    686      * then use device name reported in the list to connect to an emulated camera
    687      * service. So, if camera information for the given device name is not found
    688      * in the array, we fail this connection due to protocol violation. */
    689     ci = _camera_service_get_camera_info_by_device_name(csd, cc->device_name);
    690     if (ci == NULL) {
    691         E("%s: Cannot find camera info for device '%s'",
    692           __FUNCTION__, cc->device_name);
    693         _camera_client_free(cc);
    694         return NULL;
    695     }
    696 
    697     /* We can't allow multiple camera services for a single camera device, Lets
    698      * make sure that there is no client created for this camera. */
    699     if (ci->in_use) {
    700         E("%s: Camera device '%s' is in use", __FUNCTION__, cc->device_name);
    701         _camera_client_free(cc);
    702         return NULL;
    703     }
    704 
    705     /* We're done. Set camera in use, and succeed the connection. */
    706     ci->in_use = 1;
    707     cc->camera_info = ci;
    708 
    709     D("%s: Camera service is created for device '%s' using input channel %d",
    710       __FUNCTION__, cc->device_name, cc->inp_channel);
    711 
    712     return cc;
    713 }
    714 
    715 /********************************************************************************
    716  * Camera client queries
    717  *******************************************************************************/
    718 
    719 /* Client has queried conection to the camera.
    720  * Param:
    721  *  cc - Queried camera client descriptor.
    722  *  qc - Qemu client for the emulated camera.
    723  *  param - Query parameters. There are no parameters expected for this query.
    724  */
    725 static void
    726 _camera_client_query_connect(CameraClient* cc, QemudClient* qc, const char* param)
    727 {
    728     if (cc->camera != NULL) {
    729         /* Already connected. */
    730         W("%s: Camera '%s' is already connected", __FUNCTION__, cc->device_name);
    731         _qemu_client_reply_ok(qc, "Camera is already connected");
    732         return;
    733     }
    734 
    735     /* Open camera device. */
    736     cc->camera = camera_device_open(cc->device_name, cc->inp_channel);
    737     if (cc->camera == NULL) {
    738         E("%s: Unable to open camera device '%s'", __FUNCTION__, cc->device_name);
    739         _qemu_client_reply_ko(qc, "Unable to open camera device.");
    740         return;
    741     }
    742 
    743     D("%s: Camera device '%s' is now connected", __FUNCTION__, cc->device_name);
    744 
    745     _qemu_client_reply_ok(qc, NULL);
    746 }
    747 
    748 /* Client has queried disconection from the camera.
    749  * Param:
    750  *  cc - Queried camera client descriptor.
    751  *  qc - Qemu client for the emulated camera.
    752  *  param - Query parameters. There are no parameters expected for this query.
    753  */
    754 static void
    755 _camera_client_query_disconnect(CameraClient* cc,
    756                                 QemudClient* qc,
    757                                 const char* param)
    758 {
    759     if (cc->camera == NULL) {
    760         /* Already disconnected. */
    761         W("%s: Camera '%s' is already disconnected", __FUNCTION__, cc->device_name);
    762         _qemu_client_reply_ok(qc, "Camera is not connected");
    763         return;
    764     }
    765 
    766     /* Before we can go ahead and disconnect, we must make sure that camera is
    767      * not capturing frames. */
    768     if (cc->video_frame != NULL) {
    769         E("%s: Cannot disconnect camera '%s' while it is not stopped",
    770           __FUNCTION__, cc->device_name);
    771         _qemu_client_reply_ko(qc, "Camera is not stopped");
    772         return;
    773     }
    774 
    775     /* Close camera device. */
    776     camera_device_close(cc->camera);
    777     cc->camera = NULL;
    778 
    779     D("Camera device '%s' is now disconnected", cc->device_name);
    780 
    781     _qemu_client_reply_ok(qc, NULL);
    782 }
    783 
    784 /* Client has queried the client to start capturing video.
    785  * Param:
    786  *  cc - Queried camera client descriptor.
    787  *  qc - Qemu client for the emulated camera.
    788  *  param - Query parameters. Parameters for this query must contain a 'dim', and
    789  *      a 'pix' parameters, where 'dim' must be "dim=<width>x<height>", and 'pix'
    790  *      must be "pix=<format>", where 'width' and 'height' must be numerical
    791  *      values for the capturing video frame width, and height, and 'format' must
    792  *      be a numerical value for the pixel format of the video frames expected by
    793  *      the client. 'format' must be one of the V4L2_PIX_FMT_XXX values.
    794  */
    795 static void
    796 _camera_client_query_start(CameraClient* cc, QemudClient* qc, const char* param)
    797 {
    798     char* w;
    799     char dim[64];
    800     int width, height, pix_format;
    801 
    802     /* Sanity check. */
    803     if (cc->camera == NULL) {
    804         /* Not connected. */
    805         E("%s: Camera '%s' is not connected", __FUNCTION__, cc->device_name);
    806         _qemu_client_reply_ko(qc, "Camera is not connected");
    807         return;
    808     }
    809 
    810     /*
    811      * Parse parameters.
    812      */
    813 
    814     if (param == NULL) {
    815         E("%s: Missing parameters for the query", __FUNCTION__);
    816         _qemu_client_reply_ko(qc, "Missing parameters for the query");
    817         return;
    818     }
    819 
    820     /* Pull required 'dim' parameter. */
    821     if (get_token_value(param, "dim", dim, sizeof(dim))) {
    822         E("%s: Invalid or missing 'dim' parameter in '%s'", __FUNCTION__, param);
    823         _qemu_client_reply_ko(qc, "Invalid or missing 'dim' parameter");
    824         return;
    825     }
    826 
    827     /* Pull required 'pix' parameter. */
    828     if (get_token_value_int(param, "pix", &pix_format)) {
    829         E("%s: Invalid or missing 'pix' parameter in '%s'", __FUNCTION__, param);
    830         _qemu_client_reply_ko(qc, "Invalid or missing 'pix' parameter");
    831         return;
    832     }
    833 
    834     /* Parse 'dim' parameter, and get requested frame width and height. */
    835     w = strchr(dim, 'x');
    836     if (w == NULL || w[1] == '\0') {
    837         E("%s: Invalid 'dim' parameter in '%s'", __FUNCTION__, param);
    838         _qemu_client_reply_ko(qc, "Invalid 'dim' parameter");
    839         return;
    840     }
    841     *w = '\0'; w++;
    842     errno = 0;
    843     width = strtoi(dim, NULL, 10);
    844     height = strtoi(w, NULL, 10);
    845     if (errno) {
    846         E("%s: Invalid 'dim' parameter in '%s'", __FUNCTION__, param);
    847         _qemu_client_reply_ko(qc, "Invalid 'dim' parameter");
    848         return;
    849     }
    850 
    851     /* After collecting capture parameters lets see if camera has already
    852      * started, and if so, lets see if parameters match. */
    853     if (cc->video_frame != NULL) {
    854         /* Already started. Match capture parameters. */
    855         if (cc->pixel_format != pix_format ||cc->width != width ||
    856             cc->height != height) {
    857             /* Parameters match. Succeed the query. */
    858             W("%s: Camera '%s' is already started", __FUNCTION__, cc->device_name);
    859             _qemu_client_reply_ok(qc, "Camera is already started");
    860         } else {
    861             /* Parameters don't match. Fail the query. */
    862             E("%s: Camera '%s' is already started, and parameters don't match:\n"
    863               "Current %.4s[%dx%d] != requested %.4s[%dx%d]",
    864               __FUNCTION__, cc->device_name, (const char*)&cc->pixel_format,
    865               cc->width, cc->height, (const char*)&pix_format, width, height);
    866             _qemu_client_reply_ko(qc,
    867                 "Camera is already started with different capturing parameters");
    868         }
    869         return;
    870     }
    871 
    872     /*
    873      * Start the camera.
    874      */
    875 
    876     /* Save capturing parameters. */
    877     cc->pixel_format = pix_format;
    878     cc->width = width;
    879     cc->height = height;
    880     cc->pixel_num = cc->width * cc->height;
    881     cc->frames_cached = 0;
    882 
    883     /* Make sure that pixel format is known, and calculate video framebuffer size
    884      * along the lines. */
    885     switch (cc->pixel_format) {
    886         case V4L2_PIX_FMT_YUV420:
    887         case V4L2_PIX_FMT_YVU420:
    888         case V4L2_PIX_FMT_NV12:
    889         case V4L2_PIX_FMT_NV21:
    890             cc->video_frame_size = (cc->pixel_num * 12) / 8;
    891             break;
    892 
    893         default:
    894             E("%s: Unknown pixel format %.4s",
    895               __FUNCTION__, (char*)&cc->pixel_format);
    896             _qemu_client_reply_ko(qc, "Pixel format is unknown");
    897             return;
    898     }
    899 
    900     /* Make sure that we have a converters between the original camera pixel
    901      * format and the one that the client expects. Also a converter must exist
    902      * for the preview window pixel format (RGB32) */
    903     if (!has_converter(cc->camera_info->pixel_format, cc->pixel_format) ||
    904         !has_converter(cc->camera_info->pixel_format, V4L2_PIX_FMT_RGB32)) {
    905         E("%s: No conversion exist between %.4s and %.4s (or RGB32) pixel formats",
    906           __FUNCTION__, (char*)&cc->camera_info->pixel_format, (char*)&cc->pixel_format);
    907         _qemu_client_reply_ko(qc, "No conversion exist for the requested pixel format");
    908         return;
    909     }
    910 
    911     /* TODO: At the moment camera framework in the emulator requires RGB32 pixel
    912      * format for preview window. So, we need to keep two framebuffers here: one
    913      * for the video, and another for the preview window. Watch out when this
    914      * changes (if changes). */
    915     cc->preview_frame_size = cc->pixel_num * 4;
    916 
    917     /* Allocate buffer large enough to contain both, video and preview
    918      * framebuffers. */
    919     cc->video_frame =
    920         (uint8_t*)malloc(cc->video_frame_size + cc->preview_frame_size);
    921     if (cc->video_frame == NULL) {
    922         E("%s: Not enough memory for framebuffers %d + %d",
    923           __FUNCTION__, cc->video_frame_size, cc->preview_frame_size);
    924         _qemu_client_reply_ko(qc, "Out of memory");
    925         return;
    926     }
    927 
    928     /* Set framebuffer pointers. */
    929     cc->preview_frame = (uint16_t*)(cc->video_frame + cc->video_frame_size);
    930 
    931     /* Start the camera. */
    932     if (camera_device_start_capturing(cc->camera, cc->camera_info->pixel_format,
    933                                       cc->width, cc->height)) {
    934         E("%s: Cannot start camera '%s' for %.4s[%dx%d]: %s",
    935           __FUNCTION__, cc->device_name, (const char*)&cc->pixel_format,
    936           cc->width, cc->height, strerror(errno));
    937         free(cc->video_frame);
    938         cc->video_frame = NULL;
    939         _qemu_client_reply_ko(qc, "Cannot start the camera");
    940         return;
    941     }
    942 
    943     D("%s: Camera '%s' is now started for %.4s[%dx%d]",
    944       __FUNCTION__, cc->device_name, (char*)&cc->pixel_format, cc->width,
    945       cc->height);
    946 
    947     _qemu_client_reply_ok(qc, NULL);
    948 }
    949 
    950 /* Client has queried the client to stop capturing video.
    951  * Param:
    952  *  cc - Queried camera client descriptor.
    953  *  qc - Qemu client for the emulated camera.
    954  *  param - Query parameters. There are no parameters expected for this query.
    955  */
    956 static void
    957 _camera_client_query_stop(CameraClient* cc, QemudClient* qc, const char* param)
    958 {
    959     if (cc->video_frame == NULL) {
    960         /* Not started. */
    961         W("%s: Camera '%s' is not started", __FUNCTION__, cc->device_name);
    962         _qemu_client_reply_ok(qc, "Camera is not started");
    963         return;
    964     }
    965 
    966     /* Stop the camera. */
    967     if (camera_device_stop_capturing(cc->camera)) {
    968         E("%s: Cannot stop camera device '%s': %s",
    969           __FUNCTION__, cc->device_name, strerror(errno));
    970         _qemu_client_reply_ko(qc, "Cannot stop camera device");
    971         return;
    972     }
    973 
    974     free(cc->video_frame);
    975     cc->video_frame = NULL;
    976 
    977     D("%s: Camera device '%s' is now stopped.", __FUNCTION__, cc->device_name);
    978     _qemu_client_reply_ok(qc, NULL);
    979 }
    980 
    981 /* Client has queried next frame.
    982  * Param:
    983  *  cc - Queried camera client descriptor.
    984  *  qc - Qemu client for the emulated camera.
    985  *  param - Query parameters. Parameters for this query are formatted as such:
    986  *          video=<size> preview=<size> whiteb=<red>,<green>,<blue> expcomp=<comp>
    987  *      where:
    988  *       - 'video', and 'preview' both must be decimal values, defining size of
    989  *         requested video, and preview frames respectively. Zero value for any
    990  *         of these parameters means that this particular frame is not requested.
    991  *       - whiteb contains float values required to calculate whilte balance.
    992  *       - expcomp contains a float value required to calculate exposure
    993  *         compensation.
    994  */
    995 static void
    996 _camera_client_query_frame(CameraClient* cc, QemudClient* qc, const char* param)
    997 {
    998     int video_size = 0;
    999     int preview_size = 0;
   1000     int repeat;
   1001     ClientFrameBuffer fbs[2];
   1002     int fbs_num = 0;
   1003     size_t payload_size;
   1004     uint64_t tick;
   1005     float r_scale = 1.0f, g_scale = 1.0f, b_scale = 1.0f, exp_comp = 1.0f;
   1006     char tmp[256];
   1007 
   1008     /* Sanity check. */
   1009     if (cc->video_frame == NULL) {
   1010         /* Not started. */
   1011         E("%s: Camera '%s' is not started", __FUNCTION__, cc->device_name);
   1012         _qemu_client_reply_ko(qc, "Camera is not started");
   1013         return;
   1014     }
   1015 
   1016     /* Pull required parameters. */
   1017     if (get_token_value_int(param, "video", &video_size) ||
   1018         get_token_value_int(param, "preview", &preview_size)) {
   1019         E("%s: Invalid or missing 'video', or 'preview' parameter in '%s'",
   1020           __FUNCTION__, param);
   1021         _qemu_client_reply_ko(qc,
   1022             "Invalid or missing 'video', or 'preview' parameter");
   1023         return;
   1024     }
   1025 
   1026     /* Pull white balance values. */
   1027     if (!get_token_value(param, "whiteb", tmp, sizeof(tmp))) {
   1028         if (sscanf(tmp, "%g,%g,%g", &r_scale, &g_scale, &b_scale) != 3) {
   1029             D("Invalid value '%s' for parameter 'whiteb'", tmp);
   1030             r_scale = g_scale = b_scale = 1.0f;
   1031         }
   1032     }
   1033 
   1034     /* Pull exposure compensation. */
   1035     if (!get_token_value(param, "expcomp", tmp, sizeof(tmp))) {
   1036         if (sscanf(tmp, "%g", &exp_comp) != 1) {
   1037             D("Invalid value '%s' for parameter 'whiteb'", tmp);
   1038             exp_comp = 1.0f;
   1039         }
   1040     }
   1041 
   1042     /* Verify that framebuffer sizes match the ones that the started camera
   1043      * operates with. */
   1044     if ((video_size != 0 && cc->video_frame_size != video_size) ||
   1045         (preview_size != 0 && cc->preview_frame_size != preview_size)) {
   1046         E("%s: Frame sizes don't match for camera '%s':\n"
   1047           "Expected %d for video, and %d for preview. Requested %d, and %d",
   1048           __FUNCTION__, cc->device_name, cc->video_frame_size,
   1049           cc->preview_frame_size, video_size, preview_size);
   1050         _qemu_client_reply_ko(qc, "Frame size mismatch");
   1051         return;
   1052     }
   1053 
   1054     /*
   1055      * Initialize framebuffer array for frame read.
   1056      */
   1057 
   1058     if (video_size) {
   1059         fbs[fbs_num].pixel_format = cc->pixel_format;
   1060         fbs[fbs_num].framebuffer = cc->video_frame;
   1061         fbs_num++;
   1062     }
   1063     if (preview_size) {
   1064         /* TODO: Watch out for preview format changes! */
   1065         fbs[fbs_num].pixel_format = V4L2_PIX_FMT_RGB32;
   1066         fbs[fbs_num].framebuffer = cc->preview_frame;
   1067         fbs_num++;
   1068     }
   1069 
   1070     /* Capture new frame. */
   1071     tick = _get_timestamp();
   1072     repeat = camera_device_read_frame(cc->camera, fbs, fbs_num,
   1073                                       r_scale, g_scale, b_scale, exp_comp);
   1074 
   1075     /* Note that there is no (known) way how to wait on next frame being
   1076      * available, so we could dequeue frame buffer from the device only when we
   1077      * know it's available. Instead we're shooting in the dark, and quite often
   1078      * device will response with EAGAIN, indicating that it doesn't have frame
   1079      * ready. In turn, it means that the last frame we have obtained from the
   1080      * device is still good, and we can reply with the cached frames. The only
   1081      * case when we need to keep trying to obtain a new frame is when frame cache
   1082      * is empty. To prevent ourselves from an indefinite loop in case device got
   1083      * stuck on something (observed with some Microsoft devices) we will limit
   1084      * the loop by 2 second time period (which is more than enough to obtain
   1085      * something from the device) */
   1086     while (repeat == 1 && !cc->frames_cached &&
   1087            (_get_timestamp() - tick) < 2000000LL) {
   1088         /* Sleep for 10 millisec before repeating the attempt. */
   1089         _camera_sleep(10);
   1090         repeat = camera_device_read_frame(cc->camera, fbs, fbs_num,
   1091                                           r_scale, g_scale, b_scale, exp_comp);
   1092     }
   1093     if (repeat == 1 && !cc->frames_cached) {
   1094         /* Waited too long for the first frame. */
   1095         E("%s: Unable to obtain first video frame from the camera '%s' in %d milliseconds: %s.",
   1096           __FUNCTION__, cc->device_name,
   1097           (uint32_t)(_get_timestamp() - tick) / 1000, strerror(errno));
   1098         _qemu_client_reply_ko(qc, "Unable to obtain video frame from the camera");
   1099         return;
   1100     } else if (repeat < 0) {
   1101         /* An I/O error. */
   1102         E("%s: Unable to obtain video frame from the camera '%s': %s.",
   1103           __FUNCTION__, cc->device_name, strerror(errno));
   1104         _qemu_client_reply_ko(qc, strerror(errno));
   1105         return;
   1106     }
   1107 
   1108     /* We have cached something... */
   1109     cc->frames_cached = 1;
   1110 
   1111     /*
   1112      * Build the reply.
   1113      */
   1114 
   1115     /* Payload includes "ok:" + requested video and preview frames. */
   1116     payload_size = 3 + video_size + preview_size;
   1117 
   1118     /* Send payload size first. */
   1119     _qemu_client_reply_payload(qc, payload_size);
   1120 
   1121     /* After that send the 'ok:'. Note that if there is no frames sent, we should
   1122      * use prefix "ok" instead of "ok:" */
   1123     if (video_size || preview_size) {
   1124         qemud_client_send(qc, (const uint8_t*)"ok:", 3);
   1125     } else {
   1126         /* Still 3 bytes: zero terminator is required in this case. */
   1127         qemud_client_send(qc, (const uint8_t*)"ok", 3);
   1128     }
   1129 
   1130     /* After that send video frame (if requested). */
   1131     if (video_size) {
   1132         qemud_client_send(qc, cc->video_frame, video_size);
   1133     }
   1134 
   1135     /* After that send preview frame (if requested). */
   1136     if (preview_size) {
   1137         qemud_client_send(qc, (const uint8_t*)cc->preview_frame, preview_size);
   1138     }
   1139 }
   1140 
   1141 /* Handles a message received from the emulated camera client.
   1142  * Queries received here are represented as strings:
   1143  * - 'connect' - Connects to the camera device (opens it).
   1144  * - 'disconnect' - Disconnexts from the camera device (closes it).
   1145  * - 'start' - Starts capturing video from the connected camera device.
   1146  * - 'stop' - Stop capturing video from the connected camera device.
   1147  * - 'frame' - Queries video and preview frames captured from the camera.
   1148  * Param:
   1149  *  opaque - Camera service descriptor.
   1150  *  msg, msglen - Message received from the camera factory client.
   1151  *  client - Camera factory client pipe.
   1152  */
   1153 static void
   1154 _camera_client_recv(void*         opaque,
   1155                     uint8_t*      msg,
   1156                     int           msglen,
   1157                     QemudClient*  client)
   1158 {
   1159     /*
   1160      * Emulated camera client queries.
   1161      */
   1162 
   1163     /* Connect to the camera. */
   1164     static const char _query_connect[]    = "connect";
   1165     /* Disconnect from the camera. */
   1166     static const char _query_disconnect[] = "disconnect";
   1167     /* Start video capturing. */
   1168     static const char _query_start[]      = "start";
   1169     /* Stop video capturing. */
   1170     static const char _query_stop[]       = "stop";
   1171     /* Query frame(s). */
   1172     static const char _query_frame[]      = "frame";
   1173 
   1174     char query_name[64];
   1175     const char* query_param = NULL;
   1176     CameraClient* cc = (CameraClient*)opaque;
   1177 
   1178     /*
   1179      * Emulated camera queries are formatted as such:
   1180      *  "<query name> [<parameters>]"
   1181      */
   1182 
   1183     T("%s: Camera client query: '%s'", __FUNCTION__, (char*)msg);
   1184     if (_parse_query((const char*)msg, query_name, sizeof(query_name),
   1185         &query_param)) {
   1186         E("%s: Invalid query '%s'", __FUNCTION__, (char*)msg);
   1187         _qemu_client_reply_ko(client, "Invalid query");
   1188         return;
   1189     }
   1190 
   1191     /* Dispatch the query to an appropriate handler. */
   1192     if (!strcmp(query_name, _query_frame)) {
   1193         /* A frame is queried. */
   1194         _camera_client_query_frame(cc, client, query_param);
   1195     } else if (!strcmp(query_name, _query_connect)) {
   1196         /* Camera connection is queried. */
   1197         _camera_client_query_connect(cc, client, query_param);
   1198     } else if (!strcmp(query_name, _query_disconnect)) {
   1199         /* Camera disnection is queried. */
   1200         _camera_client_query_disconnect(cc, client, query_param);
   1201     } else if (!strcmp(query_name, _query_start)) {
   1202         /* Start capturing is queried. */
   1203         _camera_client_query_start(cc, client, query_param);
   1204     } else if (!strcmp(query_name, _query_stop)) {
   1205         /* Stop capturing is queried. */
   1206         _camera_client_query_stop(cc, client, query_param);
   1207     } else {
   1208         E("%s: Unknown query '%s'", __FUNCTION__, (char*)msg);
   1209         _qemu_client_reply_ko(client, "Unknown query");
   1210     }
   1211 }
   1212 
   1213 /* Emulated camera client has been disconnected from the service. */
   1214 static void
   1215 _camera_client_close(void* opaque)
   1216 {
   1217     CameraClient* cc = (CameraClient*)opaque;
   1218 
   1219     D("%s: Camera client for device '%s' on input channel %d is now closed",
   1220       __FUNCTION__, cc->device_name, cc->inp_channel);
   1221 
   1222     _camera_client_free(cc);
   1223 }
   1224 
   1225 /********************************************************************************
   1226  * Camera service API
   1227  *******************************************************************************/
   1228 
   1229 /* Connects a client to the camera service.
   1230  * There are two classes of the client that can connect to the service:
   1231  *  - Camera factory that is insterested only in listing camera devices attached
   1232  *    to the host.
   1233  *  - Camera device emulators that attach to the actual camera devices.
   1234  * The distinction between these two classes is made by looking at extra
   1235  * parameters passed in client_param variable. If it's NULL, or empty, the client
   1236  * connects to a camera factory. Otherwise, parameters describe the camera device
   1237  * the client wants to connect to.
   1238  */
   1239 static QemudClient*
   1240 _camera_service_connect(void*          opaque,
   1241                         QemudService*  serv,
   1242                         int            channel,
   1243                         const char*    client_param)
   1244 {
   1245     QemudClient*  client = NULL;
   1246     CameraServiceDesc* csd = (CameraServiceDesc*)opaque;
   1247 
   1248     D("%s: Connecting camera client '%s'",
   1249       __FUNCTION__, client_param ? client_param : "Factory");
   1250     if (client_param == NULL || *client_param == '\0') {
   1251         /* This is an emulated camera factory client. */
   1252         client = qemud_client_new(serv, channel, client_param, csd,
   1253                                   _factory_client_recv, _factory_client_close,
   1254                                   NULL, NULL);
   1255     } else {
   1256         /* This is an emulated camera client. */
   1257         CameraClient* cc = _camera_client_create(csd, client_param);
   1258         if (cc != NULL) {
   1259             client = qemud_client_new(serv, channel, client_param, cc,
   1260                                       _camera_client_recv, _camera_client_close,
   1261                                       NULL, NULL);
   1262         }
   1263     }
   1264 
   1265     return client;
   1266 }
   1267 
   1268 void
   1269 android_camera_service_init(void)
   1270 {
   1271     static int _inited = 0;
   1272 
   1273     if (!_inited) {
   1274         _camera_service_init(&_camera_service_desc);
   1275         QemudService*  serv = qemud_service_register( SERVICE_NAME, 0,
   1276                                                       &_camera_service_desc,
   1277                                                       _camera_service_connect,
   1278                                                       NULL, NULL);
   1279         if (serv == NULL) {
   1280             derror("%s: Could not register '%s' service",
   1281                    __FUNCTION__, SERVICE_NAME);
   1282             return;
   1283         }
   1284         D("%s: Registered '%s' qemud service", __FUNCTION__, SERVICE_NAME);
   1285     }
   1286 }
   1287 
   1288 void
   1289 android_list_web_cameras(void)
   1290 {
   1291     CameraInfo ci[MAX_CAMERA];
   1292     int connected_cnt;
   1293     int i;
   1294 
   1295     /* Enumerate camera devices connected to the host. */
   1296     connected_cnt = enumerate_camera_devices(ci, MAX_CAMERA);
   1297     if (connected_cnt <= 0) {
   1298         return;
   1299     }
   1300 
   1301     printf("List of web cameras connected to the computer:\n");
   1302     for (i = 0; i < connected_cnt; i++) {
   1303         printf(" Camera '%s' is connected to device '%s' on channel %d using pixel format '%.4s'\n",
   1304                ci[i].display_name, ci[i].device_name, ci[i].inp_channel,
   1305                (const char*)&ci[i].pixel_format);
   1306     }
   1307     printf("\n");
   1308 }
   1309