theme: awesome-green

1.应用层关闭视频流

enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;if (ioctl(fd, VIDIOC_STREAMOFF, &type) < 0)
{printf("ERR(%s):VIDIOC_STREAMOFF failed\n", __func__);return -1;
}

2.驱动层关闭视频流

调用平台关闭视频流驱动接口vidioc_streamoff

  • vidioc_streamoff
  • vb2_ioctl_streamoff
  • vb2_streamoff
int vb2_ioctl_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
{struct video_device *vdev = video_devdata(file);/*return vdev->queue->owner && vdev->queue->owner != file->private_data;*/if (vb2_queue_is_busy(vdev, file))return -EBUSY;return vb2_streamoff(vdev->queue, i);
}int vb2_streamoff(struct vb2_queue *q, enum v4l2_buf_type type)
{/*return q->fileio*/if (vb2_fileio_is_active(q)) {dprintk(1, "file io in progress\n");return -EBUSY;}return vb2_internal_streamoff(q, type);
}
  • vidioc_streamoff
  • vb2_ioctl_streamoff
  • vb2_streamoff
  • vb2_internal_streamoff
static int vb2_internal_streamoff(struct vb2_queue *q, enum v4l2_buf_type type)
{/*如果传下来的type与vb2_queue的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 = !V4L2_TYPE_IS_OUTPUT(q->type);dprintk(3, "successful\n");return 0;
}*** __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.*/
static void __vb2_queue_cancel(struct vb2_queue *q)
{unsigned int i;/** Tell driver to stop all transactions and release all queued* buffers.*//** 如果q->start_streaming_called = 1(在streaming_on中置为1)* 调用平台平台stop_streaming,*/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().*//* owned_by_drv_count变量* __enqueue_in_driver 函数里面进行inc加操作 * vb2_buffer_done 函数里面会进行 dec减操作* 理想情况下,这个值为0* 当不为0的话,说明还有buffer在被驱动操作,没有存入数据* 也就是没有执行vb2_buffer_done*/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));}//将各种状态置为0q->streaming = 0;q->start_streaming_called = 0;q->queued_count = 0;q->error = 0;/** Remove all buffers from videobuf's list...* 将所有的buffer从队列上移除*/INIT_LIST_HEAD(&q->queued_list);/** ...and done list; userspace will not receive any buffers it* has not already dequeued before initiating cancel.*/INIT_LIST_HEAD(&q->done_list);atomic_set(&q->owned_by_drv_count, 0);/*唤醒等待q->done_wq的进程*/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_internal_dqbuf() there is a critical* call to __fill_v4l2_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) {struct vb2_buffer *vb = q->bufs[i];/** 取出所有vb2_buffer,并且* 如果vb->state != VB2_BUF_STATE_DEQUEUED* 那么将vb->state = VB2_BUF_STATE_PREPARED* 调用buf_finish,这里没有实现不分析*/if (vb->state != VB2_BUF_STATE_DEQUEUED) {vb->state = VB2_BUF_STATE_PREPARED;call_void_vb_qop(vb, buf_finish, vb);}/*将vb->state置为VB2_BUF_STATE_DEQUEUED*/__vb2_dqbuf(vb);}
}static void __vb2_dqbuf(struct vb2_buffer *vb)
{struct vb2_queue *q = vb->vb2_queue;unsigned int i;/* nothing to do if the buffer is already dequeued *///如果vb->state == VB2_BUF_STATE_DEQUEUED,返回,不成立if (vb->state == VB2_BUF_STATE_DEQUEUED)return;//将vb->state置为VB2_BUF_STATE_DEQUEUEDvb->state = VB2_BUF_STATE_DEQUEUED;/* unmap DMABUF buffer *///如果q->memory类型为DMA,调用平台的unmap_dmabuf函数if (q->memory == V4L2_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;}
}
  • vidioc_streamoff
  • vb2_ioctl_streamoff
  • vb2_streamoff
  • vb2_internal_streamoff
  • stop_streaming
  • xvip_dma_stop_streaming
static void xvip_dma_stop_streaming(struct vb2_queue *vq)
{struct xvip_dma *dma = vb2_get_drv_priv(vq);struct xvip_pipeline *pipe = to_xvip_pipeline(&dma->video.entity);struct xvip_dma_buffer *buf, *nbuf;/* Stop the pipeline. *//*调用所有器件的stop_stream函数,如CSI,Sensor*/xvip_pipeline_set_stream(pipe, false);/* Stop and reset the DMA engine. 停止DMA传输*/dmaengine_terminate_all(dma->dma);/* Cleanup the pipeline and mark it as being stopped. */xvip_pipeline_cleanup(pipe);media_entity_pipeline_stop(&dma->video.entity);/* Give back all queued buffers to videobuf2. */spin_lock_irq(&dma->queued_lock);/*取出所有的vb2_buffer buf*并且唤醒等待进程*删除buffer的vb2_queue*/list_for_each_entry_safe(buf, nbuf, &dma->queued_bufs, queue) {vb2_buffer_done(&buf->buf, VB2_BUF_STATE_ERROR);list_del(&buf->queue);}spin_unlock_irq(&dma->queued_lock);
}void vb2_buffer_done(struct vb2_buffer *vb, enum vb2_buffer_state state)
{struct vb2_queue *q = vb->vb2_queue;unsigned long flags;unsigned int plane;//当vb->state不等于VB2_BUF_STATE_ACTIVE打印堆栈状态,并返回错误if (WARN_ON(vb->state != VB2_BUF_STATE_ACTIVE))return;/*如果state != VB2_BUF_STATE_DONE &&*     state != VB2_BUF_STATE_ERROR &&*       state != VB2_BUF_STATE_QUEUED* 打印堆栈状态,并且将state置为VB2_BUF_STATE_ERROR*/if (WARN_ON(state != VB2_BUF_STATE_DONE &&state != VB2_BUF_STATE_ERROR &&state != VB2_BUF_STATE_QUEUED))state = VB2_BUF_STATE_ERROR;#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++;
#endifdprintk(4, "done processing on buffer %d, state: %d\n",vb->v4l2_buf.index, state);/* sync buffers * 同步buffer*/for (plane = 0; plane < vb->num_planes; ++plane)call_void_memop(vb, finish, vb->planes[plane].mem_priv);/* Add the buffer to the done buffers list */spin_lock_irqsave(&q->done_lock, flags);vb->state = state;/**如果state != VB2_BUF_STATE_QUEUED*把vb->done_entry挂载到q->done_list链表上*/if (state != VB2_BUF_STATE_QUEUED)list_add_tail(&vb->done_entry, &q->done_list);//减少q->owned_by_drv_countatomic_dec(&q->owned_by_drv_count);spin_unlock_irqrestore(&q->done_lock, flags);/*如果state == VB2_BUF_STATE_QUEUED,返回*/if (state == VB2_BUF_STATE_QUEUED)return;/*唤醒等待队列进程*//* Inform any processes that may be waiting for buffers */wake_up(&q->done_wq);
}

V4L2框架-视频流的停止(VIDIOC_STREAMOFF)相关推荐

  1. V4L2框架分析学习

    Author:CJOK Contact:cjok.liao#gmail.com SinaWeibo:@廖野cjok 1.概述 Video4Linux2是Linux内核中关于视频设备的内核驱动框架,为上 ...

  2. V4L2框架分析学习二

    转载于:http://www.techbulo.com/1198.html v4l2_device v4l2_device在v4l2框架中充当所有v4l2_subdev的父设备,管理着注册在其下的子设 ...

  3. 二十四、V4L2框架主要结构体分析和虚拟摄像头驱动编写

    一.V4L2框架主要结构体分析 V4L2(video for linux version 2),是内核中视频设备的驱动框架,为上层访问视频设备提供统一接口. V4L2整体框架如下图: 图中主要包括两层 ...

  4. 嵌入式Linux驱动笔记(十八)------浅析V4L2框架之ioctl【转】

    转自:https://blog.csdn.net/Guet_Kite/article/details/78574781 权声明:本文为 风筝 博主原创文章,未经博主允许不得转载!!!!!!谢谢合作 h ...

  5. V4L2框架-videobuf2

    阅读原文 本文介绍在 v4l2 框架之下的数据流交互的实现与使用,主要目的是实现一个能够进行用户空间与内核空间进行数据交互.数据流格式设置.数据流 buffer 申请与释放.数据流开启与关闭的 vid ...

  6. 摄像头驱动--V4L2框架

    总体框架分析 简单的字符设备驱动的框架 复杂的字符设备驱动程序框架 采用分层的思想,例如前面学习的LCD驱动程序,内核已经将构造file_operation结构体,注册字符设备驱动register_c ...

  7. Linux v4l2框架分析

    背景 说明: Kernel版本:4.14 ARM64处理器,Contex-A53,双核 使用工具:Source Insight 3.5, Visio 1. 概述 V4L2(Video for Linu ...

  8. [Linux 基础] -- V4L2 框架 - control

    本文介绍在 v4l2 框架下面的 control 控制接口,这些接口通常用来实现一些特效控制.菜单控制等等. 一.简介 既然涉及到视频输入,就会有很多与 ISP 相关的效果,比如对比度.饱和度.色温. ...

  9. 深入理解l内核v4l2框架之video for linux 2(一)

    在看了很多关于v4l2驱动的例程之后,想深入研究下linux内核的v4l2框架,顺便把这些记录下来,以备查用. Video for Linux 2 随着一些视频或者图像硬件的复杂化,V4L2驱动也越来 ...

最新文章

  1. Python 开发者 2017 应该关注的 7 个类库
  2. wordpress mysql缓存_WordPress 对象缓存与数据库缓存
  3. 【MySQL】Java.sql.SQLException Incorrect string value: \xF0\x9F\x98\x8D\xE8\xBE...
  4. html中怎么不让网页缩放_网页中的形状图形都是怎么画出来的?
  5. php mysql合同跟踪,使用TCP协议进行路由跟踪
  6. Asp.net can do Native Code also can do it(updated)
  7. 一天一个小技巧(2)——CSDN编译器的首行缩进2字符
  8. 由input type=file /获取的file.type为空字符串引申浏览器是如何获取文件的MIME类型...
  9. 提高办公效率的方法-工具篇
  10. android系统证书管理,抓包Android 7.0+将ca证书导入到系统(设置为系统证书)
  11. 自己写的一个GPS卫星地图
  12. django+layui表格数据管理
  13. 基于OpenGL的Android系统视频转换功能实现
  14. Impala 4.0 启用 LZO
  15. 单片机看门狗c语言,单片机看门狗程序
  16. python正则表达式中括号的用法_Python的正则表达式中的圆括号到底如何使用?
  17. 盐城北大青鸟植树节丨迎接春天,种下美好
  18. c语言运行不显示图片,为何加载烟花就换了一句,将图片加载进资源,结果运行中烟花不显示...
  19. 快消产品客户运营线上营销指南
  20. 性能优化——Android热修复技术,类加载机制详解

热门文章

  1. OpenCV批量读取路径下所有图片
  2. 国产Linux系统下替代QQ和微信的不二之选
  3. 爬虫大作业-爬取B站弹幕
  4. ios html5 app上架,H5封装的IOS应用上架App Store被拒怎么办
  5. 【采样算法】拉丁超立方采样
  6. ElasticSearch深入浅出
  7. Syn-QG: Syntactic and Shallow S emantic Rules for Question Generation阅读笔记
  8. 控件、组件和插件的区别
  9. 一个新手的评价---人机交互方面(有些不搭题
  10. 【NOIP2015】洛谷2668 斗地主