Support new API for device capability 23/314423/2 accepted/tizen/unified/20240819.150137 accepted/tizen/unified/dev/20240821.053504 accepted/tizen/unified/x/20240820.013152
authorJeongmo Yang <jm80.yang@samsung.com>
Thu, 11 Jul 2024 11:05:17 +0000 (20:05 +0900)
committerJeongmo Yang <jm80.yang@samsung.com>
Thu, 1 Aug 2024 02:43:29 +0000 (11:43 +0900)
[Version] 1.1.0
[Issue Type] New feature

Change-Id: Ic6900366038e1ac4c2ab905cf9a00152021564a4
Signed-off-by: Jeongmo Yang <jm80.yang@samsung.com>
packaging/hal-backend-camera-v4l2.spec
src/hal_backend_camera_v4l2.c
src/hal_backend_camera_v4l2_private.h

index 4df07fdbcbf7e2f9e5f0b33e01bb32d11801c469..b7d69726749b2977f17135512b75ed4d95cc0dfb 100644 (file)
@@ -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
index ac799a8ea4ecdd14d16ea024eba2d796c18aea86..9e76afa336ab32683e9d5c28c4719ff8cfba5ee2 100644 (file)
@@ -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,
 };
index 97493303dc32b945d0965c0d9019917b2d174569..db67861c3b8fa52abceb5da36d774757170ca2c4 100644 (file)
@@ -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);