summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeongmo Yang <jm80.yang@samsung.com>2024-07-11 20:05:17 +0900
committerJeongmo Yang <jm80.yang@samsung.com>2024-08-01 11:43:29 +0900
commit1c2c227f44b13798d20f0b63de409a0ebe932ae7 (patch)
treea50cf240d714676026e73510a40f1a0483e4e5a7
parentcde64310caab30c3087d91a1613c1dad51489a8a (diff)
downloadcamera-v4l2-1c2c227f44b13798d20f0b63de409a0ebe932ae7.tar.gz
camera-v4l2-1c2c227f44b13798d20f0b63de409a0ebe932ae7.tar.bz2
camera-v4l2-1c2c227f44b13798d20f0b63de409a0ebe932ae7.zip
[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.spec2
-rw-r--r--src/hal_backend_camera_v4l2.c310
-rw-r--r--src/hal_backend_camera_v4l2_private.h1
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);