Linux v4l2驱动中vb2_buffer_done实现

概述

vb2_buffer_done 是驱动与videobuf2 交互的关键接口,驱动将一帧图像放入vb2 buffer时,再利用vb2_buffer_done将vb2 buffer送入videobuf2中;此函数的调用可以在中断中执行,也可以在进程中调用。

参数说明

/**
 * vb:vb2 buffer,此时驱动将一帧图像已经放入vb2 buffer
 * state:vb2 buffer状态,state为VB2_BUF_STATE_DONE时,通知 videobuf2取走buffer,state为VB2_BUF_STATE_ERROR时 通知videobuf2 buffer出错
 */
void vb2_buffer_done(struct vb2_buffer *vb, enum vb2_buffer_state state);

函数原型

void vb2_buffer_done(struct vb2_buffer *vb, enum vb2_buffer_state state)
{
	struct vb2_queue *q = vb->vb2_queue;
	unsigned long flags;

	if (WARN_ON(vb->state != VB2_BUF_STATE_ACTIVE))
		return;

	if (WARN_ON(state != VB2_BUF_STATE_DONE &&
		    state != VB2_BUF_STATE_ERROR &&
		    state != VB2_BUF_STATE_QUEUED))
		state = VB2_BUF_STATE_ERROR;           //check vb2 buffer状态

#ifdef CONFIG_VIDEO_ADV_DEBUG
	/*
	 * Although this is not a callback, it still does have to balance
	 * with the buf_queue op. So update this counter manually.
	 */
	vb->cnt_buf_done++;
#endif
	dprintk(q, 4, "done processing on buffer %d, state: %s\n",
		vb->index, vb2_state_name(state));

	if (state != VB2_BUF_STATE_QUEUED)
		__vb2_buf_mem_finish(vb);      //finish on buffer's private memory to sync caches,这里调用了vb2_queue->mem_ops->finish,最终执行函数为 vb2_cma_sg_finish(取决于vb2_queue->mem_ops的初始化)

	spin_lock_irqsave(&q->done_lock, flags);       //获取自旋锁,保存中断标志
	if (state == VB2_BUF_STATE_QUEUED) {
		vb->state = VB2_BUF_STATE_QUEUED;
	} else {
		/* Add the buffer to the done buffers list */
		list_add_tail(&vb->done_entry, &q->done_list);      //new entry to be added done_list
		vb->state = state;
	}
	atomic_dec(&q->owned_by_drv_count);        //驱动缓冲区的数量减去1

	if (state != VB2_BUF_STATE_QUEUED && vb->req_obj.req) {
		media_request_object_unbind(&vb->req_obj);
		media_request_object_put(&vb->req_obj);
	}

	spin_unlock_irqrestore(&q->done_lock, flags);         //释放自旋锁,恢复中断标志
    trace_vb2_buf_done(q, vb);

	switch (state) {
	case VB2_BUF_STATE_QUEUED:
		return;
	default:
		/* Inform any processes that may be waiting for buffers */
		wake_up(&q->done_wq);     //唤醒等待该缓冲区的进程,如果video_device->fops->poll = vb2_fop_poll, vb2_fop_poll中会收到通知(poll_wait捕获状态)
		break;
	}
}

vb2_buffer_done 在v4l2驱动中至关重要,比如isp硬件出来的图像都需要通过vb2_buffer_done送入videobuf2.

在涉及视频缓冲区处理的多媒体编程中,`vb2_buffer_done` 是 Video4Linux2 (V4L2) 框架中的一个关键函数。它通常用于标记一个缓冲区的操作已经完成,并将缓冲区返回给用户空间或重新排队以供下一次使用。这个函数常出现在 V4L2 驱动程序或与视频采集、流媒体传输相关的开发中。 `vb2_buffer_done` 的基本用法是传递一个 `struct vb2_buffer` 指针和一个状态标志,表示缓冲区操作的结果。例如: ```c vb2_buffer_done(vb, VB2_BUF_STATE_DONE); ``` 其中 `vb` 是指向缓冲区的指针,`VB2_BUF_STATE_DONE` 表示该缓冲区已经成功完成数据填充[^1]。如果出现错误,可以传递 `VB2_BUF_STATE_ERROR` 来通知框架缓冲区处理失败。 ### 常见问题与调试建议 1. **未正确初始化缓冲区** 在调用 `vb2_buffer_done` 之前,必须确保缓冲区已通过 `vb2_core_prepare_buffer` 或类似函数正确初始化。否则可能导致内核崩溃或不可预测的行为。 2. **重复调用 `vb2_buffer_done`** 如果对同一个缓冲区多次调用此函数而有重新排队,可能会导致资源泄漏或竞争条件。每个缓冲区在完成之后应被重新入队,或者仅在确认不再需要时释放。 3. **状态参数选择错误** 使用错误的状态标志(如误将 `VB2_BUF_STATE_QUEUED` 作为参数)会导致缓冲区状态机进入非法状态。应当根据实际处理结果选择 `VB2_BUF_STATE_DONE`、`VB2_BUF_STATE_ERROR` 或其他合法状态。 4. **同步问题** 多线程环境下,特别是中断服务例程中调用 `vb2_buffer_done` 时,需确保与主控逻辑的同步。可使用自旋锁(spinlock)或其他同步机制防止并发访问问题。 5. **未处理异常情况** 若在缓冲区处理过程中发生硬件错误(如 DMA 超时),应在捕获异常后调用 `vb2_buffer_done` 并传入 `VB2_BUF_STATE_ERROR`,以便上层应用及时响应并恢复[^1]。 6. **内存管理不当** 确保缓冲区所占用的内存区域在整个生命周期内有效。尤其在异步模式下,驱动可能在任意时刻访问这些缓冲区。 ### 示例代码片段 以下是一个典型的 V4L2 驱动中使用 `vb2_buffer_done` 的场景: ```c static void my_video_irq_handler(struct v4l2_subdev *sd) { struct vb2_buffer *vb = get_next_ready_buffer(); if (!vb) { pr_err("No buffer available to complete"); return; } /* 标记缓冲区为已完成 */ vb2_set_plane_payload(vb, 0, received_data_size); vb2_buffer_done(vb, VB2_BUF_STATE_DONE); } ``` 上述代码模拟了一个中断处理函数,在接收到一帧完整图像后,标记当前缓冲区为“已完成”。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值