Add -webcam commandline option to control webcam emulation

-webcam name=<name>[,dir=<direction>] options controls web cameras to use for emulation.

Change-Id: I961fd399c7e041541adda040dd24f194cc383cb9
diff --git a/android/camera/camera-capture-linux.c b/android/camera/camera-capture-linux.c
index 072d06e..50324f0 100644
--- a/android/camera/camera-capture-linux.c
+++ b/android/camera/camera-capture-linux.c
@@ -1048,6 +1048,9 @@
         if (cd != NULL) {
             LinuxCameraDevice* lcd = (LinuxCameraDevice*)cd->opaque;
             if (!_camera_device_get_info(lcd, cis + found)) {
+                char user_name[24];
+                sprintf(user_name, "webcam%d", found);
+                cis[found].display_name = ASTRDUP(user_name);
                 cis[found].in_use = 0;
                 found++;
             }
diff --git a/android/camera/camera-capture-windows.c b/android/camera/camera-capture-windows.c
index e5120ab..0fb172e 100755
--- a/android/camera/camera-capture-windows.c
+++ b/android/camera/camera-capture-windows.c
@@ -504,7 +504,11 @@
                  * but the actual numbers may vary). */
                 cis[found].frame_sizes = (CameraFrameDim*)malloc(sizeof(CameraFrameDim));
                 if (cis[found].frame_sizes != NULL) {
+                    char disp_name[24];
+                    sprintf(disp_name, "webcam%d", found);
+                    cis[found].display_name = ASTRDUP(disp_name);
                     cis[found].device_name = ASTRDUP(name);
+                    cis[found].direction = ASTRDUP("front");
                     cis[found].inp_channel = inp_channel;
                     cis[found].frame_sizes->width = wcd->frame_bitmap->bmiHeader.biWidth;
                     cis[found].frame_sizes->height = wcd->frame_bitmap->bmiHeader.biHeight;
diff --git a/android/camera/camera-common.h b/android/camera/camera-common.h
index 0cf8cea..a3fdd5f 100755
--- a/android/camera/camera-common.h
+++ b/android/camera/camera-common.h
@@ -88,12 +88,16 @@
  * representing that camera.
  */
 typedef struct CameraInfo {
+    /* User-friendly camera display name. */
+    char*               display_name;
     /* Device name for the camera. */
     char*               device_name;
     /* Input channel for the camera. */
     int                 inp_channel;
     /* Pixel format chosen for the camera. */
     uint32_t            pixel_format;
+    /* Direction the camera is facing: 'front', or 'back' */
+    char*               direction;
     /* Array of frame sizes supported for the pixel format chosen for the camera.
      * The size of the array is defined by the frame_sizes_num field of this
      * structure. */
@@ -120,8 +124,12 @@
 static __inline__ void _camera_info_free(CameraInfo* ci)
 {
     if (ci != NULL) {
+        if (ci->display_name != NULL)
+            free(ci->display_name);
         if (ci->device_name != NULL)
             free(ci->device_name);
+        if (ci->direction != NULL)
+            free(ci->direction);
         if (ci->frame_sizes != NULL)
             free(ci->frame_sizes);
         AFREE(ci);
diff --git a/android/camera/camera-service.c b/android/camera/camera-service.c
index a35f595..96d3c44 100644
--- a/android/camera/camera-service.c
+++ b/android/camera/camera-service.c
@@ -19,6 +19,7 @@
  */
 
 #include "qemu-common.h"
+#include "android/globals.h"  /* for android_hw */
 #include "android/hw-qemud.h"
 #include "android/utils/misc.h"
 #include "android/utils/system.h"
@@ -62,48 +63,6 @@
 static CameraServiceDesc    _camera_service_desc;
 
 /********************************************************************************
- * CameraServiceDesc API
- *******************************************************************************/
-
-/* Initializes camera service descriptor.
- */
-static void
-_camera_service_init(CameraServiceDesc* csd)
-{
-    /* Enumerate camera devices connected to the host. */
-    csd->camera_count = enumerate_camera_devices(csd->camera_info, MAX_CAMERA);
-    if (csd->camera_count >= 0) {
-        D("%s: Enumerated %d cameras connected to the host",
-          __FUNCTION__, csd->camera_count);
-    } else {
-        E("%s: Unable to enumerate camera devices", __FUNCTION__);
-        csd->camera_count = 0;
-        return;
-    }
-}
-
-/* Gets camera information for the given camera device name.
- * Param:
- *  cs - Initialized camera service descriptor.
- *  name - Camera device name to look up the information for.
- * Return:
- *  Camera information pointer on success, or NULL if no camera information has
- *  been found for the given device name. Note that camera information returned
- *  from this routine is constant.
- */
-static CameraInfo*
-_camera_service_get_camera_info(CameraServiceDesc* cs, const char* name)
-{
-    int n;
-    for (n = 0; n < cs->camera_count; n++) {
-        if (!strcmp(cs->camera_info[n].device_name, name)) {
-            return &cs->camera_info[n];
-        }
-    }
-    return NULL;
-}
-
-/********************************************************************************
  * Helper routines
  *******************************************************************************/
 
@@ -357,7 +316,7 @@
 }
 
 /* Represents camera information as a string formatted as follows:
- *  'name=<devname> channel=<num> pix=<format> framedims=<widh1xheight1,widh2xheight2,widhNxheightN>\n'
+ *  'name=<devname> channel=<num> pix=<format> facing=<direction> framedims=<widh1xheight1,...>\n'
  * Param:
  *  ci - Camera information descriptor to convert into a string.
  *  str - Pointer to the string buffer where to save the converted camera
@@ -394,6 +353,12 @@
     if (res) {
         return res;
     }
+    /* Append direction. */
+    snprintf(tmp, sizeof(tmp), "dir=%s ", ci->direction);
+    res = _append_string(str, str_size, tmp);
+    if (res) {
+        return res;
+    }
     /* Append supported frame sizes. */
     snprintf(tmp, sizeof(tmp), "framedims=%dx%d",
              ci->frame_sizes[0].width, ci->frame_sizes[0].height);
@@ -414,6 +379,143 @@
     return _append_string(str, str_size, "\n");
 }
 
+/* Gets camera information matching a display name.
+ * Param:
+ *  disp_name - Display name to match.
+ *  arr - Array of camera informations.
+ *  num - Number of elements in the array.
+ * Return:
+ *  Matching camera information, or NULL if matching camera information for the
+ *  given display name has not been found in the array.
+ */
+static CameraInfo*
+_camera_info_get_by_display_name(const char* disp_name, CameraInfo* arr, int num)
+{
+    int n;
+    for (n = 0; n < num; n++) {
+        if (arr[n].display_name != NULL && !strcmp(arr[n].display_name, disp_name)) {
+            return &arr[n];
+        }
+    }
+    return NULL;
+}
+
+/* Gets camera information matching a device name.
+ * Param:
+ *  device_name - Device name to match.
+ *  arr - Array of camera informations.
+ *  num - Number of elements in the array.
+ * Return:
+ *  Matching camera information, or NULL if matching camera information for the
+ *  given device name has not been found in the array.
+ */
+static CameraInfo*
+_camera_info_get_by_device_name(const char* device_name, CameraInfo* arr, int num)
+{
+    int n;
+    for (n = 0; n < num; n++) {
+        if (arr[n].device_name != NULL && !strcmp(arr[n].device_name, device_name)) {
+            return &arr[n];
+        }
+    }
+    return NULL;
+}
+
+/********************************************************************************
+ * CameraServiceDesc API
+ *******************************************************************************/
+
+/* Initializes camera service descriptor.
+ */
+static void
+_camera_service_init(CameraServiceDesc* csd)
+{
+    CameraInfo ci[MAX_CAMERA];
+    int connected_cnt;
+    int i;
+
+    /* Enumerate camera devices connected to the host. */
+    memset(ci, 0, sizeof(CameraInfo) * MAX_CAMERA);
+    memset(csd->camera_info, 0, sizeof(CameraInfo) * MAX_CAMERA);
+    csd->camera_count = 0;
+    connected_cnt = enumerate_camera_devices(ci, MAX_CAMERA);
+    if (connected_cnt <= 0) {
+        /* Nothing is connected - nothing to emulate. */
+        return;
+    }
+
+    /* For each webcam declared in hw.ini find an actual camera information
+     * descriptor, and save it into the service descriptor for the emulation. */
+    for (i = 0; i < android_hw->hw_webcam_count; i++) {
+        const char* disp_name;
+        const char* dir;
+        CameraInfo* found;
+
+        switch (i) {
+            case 0:
+                disp_name = android_hw->hw_webcam_0_name;
+                dir = android_hw->hw_webcam_0_direction;
+                break;
+            case 1:
+                disp_name = android_hw->hw_webcam_1_name;
+                dir = android_hw->hw_webcam_1_direction;
+                break;
+            case 2:
+                disp_name = android_hw->hw_webcam_2_name;
+                dir = android_hw->hw_webcam_2_direction;
+                break;
+            case 3:
+                disp_name = android_hw->hw_webcam_3_name;
+                dir = android_hw->hw_webcam_3_direction;
+                break;
+            case 4:
+                disp_name = android_hw->hw_webcam_4_name;
+                dir = android_hw->hw_webcam_4_direction;
+                break;
+            case 5:
+            default:
+                disp_name = android_hw->hw_webcam_5_name;
+                dir = android_hw->hw_webcam_5_direction;
+                break;
+        }
+        found = _camera_info_get_by_display_name(disp_name, ci, connected_cnt);
+        if (found != NULL) {
+            /* Save to the camera info array that will be used by the service.
+             * Note that we just copy everything over, and NULL the source
+             * record. */
+            memcpy(csd->camera_info + csd->camera_count, found, sizeof(CameraInfo));
+            /* Update direction parameter. */
+            if (csd->camera_info[csd->camera_count].direction != NULL) {
+                free(csd->camera_info[csd->camera_count].direction);
+            }
+            csd->camera_info[csd->camera_count].direction = ASTRDUP(dir);
+            D("Camera %d '%s' connected to '%s' facing %s using %.4s pixel format",
+              csd->camera_count, csd->camera_info[csd->camera_count].display_name,
+              csd->camera_info[csd->camera_count].device_name,
+              csd->camera_info[csd->camera_count].direction,
+              (const char*)(&csd->camera_info[csd->camera_count].pixel_format));
+            csd->camera_count++;
+            memset(found, 0, sizeof(CameraInfo));
+        }
+    }
+}
+
+/* Gets camera information for the given camera device name.
+ * Param:
+ *  cs - Initialized camera service descriptor.
+ *  device_name - Camera's device name to look up the information for.
+ * Return:
+ *  Camera information pointer on success, or NULL if no camera information has
+ *  been found for the given device name.
+ */
+static CameraInfo*
+_camera_service_get_camera_info_by_device_name(CameraServiceDesc* cs,
+                                               const char* device_name)
+{
+    return _camera_info_get_by_device_name(device_name, cs->camera_info,
+                                           cs->camera_count);
+}
+
 /********************************************************************************
  * Helpers for handling camera client queries
  *******************************************************************************/
@@ -743,7 +845,7 @@
      * then use device name reported in the list to connect to an emulated camera
      * service. So, if camera information for the given device name is not found
      * in the array, we fail this connection due to protocol violation. */
-    ci = _camera_service_get_camera_info(csd, cc->device_name);
+    ci = _camera_service_get_camera_info_by_device_name(csd, cc->device_name);
     if (ci == NULL) {
         E("%s: Cannot find camera info for device '%s'",
           __FUNCTION__, cc->device_name);
@@ -1303,3 +1405,25 @@
         D("%s: Registered '%s' qemud service", __FUNCTION__, SERVICE_NAME);
     }
 }
+
+void
+android_list_web_cameras(void)
+{
+    CameraInfo ci[MAX_CAMERA];
+    int connected_cnt;
+    int i;
+
+    /* Enumerate camera devices connected to the host. */
+    connected_cnt = enumerate_camera_devices(ci, MAX_CAMERA);
+    if (connected_cnt <= 0) {
+        return;
+    }
+
+    printf("List of web cameras connected to the computer:\n");
+    for (i = 0; i < connected_cnt; i++) {
+        printf(" Camera '%s' is connected to device '%s' on channel %d using pixel format '%.4s'\n",
+               ci[i].display_name, ci[i].device_name, ci[i].inp_channel,
+               (const char*)&ci[i].pixel_format);
+    }
+    printf("\n");
+}
diff --git a/android/camera/camera-service.h b/android/camera/camera-service.h
index 6794187..e8df288 100644
--- a/android/camera/camera-service.h
+++ b/android/camera/camera-service.h
@@ -24,4 +24,7 @@
 /* Initializes camera emulation service over qemu pipe. */
 extern void android_camera_service_init(void);
 
+/* Lists available web cameras. */
+extern void android_list_web_cameras(void);
+
 #endif  /* ANDROID_CAMERA_CAMERA_SERVICE_H_ */