1、常用的結構體在核心目錄include/linux/videodev2.h中定義
2、常用的ioctl介面命令也在include/linux/videodev2.h中定義
3、操作流程
v4l2提供了很多訪問介面,你可以根據具體需要選擇操作方法。需要注意的是,很少有驅動完全實現了所有的介面功能。所以在使用時需要參考驅動原始碼,或仔細閱讀驅動提供者的使用說明。
下面列舉出一種操作的流程,供參考。
(1)開啟裝置檔案
int fd = open(devicename,mode);
devicename:/dev/video0、/dev/video1 ……
mode:o_rdwr [| o_nonblock]
(2)取得裝置的capability
struct v4l2_capability capability;
int ret = ioctl(fd, vidioc_querycap, &capability);
struct v4l2_input input;
……初始化input
int ret = ioctl(fd, vidioc_querycap, &input);
v4l2_std_id std;
do while (ret == -1 && errno == eagain);
switch (std)
struct v4l2_format fmt;
fmt.type = v4l2_buf_type_video_output;
fmt.fmt.pix.pixelformat = v4l2_pix_fmt_uyvy;
fmt.fmt.pix.height = height;
fmt.fmt.pix.width = width;
fmt.fmt.pix.field = v4l2_field_interlaced;
ret = ioctl(fd, vidioc_s_fmt, &fmt);
if(ret)
(6)向驅動申請幀快取
struct v4l2_requestbuffers req;
if (ioctl(fd, vidioc_reqbufs, &req) == -1)
(7)獲取每個快取的資訊,並mmap到使用者空間
typedef struct videobuffer videobuffer;
videobuffer* buffers = calloc( req.count, sizeof(*buffers) );
struct v4l2_buffer buf;
for (numbufs = 0; numbufs < req.count; numbufs++)
buffers[numbufs].length = buf.length;
// 轉換成相對位址
buffers[numbufs].start = mmap(null, buf.length,
prot_read | prot_write,
map_shared,
fd, buf.m.offset);
if (buffers[numbufs].start == map_failed)
int buf_type= v4l2_buf_type_video_capture;
int ret = ioctl(fd, vidioc_streamon, &buf_type);
(9)取出fifo快取中已經取樣的幀快取
struct v4l2_buffer buf;
memset(&buf,0,sizeof(buf));
buf.type=v4l2_buf_type_video_capture;
buf.memory=v4l2_memory_mmap;
buf.index=0;//此值由下面的ioctl返回
if (ioctl(fd, vidioc_dqbuf, &buf) == -1)
(10)將剛剛處理完的緩衝重新入佇列尾,這樣可以迴圈採集
if (ioctl(fd, vidioc_qbuf, &buf) == -1)
int ret = ioctl(fd, vidioc_streamoff, &buf_type);
close(fd);
四、 v4l2驅動框架
上述流程的各個操作都需要有底層v4l2驅動的支援。核心中有一些非常完善的例子。
1、v4l2驅動註冊、登出函式
video核心層(drivers/media/video/videodev.c)提供了註冊函式
int video_register_device(struct video_device *vfd, int type, int nr)
video_device: 要構建的核心資料結構
type: 表示裝置型別,此裝置號的基位址受此變數的影響
nr: 如果end-base>nr>0 :次裝置號=base(基準值,受type影響)+nr;
否則:系統自動分配合適的次裝置號
具體驅動只需要構建video_device結構,然後呼叫註冊函式既可。
如:zc301_core.c中的
err = video_register_device(cam->v4ldev, vfl_type_grabber,
video_nr[dev_nr]);
video核心層(drivers/media/video/videodev.c)提供了登出函式
void video_unregister_device(struct video_device *vfd)
2、struct video_device 的構建
strcpy(cam->v4ldev->name, "zc0301[p] pc camera");
cam->v4ldev->owner = this_module;
cam->v4ldev->type = vid_type_capture | vid_type_scales;
cam->v4ldev->fops = &zc0301_fops;
cam->v4ldev->minor = video_nr[dev_nr];
cam->v4ldev->release = video_device_release;
video_set_drvdata(cam->v4ldev, cam);
大家發現在這個zc301的驅動中並沒有實現struct video_device中的很多操作函式,如:vidioc_querycap、vidioc_g_fmt_cap等。主要原因是struct file_operations zc0301_fops中的zc0301_ioctl實現了前面的所有ioctl操作。所以就不需要在struct video_device再實現struct video_device中的那些操作了。
另一種實現方法如下:
static struct video_device camif_dev =
;static struct file_operations camif_fops =
;注意:video_ioctl2是videodev.c中是實現的。video_ioctl2中會根據ioctl不同的cmd來呼叫video_device中的操作方法。
3、video核心層的實現
參見核心/drivers/media/videodev.c
static int __init videodev_init(void)
ret = class_register(&video_class);……}
(2)v4l2驅動註冊函式的實現
int video_register_device(struct video_device *vfd, int type, int nr)
/* 計算出次裝置號 */
mutex_lock(&videodev_lock);
if (nr >= 0 && nr < end-base)
} else
從上面的註冊函式中可以看出v4l2驅動的註冊事實上只是完成了裝置節點的建立,如:/dev/video0。和video_device結構指標的儲存。
int fd = open(/dev/video0, o_rdwr);
對應/dev/video0的檔案操作結構是/drivers/media/videodev.c中定義的video_fops。
static const struct file_operations video_fops=
;奇怪吧,這裡只實現了open操作。那麼後面的其它操作呢?還是先看看video_open吧。
static int video_open(struct inode *inode, struct file *file)
}old_fops = file->f_op;
file->f_op = fops_get(vfl->fops);//替換此開啟檔案的file_operation結構。後面的其它針對此檔案的操作都由新的結構來負責了。也就是由每個具體的video_device的fops負責。
if(file->f_op->open)
err = file->f_op->open(inode,file);
if (err) ……}
以上是我對v4l2的一些理解,希望能對大家了解v4l2有一些幫助!
V4L2 API及資料結構
1 常用的結構體在核心目錄include linux videodev2.h中定義 structv4l2 requestbuffers 申請幀緩衝,對應命令vidioc reqbufs structv4l2 format 幀的格式,對應命令vidioc g fmt vidioc s fmt等 str...
V4L2 API及資料結構
1 常用的結構體在核心目錄include linux videodev2.h中定義 struct v4l2 requestbuffers 申請幀緩衝,對應命令vidioc reqbufs struct v4l2 format 幀的格式,對應命令vidioc g fmt vidioc s fmt等 s...
v4l2的結構體之v4l2 device
乙個硬體裝置可能包含多個子裝置,比如乙個電視卡除了有capture裝置,可能還有vbi裝置或者fm tunner。而v4l2 device就是所有這些裝置的根節點,負責管理所有的子裝置,可將該抽象為soc的資料採集器,如csi mipi isp等soc的控制器。struct v4l2 device ...