V4L2的學習筆記

2021-05-27 03:08:06 字數 4477 閱讀 9198

學習的時候最好參看官方的v4l2開發文件,是英文,更詳細透徹。

借鑑:一.什麼是

video4linux

1. 開啟裝置檔案。

vidioc_s_std,vidioc_s_fmt,struct v4l2_std_id,struct v4l2_format

5. 向驅動申請幀緩衝,一般不超過5個。

struct v4l2_requestbuffers

6. 將申請到的幀緩衝對映到使用者空間,這樣就可以直接操作採集到的幀了,而不必去複製。

mmap

7. 將申請到的幀緩衝全部入佇列,以便存放採集到的資料

vidioc_streamon

9. 出佇列以取得已採集資料的幀緩衝,取得原始採集資料。

vidioc_dqbuf

10. 將緩衝重新入佇列尾,這樣可以迴圈採集。

close(fd);

三、常用的結構體(參見/usr/include/linux/videodev2.h):

struct v4l2_requestbuffers reqbufs;//

向驅動申請幀緩衝的請求,裡面包含申請的個數

struct v4l2_capability cap;//

struct v4l2_input input; //

struct v4l2_standard std;//

ntsc

struct v4l2_format fmt;//幀的格式,比如寬度,高度等

struct v4l2_buffer buf;//

代表驅動中的一幀

v4l2_std_id stdid;//

v4l2_std_pal_b

struct v4l2_queryctrl query;//查詢的控制

struct v4l2_control control;//

具體控制的值

下面具體說明開發流程(網上找的啦,也在學習麼)

// 用非阻塞模式開啟攝像頭裝置 

int camerafd;  

camerafd = open(「/dev/video0″, o_rdwr | o_nonblock, 0);  

// 如果用阻塞模式開啟攝像頭裝置,上述**變為:

//camerafd = open(」/dev/video0″, o_rdwr, 0);

關於阻塞模式和非阻塞模式

設定屬性及採集方式

extern int

ioctl

(int

__fd, unsigned long int

__request, …) __throw;

__fd

__request

:具體的命令標誌符。

在進行v4l2開發中,一般會用到以下的命令標誌符:

vidioc_reqbufs

:分配記憶體

vidioc_querybuf

:把vidioc_reqbufs中分配的資料快取轉換成實體地址

vidioc_querycap

:查詢驅動功能

vidioc_enum_fmt

vidioc_s_fmt

:設定當前驅動的頻捕獲格式

vidioc_g_fmt

:讀取當前驅動的頻捕獲格式

vidioc_try_fmt

:驗證當前驅動的顯示格式

vidioc_cropcap

:查詢驅動的修剪能力

vidioc_s_crop

vidioc_g_crop

vidioc_qbuf

:把資料從快取中讀取出來

vidioc_dqbuf

:把資料放回快取佇列

vidioc_streamon

vidioc_streamoff

vidioc_querystd

這些io呼叫,有些是必須的,有些是可選擇的。

在亞洲,一般使用pal(720x576)制式的攝像頭,而歐洲一般使用ntsc(720x480),使用vidioc_querystd來檢測:

v4l2_std_id std;  

do  while (ret == -1 && errno == eagain);  

switch (std)  

struct v4l2_format    fmt;  

memset ( &fmt, 0, sizeof(fmt) );  

fmt.type = v4l2_buf_type_video_capture;  

fmt.fmt.pix.width = 720;  

fmt.fmt.pix.height = 576;  

fmt.fmt.pix.pixelformat = v4l2_pix_fmt_yuyv;  

fmt.fmt.pix.field = v4l2_field_interlaced;  

if (ioctl(fd, vidioc_s_fmt, &fmt) == -1)  

v4l2_format

結構體定義如下:

struct v4l2_format  

fmt;  

};  

struct v4l2_pix_format  

;

分配記憶體

struct v4l2_requestbuffers  req;  

if (ioctl(fd, vidioc_reqbufs, &req) == -1)  

v4l2_requestbuffers

定義如下:

struct v4l2_requestbuffers  

;

獲取並記錄快取的物理空間

使用vidioc_reqbufs,我們獲取了req.count個快取,下一步通過呼叫vidioc_querybuf命令來獲取這些快取的位址,然後使用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)   

// 放入快取佇列

if (ioctl(fd, vidioc_qbuf, &buf) == -1)   

}

作業系統一般把系統使用的記憶體劃分成使用者空間和核心空間,分別由應用程式管理和作業系統管理。應用程式可以直接訪問記憶體的位址,而核心空間存放的是 供核心訪問的**和資料,使用者不能直接訪問。v4l2捕獲的資料,最初是存放在核心空間的,這意味著使用者不能直接訪問該段記憶體,必須通過某些手段來轉換地 址。

read

、write方式

:在使用者空間和核心空間不斷拷貝資料,占用了大量使用者記憶體空間,效率不高。

記憶體對映方式:

把裝置裡的記憶體對映到應用程式中的記憶體控制項,直接處理裝置記憶體,這是一種有效的方式。上面的mmap函式就是使用這種方式。

使用者指標模式

:記憶體片段由應用程式自己分配。這點需要在v4l2_requestbuffers裡將memory欄位設定成v4l2_memory_userptr。

處理採集資料

v4l2

struct v4l2_buffer buf;  

memset(&buf,0,sizeof(buf));  

buf.type=v4l2_buf_type_video_capture;  

buf.memory=v4l2_memory_mmap;  

buf.index=0;  

//讀取快取

if (ioctl(camerafd, vidioc_dqbuf, &buf) == -1)  

//重新放入快取佇列

if (ioctl(camerafd, vidioc_qbuf, &buf) == -1) 

close

(camerafd)

還需要使用munmap方法。

V4L2程式設計

include include include include include include include include include include typedef struct buftype buftype user buf int n buffer 0 開啟攝像頭裝置 int ope...

V4L2 程式設計

v4l2程式設計 1.定義 2.工作流程 開啟裝置 檢查和設定裝置屬性 設定幀格式 設定一種輸入輸出方法 緩衝區管理 迴圈獲取資料 關閉裝置。3.裝置的開啟和關閉 include int open const char device name,int flags include int close ...

V4L2程式設計筆記 1

這兩天接到乙個同學的專案,v4l2 qt顯示的,我v4l2先用c語言調出來了,下面是幾篇文章我的筆記 首先是在網上找到的v4l2程式設計框架,v4l2應用程式框架 v4l2 較v4l 有較大的改動,並已成為 2.6的標準介面,函蓋 video dvb fm.多數驅動都在向 v4l2 遷移。更好地了解...