From b8dcaffaf7dcb0c795d2776abf3bb75196f8527c Mon Sep 17 00:00:00 2001 From: Vladimir Chtchetkine Date: Sat, 17 Sep 2011 11:15:47 -0700 Subject: Add -webcam commandline option to control webcam emulation -webcam name=[,dir=] options controls web cameras to use for emulation. Change-Id: I961fd399c7e041541adda040dd24f194cc383cb9 --- android/camera/camera-capture-linux.c | 3 + android/camera/camera-capture-windows.c | 4 + android/camera/camera-common.h | 8 ++ android/camera/camera-service.c | 212 +++++++++++++++++++++++++------- android/camera/camera-service.h | 3 + 5 files changed, 186 insertions(+), 44 deletions(-) (limited to 'android/camera') 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 @@ enumerate_camera_devices(CameraInfo* cis, int max) 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 @@ enumerate_camera_devices(CameraInfo* cis, int max) * 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 @@ typedef struct CameraFrameDim { * 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__ CameraInfo* _camera_info_alloc(void) 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 @@ struct CameraServiceDesc { 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 @@ _append_string(char** str_buf, size_t* str_buf_size, const char* str) } /* Represents camera information as a string formatted as follows: - * 'name= channel= pix= framedims=\n' + * 'name= channel= pix= facing= framedims=\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 @@ _camera_info_to_string(const CameraInfo* ci, char** str, size_t* str_size) { 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 @@ _camera_info_to_string(const CameraInfo* ci, char** str, size_t* str_size) { 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 @@ _camera_client_create(CameraServiceDesc* csd, const char* param) * 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 @@ android_camera_service_init(void) 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_ */ -- cgit v1.1