V4L2 API及資料結構

2021-06-08 05:47:30 字數 4625 閱讀 5513

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 ...