v4l程式設計基礎

2021-06-03 00:33:52 字數 4002 閱讀 2130

我們都知道,在linux中,為了遮蔽使用者對裝置訪問的複雜性,採用了裝置檔案,即可以通過

像訪問普通檔案一樣的方式來對裝置進行訪問讀寫。電視卡在linux中和印表機,滑鼠一樣,屬於字元

裝置。其主裝置號是81,在實際操作上,訪問控制電視卡也和一般的裝置檔案沒有什麼不同。用open

開啟裝置,

int fd;

fd = open("/dev/video0",o_rdwr);

用一系列的ioctl發命令控制裝置。v4l支援的ioctl命令大概有二十幾個,為了盡快的編出乙個

簡單的圖象捕捉程式,讓我們先來看看幾個主要的命令:

1. ioctl(fd,vidiocgcap,&cap);

該命令主要是為了獲取電視卡的功能資訊。例如電視卡的名稱,型別,channel等。引數cap是

乙個結構,當ioctl命令返回時,結構的各成員就被賦值了,結構體的定義為:

struct video_capability

;channel 指的是有幾個訊號輸入源,例如television,composite,s-video等。

2.ioctl(fd,vidiocgchan,&vc)

3.ioctl(fd,vidiocschan.&vc)

這兩個命令用來取得和設定電視卡的channel資訊,例如使用那個輸入源,制式等。

vc 是乙個video_channel 結構,其定義為:

struct video_capability

;struct video_channel

;成員channel代表輸入源,通常,0: television 1:composite1 2:s-video

name 表示該輸入源的名稱。

norm 表示制式,通常,0:pal 1:ntsc 2:secam 3:auto

4. ioctl(fd,vidiocgmbuf,*mbuf)

獲得電視卡快取的資訊,引數mbuf是video_mbuf結構。其定義如下:

struct video_mbuf

;size是快取的大小,frames表明該電視卡的快取可以容納的幀數,陣列offsets則表明

對應一幀的起始位置,0幀對應offsets[0],1幀對應offsets[1]....

執行完該命令後,就可以用mmap函式將快取對映到記憶體中了。大致用法可以參考以下的代

碼struct video_mbuf mbuf;

unsigned char *buf1,*buf2;

if(ioctl(fd,vidiocgmbuf,&mbuf)<0)

printf("the frame number is %d\n",mbuf.frames);

buf1 = (unsigned char*)mmap(0,mbuf.size,prot_read|prot_write,map_shared,fd.0);

buf1 = buf1 + mbuf.offset[0];

buf2 = buf1 + mbuf.offset[1];//當然,如果mbuf.frames=1,就不需要下面的了。

......

5. ioctl(fd.vidiocmcapture,&mm)

啟動硬體去捕捉圖象,mm 是video_mmap 結構,設定捕捉圖象需要設定的資訊。結構體

如下定義:

struct video_mmap

;frame :設定當前是第幾幀

height,width:設定圖象的高和寬。

format :顏色模式

要注意的是,該命令是非阻塞的,也就是說,它僅僅設定了硬體,而不負責是否捕捉到圖象。

要確定是否捕捉到圖象,要用到下乙個命令。

6. ioctl(fd,vidiocsync,&frame)

等待捕捉到這一幀圖象。frame 是要等待的圖象,它的值應和上乙個命令中設定的frame相對應。

開始實際程式的編寫吧。

下面我們會編乙個程式,將捕捉到的圖象存為jpeg檔案。為此,還要向大家介紹乙個函式,

int write_jpeg(char *filename,unsigned char *buf,int quality,int width, int height, int gray)

cinfo.err = jpeg_std_error(&jerr);

jpeg_create_compress(&cinfo);

jpeg_stdio_dest(&cinfo, fp);

cinfo.image_width  = width;

cinfo.image_height = height;

cinfo.input_components = gray ? 1: 3;

cinfo.in_color_space = gray ? jcs_grayscale: jcs_rgb;

jpeg_set_defaults(&cinfo);

jpeg_set_quality(&cinfo, quality, true);

jpeg_start_compress(&cinfo, true);

line_length = gray ? width : width * 3;

for (i = 0, line = buf; i < height; i++, line += line_length)

jpeg_write_scanlines(&cinfo, &line, 1);

jpeg_finish_compress(&(cinfo));

jpeg_destroy_compress(&(cinfo));

fclose(fp);

return 0;

}這個函式很通用,它的作用是把buf中的資料壓縮成jpeg格式。

/*         下面是乙個完整的程式 test.c

*           gcc test.c -o test -ljpeg

*/#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#define width  320

#define height 240

#define v4l_device "/dev/video0"

main()

if(ioctl(fd, vidiocgcap, &vcap)<0)

fprintf(stderr,"video capture device name : %s\n",vcap.name);

for(i=0;ifprintf(stderr,"video source (%d) name : %s\n",i, vc.name);

}vc.channel =1;

vc.norm=1;

if(ioctl(fd, vidiocschan, &vc) < 0)

if(ioctl(fd, vidiocgmbuf, &mbuf) < 0)

fprintf(stderr,"the frames number is %d\n",mbuf.frames); 

buf = (unsigned char*)mmap(0, mbuf.size, prot_read|prot_write, map_shared, fd, 0);

if((int)buf < 0)

mm.frame  = 0;

mm.height = height;

mm.width  = width;

mm.format = video_palette_rgb24;

if(ioctl(fd, vidiocmcapture, &mm)<0)

if(ioctl(fd, vidiocsync, &mm.frame)<0)

if(-1 == (write_jpeg("./pic001.jpeg",buf,75,width,height,0)))

munmap(buf,mbuf.size);

close(fd);

}

V4L基礎概念

1.video4linux基礎相關 1.1 v4l的介紹與一些基礎知識的介紹 i.首先說明一下video4linux v4l ii.linux系統中的檔案操作 1.2 建立一套簡單的v4l函式庫 這裡先給出接下來將要開發出來函式的乙個總覽。相關結構體和函式的定義我們就放到乙個名為v4l.h的檔案中,...

V4L 簡介及其與V4L2區別

由於早期的 v4l 有很多缺陷,bill dirks 等人對其進行了重新設計,並取名為video for linux 2 v4l2使用 最早出現於linux2.5.x 版本。v4l2 相比於v4l 有更好的擴充套件性和靈活性,並且支援的硬體裝置更多。因此在應用程式v4l程式設計實際是指v4l2,我們...

V4L2程式設計

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