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. */
52typedef struct CameraServiceDesc CameraServiceDesc;
53struct 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. */
63static 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 */
86static 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 */
127static 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 */
172static 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 */
231static 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 */
253static 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 */
277static 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 */
312static 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 */
356static 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 */
375static 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 */
407static 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 */
451static 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 */
463static 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 */
483static 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 */
525static 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. */
564static 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 */
578typedef struct CameraClient CameraClient;
579struct 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. */
616static 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 */
648static 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 */
725static 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 */
754static 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 */
795static 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 */
956static 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 */
995static 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 */
1153static 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. */
1214static 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 */
1239static 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
1268void
1269android_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
1288void
1289android_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