/* * Copyright (c) Hisilicon Technologies Co., Ltd. 2019-2020. All rights reserved. * Description: camera api adapter * Create: 2020-02-17 * Author: Camera Group */ #include "uapi_camera.h" #include #include #include #include #include #include #include "securec.h" #include "uapi_camera_stream_manager.h" #include "uapi_camera_device_manager.h" #include "uapi_camera_proc_manager.h" #include "uapi_camera_utils_statistics.h" #include "uapi_camera_hotplug_manager.h" #define MAIN_DATA_SLEEP 50 #define uapi_camera_lock(mutex) (void)pthread_mutex_lock((pthread_mutex_t *)(mutex)) #define uapi_camera_unlock(mutex) (void)pthread_mutex_unlock((pthread_mutex_t *)(mutex)) #define uapi_camera_main_lock(mutex) (void)pthread_mutex_lock((pthread_mutex_t *)(mutex)) #define uapi_camera_main_unlock(mutex) (void)pthread_mutex_unlock((pthread_mutex_t *)(mutex)) static pthread_mutex_t g_camera_mutex = PTHREAD_MUTEX_INITIALIZER; static uapi_camera_hotplug_callback_func g_camera_callback = NULL; static uapi_camera_bool g_init = FALSE; static void device_hotplug_callback(const uapi_camera_hotplug_event_msg *msg) { uapi_info_camera("dev:%s, event:%d\n", msg->dev_path, msg->event_type); int32_t ret = UAPI_CAM_ERROR; uapi_camera_lock(&g_camera_mutex); if (msg->event_type == UAPI_CAMERA_HOTPLUG_IN) { ret = uapi_camera_device_add_by_path(msg->dev_path); } else if (msg->event_type == UAPI_CAMERA_HOTPLUG_OUT) { ret = uapi_camera_device_remove_by_path(msg->dev_path); } uapi_camera_unlock(&g_camera_mutex); if (ret != UAPI_CAM_NO_ERROR) { return; } if (g_camera_callback == NULL) { uapi_err_camera("no callback for hotplug has been registered\n"); return; } uapi_camera_lock(&g_camera_mutex); g_camera_callback(msg); uapi_camera_unlock(&g_camera_mutex); } static int32_t main_package_stream_decode(const stream_buf_pipe *stream_buf, uint32_t stream_id, const uapi_camera_device_mng *device_mng) { int32_t result = UAPI_CAM_ERROR; uapi_stream_buffer_mng *buffer_mng = NULL; uapi_camera_stream_mng *stream_mng = NULL; stream_buf_pipe stream_buf_tmp; stream_buf_tmp.uvc_buf = stream_buf->uvc_buf; stream_buf_tmp.buf_valid_len = stream_buf->buf_valid_len; stream_mng = uapi_camera_stream_get_mng_by_id(stream_id); if (stream_mng == NULL) { return result; } uapi_cam_stream_lock(&stream_mng->stream_mutex); if (stream_mng->is_used == TRUE) { buffer_mng = uapi_camera_stream_buf_pop(stream_mng, FALSE); } if (buffer_mng != NULL) { result = device_mng->device_interface->stream_decode(&stream_buf_tmp, &buffer_mng->stream_buffer, stream_mng->attr.stream_transpath, &stream_id); } if (result != UAPI_CAM_NO_ERROR) { uapi_cam_stream_unlock(&stream_mng->stream_mutex); return result; } utils_statistics_frames(device_mng->statistic_handle, stream_buf_tmp, stream_id_to_index(stream_id)); uapi_camera_stream_buf_pop(stream_mng, TRUE); uapi_camera_stream_enqueue_data(UAPI_CAMERA_CMD_TYPE_DATA_CB, &buffer_mng->stream_buffer, stream_mng); uapi_cam_stream_unlock(&stream_mng->stream_mutex); return result; } static void main_package_stream_process(stream_request_inter *dq_buffer, uint32_t stream_id, const uapi_camera_device_mng *device_mng) { stream_buf_pipe *stream_buf = NULL; stream_buf = &dq_buffer->stream_buf[INNER_BUFFER_INDEX_STREAM]; if (dq_buffer->stream_buf_num <= 0 || stream_buf->uvc_buf == NULL || device_mng == NULL) { return; } if (device_mng->device_interface == NULL || device_mng->device_interface->stream_decode == NULL) { uapi_err_camera("stream_decode interface is null\n"); goto FLAG_RELEASE_BUF; } int32_t ret = main_package_stream_decode(stream_buf, stream_id, device_mng); if (ret != UAPI_CAM_NO_ERROR) { uapi_info_camera("main_package_stream_decode failure ret=0x%x \n", ret); } FLAG_RELEASE_BUF: dq_buffer->stream_buf[INNER_BUFFER_INDEX_STREAM].buf_valid_len = 0; // flag this buf can qbuf used dq_buffer->stream_buf[INNER_BUFFER_INDEX_STREAM].enbale_que = TRUE; if (device_mng->device_interface != NULL && device_mng->device_interface->stream_qbuf != NULL) { ret = device_mng->device_interface->stream_qbuf(device_mng->fd, stream_id_to_index(stream_id), dq_buffer); if (ret != UAPI_CAM_NO_ERROR) { uapi_info_camera("stream_qbuf failure ret=0x%x \n", ret); } } return; } static void copy_stream_buffer(uapi_camera_stream_buffer *buffer_dst, const uapi_camera_stream_buffer *buffer_src) { buffer_dst->stream_buffer_len = buffer_src->stream_buffer_len; buffer_dst->stream_valid_len = buffer_src->stream_valid_len; if (memcpy_s(buffer_dst->meta_buffer, sizeof(uapi_camera_stream_meta_des), buffer_src->meta_buffer, sizeof(uapi_camera_stream_meta_des)) != EOK) { uapi_err_camera("memcpy meta_buffer failed\n"); } if (memcpy_s(buffer_dst->stream_buffer, buffer_src->stream_buffer_len, buffer_src->stream_buffer, buffer_src->stream_valid_len) != EOK) { uapi_err_camera("memcpy stream_buffer failed\n"); } } static void fork_stream_process(uapi_camera_device_mng *device_mng, const uapi_stream_buffer_mng *buffer_mng, const uapi_camera_stream_mng *stream_mng) { if (buffer_mng->stream_buffer.stream_buffer_len < buffer_mng->stream_buffer.stream_valid_len) { return; } uapi_stream_buffer_mng *buffer_mng_stream = NULL; uapi_camera_stream_buffer temp_buffer = {0}; temp_buffer.stream_buffer = malloc(buffer_mng->stream_buffer.stream_buffer_len); if (temp_buffer.stream_buffer == NULL) { uapi_err_camera("malloc stream_buffer failed\n"); return; } temp_buffer.meta_buffer = malloc(sizeof(uapi_camera_stream_meta_des)); if (temp_buffer.meta_buffer == NULL) { uapi_err_camera("malloc meta_buffer failed\n"); free(temp_buffer.stream_buffer); return; } copy_stream_buffer(&temp_buffer, &buffer_mng->stream_buffer); uapi_camera_stream_enqueue_data(UAPI_CAMERA_CMD_TYPE_DATA_CB, &buffer_mng->stream_buffer, stream_mng); for (int32_t i = 0; i < UAPI_CAMERA_STREAM_MAX_NUM; i++) { if (device_mng->stream[i].fork_flag == FALSE || device_mng->stream[i].stream_id == stream_mng->stream_id) { continue; } buffer_mng_stream = uapi_camera_stream_buf_pop(&device_mng->stream[i], TRUE); if (buffer_mng_stream == NULL) { continue; } copy_stream_buffer(&buffer_mng_stream->stream_buffer, &temp_buffer); uapi_camera_stream_enqueue_data(UAPI_CAMERA_CMD_TYPE_DATA_CB, &buffer_mng_stream->stream_buffer, &device_mng->stream[i]); } free(temp_buffer.stream_buffer); free(temp_buffer.meta_buffer); } static void main_nonpackage_stream_process(const stream_request_inter *dq_buffer, uint32_t stream_index, uapi_camera_device_mng *device_mng) { if (dq_buffer->stream_buf_num <= 0 || dq_buffer->stream_buf[0].uvc_buf == NULL || device_mng == NULL) { return; } uapi_camera_stream_mng *stream_mng = &device_mng->stream[stream_index]; uint8_t buf_index = dq_buffer->stream_buf[0].buf_index; uapi_stream_buffer_mng *buffer_mng = &stream_mng->buffer_mng[buf_index]; if (buffer_mng == NULL) { return; } uapi_cam_stream_lock(&stream_mng->stream_mutex); if (uapi_camera_stream_buf_pop(stream_mng, TRUE) == NULL) { uapi_err_camera("uapi_camera_stream_buf_pop failed \n"); } if (stream_mng->fork_flag == FALSE) { buffer_mng->stream_buffer.stream_valid_len = dq_buffer->stream_buf[INNER_BUFFER_INDEX_STREAM].buf_valid_len; } if (device_mng->fork_flag == TRUE) { fork_stream_process(device_mng, buffer_mng, stream_mng); } else { uapi_camera_stream_enqueue_data(UAPI_CAMERA_CMD_TYPE_DATA_CB, &buffer_mng->stream_buffer, stream_mng); } uapi_cam_stream_unlock(&stream_mng->stream_mutex); return; } static void *main_thread_process(void *arg) { uapi_camera_device_mng *device_mng = (uapi_camera_device_mng *)arg; stream_buf_pipe q_buf; stream_request_inter dq_buffer = { 1, &q_buf }; uint32_t stream_index, stream_id; int32_t result; if (device_mng == NULL || device_mng->device_interface == NULL || device_mng->device_interface->stream_dqbuf == NULL) { return NULL; } uapi_camera_device_main_thread_mng *thread_mng = &device_mng->main_thread; if (thread_mng == NULL) { return NULL; } uapi_camera_device_set_thread_name("cam_", device_mng->camera_id); while (thread_mng->is_thread_exit == FALSE) { if (memset_s(&q_buf, sizeof(q_buf), 0, sizeof(q_buf)) != EOK) { uapi_fatal_camera("memset_s fatal\n"); continue; } stream_index = UAPI_CAM_INVALID_ID; result = device_mng->device_interface->stream_dqbuf(device_mng->fd, &stream_index, UAPI_CAMERA_TRANS_PATH_USB_UVC, &dq_buffer); if (result != UAPI_CAM_NO_ERROR) { usleep(MAIN_DATA_SLEEP); continue; } stream_id = stream_id_create((uint32_t)device_mng->camera_id, stream_index); if (device_mng->device_interface->stream_decode != NULL) { main_package_stream_process(&dq_buffer, stream_id, device_mng); } else { main_nonpackage_stream_process(&dq_buffer, stream_index, device_mng); utils_statistics_frames(device_mng->statistic_handle, q_buf, stream_index); } } uapi_camera_main_unlock(&device_mng->main_thread.exit_mutex); uapi_info_camera("main thread exit while ok\n"); return NULL; } static int32_t main_thread_create(uapi_camera_device_mng *device_mng) { check_cam_ptr_return(device_mng); if (device_mng->main_thread.is_inited == TRUE) { return UAPI_CAM_NO_ERROR; } device_mng->main_thread.is_thread_exit = FALSE; pthread_mutex_init(&device_mng->main_thread.exit_mutex, NULL); uapi_camera_main_lock(&device_mng->main_thread.exit_mutex); // only for exit thread, consume first lock if (pthread_create(&device_mng->main_thread.main_thread_id, NULL, main_thread_process, (void *)(device_mng)) != 0) { uapi_fatal_camera("pthread_create main_thread_process errno \n"); return UAPI_CAM_CREATE_ERR; } device_mng->main_thread.is_inited = TRUE; uapi_info_camera("main_thread create success\n"); return UAPI_CAM_NO_ERROR; } static int32_t main_thread_destory(uapi_camera_device_mng *device_mng) { check_cam_ptr_return(device_mng); if (device_mng->main_thread.is_inited == FALSE) { return UAPI_CAM_NO_ERROR; } device_mng->main_thread.is_thread_exit = TRUE; uapi_camera_main_lock(&device_mng->main_thread.exit_mutex); pthread_join(device_mng->main_thread.main_thread_id, NULL); uapi_camera_main_unlock(&device_mng->main_thread.exit_mutex); pthread_mutex_destroy(&device_mng->main_thread.exit_mutex); device_mng->main_thread.is_inited = FALSE; uapi_info_camera("main_thread destory success\n"); return UAPI_CAM_NO_ERROR; } static int32_t stream_qbuf(uint32_t stream_id, const uapi_stream_buffer_mng *buffer_mng, const uapi_camera_device_mng *device_mng) { check_cam_ptr_return(buffer_mng); check_cam_ptr_return(device_mng); stream_request_inter dq_buffer; dq_buffer.stream_buf_num = 0; stream_buf_pipe q_buf[1]; if (device_mng->device_interface != NULL && device_mng->device_interface->stream_qbuf != NULL && device_mng->device_interface->stream_decode == NULL) { q_buf[INNER_BUFFER_INDEX_STREAM].buf_index = buffer_mng->index; q_buf[INNER_BUFFER_INDEX_STREAM].uvc_buf = buffer_mng->stream_buffer.stream_buffer; q_buf[INNER_BUFFER_INDEX_STREAM].priv_data = buffer_mng->stream_buffer.priv_data; q_buf[INNER_BUFFER_INDEX_STREAM].stream_buf_len = buffer_mng->stream_buffer.stream_buffer_len; q_buf[INNER_BUFFER_INDEX_STREAM].buf_valid_len = buffer_mng->stream_buffer.stream_valid_len; dq_buffer.stream_buf_num = 1; dq_buffer.stream_buf = q_buf; int32_t ret = device_mng->device_interface->stream_qbuf(device_mng->fd, stream_id_to_index(stream_id), &dq_buffer); if (ret != UAPI_CAM_NO_ERROR) { uapi_err_camera("stream_qbuf failure ret=0x%x \n", ret); } return ret; } return UAPI_CAM_NO_ERROR; } int32_t uapi_camera_init() { int32_t ret; uapi_info_camera(" %s\n", uapi_camera_ver(UAPI_CAMERA_MAINVER, UAPI_CAMERA_SUBVER1, UAPI_CAMERA_SUBVER2)); if (g_init == TRUE) { uapi_info_camera("already init, return\n"); return UAPI_CAM_NO_ERROR; } ret = uapi_camera_hotplug_init(); if (ret != UAPI_CAM_NO_ERROR) { uapi_info_camera("uapi_camera_hotplug_init failed\n"); return UAPI_CAM_ERROR; } ret = uapi_camera_uapi_init(); if (ret != UAPI_CAM_NO_ERROR) { uapi_err_camera("uapi_camera_uapi_init failed\n"); uapi_camera_hotplug_deinit(); return UAPI_CAM_ERROR; } ret = uapi_camera_device_mng_init(); if (ret != UAPI_CAM_NO_ERROR) { uapi_err_camera("uapi_camera_device_mng_init failed\n"); uapi_camera_uapi_deinit(); uapi_camera_hotplug_deinit(); return UAPI_CAM_ERROR; } uapi_camera_proc_mng_init(); uapi_camera_lock(&g_camera_mutex); ret = uapi_camera_device_scan(); if (ret != UAPI_CAM_NO_ERROR) { uapi_err_camera("fail to scan_video_device 0x%x\n", ret); } uapi_camera_unlock(&g_camera_mutex); g_init = TRUE; return UAPI_CAM_NO_ERROR; } int32_t uapi_camera_deinit() { uapi_info_camera("enter \n"); if (g_init == FALSE) { uapi_info_camera("already deinit, return\n"); return UAPI_CAM_NO_ERROR; } uapi_camera_hotplug_deinit(); uapi_camera_device_mng_deinit(); uapi_camera_proc_mng_deinit(); uapi_camera_uapi_deinit(); g_init = FALSE; return UAPI_CAM_NO_ERROR; } int32_t uapi_camera_device_get_list(uapi_camera_device_basic_cap *camera_list, uint32_t list_num, uint32_t *camera_num) { int32_t ret; uint32_t device_count = 0; uapi_camera_device_mng *device_mng = NULL; check_cam_ptr_return(camera_list); check_cam_ptr_return(camera_num); *camera_num = 0; uapi_camera_device_mng *device_global_mng = uapi_camera_device_get_global_mng(); if (device_global_mng == NULL) { return UAPI_CAM_NO_INIT_ERR; } for (int8_t i = 0; (i < UAPI_CAMERA_DEVICE_MAX_NUM) && (device_count < list_num); ++i) { device_mng = &device_global_mng[i]; if ((device_mng->camera_id == UAPI_CAM_INVALID_ID) || (!device_mng->is_available)) { continue; } camera_list[device_count].camera_id = device_mng->camera_id; ret = strcpy_s(camera_list[device_count].dev_path, UAPI_CAMERA_DEV_PATH_MAX_LEN, device_mng->camera_dev_path); if (ret != EOK) { uapi_info_camera("strcpy_s failure 0x%x\n", ret); return UAPI_CAM_INVALID_PARA_ERR; } camera_list[device_count].type = device_mng->basic_info.type; camera_list[device_count].hdmi_stream_supported = device_mng->basic_info.stream_over_hdmi_supported; camera_list[device_count].multi_stream_supported = device_mng->basic_info.multi_stream_supported; uapi_info_camera("multi_stream_supported= %d\n", camera_list[device_count].multi_stream_supported); device_count++; } uapi_info_camera("device_count= %d\n", device_count); *camera_num = device_count; return UAPI_CAM_NO_ERROR; } int32_t uapi_camera_device_get_basic_cap(uint32_t camera_id, uapi_camera_device_basic_cap *cap) { uapi_info_camera("enter camera_id =0x%x \n", camera_id); check_cam_ptr_return(cap); uapi_camera_device_mng *device_mng = NULL; int32_t ret = uapi_camera_device_get_mng_by_id(camera_id, &device_mng); if (ret != UAPI_CAM_NO_ERROR) { return ret; } uapi_camera_basic_available_info *basic_feature = &(device_mng->basic_info); cap->camera_id = device_mng->camera_id; cap->type = basic_feature->type; cap->hdmi_stream_supported = basic_feature->stream_over_hdmi_supported; cap->multi_stream_supported = basic_feature->multi_stream_supported; ret = strcpy_s(cap->dev_path, UAPI_CAMERA_DEV_PATH_MAX_LEN, device_mng->camera_dev_path); if (ret != EOK) { uapi_info_camera("strcpy_s failure 0x%x\n", ret); return UAPI_CAM_INVALID_PARA_ERR; } uapi_info_camera("multi_stream_supported= %d\n", cap->multi_stream_supported); return ret; } int32_t uapi_camera_device_open(uint32_t camera_id) { uapi_info_camera("enter camera_id =0x%x \n", camera_id); uapi_camera_device_mng *device_mng = NULL; int32_t ret = uapi_camera_device_get_mng_by_id(camera_id, &device_mng); if (ret != UAPI_CAM_NO_ERROR) { return ret; } uapi_camera_lock(&device_mng->camera_mutex); if (device_mng->fd >= 0) { uapi_info_camera("this camera_id =0x%x is already opened\n", camera_id); uapi_camera_unlock(&device_mng->camera_mutex); return UAPI_CAM_NO_ERROR; } if (device_mng->device_interface == NULL || device_mng->device_interface->device_open == NULL) { uapi_camera_unlock(&device_mng->camera_mutex); return UAPI_CAM_NULL_PTR_ERR; } if (device_mng->device_interface->device_power_up != NULL) { uapi_camera_lock(&g_camera_mutex); ret = device_mng->device_interface->device_power_up(device_mng->camera_dev_path, UAPI_CAMERA_DEV_PATH_MAX_LEN); if (ret != UAPI_CAM_NO_ERROR) { uapi_camera_unlock(&g_camera_mutex); uapi_camera_unlock(&device_mng->camera_mutex); return UAPI_CAM_NULL_PTR_ERR; } uapi_camera_unlock(&g_camera_mutex); } int32_t fd = device_mng->device_interface->device_open(device_mng->camera_dev_path); if (fd < 0) { uapi_fatal_camera("open camera err.0x%x\n", fd); uapi_camera_unlock(&device_mng->camera_mutex); return UAPI_CAM_DEV_OPEN_ERR; } device_mng->statistic_handle = utils_statistics_init(device_mng); device_mng->fd = fd; uapi_info_camera("ok camera_id =0x%x fd=0x%x\n", camera_id, fd); uapi_camera_unlock(&device_mng->camera_mutex); return UAPI_CAM_NO_ERROR; } int32_t uapi_camera_device_close(uint32_t camera_id) { uapi_camera_device_mng *device_mng = NULL; int32_t ret = uapi_camera_device_get_mng_by_id(camera_id, &device_mng); if (ret != UAPI_CAM_NO_ERROR) { uapi_info_camera("device of camera_id =0x%x is not exist\n", camera_id); return UAPI_CAM_NO_ERROR; } uapi_info_camera("enter camera_id 0x%x\n", camera_id); if (device_mng->device_interface == NULL || device_mng->device_interface->device_close == NULL) { return UAPI_CAM_INVALID_PARA_ERR; } uapi_camera_lock(&device_mng->camera_mutex); if (device_mng->fd < 0) { uapi_info_camera("this camera_id =0x%x is already closed\n", camera_id); uapi_camera_unlock(&device_mng->camera_mutex); return UAPI_CAM_NO_ERROR; } if (uapi_camera_device_check_stream_exist(device_mng) == TRUE) { uapi_camera_unlock(&device_mng->camera_mutex); return UAPI_CAM_ERROR; } ret = device_mng->device_interface->device_close(device_mng->fd, device_mng->camera_dev_path); if (ret != UAPI_CAM_NO_ERROR) { uapi_fatal_camera("close camera err.\n"); } if (device_mng->device_interface->device_power_down != NULL) { uapi_camera_lock(&g_camera_mutex); ret = device_mng->device_interface->device_power_down(device_mng->camera_dev_path, UAPI_CAMERA_DEV_PATH_MAX_LEN); if (ret != UAPI_CAM_NO_ERROR) { uapi_err_camera("power down err.\n"); } uapi_camera_unlock(&g_camera_mutex); } utils_statistics_deinit(device_mng->statistic_handle); device_mng->statistic_handle = UAPI_CAM_INVALID_ID; device_mng->fd = UAPI_CAM_INVALID_FD; (void)uapi_camera_device_update_status(); uapi_info_camera("ok camera_id 0x%x\n", camera_id); uapi_camera_unlock(&device_mng->camera_mutex); return UAPI_CAM_NO_ERROR; } int32_t uapi_camera_device_get_info(uint32_t camera_id, uapi_camera_device_info *info) { check_cam_ptr_return(info); uapi_camera_device_mng *device_mng = NULL; int32_t ret = uapi_camera_device_get_mng_by_id(camera_id, &device_mng); if (ret != UAPI_CAM_NO_ERROR) { return ret; } ret = device_mng->device_interface->device_get_meta(device_mng->fd, 0, info); if (ret != UAPI_CAM_NO_ERROR) { uapi_err_camera("ret=0x%x optype =0x%x\n", ret, info->op_type); return ret; } return UAPI_CAM_NO_ERROR; } int32_t uapi_camera_device_set_info(uint32_t camera_id, const uapi_camera_device_info *info) { check_cam_ptr_return(info); uapi_camera_device_mng *device_mng = NULL; int32_t ret = uapi_camera_device_get_mng_by_id(camera_id, &device_mng); if (ret != UAPI_CAM_NO_ERROR) { return ret; } uapi_camera_lock(&device_mng->camera_mutex); ret = device_mng->device_interface->device_set_meta(device_mng->fd, 0, info); if (ret != UAPI_CAM_NO_ERROR) { uapi_fatal_camera("device_interface errno ret=0x%x \n", ret); uapi_camera_unlock(&device_mng->camera_mutex); return ret; } uapi_camera_unlock(&device_mng->camera_mutex); return UAPI_CAM_NO_ERROR; } static void print_stream_info(uint32_t camera_id, const uapi_camera_stream_init_attr *attr) { uapi_info_camera("camera_id=%d %s %dX%d fps=%d, still_capture:%d, stream_transpath:%d, pixformat:%c%c%c%c\n", camera_id, attr->format.description, attr->format.width, attr->format.height, attr->format.frame_rate[0], attr->still_capture, attr->stream_transpath, get_offset_0bit(attr->format.pixelformat), get_offset_8bit(attr->format.pixelformat), get_offset_16bit(attr->format.pixelformat), get_offset_24bit(attr->format.pixelformat)); } static int32_t compare_format(const uapi_camera_stream_init_attr *attr, const uapi_camera_device_mng *device_mng) { if (attr->format.pixelformat != device_mng->stream[0].attr.format.pixelformat || attr->format.width != device_mng->stream[0].attr.format.width || attr->format.height != device_mng->stream[0].attr.format.height || attr->format.frame_rate[0] != device_mng->stream[0].attr.format.frame_rate[0]) { return UAPI_CAM_ERROR; } return UAPI_CAM_NO_ERROR; } int32_t uapi_camera_stream_create(uint32_t camera_id, const uapi_camera_stream_init_attr *attr, uint32_t *stream_id) { check_cam_ptr_return(attr); check_cam_ptr_return(stream_id); print_stream_info(camera_id, attr); uapi_camera_device_mng *device_mng = NULL; int32_t ret = uapi_camera_device_get_mng_by_id(camera_id, &device_mng); if (ret != UAPI_CAM_NO_ERROR) { return ret; } uapi_camera_lock(&device_mng->camera_mutex); uapi_camera_stream_mng *stream_mng = uapi_camera_device_get_free_streammng(device_mng); if (stream_mng == NULL) { uapi_camera_unlock(&device_mng->camera_mutex); return UAPI_CAM_INVALID_PARA_ERR; } if (device_mng->basic_info.multi_stream_supported == FALSE && device_mng->stream[0].is_used == TRUE) { ret = compare_format(attr, device_mng); if (ret != UAPI_CAM_NO_ERROR) { goto CREATE_FAILD; } stream_mng->fork_flag = TRUE; device_mng->fork_flag = TRUE; uapi_info_camera("this is fork stream \n"); } else { ret = device_mng->device_interface->stream_create(device_mng->fd, attr, stream_mng->stream_index); if (ret != UAPI_CAM_NO_ERROR) { uapi_err_camera("Warning device_interface stream_create ret=0x%x \n", ret); goto CREATE_FAILD; } } ret = uapi_camera_stream_init_manager(stream_mng, attr, device_mng->camera_id, device_mng->fd); if (ret != UAPI_CAM_NO_ERROR) { goto CREATE_FAILD; } if (uapi_camera_device_check_stream_on_uvc(device_mng, TRUE) == TRUE) { ret = main_thread_create(device_mng); } if (ret == UAPI_CAM_NO_ERROR) { *stream_id = stream_mng->stream_id; uapi_info_camera("stream_id =0x%x stream_fd=0x%x sucess\n", *stream_id, stream_mng->stream_fd); } else { uapi_camera_stream_deinit_manager(stream_mng); uapi_err_camera("failed, ret=0x%x\n", ret); } CREATE_FAILD: uapi_camera_unlock(&device_mng->camera_mutex); return ret; } int32_t uapi_camera_stream_destroy(uint32_t stream_id) { uapi_info_camera("enter stream_id=0x%x \n", stream_id); uint32_t camera_id = stream_id_to_camera_id(stream_id); uapi_camera_device_mng *device_mng = NULL; int32_t ret = uapi_camera_device_get_mng_by_id(camera_id, &device_mng); if (ret != UAPI_CAM_NO_ERROR) { return ret; } uapi_camera_lock(&device_mng->camera_mutex); uapi_camera_stream_mng *stream_mng = uapi_camera_stream_get_mng_by_id(stream_id); if (stream_mng == NULL) { uapi_camera_unlock(&device_mng->camera_mutex); return UAPI_CAM_INVALID_PARA_ERR; } if (stream_mng->is_stream_on) { uapi_fatal_camera("Warning is_stream_on is TRUE ,please to off it first\n"); uapi_camera_unlock(&device_mng->camera_mutex); return UAPI_CAM_DESTROY_ERR; } if (stream_mng->fork_flag == FALSE) { ret = device_mng->device_interface->stream_destroy(stream_mng->stream_fd, stream_mng->stream_index, stream_mng->attr.stream_transpath); if (ret != UAPI_CAM_NO_ERROR) { uapi_fatal_camera("device_interface errno ret=0x%x \n", ret); } } device_mng->ever_on = FALSE; stream_mng->is_used = FALSE; if (uapi_camera_device_check_stream_on_uvc(device_mng, TRUE) == FALSE) { ret = main_thread_destory(device_mng); } uapi_camera_stream_deinit_manager(stream_mng); uapi_camera_unlock(&device_mng->camera_mutex); uapi_info_camera("exit stream_id=0x%x, ret=0x%x\n", stream_id, ret); return ret; } int32_t uapi_camera_stream_register_callback(uint32_t stream_id, const uapi_camera_stream_callback_func callback) { if (callback == NULL) { uapi_info_camera("enter set callback is NULL\n"); } uapi_camera_stream_mng *stream_mng = uapi_camera_stream_get_mng_by_id(stream_id); if (stream_mng == NULL) { return UAPI_CAM_INVALID_PARA_ERR; } uapi_cam_stream_lock(&stream_mng->stream_mutex); stream_mng->stream_callback = callback; uapi_cam_stream_unlock(&stream_mng->stream_mutex); return UAPI_CAM_NO_ERROR; } int32_t uapi_camera_stream_unregister_callback(uint32_t stream_id, const uapi_camera_stream_callback_func callback) { (void)callback; return uapi_camera_stream_register_callback(stream_id, NULL); } int32_t uapi_camera_stream_request(uint32_t stream_id, const uapi_camera_stream_buffer *stream_buffer, const uint8_t buffer_num) { check_cam_ptr_return(stream_buffer); if (buffer_num > UAPI_CAMERA_STREAM_BUFF_MAX_NUM || buffer_num == 0) { return UAPI_CAM_INVALID_PARA_ERR; } uint32_t camera_id = stream_id_to_camera_id(stream_id); uapi_camera_device_mng *device_mng = NULL; int32_t ret = uapi_camera_device_get_mng_by_id(camera_id, &device_mng); if (ret != UAPI_CAM_NO_ERROR) { return ret; } uapi_camera_stream_mng *stream_mng = uapi_camera_stream_get_mng_by_id(stream_id); if (stream_mng == NULL) { return UAPI_CAM_INVALID_PARA_ERR; } for (uint8_t i = 0; i < buffer_num; i++) { uapi_stream_buffer_mng *buffer_mng = uapi_camera_stream_buf_push(stream_mng, &stream_buffer[i]); if (buffer_mng == NULL) { ret = UAPI_CAM_MEM_ERR; break; } if (stream_mng->fork_flag == FALSE) { ret = stream_qbuf(stream_id, buffer_mng, device_mng); if (ret != UAPI_CAM_NO_ERROR) { uapi_err_camera("stream_stream_qbuf failed ret=0x%x \n", ret); } } } return ret; } int32_t uapi_camera_stream_on(uint32_t stream_id) { uint32_t camera_id = stream_id_to_camera_id(stream_id); uapi_camera_device_mng *device_mng = NULL; int32_t ret = uapi_camera_device_get_mng_by_id(camera_id, &device_mng); if (ret != UAPI_CAM_NO_ERROR) { uapi_fatal_camera("stream_on errno: 0x%x \n", ret); return ret; } uapi_info_camera("enter stream_id=0x%x \n", stream_id); uapi_camera_lock(&device_mng->camera_mutex); uapi_camera_stream_mng *stream_mng = uapi_camera_stream_get_mng_by_id(stream_id); if (stream_mng == NULL) { uapi_camera_unlock(&device_mng->camera_mutex); return UAPI_CAM_INVALID_PARA_ERR; } if (stream_mng->is_stream_on) { uapi_camera_unlock(&device_mng->camera_mutex); return UAPI_CAM_NO_ERROR; } if (stream_mng->fork_flag == FALSE) { if (device_mng->basic_info.multi_stream_supported == FALSE && device_mng->ever_on == TRUE) { ret = uapi_camera_stream_re_qbuf(stream_mng); if (ret != UAPI_CAM_NO_ERROR) { uapi_err_camera("uapi_camera_stream_re_qbuf failed errno: 0x%x \n", ret); uapi_camera_unlock(&device_mng->camera_mutex); return ret; } } ret = device_mng->device_interface->stream_on(stream_mng->stream_fd, stream_mng->stream_index, stream_mng->attr.stream_transpath); if (ret != UAPI_CAM_NO_ERROR) { uapi_fatal_camera("stream_on errno: 0x%x \n", ret); uapi_camera_unlock(&device_mng->camera_mutex); return ret; } device_mng->ever_on = TRUE; utils_statistics_start(device_mng->statistic_handle, stream_mng->stream_index, stream_mng->attr.stream_transpath); } uapi_cam_stream_lock(&stream_mng->stream_mutex); stream_mng->is_stream_on = TRUE; uapi_cam_stream_unlock(&stream_mng->stream_mutex); uapi_camera_unlock(&device_mng->camera_mutex); uapi_info_camera("exit stream_id=0x%x, ret:0x%x \n", stream_id, ret); return ret; } int32_t uapi_camera_stream_off(uint32_t stream_id) { uint32_t camera_id = stream_id_to_camera_id(stream_id); uapi_camera_device_mng *device_mng = NULL; int32_t ret = uapi_camera_device_get_mng_by_id(camera_id, &device_mng); if (ret != UAPI_CAM_NO_ERROR) { uapi_fatal_camera("stream_off errno: 0x%x \n", ret); return ret; } uapi_info_camera("enter stream_id=0x%x \n", stream_id); uapi_camera_lock(&device_mng->camera_mutex); uapi_camera_stream_mng *stream_mng = uapi_camera_stream_get_mng_by_id(stream_id); if (stream_mng == NULL) { uapi_camera_unlock(&device_mng->camera_mutex); return UAPI_CAM_INVALID_PARA_ERR; } if (stream_mng->is_stream_on == FALSE) { uapi_camera_unlock(&device_mng->camera_mutex); return UAPI_CAM_NO_ERROR; } if (stream_mng->fork_flag == FALSE) { uapi_info_camera("device start to stream(%u) off\n", stream_id); ret = device_mng->device_interface->stream_off(stream_mng->stream_fd, stream_mng->stream_index, stream_mng->attr.stream_transpath); if (ret != UAPI_CAM_NO_ERROR) { uapi_fatal_camera("stream_off errno: 0x%x \n", ret); } } utils_statistics_stop(device_mng->statistic_handle, stream_mng->stream_index, stream_mng->valid_buf_count); uapi_cam_stream_lock(&stream_mng->stream_mutex); stream_mng->is_stream_on = FALSE; uapi_cam_stream_unlock(&stream_mng->stream_mutex); uapi_camera_unlock(&device_mng->camera_mutex); uapi_info_camera("exit stream_id=0x%x, ret:0x%x\n", stream_id, ret); return ret; } int32_t uapi_camera_stream_get_info(uint32_t stream_id, uapi_camera_stream_info *info) { check_cam_ptr_return(info); uint32_t camera_id = stream_id_to_camera_id(stream_id); uapi_camera_device_mng *device_mng = NULL; int32_t ret = uapi_camera_device_get_mng_by_id(camera_id, &device_mng); if (ret != UAPI_CAM_NO_ERROR) { uapi_fatal_camera("stream info errno: 0x%x \n", ret); return ret; } uapi_camera_stream_mng *stream_mng = uapi_camera_stream_get_mng_by_id(stream_id); if (stream_mng == NULL) { return UAPI_CAM_INVALID_PARA_ERR; } ret = device_mng->device_interface->stream_get_meta(stream_mng->stream_fd, stream_mng->stream_index, info); if (ret != UAPI_CAM_NO_ERROR) { uapi_err_camera("stream_get_meta stream_fd =0x%x errno ret=0x%x \n", stream_mng->stream_fd, ret); return ret; } return UAPI_CAM_NO_ERROR; } int32_t uapi_camera_stream_set_info(uint32_t stream_id, const uapi_camera_stream_info *info) { check_cam_ptr_return(info); uint32_t camera_id = stream_id_to_camera_id(stream_id); uapi_camera_device_mng *device_mng = NULL; int32_t ret = uapi_camera_device_get_mng_by_id(camera_id, &device_mng); if (ret != UAPI_CAM_NO_ERROR) { uapi_fatal_camera("stream_set info errno: 0x%x \n", ret); return ret; } uapi_camera_lock(&device_mng->camera_mutex); uapi_camera_stream_mng *stream_mng = uapi_camera_stream_get_mng_by_id(stream_id); if (stream_mng == NULL) { uapi_camera_unlock(&device_mng->camera_mutex); return UAPI_CAM_INVALID_PARA_ERR; } if (stream_mng->fork_flag == FALSE) { ret = device_mng->device_interface->stream_set_meta(stream_mng->stream_fd, stream_mng->stream_index, info); if (ret != UAPI_CAM_NO_ERROR) { uapi_fatal_camera("device_interface errno ret=0x%x \n", ret); uapi_camera_unlock(&device_mng->camera_mutex); return ret; } } if (info->type == UAPI_CAMERA_STREAM_INFO_FORMAT_INFO) { if (memcpy_s(&(stream_mng->attr.format), sizeof(uapi_camera_stream_format_info), &(info->u.format_info), sizeof(info->u.format_info)) != EOK) { uapi_err_camera("update stream attr failed\n"); } } uapi_camera_unlock(&device_mng->camera_mutex); return UAPI_CAM_NO_ERROR; } int32_t uapi_camera_device_get_formats_size(uint32_t camera_id, uint32_t *format_num) { if (format_num == NULL) { uapi_fatal_camera("format_num is NULL \n"); return UAPI_CAM_INVALID_PARA_ERR; } uint16_t list_num = 0; uapi_camera_device_mng *device_mng = NULL; int32_t ret = uapi_camera_device_get_mng_by_id(camera_id, &device_mng); if (ret != UAPI_CAM_NO_ERROR) { uapi_fatal_camera("device fail to get mng errno: 0x%x \n", ret); return ret; } uapi_camera_lock(&device_mng->camera_mutex); ret = device_mng->device_interface->device_get_formats_size(device_mng->fd, &list_num); if (ret == UAPI_CAM_ERROR) { uapi_fatal_camera("fail to get formats size errno: 0x%x \n", ret); uapi_camera_unlock(&device_mng->camera_mutex); return ret; } *format_num = list_num; uapi_camera_unlock(&device_mng->camera_mutex); uapi_dbg_camera("camera_id:%d, list_num:%d\n", camera_id, *format_num); return UAPI_CAM_NO_ERROR; } int32_t uapi_camera_device_get_formats(uint32_t camera_id, uapi_camera_stream_format_info *format_array, const int32_t array_length) { check_cam_ptr_return(format_array); uapi_camera_device_mng *device_mng = NULL; int32_t ret = uapi_camera_device_get_mng_by_id(camera_id, &device_mng); if (ret != UAPI_CAM_NO_ERROR) { uapi_fatal_camera("device get fmt errno: 0x%x \n", ret); return ret; } uapi_camera_lock(&device_mng->camera_mutex); ret = device_mng->device_interface->device_get_formats(device_mng->fd, format_array, array_length); uapi_camera_unlock(&device_mng->camera_mutex); uapi_info_camera("%s, format num:%d\n", (ret == UAPI_CAM_NO_ERROR ? "success" : "failed"), array_length); if (ret == UAPI_CAM_NO_ERROR) { for (int32_t i = 0; i < array_length; i++) { uapi_info_camera("encode description:%s--(%c%c%c%c)\n", format_array[i].description, get_offset_0bit(format_array[i].pixelformat), get_offset_8bit(format_array[i].pixelformat), get_offset_16bit(format_array[i].pixelformat), get_offset_24bit(format_array[i].pixelformat)); uapi_info_camera("width:%d--height:%d\n", format_array[i].width, format_array[i].height); uapi_info_camera("frame_rate_num:%d\n", format_array[i].frame_rate_num); for (uint8_t j = 0; j < format_array[i].frame_rate_num; j++) { uapi_info_camera("frame_rate(%d):%d\n", j, format_array[i].frame_rate[j]); } } } return ret; } int32_t uapi_camera_module_install(uint32_t camera_id, const uapi_camera_module_package *module, uapi_camera_bool sync) { check_cam_ptr_return(module); uapi_camera_device_mng *device_mng = NULL; int32_t ret = uapi_camera_device_get_mng_by_id(camera_id, &device_mng); if (ret != UAPI_CAM_NO_ERROR) { return ret; } uapi_camera_lock(&device_mng->camera_mutex); if (device_mng->device_interface->module_install != NULL) { ret = device_mng->device_interface->module_install(module, sync); } uapi_camera_unlock(&device_mng->camera_mutex); return ret; } int32_t uapi_camera_module_uninstall(uint32_t camera_id, const uapi_camera_module_package *module) { check_cam_ptr_return(module); uapi_camera_device_mng *device_mng = NULL; int32_t ret = uapi_camera_device_get_mng_by_id(camera_id, &device_mng); if (ret != UAPI_CAM_NO_ERROR) { return ret; } uapi_camera_lock(&device_mng->camera_mutex); if (device_mng->device_interface->module_uninstall != NULL) { ret = device_mng->device_interface->module_uninstall(module); } uapi_camera_unlock(&device_mng->camera_mutex); return ret; } int32_t uapi_camera_report_register_callback(uint32_t camera_id, const uapi_camera_report_callback_func callback, const void *priv_data) { check_cam_ptr_return(callback); uapi_camera_device_mng *device_mng = NULL; int32_t ret = uapi_camera_device_get_mng_by_id(camera_id, &device_mng); if (ret != UAPI_CAM_NO_ERROR) { return ret; } uapi_camera_lock(&device_mng->camera_mutex); if (device_mng->device_interface->register_report_callback != NULL) { ret = device_mng->device_interface->register_report_callback(camera_id, callback, priv_data); } uapi_camera_unlock(&device_mng->camera_mutex); return ret; } int32_t uapi_camera_report_unregister_callback(uint32_t camera_id, const uapi_camera_report_callback_func callback) { uapi_camera_device_mng *device_mng = NULL; int32_t ret = uapi_camera_device_get_mng_by_id(camera_id, &device_mng); if (ret != UAPI_CAM_NO_ERROR) { return ret; } uapi_camera_lock(&device_mng->camera_mutex); if (device_mng->device_interface->unregister_report_callback != NULL) { ret = device_mng->device_interface->unregister_report_callback(camera_id, callback); } uapi_camera_unlock(&device_mng->camera_mutex); return ret; } int32_t uapi_camera_hotplug_register_callback(const uapi_camera_hotplug_callback_func callback) { if (callback == NULL) { uapi_err_camera("enter set callback is NULL\n"); return UAPI_CAM_INVALID_PARA_ERR; } uapi_camera_lock(&g_camera_mutex); g_camera_callback = callback; uapi_camera_unlock(&g_camera_mutex); (void)uapi_camera_hotplug_set_callback(device_hotplug_callback); for (uint32_t i = 0; i < get_plugin_interfaces_num(); i++) { uapi_camera_device_interface *device_interface = uapi_camera_device_get_interface(i); if ((device_interface != NULL) && (device_interface->register_hotplug_callback != NULL)) { (void)device_interface->register_hotplug_callback(device_hotplug_callback); } } return UAPI_CAM_NO_ERROR; } int32_t uapi_camera_hotplug_unregister_callback() { uapi_camera_lock(&g_camera_mutex); g_camera_callback = NULL; uapi_camera_unlock(&g_camera_mutex); (void)uapi_camera_hotplug_set_callback(NULL); for (uint32_t i = 0; i < get_plugin_interfaces_num(); i++) { uapi_camera_device_interface *device_interface = uapi_camera_device_get_interface(i); if ((device_interface != NULL) && (device_interface->register_hotplug_callback != NULL)) { (void)device_interface->unregister_hotplug_callback(); } } return UAPI_CAM_NO_ERROR; } int32_t uapi_camera_state_monitor_register_callback(const uapi_camera_state_monitor_callback_func callback) { if (callback == NULL) { uapi_err_camera("enter set callback is NULL\n"); return UAPI_CAM_INVALID_PARA_ERR; } camera_proc_state_monitor_set_callback(callback); return UAPI_CAM_NO_ERROR; } int32_t uapi_camera_state_monitor_unregister_callback() { camera_proc_state_monitor_set_callback(NULL); return UAPI_CAM_NO_ERROR; }