本文共 21184 字,大约阅读时间需要 70 分钟。
记录下linux v4l2相关知识。
1. v4l2 - Video For Linux 2 version.
即内核中关于视频(audio, radio其实也可以用) 处理的驱动框架。
常见如摄像头采集, 编解码器等 都可以用v4l2框架。
2. 用户态编程
网络上有很多相关文档。
和大部分linux设备驱动一样, 用户态主要操作有
open, close, read, write, mmap, ioctl等等操作。
通常编写v4l2应用有如下流程。
1) open打开设备
2) ioctl - VIDIOC_QUERYCAP - 获取设备能力 (capture或者output等)
3). 格式, 帧率等相关
ioctl - VIDIOC_ENUM_FMT - 枚举设备支持的格式 (yuyv, mjpeg, h264等)
ioctl - VIDIOC_G_FMT
ioctl - VIDIOC_S_FMT
ioctl - VIDIOC_G_PARM
ioctl - VIDIOC_S_PARM
4). 申请帧缓存
ioctl - VIDIOC_REQBUFS - 申请几个帧缓存, 用户输出
5). 将分配的内存映射到用户态
VIDIOC_QUERYBUF - 查询buf信息
mmap - 将申请的内存映射到用户态
6). queue buffer
VIDIOC_QBUF 将内存 放入 video 设备内部队列
7). 打开码流
VIDIOC_STREAMON
8). dequeue buffer
VIDIOC_DQBUF 后去处理完的数据
9). 用户态对dequeue的buffer进行处理 (如显示, 存储, 传输等)
10). queue buffer - 把内存返还给video设备
3. 内核态驱动
内核态驱动有一套v42 驱动框架
和大部分设备驱动框架类似,
主要为 初始化设备结构体, 注册video设备到v4l2-core核心, 即可...
故其中最重要的函数为
video_register_device
函数原型:
static inline int __must_check video_register_device(struct video_device *vdev,
› › int type, int nr)
我们就从它开始, 向v4l2-core核心注册的设备是怎么样的?
/* * Newer version of video_device, handled by videodev2.c * ›This version moves redundant code from video device code to *› the common handler */ struct video_device { #if defined(CONFIG_MEDIA_CONTROLLER) › struct media_entity entity; #endif › /* device ops */ › const struct v4l2_file_operations *fops; › /* sysfs */ › struct device dev;› › /* v4l device */ › struct cdev *cdev;› › /* character device */ › struct v4l2_device *v4l2_dev;› /* v4l2_device parent */ › /* Only set parent if that can't be deduced from v4l2_dev */ › struct device *dev_parent;› /* device parent */ › /* Control handler associated with this device node. May be NULL. */ › struct v4l2_ctrl_handler *ctrl_handler; › /* vb2_queue associated with this device node. May be NULL. */ › struct vb2_queue *queue; › /* Priority state. If NULL, then v4l2_dev->prio will be used. */ › struct v4l2_prio_state *prio; › /* device info */ › char name[32]; › int vfl_type;› /* device type */ › int vfl_dir;› /* receiver, transmitter or m2m */ › /* 'minor' is set to -1 if the registration failed */ › int minor; › u16 num; › /* use bitops to set/clear/test flags */ › unsigned long flags; › /* attribute to differentiate multiple indices on one physical device */ › int index; › /* V4L2 file handles */ › spinlock_t› › fh_lock; /* Lock for all v4l2_fhs */ › struct list_head› fh_list; /* List of struct v4l2_fh */ › int debug;› › › /* Activates debug level*/ › /* Video standard vars */ › v4l2_std_id tvnorms;› › /* Supported tv norms */ › /* callbacks */ › void (*release)(struct video_device *vdev); › /* ioctl callbacks */ › const struct v4l2_ioctl_ops *ioctl_ops; › DECLARE_BITMAP(valid_ioctls, BASE_VIDIOC_PRIVATE); › /* serialization lock */ › DECLARE_BITMAP(disable_locking, BASE_VIDIOC_PRIVATE); › struct mutex *lock; };
video_device是一个怎样的设备, 上面就给出了很多描述
如
1). v4l2_file_opeations - v4l2的文件操作集, 即open, read, write, close, poll, select, ioctl等
2). device, cdev结构体, v4l2是一个字符设备
3). v4l2_device *v4l2_dev, 和上述一样, 是更common的一种描述, 有点继承的味道...
4). v4l2_cltr_handler *ctlr_handler, 控制句柄
5). vb2_queue *queue, 内部使用的vb2_queue队列 (此为v4l2和v4l的一个区别, 以前v4l的版本使用video_queue结构体)
6). release, 设备被释放后的callback函数
7). v4l2_ioctl_ops *ioctl_ops, 具体的ioctl的操作集合(如query_caps, enum_fmt, s_fmt, g_fmt等)
转载地址:http://cpcrj.baihongyu.com/