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,
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)
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;
}
}
-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;
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;
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;
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);
&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;
}
}
- 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;
}
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");
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;
}
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
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;
}
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;
}
+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;
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;
.init = camera_v4l2_backend_init,
.exit = camera_v4l2_backend_exit,
.major_version = 1,
- .minor_version = 0,
+ .minor_version = 1,
};