You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1106 lines
41 KiB

/*
* 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 <string.h>
#include <stddef.h>
#include <sys/ioctl.h>
#include <malloc.h>
#include <fcntl.h>
#include <unistd.h>
#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;
}