ais client调用略解(QNX)
慢慢总结camera相关的东西吧
software architecture
一、ais client 相关API
qcarcam_ret_t qcarcam_initialize(qcarcam_init_t* p_init_params);
qcarcam_ret_t qcarcam_uninitialize(void);
qcarcam_ret_t qcarcam_uninitialize(void);
qcarcam_ret_t qcarcam_query_inputs(qcarcam_input_t* p_inputs, unsigned int size, unsigned int* ret_size);
qcarcam_ret_t qcarcam_query_diagnostics(void* p_diag_info, unsigned int diag_size);
qcarcam_hndl_t qcarcam_open(qcarcam_input_desc_t desc);
qcarcam_ret_t qcarcam_close(qcarcam_hndl_t hndl);
qcarcam_ret_t qcarcam_g_param(qcarcam_hndl_t hndl, qcarcam_param_t param, qcarcam_param_value_t* p_value);
qcarcam_ret_t qcarcam_s_param(qcarcam_hndl_t hndl, qcarcam_param_t param, const qcarcam_param_value_t* p_value);
qcarcam_ret_t qcarcam_s_buffers(qcarcam_hndl_t hndl, qcarcam_buffers_t* p_buffers);
qcarcam_ret_t qcarcam_start(qcarcam_hndl_t hndl);
qcarcam_ret_t qcarcam_stop(qcarcam_hndl_t hndl);
qcarcam_ret_t qcarcam_pause(qcarcam_hndl_t hndl);
qcarcam_ret_t qcarcam_resume(qcarcam_hndl_t hndl);
qcarcam_ret_t qcarcam_get_frame(qcarcam_hndl_t hndl, qcarcam_frame_info_t* p_frame_info,
unsigned long long int timeout, unsigned int flags);
qcarcam_ret_t qcarcam_release_frame(qcarcam_hndl_t hndl, unsigned int idx);
二、API调用
1.client workflow
2.workflow相关API解释及调用
2.1 qcarcam_query_inputs
// @brief Queries available inputs. To get the number of available inputs to query, call with p_inputs set to NULL.
//
// @param p_inputs Pointer to array inputs. If NULL, then ret_size returns number of available inputs to query
// @param size Number of elements in array
// @param ret_size If p_inputs is set, number of elements in array that were filled
// If p_inputs is NULL, number of available inputs to query
//
// @return QCARCAM_RET_OK if successful.
// QCARCAM_RET_BUSY if engine has not finished detection of all available inputs. Will only return available
// inputs up to this point in time.
qcarcam_ret_t qcarcam_query_inputs(qcarcam_input_t* p_inputs, unsigned int size, unsigned int* ret_size);
// 先查询当前具体有多少可用的摄像头
unsigned int queryNumInputs = 0, queryFilled = 0;
ret = qcarcam_query_inputs(NULL, 0, &queryNumInputs);
// 分配相关配置,并查询queryNumInputs数量的摄像头信息
qcarcam_input_t *pInputs;
ret = qcarcam_query_inputs(pInputs, queryNumInputs, &queryFilled);
// 打印查询到的摄像头信息
for (i = 0; i < queryFilled; i++)
{
QCARCAM_INFOMSG("%d: input_id=%d, res=%dx%d fmt=0x%08x fps=%.2f flags=0x%x",
i, pInputs[i].desc,
pInputs[i].res[0].width, pInputs[i].res[0].height,
pInputs[i].color_fmt[0], pInputs[i].res[0].fps, pInputs[i].flags);
}
2.2 qcarcam_open
// qcarcam_open
// @brief Opens handle to input
// @param desc Unique identifier of input to be opened
// @return NOT NULL if successful; NULL on failure
qcarcam_hndl_t qcarcam_open(qcarcam_input_desc_t desc);
// 每个摄像头的管理都需要起一个线程去管理,不展开线程,只看调用
for (input_idx = 0; input_idx < gCtxt.numInputs; input_idx++) {
rc = CameraCreateThread(QCARCAM_THRD_PRIO, 0, &qcarcam_test_setup_input_ctxt_thread, &gCtxt.inputs[input_idx], 0, thread_name, &input_ctxt->thread_handle);
}
input_ctxt->qcarcam_context = qcarcam_open(input_ctxt->qcarcam_input_id);
2.3 qcarcam_s_buffers
// @brief Opens handle to input
// @param desc Unique identifier of input to be opened
// @return NOT NULL if successful; NULL on failure
qcarcam_ret_t qcarcam_s_buffers(qcarcam_hndl_t hndl, qcarcam_buffers_t* p_buffers);
// 分配相应的buffer个数[1-12]和对应大小(根据不同的颜色格式进行分配)
// Allocate an additional buffer to be shown in case of signal loss
qcarcam_test_input_t *input_ctxt = &gCtxt.inputs[input_idx];
output_n_buffers = input_ctxt->buffers_param[QCARCAM_TEST_BUFFERS_OUTPUT].n_buffers + 1;
input_ctxt->p_buffers_output.n_buffers = output_n_buffers; // 用户传入
input_ctxt->p_buffers_output.color_fmt = input_ctxt->buffers_param[QCARCAM_TEST_BUFFERS_OUTPUT].format;
input_ctxt->p_buffers_output.buffers = (qcarcam_buffer_t *)calloc(input_ctxt->p_buffers_output.n_buffers, sizeof(*input_ctxt->p_buffers_output.buffers));
for (i = 0; i < output_n_buffers; ++i) {
input_ctxt->p_buffers_output.buffers[i].n_planes = 1;
input_ctxt->p_buffers_output.buffers[i].planes[0].width = input_ctxt->buffers_param[QCARCAM_TEST_BUFFERS_OUTPUT].width;
input_ctxt->p_buffers_output.buffers[i].planes[0].height = input_ctxt->buffers_param[QCARCAM_TEST_BUFFERS_OUTPUT].height;
}
// 向ais设置该buffer数组
ret = qcarcam_s_buffers(input_ctxt->qcarcam_context, &input_ctxt->p_buffers_output);
2.4 qcarcam_start
// @brief Start input
// @param hndl Handle of input
// @return QCARCAM_RET_OK if successful
qcarcam_ret_t qcarcam_start(qcarcam_hndl_t hndl);
ret = qcarcam_start(input_ctxt->qcarcam_context);
2.5 qcarcam_get_frame
// @param hndl Handle of input
// @param p_frame_info Pointer to frame information that will be filled
// @param timeout Max wait time in ns for frame to be available before timeout
// @param flags Flags
// @return QCARCAM_RET_OK if successful; QCARCAM_RET_TIMEOUT if timeout
qcarcam_ret_t qcarcam_get_frame(qcarcam_hndl_t hndl, qcarcam_frame_info_t* p_frame_info,
unsigned long long int timeout, unsigned int flags);
// 使用回调来响应帧数据则可以不设置frame_timeout
// 回调事件
qcarcam_param_value_t param;
param.ptr_value = (void *)qcarcam_test_event_cb;
ret = qcarcam_s_param(input_ctxt->qcarcam_context, QCARCAM_PARAM_EVENT_CB, ¶m);
param.uint_value = QCARCAM_EVENT_FRAME_READY | QCARCAM_EVENT_INPUT_SIGNAL |QCARCAM_EVENT_DESR_LDO|
QCARCAM_EVENT_ERROR | QCARCAM_EVENT_VENDOR | QCARCAM_EVENT_FRAME_FREEZE;
ret = qcarcam_s_param(input_ctxt->qcarcam_context, QCARCAM_PARAM_EVENT_MASK, ¶m);
/*no timeout when using event callback as frame is ready as soon as we get callback*/
if (input_ctxt->use_event_callback) {
input_ctxt->frame_timeout = 0;
} else {
input_ctxt->frame_timeout = (p_xml_input->properties.frame_timeout == -1) ?
QCARCAM_TEST_DEFAULT_GET_FRAME_TIMEOUT : p_xml_input->properties.frame_timeout * 1000 * 1000;
}
qcarcam_frame_info_t frame_info;
ret = qcarcam_get_frame(input_ctxt->qcarcam_context, &frame_info, input_ctxt->frame_timeout, 0);
2.6 client process
// 这里的客户端处理帧数据,我们直接给它推到显示上面
qcarcam_test_post_to_display(input_ctxt);
2.7 qcarcam_release_frame
// client处理完后需要释放掉当前帧,将buffer归还给ais继续处理
// @param hndl Handle of input
// @param idx Index into the qcarcam_buffers_t buffers table to reenqueue
// @return QCARCAM_RET_OK if successful
qcarcam_ret_t qcarcam_release_frame(qcarcam_hndl_t hndl, unsigned int idx);
ret = qcarcam_release_frame(input_ctxt->qcarcam_context, rel_idx);
3.设置或获取摄像头相关厂商信息及其它信息
// @param hndl Handle of input
// @param param Parameter to get
// @param p_value Pointer to structure of value that will be retrieved
// @return QCARCAM_RET_OK if successful
qcarcam_ret_t qcarcam_g_param(qcarcam_hndl_t hndl, qcarcam_param_t param, qcarcam_param_value_t* p_value);
// @param hndl Handle of input
// @param param Parameter to set
// @param p_value Pointer to structure of value that will be set
// @return QCARCAM_RET_OK if successful
qcarcam_ret_t qcarcam_s_param(qcarcam_hndl_t hndl, qcarcam_param_t param, const qcarcam_param_value_t* p_value);
/// @brief Parameter settings
typedef enum
{
QCARCAM_PARAM_EVENT_CB = 0x1, ///< Event callback function.
QCARCAM_PARAM_EVENT_MASK, ///< Mask of events
QCARCAM_PARAM_COLOR_FMT, ///< Output color format.
QCARCAM_PARAM_RESOLUTION, ///< Input dev resolution.
QCARCAM_PARAM_BRIGHTNESS,
QCARCAM_PARAM_CONTRAST,
QCARCAM_PARAM_MIRROR_H, ///< Horizontal mirror.
QCARCAM_PARAM_MIRROR_V, ///< Vertical mirror.
QCARCAM_PARAM_FRAME_RATE,
QCARCAM_PARAM_VID_STD, ///< Video standard
QCARCAM_PARAM_CURRENT_VID_STD, ///< Video standard
QCARCAM_PARAM_STATUS, ///< Video lock status
QCARCAM_PARAM_LATENCY_MAX, ///< Max buffer latency in frame done Q
QCARCAM_PARAM_LATENCY_REDUCE_RATE, ///< Number of buffers to drop when max latency reached
QCARCAM_PARAM_PRIVATE_DATA,
QCARCAM_PARAM_INJECTION_START,
QCARCAM_PARAM_EXPOSURE, ///< exposure setting
QCARCAM_PARAM_HUE, ///< hue setting
QCARCAM_PARAM_SATURATION, ///< saturation setting
QCARCAM_PARAM_HDR_EXPOSURE,
QCARCAM_PARAM_GAMMA, ///< gamma setting
QCARCAM_PARAM_OPMODE, ///< operation mode
QCARCAM_PARAM_ISP_CTRLS, ///< ISP controls
QCARCAM_PARAM_REMOTE_DEVICE, ///< remote read/write
QCARCAM_PARAM_VENDOR, ///< vendor param
QCARCAM_PARAM_INPUT_MODE, ///< Input device mode.
QCARCAM_PARAM_MASTER, ///< Set the client as master
QCARCAM_PARAM_EVENT_CHANGE_SUBSCRIBE, ///< Event subscription
QCARCAM_PARAM_EVENT_CHANGE_UNSUBSCRIBE, ///< Event unsubscribe
QCARCAM_PARAM_NUM, ///< total number of valid parameters.
QCARCAM_PARAM_MAX = 0x7FFFFFFF
} qcarcam_param_t;
// 获取配置
ret = qcarcam_g_param(input_ctxt->qcarcam_context, QCARCAM_PARAM_VENDOR, ¶m);
// 设置配置
qcarcam_param_value_t param;
param.vendor_param.data[0] = 0x12345678;
param.vendor_param.data[1] = 0xfedcba98;
ret = qcarcam_s_param(input_ctxt->qcarcam_context, QCARCAM_PARAM_VENDOR, ¶m);
三、一些event事件处理
typedef enum
{
QCARCAM_EVENT_FRAME_READY = 1 << 0, ///< Frame ready to be dequeued using get_frame API
QCARCAM_EVENT_INPUT_SIGNAL = 1 << 1, ///< Payload will contain qcarcam_input_signal_t
QCARCAM_EVENT_ERROR = 1 << 2, ///< Error event with qcarcam_event_error_t payload
QCARCAM_EVENT_VENDOR = 1 << 3, ///< Vendor event
QCARCAM_EVENT_PROPERTY_NOTIFY = 1 << 4, ///< Property events
QCARCAM_EVENT_FRAME_SOF = 1 << 5, ///< SOF event
QCARCAM_EVENT_RECOVERY = 1 << 6, ///< Recovery in progress event
QCARCAM_EVENT_RECOVERY_SUCCESS = 1 << 7, ///< Recovery successful event
QCARCAM_EVENT_ERROR_ABORTED = 1 << 8, ///< Recovery failed event
QCARCAM_EVENT_FRAME_FREEZE = 1 << 9, ///< Frozen frame event with qcarcam_frame_freeze_t payload
QCARCAM_EVENT_DESR_LDO = 1 << 10 ///< Deserializer and MPQ ldo error detection event 自定义
} qcarcam_event_t;
typedef union
{
unsigned int uint_payload; ///< unsigned int type
qcarcam_desr_ldo_signal_t desr_ldo; /// 自定义
qcarcam_frame_freeze_t frame_freeze; ///< Frame freeze
qcarcam_vendor_param_t vendor_data; ///< vendor data paylaod
unsigned int array[QCARCAM_MAX_PAYLOAD_SIZE]; ///< max event payload
} qcarcam_event_payload_t;
1 client的相关event事件注册
qcarcam_param_value_t param;
param.ptr_value = (void *)qcarcam_test_event_cb;
ret = qcarcam_s_param(input_ctxt->qcarcam_context, QCARCAM_PARAM_EVENT_CB, ¶m);
param.uint_value = QCARCAM_EVENT_FRAME_READY | QCARCAM_EVENT_INPUT_SIGNAL |QCARCAM_EVENT_DESR_LDO|
QCARCAM_EVENT_ERROR | QCARCAM_EVENT_VENDOR | QCARCAM_EVENT_FRAME_FREEZE;
ret = qcarcam_s_param(input_ctxt->qcarcam_context, QCARCAM_PARAM_EVENT_MASK, ¶m);
// event函数
static void qcarcam_test_event_cb(qcarcam_hndl_t hndl, qcarcam_event_t event_id, qcarcam_event_payload_t *p_payload)
2 QCARCAM_EVENT_FRAME_READY事件
该事件为ais数据帧准备好后的通知事件,告知client,此时已有相应的index数据帧准备好,此时可以调用qcarcam_get_frame去获取对应的数据buffer,此处参考 > 2.5 qcarcam_get_frame
3 QCARCAM_EVENT_INPUT_SIGNAL事件
该事件用于检测摄像头各link的连接状态,在该event_id下还有细分的子id,p_payload.uint_payload = QCARCAM_INPUT_SIGNAL_LOST和p_payload.uint_payload = QCARCAM_INPUT_SIGNAL_VALID;
对应的子id处理如下:
case QCARCAM_INPUT_SIGNAL_LOST:
ret = qcarcam_stop(input_ctxt->qcarcam_context);
case QCARCAM_INPUT_SIGNAL_VALID:
ret = qcarcam_start(input_ctxt->qcarcam_context);
4 QCARCAM_EVENT_ERROR事件
该事件是ais系统内部上报的ERROR事件,属于严重的系统故障,需要采取相应的方法进行处理,该event_id包含多个子id,每一个子id都需要进行对应的处理。
// 该ID为连接异常ID,通常出现该ID的原因为client长时间未响应造成的,这里的处理比较简单除暴,可以尝试重新建立client与server的连接
case QCARCAM_CONN_ERROR:
abort_test();
// 该ID通常为mipi数据流异常产生的事件,该事件通常出现在hotplug和长时间丢包时产生,该事件需要保证rdi链路重启,也就是所有摄像头的调用完成全开全关
case QCARCAM_FATAL_ERROR:
qcarcam_input_stop(input_ctxt);
usleep(200000);
qcarcam_input_start(input_ctxt);
// 该ID为帧同步错误,产生的原因一般是数据链不稳定,缺失SOF或EOF导致,处理的方法可以尝试和QCARCAM_FATAL_ERROR一致
case QCARCAM_FRAMESYNC_ERROR:
// 该ID为帧同步错误,产生的原因一般是数据链不稳定,缺失SOF或EOF导致rdi数据链路超出最大长度,处理的方法可以尝试和QCARCAM_FATAL_ERROR一致
case QCARCAM_IFE_OVERFLOW_ERROR: