intvb2_core_streamoff(structvb2_queue*q,unsignedint type){if(type != q->type){dprintk(1,"invalid stream type\n");return-EINVAL;}/*
* Cancel will pause streaming and remove all buffers from the driver
* and videobuf, effectively returning control over them to userspace.
*
* Note that we do this even if q->streaming == 0: if you prepare or
* queue buffers, and then call streamoff without ever having called
* streamon, you would still expect those buffers to be returned to
* their normal dequeued state.
*/__vb2_queue_cancel(q);
q->waiting_for_buffers =!q->is_output;
q->last_buffer_dequeued = false;dprintk(3,"successful\n");return0;}EXPORT_SYMBOL_GPL(vb2_core_streamoff);
3.2 __vb2_queue_cancel函数
/**
* __vb2_queue_cancel() - cancel and stop (pause) streaming
*
* Removes all queued buffers from driver's queue and all buffers queued by
* userspace from videobuf's queue. Returns to state after reqbufs.
*/staticvoid__vb2_queue_cancel(structvb2_queue*q){unsignedint i;/*
* Tell driver to stop all transactions and release all queued
* buffers.
*/if(q->start_streaming_called)call_void_qop(q, stop_streaming, q);/*
* If you see this warning, then the driver isn't cleaning up properly
* in stop_streaming(). See the stop_streaming() documentation in
* videobuf2-core.h for more information how buffers should be returned
* to vb2 in stop_streaming().
*/if(WARN_ON(atomic_read(&q->owned_by_drv_count))){for(i =0; i < q->num_buffers;++i)if(q->bufs[i]->state == VB2_BUF_STATE_ACTIVE)vb2_buffer_done(q->bufs[i], VB2_BUF_STATE_ERROR);/* Must be zero now */WARN_ON(atomic_read(&q->owned_by_drv_count));}// 重置各种数据成员
q->streaming =0;
q->start_streaming_called =0;
q->queued_count =0;
q->error =0;// 清空queued_list/*
* Remove all buffers from videobuf's list...
*/INIT_LIST_HEAD(&q->queued_list);// 清空done_list/*
* ...and done list; userspace will not receive any buffers it
* has not already dequeued before initiating cancel.
*/INIT_LIST_HEAD(&q->done_list);//设置owned_by_drv_count为0atomic_set(&q->owned_by_drv_count,0);// 唤醒等待线程/*
* 可能如下?
* 1.其他应用在使用poll
* 2.其他应用在dqbuf
*/wake_up_all(&q->done_wq);/*
* Reinitialize all buffers for next use.
* Make sure to call buf_finish for any queued buffers. Normally
* that's done in dqbuf, but that's not going to happen when we
* cancel the whole queue. Note: this code belongs here, not in
* __vb2_dqbuf() since in vb2_core_dqbuf() there is a critical
* call to __fill_user_buffer() after buf_finish(). That order can't
* be changed, so we can't move the buf_finish() to __vb2_dqbuf().
*/for(i =0; i < q->num_buffers;++i){structvb2_buffer*vb = q->bufs[i];if(vb->state == VB2_BUF_STATE_PREPARED ||
vb->state == VB2_BUF_STATE_QUEUED){unsignedint plane;for(plane =0; plane < vb->num_planes;++plane)call_void_memop(vb, finish,
vb->planes[plane].mem_priv);}if(vb->state != VB2_BUF_STATE_DEQUEUED){
vb->state = VB2_BUF_STATE_PREPARED;call_void_vb_qop(vb, buf_finish, vb);}__vb2_dqbuf(vb);}}
3.2 __vb2_dqbuf函数
/**
* __vb2_dqbuf() - bring back the buffer to the DEQUEUED state
*/staticvoid__vb2_dqbuf(structvb2_buffer*vb){structvb2_queue*q = vb->vb2_queue;unsignedint i;// 检查状态是否为出队列了/* nothing to do if the buffer is already dequeued */if(vb->state == VB2_BUF_STATE_DEQUEUED)return;//设置出队列状态VB2_BUF_STATE_DEQUEUED
vb->state = VB2_BUF_STATE_DEQUEUED;//unmap 释放内存/* unmap DMABUF buffer */if(q->memory == VB2_MEMORY_DMABUF)for(i =0; i < vb->num_planes;++i){if(!vb->planes[i].dbuf_mapped)continue;call_void_memop(vb, unmap_dmabuf, vb->planes[i].mem_priv);
vb->planes[i].dbuf_mapped =0;}}