我們都知道,在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...