[Camera]高通平台 camera 的 super buffer

super buffer 在 qcamera2\hal 层的使用

super buffer 是高通hal1中常用的概念,对应的数据结构是:mm_camera_super_buf_t

/** mm_camera_super_buf_t: super buf structure for bundled
*   stream frames
*    @camera_handle : camera handler to uniquely identify
*              a camera object
*    @ch_id : channel handler to uniquely ideentify a channel
*           object
*    @num_bufs : number of buffers in the super buf, should not
*              exceeds MAX_STREAM_NUM_IN_BUNDLE
*    @bufs : array of buffers in the bundle
**/
typedef struct {
    uint32_t camera_handle;
    uint32_t ch_id;
    uint32_t num_bufs;
    uint8_t bUnlockAEC;
    uint8_t bReadyForPrepareSnapshot;
    mm_camera_buf_def_t* bufs[MAX_STREAM_NUM_IN_BUNDLE];
} mm_camera_super_buf_t;

很明显mm_camera_super_buf_t 是由mm_camera_buf_def_t 组合而成。
其中 mm_camera_buf_def_t 是具体管理图像数据并且和v4l2交互的:

/** mm_camera_buf_def_t: structure for stream frame buf
*    @stream_id : stream handler to uniquely identify a stream
*               object
*    @buf_idx : index of the buf within the stream bufs, to be
*               filled during mem allocation
*    @timespec_ts : time stamp, to be filled when DQBUF is
*                 called
*    @frame_idx : frame sequence num, to be filled when DQBUF
*    @plane_buf  : Frame plane definition
*    @fd : file descriptor of the frame buffer, to be filled
*        during mem allocation
*    @buffer : pointer to the frame buffer, to be filled during
*            mem allocation
*    @frame_len : length of the whole frame, to be filled during
*               mem allocation
*    @mem_info : user specific pointer to additional mem info
*    @flags:  v4l2_buffer flags, used to report error in data buffers
*    @cache_flags: Stores cache related read/write flags
**/
typedef struct mm_camera_buf_def {
    uint32_t stream_id;
    cam_stream_type_t stream_type;
    cam_stream_buf_type buf_type;
    uint32_t buf_idx;
    uint8_t is_uv_subsampled;
    struct timespec ts;
    uint32_t frame_idx;
    union {
        mm_camera_plane_buf_def_t planes_buf;
        mm_camera_user_buf_def_t user_buf;
    };
    int fd;
    void *buffer;
    size_t frame_len;
    void *mem_info;
    uint32_t flags;
    uint32_t cache_flags;
} mm_camera_buf_def_t;

super buffer广泛用于 stream 和 channel 的回调函数中:
源自高通开源代码QCamera2HWI.h
图片源自高通开源代码QCamera2HWI.h

stream 和 channel 都需要 super buffer,他们不同之处在于:

  1. stream 回调用来处理实时性较强的场景:如Preview。
    2.channel 回调用来处理 需要从多个 stream 中取出数据的任务,例如:Snapshot 场景会用到图像数据和metadata 数据。

这些回调函数拿到 super buffer 后会进一步会取出自己需要的子buffer(也就是上文中提到的mm_camera_buf_def_t* bufs[])。例如 Preview 回调中:

void QCamera2HardwareInterface::preview_stream_cb_routine(mm_camera_super_buf_t *super_frame,
                                                          QCameraStream * stream,
                                                          void *userdata)
 {
 	......
 	/*只需要取到预览buffer bufs[0] 就可以*/
 	QCameraGrallocMemory *memory = (QCameraGrallocMemory *)super_frame->bufs[0]->mem_info;
 	......
 	mm_camera_buf_def_t *frame = super_frame->bufs[0];
 	......
 }                                                       
void QCamera2HardwareInterface::zsl_channel_cb(mm_camera_super_buf_t *recvd_frame,
                                               void *userdata)
{
	......
	
	......
}

Snapshot 回调则毕竟复杂这里不做展开。

综上可见 super buffer 是用来给 stream 以及 channel 的回调函数提供统一接口。

super buffer 在 mm-camera-interface 层中的管理

上述回调函数会在 mm-camera-interface 中调用。也就是说 mm-camera-interface 会管理 super buffer 并且给这些回调函数传参。
阅读 mm_camera_channel.c 源码:

/*===========================================================================
 * FUNCTION   : mm_channel_superbuf_queue_init
 *
 * DESCRIPTION: initialize superbuf queue in the channel
 *
 * PARAMETERS :
 *   @queue   : ptr to superbuf queue to be initialized
 *
 * RETURN     : int32_t type of status
 *              0  -- success
 *              -1 -- failure
 *==========================================================================*/
int32_t mm_channel_superbuf_queue_init(mm_channel_queue_t * queue)
{
    return cam_queue_init(&queue->que);
}

static inline int32_t cam_queue_init(cam_queue_t *queue)
{
    pthread_mutex_init(&queue->lock, NULL);
    cam_list_init(&queue->head.list);
    queue->size = 0;
    return 0;
}

可见 super buffer 是放在队列中管理。队列又是由链表实现。
高通代码很贴心的把 super buffer 的队列操作放在一起:

/* channel super queue functions */
int32_t mm_channel_superbuf_queue_init(mm_channel_queue_t * queue);
int32_t mm_channel_superbuf_queue_deinit(mm_channel_queue_t * queue);
int32_t mm_channel_superbuf_comp_and_enqueue(mm_channel_t *ch_obj,
                                             mm_channel_queue_t * queue,
                                             mm_camera_buf_info_t *buf);
mm_channel_queue_node_t* mm_channel_superbuf_dequeue(
        mm_channel_queue_t * queue, mm_channel_t *ch_obj);

super buffer队列操作在下面函数中:

int32_t mm_channel_start(mm_channel_t *my_obj)
{
	......
	//队列初始化
	mm_channel_superbuf_queue_init(&my_obj->bundle.superbuf_queue);
	......
	//使用下面两个函数来负责super buffer分发,填充,入队和出队
	       mm_camera_cmd_thread_launch(&my_obj->cb_thread,
                                    mm_channel_dispatch_super_buf,
                                    (void*)my_obj);
        mm_camera_cmd_thread_launch(&my_obj->cmd_thread,
                                    mm_channel_process_stream_buf,
                                    (void*)my_obj);
 ......                                  
}

其中大部分事件接收后的业务逻辑都放在 mm_channel_process_stream_buf 函数:

/*===========================================================================
 * FUNCTION   : mm_channel_process_stream_buf
 *
 * DESCRIPTION: handle incoming buffer from stream in a bundle. In this function,
 *              matching logic will be performed on incoming stream frames.
 *              Will depends on the bundle attribute, either storing matched frames
 *              in the superbuf queue, or sending matched superbuf frames to upper
 *              layer through registered callback.
 *
 * PARAMETERS :
 *   @cmd_cb  : ptr storing matched super buf information
 *   @userdata: user data ptr
 *
 * RETURN     : none
 *==========================================================================*/
static void mm_channel_process_stream_buf(mm_camera_cmdcb_t * cmd_cb,
                                          void *user_data)
{
......
    if (MM_CAMERA_CMD_TYPE_DATA_CB  == cmd_cb->cmd_type) {
        /* comp_and_enqueue */
        //mm_channel_superbuf_comp_and_enqueue 把buffer加入stream 队列中,再填充 组装
        mm_channel_superbuf_comp_and_enqueue(
                        ch_obj,
                        &ch_obj->bundle.superbuf_queue,
                        &cmd_cb->u.buf);       
......
 /* dequeue */
 //创建info对象用来储存buffer并且发给上层
        mm_channel_node_info_t info; 
......
// dequeue buffer 并且填充给 info
                 node = mm_channel_superbuf_dequeue_frame_internal(
                                ch_queue, match_frame);
                        if (node != NULL) {
                            info.ch_obj[info.num_nodes] = fs.ch_obj[j];
                            info.node[info.num_nodes] = node;
                           
     ......
                 /* dispatch superbuf */
                 //将 info 发送出去
            mm_channel_send_super_buf(&info);
HAL mm_camera dispatchingThread dataCbThread stream V4L2 register callback StratChannel:start init spuer buffer queue luanch lunch MM_STREAM_EVT_QBUF config V4L2 VIDIOC_QBUF wait SOF irq VIDIOC_DQBUF MM_CAMERA_CMD_TYPE_DATA_CB comp and enqueue MM_CAMERA_CMD_TYPE_SUPER_BUF_DATA_CB super_buf_notify_cb HAL mm_camera dispatchingThread dataCbThread stream V4L2
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值