Video4linux编程_第1页
Video4linux编程_第2页
Video4linux编程_第3页
Video4linux编程_第4页
Video4linux编程_第5页
已阅读5页,还剩5页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、Video4linux 编程2.1 Video4linux 简介Video4Linux 是为市场现在常见的电视捕获卡和并口及USB 口的摄像头提供统一的编程接口。同时也提供无线电通信和文字电视广播解码和垂直消隐的数据接口。本文主要针对USB 摄像头设备文件/dev/video0 ,进行视频图像采集方面的基于 Video4Linux 的 USB 摄像头图像采集实现戴小鼠 daily3- 4 -程序设计。2.2 Video4linux 编程指南1 .视频编程的流程( 1 )打开视频设备:( 2)读取设备信息( 3)更改设备当前设置(可以不做)( 4)进行视频采集,两种方法:a.内存映射b.直接从设

2、备读取( 5)对采集的视频进行处理( 6)关闭视频设备。定义的数据结构及使用函数struct _v4l_structint fd;struct video_capability capability;struct video_buffer buffer;struct video_window window;struct video_channel channel8;struct video_picture picture;struct video_mmap mmap;struct video_mbuf mbuf;unsigned char *map;typedef struct _v4l_st

3、ruct v4l_device;extern int v4l_open(char *, v4l_device *);extern int v4l_close(v4l_device *);extern int v4l_get_capability(v4l_device *);extern int v4l_set_norm(v4l_device *, int);extern int v4l_get_picture(v4l_device *);extern int v4l_grab_init(v4l_device *, int, int);extern int v4l_grab_frame(v4l_

4、device *, int);extern int v4l_grab_sync(v4l_device *);extern int v4l_mmap_init(v4l_device *);基于 Video4Linux 的 USB 摄像头图像采集实现戴小鼠 daily3- 5 -extern int v4l_get_mbuf(v4l_device *);extern int v4l_get_picture(v4l_device *);extern int v4l_grab_picture(v4l_device *, unsigned int);extern int v4l_set_buffer(v

5、4l_device *);extern int v4l_get_buffer(v4l_device *);extern int v4l_switch_channel(v4l_device *, int);3.Video4linux 支持的数据结构及其用途( 1 ) video_capability 包含设备的基本信息(设备名称、支持的最大最小分辨率、信号源信息等)name32 设备名称maxwidthmaxheightminwidthminheightChannels 信号源个数type 是否能 capture , 彩色还是黑白,是否能裁剪等等。值如VID_TYPE_CAPTURE 等( 2)

6、 video_picture 设备采集的图象的各种属性Brightness 065535 huecolourcontrastwhitenessdepth 8 16 24 32palette VIDEO_PALETTE_RGB24 | VIDEO_PALETTE_RGB565|VIDEO_PALETTE_JPEG| VIDEO_PALETTE_RGB32( 3) video_channel 关于各个信号源的属性Channel 信号源的编号nametunersType VIDEO_TYPE_TV | IDEO_TYPE_CAMERANorm 制式 PAL|NSTC|SECAM|AUTO( 4) v

7、ideo_window 包含关于 capture area的信息x x windows 中的坐标.y y windows 中的坐标.width The width of the image capture.height The height of the image capture.chromakey A host order RGB32 value for the chroma key.基于 Video4Linux 的 USB 摄像头图像采集实现戴小鼠 daily3- 6 -flags Additional capture flags.clips A list of clipping rec

8、tangles. (Set only)clipcount The number of clipping rectangles. (Set only)( 5) video_mbuf 利用 mmap 进行映射的帧的信息size 每帧大小Frames 最多支持的帧数Offsets 每帧相对基址的偏移( 6) video_mmap 用于 mmap4.关键步骤介绍【注】接多个摄像头。方法如下:买一个 usb hub接到开发板的usb host上。cat/proc/devices 可以知道 video capture device 的 major 是 81, 再 ls T /dev 看至U videoO

9、的次设备号是0。两个摄像头当然要两个设备号,所以mknod /dev/video1 c 81 1 ,如果接 4 个,就 mknod /dev/video2 c 81 2,mknod /dev/video3 c 81 3 。依次类推。( 1 )打开视频:int v4l_open(char *dev, v4l_device *vd)if (!dev)dev = ” /dev/video0 ”;if (vd ->fd = open(dev, O_RDWR) fd, VIDIOCGCAP, &(vd->capability) capability 各分量基于 Video4Linux

10、 的 USB 摄像头图像采集实现戴小鼠 daily3- 7 -( 3)读 video_picture 中信息int v4l_get_picture(v4l_device *vd)if (ioctl(vd ->fd, VIDIOCGPICT, &(vd->picture) picture.colour = 65535; if(ioctl(vd->fd, VIDIOCSPICT, &(vd->picture) capability 中的信息 int v4l_get_channels(v4l_device *vd) int i;for (i = 0; i ca

11、pability.channels; i+) vd ->channel .channel = i;if (ioctl(vd ->fd, VIDIOCGCHAN, &(vd->channel) fd);return 0;基于 Video4Linux 的 USB 摄像头图像采集实现戴小鼠 daily3- 8 -重点:截取图象的两种方法一、用mmap (内存映射)方式截取视频mmap( )系统调用使得进程之间通过映射同一个普通文件实现共享内存。普通文件被映射到进程地址空间后,进程可以向访问普通内存一样对文件进行访问,不必再调用read(), write ()等操作。两个不同

12、进程A、B共享内存的意思是,同一块物理内存被映射到进程A、 B 各自的进程地址空间。进程A 可以即时看到进程 B 对共享内存中数据的更新,反之亦然。采用共享内存通信的一个显而易见的好处是效率高,因为进程可以直接读写内存,而不需要任何数据的拷贝( 1 )设置 picture 的属性(2)初始化video_mbuf,以得到所映射的buffer的信息ioctl(vd->fd, VIDIOCGMBUF , &(vd->mbuf)( 3)可以修改video_mmap 和帧状态的当前设置( 4)将mmap 与 video_mbuf 绑定void* mmap ( void * addr

13、, size_t len , int prot , int flags , int fd , off_t offset )len:映射到调用进程地址空间的字节数,它从被映射文件开头offset个字节开始算起Prot:指定共享内存的访问权限 PROT_READ (可读),PROT_WRITE (可写): PROT_EXEC (可执行)Flags: MAP_SHARED MAP_PRIVATE 中必选一个,MAP_ FIXED 不推荐使用Addr:共内存享的起始地址,一般设0,表示由系统分配Mmap( ) 返回值是系统实际分配的起始地址int v4l_mmap_init(v4l_device *v

14、d) if (v4l_get_mbuf(vd) map = mmap(0, vd->mbuf.size, PROT_READ|PROT_WRITE,MAP_SHARED, vd->fd, 0) fd, VIDIOCMCAPTURE, &(vd->mmap) ;若调用成功,开始一帧的截取,是非阻塞的,是否截取完毕留给VIDIOCSYNC 来判断( 6)调用VIDIOCSYNC 等待一帧截取结束if(ioctl(vd->fd, VIDIOCSYNC, &frame) map + vd->mbuf.offsetsvd->frame 得到。采集工作结

15、束后调用munmap 取消绑定munmap(vd->map, vd->mbuf.size)在实际应用时还可以采用缓冲队列等方式。二、视频截取的第二种方法:直接读设备关于缓冲大小,图象等的属性须由使用者事先设置调用 read();int read (要访问的文件描述符;指向要读写的信息的指针;应该读写的字符数);返回值为实际读写的字符数int len ;unsigned char*vd->map=(unsigned char *) malloc(vd ?capability.maxwidth*vd ?capability.maxheight );len = read(vd ?f

16、d,vd ? vd->map,vd?capability.maxwidth*vd ?capability.maxheight*3 );基于 Video4Linux 的 USB 摄像头图像采集实现戴小鼠 daily3- 10 -2.3 编程实例(mouse_capture)不管是 ov511 还是 zc301 的摄像头,它们采集的方式都是相同的,只不过采集到的数据有所差异,ov511 的就是 rgb 的位流,而zc301 是 jpeg 编码的位流。mouse_capture是根据servfox改编的一个专门从zc301摄像头获取一张jpeg图片,用来测试摄像头是否加载成功的小程序。这样就可

17、以不用cat /dev/video0>1.jpg 来测试摄像头是否正常。cat 命令一运行,就源源不断地采集jpeg 流。但是采到的图片只能显示第一个jpeg 头和 jpeg 尾之间的数据。mouse_capture 仅仅获得一张完整的 jpeg。 可以从()处下载参考。现将主要函数的功能介绍如下:static int GetVideoPict (struct vdIn *vd);/ 获取图片属性信息。static int SetVideoPict (struct vdIn *vd);/ 设置图片属性。static int isSpcaChip (const char *BridgeNa

18、me);/ 测试芯片类型static int GetStreamId (const char *BridgeName); / 测试输出数据的格式static int GetDepth (int format);/ 获取颜色深度。void exit_fatal(char *messages);/ 错误显示。int init_videoIn(struct vdIn *vd,char *device,int width,int height,int format,int grabmethod);/ 初始化设备。int convertframe(unsigned char *dst,unsigned

19、char *src, int width,int height, intformatIn, int size);/ 把共享缓冲区中的数据放到一个变量中,通知系统已获得一帧。int v4lGrab (struct vdIn *vd,char *filename );/ 从摄像头采集图片。int close_v4l (struct vdIn *vd);/ 关闭摄像头。int get_jpegsize (unsigned char *buf, int insize);/ 获取 jpeg 图片大小。三 实例程序3.1 LCD 实时显示从ov511 上采集的图像参考 HHARM9-EDU/applica

20、tions/usbcam2lcd 。从摄像头获取bmp 位流直接显示在 framebuffer 中。此程序图像的采集采用read 的方式,注意由于lcd 液晶屏显示的是 16bits 的 RGB 图片,所以,ov511 输出的图片格式也应该是16bits 的 RGB 图片数据,宏VIDEO_PALETTE_RGB565定义的就是16bits的RGB数据图片。而linux自带的 ov511 驱动中图像采集是32 位的,这样采集到的图片显示在lcd 上是雪花点。因此需要修改驱动。在kernet/driver/usb/目录下有ov511芯片的驱动ov511.c,驱基于 Video4Linux 的 U

21、SB 摄像头图像采集实现戴小鼠 daily3- 11 -动里的 ov51x_set_default_params 函数是设置芯片默认的输出图片的格式,该函数中的for (i = 0; i frame.width = ov511->maxwidth;ov511->frame.height = ov511->maxheight;ov511->frame.bytes_read = 0;if (force_palette)ov511->frame.format = force_palette;elseov511->frame.format = VIDEO_P ALE

22、TTE_RGB24;ov511->frame.depth = ov511_get_depth(ov511->frame.format);部分语句是主要设置ov511 默认输出图片格式的,其中maxwidth 和 maxheight设置了图片的最大的宽度和高度。Ifelse语句设置了图片的格式,作如下的修改:for (i = 0; i frame.width = ov511->maxwidth;ov511->frame.height = ov511->maxheight;ov511->frame.bytes_read = 0;ov511->frame.f

23、ormat = VIDEO_P ALETTE_RGB565;ov511->frame.depth = ov511_get_depth(ov511->frame.format);如果需要,也可以改变图片的默认输出大小。3.2 LCD 实时显示从zc301 上采集的图像编程思想:从摄像头采集到的图片存放在本地文件夹,通过minigui 加载 jpeg来实现显示。具体过程:1 从网上下载jpegsrc-6b 的 jpeg 库,交叉编译。(1) ./configure -enable-static -enable-shared -prefix=.libs(2)修改Makefile ,将编译

24、器改成交叉编译器。例如:我改成/opt/host/armv4l/bin/armv4l-unknown-linux-gcc( 3) make 后即在 .libs 目录中生成for arm 的libjpeg.a, libjpeg.la,libjpeg.so,libjpeg.so.62,libjpeg.so.62.0.0 。将这些文件拷贝到系基于 Video4Linux 的 USB 摄像头图像采集实现戴小鼠 daily3- 12 -统库文件目录,我的是/usr/lib 中。2 .因为看从zc301采集的图片的二进制位流,jpeg头是ff d8 ff db。而在minigui库文件 libminigu

25、i 的源文件src/mybmp/jpeg.c 中, load_jpg 和 check_jpg 的时候测试的头位 EXIF 和 JFIF 两种格式的jpeg 图片。这两种对应的二进制分别是ff d8 ff e1 和 ff d8ff e0°所以我们minigui通过判断认为这是错误的jpeg格式而不加载,故无法显示。实际上通过测试,在源码中去掉这两个判断就能正确加载。3 .交叉编译minigui(1 ) 编译库:./configure -host=arm-unknown-linux -enable-jpgsupport=yes-enable-pngsupport=no -enable-g

26、ifsupport=no -disable-lite-prefix=/HHARM9-EDU/applications/minigui-free/nfsroot-enable-smdk2410ial=yesmakemake install(2)编译实例程序时,要加上jpeg库的支持,即在Makefile中加上-ljpeg。止匕时将在 nfsroot 生成的库文件和可执行文件移到ramdisk.image.gz 相应的目录下。(具体参考华恒的2410 开发手册)。3 Minigui 程序的编写编程小技巧,我采取的方法是一刻不停地从摄像头采集到图片存储在/tmp/1.jpg 中,在 minigui

27、中通过 loadbitmap 函数来加载图片。而图片加载后不会自动更新,不能自动根据1.jpg 的改变自动变化。因此,我在程序中设定一个timer。每隔100ms刷新屏幕,基本上实现实时更新了。而出现另外一个问题,刷新时会以背景色来填充桌面,导致屏幕闪烁严重。故想到采用MSG_ERASEBKGND 的方式,用前一张图片做为刷新屏幕时的填充背景图片。这样就保证了lcd 上图像的连续性啦。Minigui程序如下:其中一些自定义的函数跟 mouse_capture中的一样,只是变采集单幅到采集多幅。具体您可以自己改一下:) 。也可以向我索取源码。#include#include#include#in

28、clude#include#include "spcav4l.h"#define IDTIMER 100static BITMAP bmp;基于 Video4Linux 的 USB 摄像头图像采集实现戴小鼠 daily3- 13 -static int LoadBmpWinProc(HWND hWnd, int message, WP ARAM wParam, LPARAM lParam) HDC hdc;RECT rc=0,0,240,320;switch (message) case MSG_CREATE:SetTimer(hWnd,IDTIMER,100);retur

29、n 0;case MSG_ERASEBKGND:RECT rcTemp;if( LoadBitmap(HDC_SCREEN,&bmp,"/tmp/1.jpg")printf("load wrong!n");return -1;GetClientRect(hWnd, &rcTemp);hdc = BeginPaint (hWnd);FillBoxWithBitmap (hdc, rcTemp.left, rcTemp.top, rcTemp.right-rcTemp.left, rcTemp.bottom-rcTemp.top, &

30、bmp);EndPaint(hWnd, hdc);return 0;case MSG_TIMER:InvalidateRect(hWnd,&rc,TRUE);return 0;case MSG_CLOSE:UnloadBitmap (&bmp);DestroyMainWindow (hWnd);PostQuitMessage (hWnd);return 0;return DefaultMainWinProc(hWnd, message, wParam, lParam);int MiniGUIMain (int argc, const char* argv)MSG Msg;HWN

31、D hMainWnd;MAINWINCREATE CreateInfo;char videodevice = "/dev/video0"char jpegfile = "/tmp/1.jpg"int grabmethod = 0;基于 Video4Linux 的 USB 摄像头图像采集实现戴小鼠 daily3- 14 -int format = VIDEO_P ALETTE_JPEG;int width = 240;int height = 320;int i;#ifdef _LITE_VERSIONSetDesktopRect(0, 0, 1024, 768);#endifCreateInfo.dwStyle = WS_VISIBLE | WS_BORDER | WS_CAPTION;CreateInfo.dwExStyle = WS

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论