V4L2程式設計 轉

2021-05-23 11:25:18 字數 4338 閱讀 7194

前言:目前正在忙於arm

平台的linux

應用程式的開發(其實是剛剛起步學習啦)。底層的東西不用考慮了,開發板子提供了

nand bootloader

,和linux 2.6

的原始碼,而且都編譯好了。自己編譯的

bootloader

可以用,但是

linux

編譯後,檔案很大,暫且就用人家編譯的系統,先專心寫應用程式 吧。。

正文:要做的任務是,把一塊板子上的攝像頭採集的影象和聲卡採集的聲音(貌似很囉嗦哈)通過tcp/ip

lcdv4l2

的api。一.

什麼是video4linux

video4linux2(簡稱

v4l2),

是linux

linux

/dev/video0

下。二. 1.

int fd=open(

」/dev/video0

″,o_rdwr);

2.取得裝置的

capability

,或者音訊輸入輸出等。

vidioc_querycap,struct v4l2_capability

vidioc_s_input,struct v4l2_input

pal,

ntsc

,幀的格式個包括寬度和高度等。

vidioc_s_std,vidioc_s_fmt,struct v4l2_std_id,struct v4l2_format

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

struct v4l2_requestbuffers

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

mmap

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

.vidioc_qbuf,struct v4l2_buffer

vidioc_streamon

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

vidioc_dqbuf

10.將緩衝重新入佇列尾

,這樣可以迴圈採集。

vidioc_qbuf

vidioc_streamoff

close(fd);

三、常用的結構體(

參見/usr/include/linux/videodev2.h)

:struct v4l2_requestbuffers reqbufs;//向驅動申請幀緩衝的請求,裡面包含申請的個數

pal,

ntsc

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

struct v4l2_buffer buf;//代表驅動中的一幀

v4l2_std_pal_b

struct v4l2_queryctrl query;//查詢的控制

struct v4l2_control control;//具體控制的值

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

在v4l2

open

函式開啟這個裝置:

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

intcamerafd;

camerafd

open

(「/dev/video0

″o_rdwr

o_nonblock

, 0);

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

//camerafd = open(」

/dev/video0

″, o_rdwr, 0);

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

)裡的東西返回給應用程式。

設定屬性及採集方式

程式設計中,一般使用

ioctl

函式來對裝置的

i/o通道進行管理:

extern int

ioctl

(int

__fd

unsigned long int

__request

…__throw;

__fd:裝置的

id,例如剛才用

open

camerafd

;__request:具體的命令標誌符。

在進行v4l2

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

vidioc_reqbufs:分配記憶體

vidioc_querybuf:把

vidioc_reqbufs

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

vidioc_querycap:查詢驅動功能

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

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

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

vidioc_cropcap:查詢驅動的修剪能力

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

vidioc_dqbuf:把資料放回快取佇列

pal或

ntsc

。這些io

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

在亞洲,一般使用pal

(720x576

)制式的攝像頭,而歐洲一般使用

ntsc

(720x480

),使用

vidioc_querystd

來檢測:

v4l2_std_id std;

do 分配記憶體

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。

處理採集資料

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程式設計例項

include include include include include include include include include include include include include include define req buf num 4 申請的緩衝區個數,最多5個,緩衝區...