記錄下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等)