struct V4l2_device/video_device/v4l2_buffer/v4l2_subdev/ Video for Linux Two
阿新 • • 發佈:2019-01-31
V4L2核心API提供了一套標準方法的用於處理視訊緩衝器(稱為“videobuf”)。這些方法允許驅動程式以一致的方式來實現read(),mmap()和overlay()。目前使用的裝置上的視訊緩衝器,支援scatter/gather方法(videobuf-dma-SG),線性存取的DMA的(videobuf-DMA-contig),vmalloc分配的緩衝區,主要用於在USB驅動程式(DMA緩衝區的方法videobuf-vmalloc)。
videobuf層的功能為一種V4L2驅動和使用者空間之間的粘合層。它可以處理儲存視訊幀緩衝區的分配和管理。有一組可用於執行許多標準的POSIX I / O系統呼叫的功能,包括read(),poll()的,happily,mmap()。另一套功能可以用來實現大部分的V4L2的ioctl()呼叫相關的流式I/ O的,包括緩衝區分配,排隊和dequeueing,流控制。驅動作者使用videobuf規定了一些設計決定,但回收期在驅動器和一個V4L2的使用者空間API的貫徹實施在減少程式碼的形式。
關於videobuf的層的更多資訊,請參閱Documentation/video4linux/videobuf
V4l2驅動架構
所有的驅動程式有以下結構:
1) 每個裝置包含裝置狀態的例項結構。
2) 子裝置的初始化和命令方式(如果有).
3) 建立V4L2的裝置節點 (/dev/videoX, /dev/vbiX and /dev/radioX)和跟蹤裝置節點的具體資料。
4)檔案控制代碼特定的結構,包含每個檔案控制代碼資料;
5) 視訊緩衝處理。
驅動原始碼分析
vivi.c 虛擬視訊驅動程式----- 此程式碼模擬一個真正的視訊裝置V4L2 API (位於drivers/media/video目錄下)
入口:+int __init vivi_init(void)
+ vivi_create_instance(i) /*建立裝置*//**/。
+ 分配一個vivi_dev的結構體 /*它巢狀這結構體v4l2_device 和video_device*/
+ v4l2_device_register(NULL, &dev->v4l2_dev);/*註冊vivi_dev中的V4l2_device*/
+ 初始化視訊的DMA佇列
+ 初始化鎖
+ video_device_alloc(); 動態分配video_device結構體
+ 構建一個video_device結構體 vivi_template 並賦給上面分配的video_device
static struct video_device vivi_template = {
. name = "vivi",
.fops = &vivi_fops,
.ioctl_ops = &vivi_ioctl_ops,
.minor = -1,
.release = video_device_release,
.tvnorms = V4L2_STD_525_60,
.current_norm = V4L2_STD_NTSC_M,
};
+ video_set_drvdata(vfd, dev);設定驅動程式專有資料
+ 所有控制元件設定為其預設值
+ list_add_tail(&dev->vivi_devlist, &vivi_devlist);新增到裝置列表
+ 構建 v4l2_file_operations 結構體vivi_fops 並實現.open .release .read .poll .mmap函式----- .ioctl 用標準的v4l2控制處理程式
+ 構建 v4l2_ioctl_ops結構體 vivi_ioctl_ops
static const struct v4l2_ioctl_ops vivi_ioctl_ops = {
.vidioc_querycap = vidioc_querycap,
.vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
.vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
.vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
.vidioc_reqbufs = vidioc_reqbufs,
.vidioc_querybuf = vidioc_querybuf,
.vidioc_qbuf = vidioc_qbuf,
.vidioc_dqbuf = vidioc_dqbuf,
.vidioc_s_std = vidioc_s_std,
.vidioc_enum_input = vidioc_enum_input,
.vidioc_g_input = vidioc_g_input,
.vidioc_s_input = vidioc_s_input,
.vidioc_queryctrl = vidioc_queryctrl,
.vidioc_g_ctrl = vidioc_g_ctrl,
.vidioc_s_ctrl = vidioc_s_ctrl,
.vidioc_streamon = vidioc_streamon,
.vidioc_streamoff = vidioc_streamoff,
#ifdef CONFIG_VIDEO_V4L1_COMPAT
.vidiocgmbuf = vidiocgmbuf,
#endif
};
+ int vivi_open(struct file *file)
+ vivi_dev *dev = video_drvdata(file); 訪問驅動程式專用資料
+ 分配+初始化控制代碼(vivi_fh)資料
+ 重置幀計數器
+ videobuf_queue_vmalloc_init(); 初始化視訊緩衝佇列
+ 開啟一個新執行緒用於開始和暫停
+ 實現自定義的v4l2_ioctl_ops 函式
videobuf層的功能為一種V4L2驅動和使用者空間之間的粘合層。它可以處理儲存視訊幀緩衝區的分配和管理。有一組可用於執行許多標準的POSIX I / O系統呼叫的功能,包括read(),poll()的,happily,mmap()。另一套功能可以用來實現大部分的V4L2的ioctl()呼叫相關的流式I/ O的,包括緩衝區分配,排隊和dequeueing,流控制。驅動作者使用videobuf規定了一些設計決定,但回收期在驅動器和一個V4L2的使用者空間API的貫徹實施在減少程式碼的形式。
關於videobuf的層的更多資訊,請參閱Documentation/video4linux/videobuf
V4l2驅動架構
所有的驅動程式有以下結構:
1) 每個裝置包含裝置狀態的例項結構。
2) 子裝置的初始化和命令方式(如果有).
3) 建立V4L2的裝置節點 (/dev/videoX, /dev/vbiX and /dev/radioX)和跟蹤裝置節點的具體資料。
4)檔案控制代碼特定的結構,包含每個檔案控制代碼資料;
5) 視訊緩衝處理。
驅動原始碼分析
vivi.c 虛擬視訊驅動程式----- 此程式碼模擬一個真正的視訊裝置V4L2 API (位於drivers/media/video目錄下)
入口:+int __init vivi_init(void)
+ vivi_create_instance(i) /*建立裝置*//**/。
+ 分配一個vivi_dev的結構體 /*它巢狀這結構體v4l2_device 和video_device*/
+ v4l2_device_register(NULL, &dev->v4l2_dev);/*註冊vivi_dev中的V4l2_device*/
+ 初始化視訊的DMA佇列
+ 初始化鎖
+ video_device_alloc(); 動態分配video_device結構體
+ 構建一個video_device結構體 vivi_template 並賦給上面分配的video_device
static struct video_device vivi_template = {
. name = "vivi",
.fops = &vivi_fops,
.ioctl_ops = &vivi_ioctl_ops,
.minor = -1,
.release = video_device_release,
.tvnorms = V4L2_STD_525_60,
.current_norm = V4L2_STD_NTSC_M,
};
+ video_set_drvdata(vfd, dev);設定驅動程式專有資料
+ 所有控制元件設定為其預設值
+ list_add_tail(&dev->vivi_devlist, &vivi_devlist);新增到裝置列表
+ 構建 v4l2_file_operations 結構體vivi_fops 並實現.open .release .read .poll .mmap函式----- .ioctl 用標準的v4l2控制處理程式
+ 構建 v4l2_ioctl_ops結構體 vivi_ioctl_ops
static const struct v4l2_ioctl_ops vivi_ioctl_ops = {
.vidioc_querycap = vidioc_querycap,
.vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
.vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
.vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
.vidioc_reqbufs = vidioc_reqbufs,
.vidioc_querybuf = vidioc_querybuf,
.vidioc_qbuf = vidioc_qbuf,
.vidioc_dqbuf = vidioc_dqbuf,
.vidioc_s_std = vidioc_s_std,
.vidioc_enum_input = vidioc_enum_input,
.vidioc_g_input = vidioc_g_input,
.vidioc_s_input = vidioc_s_input,
.vidioc_queryctrl = vidioc_queryctrl,
.vidioc_g_ctrl = vidioc_g_ctrl,
.vidioc_s_ctrl = vidioc_s_ctrl,
.vidioc_streamon = vidioc_streamon,
.vidioc_streamoff = vidioc_streamoff,
#ifdef CONFIG_VIDEO_V4L1_COMPAT
.vidiocgmbuf = vidiocgmbuf,
#endif
};
+ int vivi_open(struct file *file)
+ vivi_dev *dev = video_drvdata(file); 訪問驅動程式專用資料
+ 分配+初始化控制代碼(vivi_fh)資料
+ 重置幀計數器
+ videobuf_queue_vmalloc_init(); 初始化視訊緩衝佇列
+ 開啟一個新執行緒用於開始和暫停
+ 實現自定義的v4l2_ioctl_ops 函式