diff options
author | Jeongmo Yang <jm80.yang@samsung.com> | 2024-07-11 20:05:17 +0900 |
---|---|---|
committer | Jeongmo Yang <jm80.yang@samsung.com> | 2024-08-01 11:43:29 +0900 |
commit | 1c2c227f44b13798d20f0b63de409a0ebe932ae7 (patch) | |
tree | a50cf240d714676026e73510a40f1a0483e4e5a7 | |
parent | cde64310caab30c3087d91a1613c1dad51489a8a (diff) | |
download | camera-v4l2-1c2c227f44b13798d20f0b63de409a0ebe932ae7.tar.gz camera-v4l2-1c2c227f44b13798d20f0b63de409a0ebe932ae7.tar.bz2 camera-v4l2-1c2c227f44b13798d20f0b63de409a0ebe932ae7.zip |
Support new API for device capabilityaccepted/tizen/unified/x/20240820.013152accepted/tizen/unified/dev/20240821.053504accepted/tizen/unified/20240819.150137
[Version] 1.1.0
[Issue Type] New feature
Change-Id: Ic6900366038e1ac4c2ab905cf9a00152021564a4
Signed-off-by: Jeongmo Yang <jm80.yang@samsung.com>
-rw-r--r-- | packaging/hal-backend-camera-v4l2.spec | 2 | ||||
-rw-r--r-- | src/hal_backend_camera_v4l2.c | 310 | ||||
-rw-r--r-- | src/hal_backend_camera_v4l2_private.h | 1 |
3 files changed, 280 insertions, 33 deletions
diff --git a/packaging/hal-backend-camera-v4l2.spec b/packaging/hal-backend-camera-v4l2.spec index 4df07fd..b7d6972 100644 --- a/packaging/hal-backend-camera-v4l2.spec +++ b/packaging/hal-backend-camera-v4l2.spec @@ -8,7 +8,7 @@ Name: hal-backend-camera-v4l2 Summary: Tizen Camera Hal using generic V4L2 interface -Version: 1.0.0 +Version: 1.1.0 Release: 0 Group: Multimedia/Libraries License: Apache-2.0 diff --git a/src/hal_backend_camera_v4l2.c b/src/hal_backend_camera_v4l2.c index ac799a8..9e76afa 100644 --- a/src/hal_backend_camera_v4l2.c +++ b/src/hal_backend_camera_v4l2.c @@ -58,7 +58,8 @@ static gboolean g_is_virtual_camera_mode; static uint32_t g_virtual_camera_bytesused; static gulong g_virtual_camera_frame_delay; static camera_device_info_list_s *g_device_info_list; -static guint32 g_device_caps; +static camera_device_capability_list_s *g_device_capability_list; +static guint32 g_device_caps[DEVICE_COUNT_MAX]; static GMutex g_device_info_lock; static uint32_t g_virtual_camera_format[VIRTUAL_CAMERA_FMT_MAX] = { V4L2_PIX_FMT_YUV420, @@ -75,15 +76,157 @@ static void __camera_hal_v4l2_destructor(void) __attribute__((destructor)); static void __camera_send_message(hal_camera_handle *handle, camera_message_type_e type, int value); -static void __camera_hal_v4l2_destructor(void) +static void __camera_release_device_info_list(void) { - LOGD("release device info list %p", g_device_info_list); + if (!g_device_info_list) { + LOGI("no device info list"); + return; + } + + LOGD("release device info list[%p]", g_device_info_list); g_free(g_device_info_list); g_device_info_list = NULL; +} - return; + +static void __camera_release_device_capability_list(void) +{ + int device_index = 0; + int format_index = 0; + int resolution_index = 0; + int freed_size = 0; + camera_device_capability_s *_capability = NULL; + camera_device_capability_format_s *_capability_format = NULL; + camera_device_capability_resolution_s *_capability_resolution = NULL; + + if (!g_device_capability_list) { + LOGI("no device capability list"); + return; + } + + LOGI("release capability list[%p]", g_device_capability_list); + + for (device_index = 0 ; device_index < g_device_capability_list->device_count ; device_index++) { + freed_size = 0; + + _capability = g_device_capability_list->capability[device_index]; + if (!_capability) { + LOGW("NULL capability for index[%d]", device_index); + continue; + } + + g_device_capability_list->capability[device_index] = NULL; + + LOGV("device[i:%d][%p] format count[%d]", + device_index, _capability, _capability->format_count); + + for (format_index = 0 ; format_index < _capability->format_count ; format_index++) { + _capability_format = _capability->format[format_index]; + if (!_capability_format) { + LOGW(" NULL capability format for index[%d]", format_index); + continue; + } + + _capability->format[format_index] = NULL; + + LOGV(" format[i:%d][%p] pixel format[%d], resolution count[%d]", + format_index, _capability_format, _capability_format->pixel_format, + _capability_format->resolution_count); + + for (resolution_index = 0 ; resolution_index < _capability_format->resolution_count ; resolution_index++) { + _capability_resolution = _capability_format->resolution[resolution_index]; + if (!_capability_resolution) { + LOGW(" NULL capability resolution for index[%d]", resolution_index); + continue; + } + + _capability_format->resolution[resolution_index] = NULL; + + LOGV(" resolution[i:%d][%p] %dx%d, fps count[%d]", + resolution_index, _capability_resolution, + _capability_resolution->width, _capability_resolution->height, + _capability_resolution->fps_list.count); + + g_free(_capability_resolution); + freed_size += sizeof(camera_device_capability_resolution_s); + } + + g_free(_capability_format); + freed_size += sizeof(camera_device_capability_format_s); + } + + g_free(_capability); + freed_size += sizeof(camera_device_capability_s); + + LOGI("device[%d] freed size[%d]", device_index, freed_size); + } + + g_free(g_device_capability_list); + g_device_capability_list = NULL; +} + + +static void __camera_hal_v4l2_destructor(void) +{ + __camera_release_device_info_list(); + __camera_release_device_capability_list(); +} + + +#ifdef DUMP_DEVICE_CAPABILITY +static void __camera_dump_device_capability(void) +{ + int device_index = 0; + int format_index = 0; + int resolution_index = 0; + int fps_index = 0; + camera_device_capability_s *_capability = NULL; + camera_device_capability_format_s *_capability_format = NULL; + camera_device_capability_resolution_s *_capability_resolution = NULL; + + g_autoptr(GMutexLocker) locker = g_mutex_locker_new(&g_device_info_lock); + + if (!g_device_capability_list) + return; + + for (device_index = 0 ; device_index < g_device_capability_list->device_count ; device_index++) { + _capability = g_device_capability_list->capability[device_index]; + if (!_capability) { + LOGW("NULL capability[%d]", device_index); + continue; + } + + LOGI("device[%02d] format count[%d]", device_index, _capability->format_count); + + for (format_index = 0 ; format_index < _capability->format_count ; format_index++) { + _capability_format = _capability->format[format_index]; + if (!_capability_format) { + LOGW("\tNULL capability format[%d]", format_index); + continue; + } + + LOGI("\tformat[%02d] %d, resolution count[%d]", resolution_index, + _capability_format->pixel_format, _capability_format->resolution_count); + + for (resolution_index = 0 ; resolution_index < _capability_format->resolution_count ; resolution_index++) { + _capability_resolution = _capability_format->resolution[resolution_index]; + if (!_capability_resolution) { + LOGW("\t\tNULL capability resolution[%d]", resolution_index); + continue; + } + + LOGI("\t\tresolution[%02d] %dx%d, fps count[%d]", resolution_index, + _capability_resolution->width, _capability_resolution->height, + _capability_resolution->fps_list.count); + + for (fps_index = 0 ; fps_index < _capability_resolution->fps_list.count ; fps_index++) + LOGI("\t\t\tfps[%02d] %d", fps_index, _capability_resolution->fps_list.fps[fps_index]); + } + } + } } +#endif /* DUMP_DEVICE_CAPABILITY */ static void __camera_send_message(hal_camera_handle *handle, camera_message_type_e type, int value) @@ -510,6 +653,11 @@ static void __camera_get_fps_list(int device_fd, guint32 pixel_format, int width continue; } + if (ival.discrete.numerator != 1) { + LOGI("\t\t\t\tFramerate[%u/%u] SKIP", ival.discrete.denominator, ival.discrete.numerator); + continue; + } + LOGI("\t\t\t\tFramerate[%u/%u]", ival.discrete.denominator, ival.discrete.numerator); fps_list->fps[fps_count++] = ival.discrete.denominator; } @@ -518,7 +666,8 @@ static void __camera_get_fps_list(int device_fd, guint32 pixel_format, int width } -static int __camera_get_device_info(int device_index, int device_fd, camera_device_info_s *device_info, char *node_path) +static int __camera_get_device_info(int device_index, int device_fd, char *node_path, + camera_device_info_s *device_info, camera_device_capability_s **device_capability) { int format_index = 0; int format_count = 0; @@ -527,15 +676,21 @@ static int __camera_get_device_info(int device_index, int device_fd, camera_devi int camera_format = 0; struct v4l2_fmtdesc v4l2_format; struct v4l2_frmsizeenum v4l2_frame; + camera_device_capability_s *_capability = NULL; + int alloc_size = 0; if (device_fd < 0 || !device_info || !node_path) { LOGE("invalid param %d %p %p", device_fd, device_info, node_path); return CAMERA_ERROR_INVALID_PARAMETER; } - LOGD("Get Supported format, resolution and fps"); + LOGI("Get Supported format, resolution and fps"); + + _capability = g_new0(camera_device_capability_s, 1); for (format_index = 0, format_count = 0 ; ; format_index++) { + camera_device_capability_format_s *_capability_format = NULL; + memset(&v4l2_format, 0x0, sizeof(struct v4l2_fmtdesc)); v4l2_format.index = format_index; @@ -566,9 +721,11 @@ static int __camera_get_device_info(int device_index, int device_fd, camera_devi continue; } - device_info->format_list.formats[format_count++] = camera_format; + _capability_format = g_new0(camera_device_capability_format_s, 1); for (resolution_index = 0, resolution_count = 0 ; ; resolution_index++) { + camera_device_capability_resolution_s *_capability_resolution = NULL; + memset(&v4l2_frame, 0x0, sizeof(struct v4l2_frmsizeenum)); v4l2_frame.index = resolution_index; @@ -602,7 +759,15 @@ static int __camera_get_device_info(int device_index, int device_fd, camera_devi device_info->video_list.resolutions[resolution_count].width = v4l2_frame.discrete.width; device_info->video_list.resolutions[resolution_count].height = v4l2_frame.discrete.height; - LOGD("\t\tsize[%d] %ux%u", resolution_count, + _capability_resolution = g_new0(camera_device_capability_resolution_s, 1); + alloc_size += sizeof(camera_device_capability_resolution_s); + + _capability_format->resolution[resolution_count] = _capability_resolution; + + _capability_resolution->width = v4l2_frame.discrete.width; + _capability_resolution->height = v4l2_frame.discrete.height; + + LOGD("\t\tresolution[%d] %u x %u", resolution_count, v4l2_frame.discrete.width, v4l2_frame.discrete.height); @@ -613,6 +778,7 @@ static int __camera_get_device_info(int device_index, int device_fd, camera_devi &device_info->preview_fps_list[resolution_count]); memcpy(&device_info->video_fps_list[resolution_count], &device_info->preview_fps_list[resolution_count], sizeof(camera_fps_list_s)); + memcpy(&_capability_resolution->fps_list, &device_info->preview_fps_list[resolution_count], sizeof(camera_fps_list_s)); resolution_count++; break; @@ -638,20 +804,51 @@ static int __camera_get_device_info(int device_index, int device_fd, camera_devi } } - device_info->preview_list.count = resolution_count; - device_info->capture_list.count = resolution_count; - device_info->video_list.count = resolution_count; + if (resolution_count > 0) { + _capability_format->pixel_format = camera_format; + _capability_format->resolution_count = resolution_count; + _capability->format[format_count] = _capability_format; + alloc_size += sizeof(camera_device_capability_format_s); + + device_info->format_list.formats[format_count] = camera_format; - LOGD("\t\tresolution count [%d]", resolution_count); + device_info->preview_list.count = resolution_count; + device_info->capture_list.count = resolution_count; + device_info->video_list.count = resolution_count; + + LOGD("\t\tresolution count [%d]", resolution_count); + + format_count++; + } else { + LOGW("\t\tno resolution for format[%d]", camera_format); + g_free(_capability_format); + _capability_format = NULL; + } } - device_info->index = device_index; - device_info->format_list.count = format_count; - device_info->facing_direction = CAMERA_FACING_DIRECTION_EXTERNAL; - snprintf(device_info->name, sizeof(device_info->name), "V4L2_CAMERA"); - snprintf(device_info->node_path, sizeof(device_info->node_path), "%s", node_path); + if (format_count > 0) { + alloc_size += sizeof(camera_device_capability_s); + + device_info->index = device_index; + device_info->format_list.count = format_count; + device_info->facing_direction = CAMERA_FACING_DIRECTION_EXTERNAL; + snprintf(device_info->name, sizeof(device_info->name), "V4L2_CAMERA"); + snprintf(device_info->node_path, sizeof(device_info->node_path), "%s", node_path); + + _capability->device_index = device_index; + _capability->format_count = format_count; + + if (device_capability) + *device_capability = _capability; + + LOGD("\tformat count [%d]", format_count); + } else { + LOGW("\tno format for device[%d]", device_index); + g_free(_capability); + _capability = NULL; + } - LOGD("\tformat count [%d]", format_count); + LOGI("\tallocated size[%d] for capability", alloc_size); return CAMERA_ERROR_NONE; } @@ -670,8 +867,9 @@ static int __camera_get_device_info_list(void) struct v4l2_capability v4l2_cap; guint32 device_caps; camera_device_info_list_s *device_info_list = NULL; + camera_device_capability_list_s *device_capability_list = NULL; - g_mutex_lock(&g_device_info_lock); + g_autoptr(GMutexLocker) locker = g_mutex_locker_new(&g_device_info_lock); if (g_device_info_list) { LOGD("device info list is already existed"); @@ -686,14 +884,24 @@ static int __camera_get_device_info_list(void) goto _GET_DEVICE_INFO_LIST_DONE; } - if (g_is_virtual_camera_mode) { - device_count = 1; + device_capability_list = g_new0(camera_device_capability_list_s, 1); + if (!device_capability_list) { + LOGE("failed to alloc device capability structure"); + ret = CAMERA_ERROR_OUT_OF_MEMORY; + goto _GET_DEVICE_INFO_LIST_DONE; + } - ret = __camera_get_device_info(0, 0, &device_info_list->device_info[0], "VIRTUAL_CAMERA"); + if (g_is_virtual_camera_mode) { + ret = __camera_get_device_info(0, 0, "VIRTUAL_CAMERA", + &device_info_list->device_info[0], + &device_capability_list->capability[0]); device_info_list->count = device_count; g_device_info_list = device_info_list; + device_capability_list->device_count = device_count; + g_device_capability_list = device_capability_list; + goto _GET_DEVICE_INFO_LIST_DONE; } @@ -749,6 +957,9 @@ static int __camera_get_device_info_list(void) continue; } + LOGI("driver[%s], card[%s], bus_info[%s]", + v4l2_cap.driver, v4l2_cap.card, v4l2_cap.bus_info); + if (v4l2_cap.capabilities & V4L2_CAP_DEVICE_CAPS) device_caps = v4l2_cap.device_caps; else @@ -761,30 +972,43 @@ static int __camera_get_device_info_list(void) continue; } - ret = __camera_get_device_info(device_count, device_fd, - &device_info_list->device_info[device_count], glob_buf.gl_pathv[i]); + ret = __camera_get_device_info(device_count, + device_fd, glob_buf.gl_pathv[i], + &device_info_list->device_info[device_count], + &device_capability_list->capability[device_count]); v4l2_close(device_fd); - if (ret == CAMERA_ERROR_NONE) { + if (ret == CAMERA_ERROR_NONE && device_capability_list->capability[device_count]) { + g_device_caps[device_count] = device_caps; + LOGI("device[%02d] device caps [0x%08x]", device_count, device_caps); device_count++; - g_device_caps = device_caps; - LOGI("device caps [0x%08x]", g_device_caps); } } device_info_list->count = device_count; g_device_info_list = device_info_list; - LOGD("new g_device_info_list %p - device count %d", + device_capability_list->device_count = device_count; + g_device_capability_list = device_capability_list; + + LOGD("new device info list[%p], device count %d", g_device_info_list, device_count); + LOGD("new device capability list[%p], device count %d", + g_device_capability_list, device_count); + +#ifdef DUMP_DEVICE_CAPABILITY + __camera_dump_device_capability(); +#endif /* DUMP_DEVICE_CAPABILITY */ + _GET_DEVICE_INFO_LIST_DONE: - g_mutex_unlock(&g_device_info_lock); LOGD("ret 0x%x", ret); - if (ret != CAMERA_ERROR_NONE) + if (ret != CAMERA_ERROR_NONE) { g_free(device_info_list); + g_free(device_capability_list); + } return ret; } @@ -1610,7 +1834,7 @@ int camera_v4l2_open_device(void *camera_handle, int device_index) goto _OPEN_DEVICE_EXIT; } - if (g_device_caps & V4L2_CAP_VIDEO_CAPTURE_MPLANE) + if (g_device_caps[device_index] & V4L2_CAP_VIDEO_CAPTURE_MPLANE) handle->buffer_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; else handle->buffer_type = V4L2_BUF_TYPE_VIDEO_CAPTURE; @@ -2747,6 +2971,27 @@ int camera_v4l2_set_batch_command(void *camera_handle, camera_batch_command_cont } +int camera_v4l2_get_device_capability_list(camera_device_capability_list_s *device_capability_list) +{ + int ret = 0; + + if (!device_capability_list) { + LOGE("NULL pointer for device_capability_list"); + return CAMERA_ERROR_INVALID_PARAMETER; + } + + ret = __camera_get_device_info_list(); + if (ret != CAMERA_ERROR_NONE) { + LOGE("get device info failed"); + return ret; + } + + memcpy(device_capability_list, g_device_capability_list, sizeof(camera_device_capability_list_s)); + + return CAMERA_ERROR_NONE; +} + + static int camera_v4l2_backend_init(void **data) { hal_backend_camera_funcs *funcs = NULL; @@ -2813,6 +3058,7 @@ static int camera_v4l2_backend_init(void **data) funcs->get_extra_preview_bitrate = camera_v4l2_get_extra_preview_bitrate; funcs->set_extra_preview_gop_interval = camera_v4l2_set_extra_preview_gop_interval; funcs->get_extra_preview_gop_interval = camera_v4l2_get_extra_preview_gop_interval; + funcs->get_device_capability_list = camera_v4l2_get_device_capability_list; g_is_virtual_camera_mode = getenv(ENV_VIRTUAL_CAMERA) ? TRUE : FALSE; @@ -2845,5 +3091,5 @@ hal_backend hal_backend_camera_data = { .init = camera_v4l2_backend_init, .exit = camera_v4l2_backend_exit, .major_version = 1, - .minor_version = 0, + .minor_version = 1, }; diff --git a/src/hal_backend_camera_v4l2_private.h b/src/hal_backend_camera_v4l2_private.h index 9749330..db67861 100644 --- a/src/hal_backend_camera_v4l2_private.h +++ b/src/hal_backend_camera_v4l2_private.h @@ -115,6 +115,7 @@ typedef struct _camera_hal_handle { int camera_v4l2_init(void **camera_handle); int camera_v4l2_deinit(void *camera_handle); int camera_v4l2_get_device_info_list(camera_device_info_list_s *device_info_list); +int camera_v4l2_get_device_capability_list(camera_device_capability_list_s *device_capability_list); int camera_v4l2_open_device(void *camera_handle, int device_index); int camera_v4l2_open_device_ext(void *camera_handle, const char *device_name); int camera_v4l2_close_device(void *camera_handle); |