免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 985 | 回复: 0
打印 上一主题 下一主题

V4L接口 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-09-12 11:49 |只看该作者 |倒序浏览

用一系列的ioctl发命令控制设备。v4l支持的ioctl命令大概有二十几个,为了尽快的编出一个简单的图象捕捉程序,让我们先来看看几个主要的命令:1. ioctl(fd,VIDIOCGCAP,&cap);
   该命令主要是为了获取电视卡的功能信息。例如电视卡的名称,类型,channel等。参数cap是一个结构,当ioctl命令返回时,结构的各成员就被赋值了,结构体的定义为:struct video_capability{char name[32];int type;int channels; /* Num channels */int audios; /* Num audio devices */int maxwidth; /* Supported width */int maxheight; /* And height */int minwidth; /* Supported width */int minheight; /* And height */};channel 指的是有几个信号输入源,例如television,composite,s-video等。2.ioctl(fd,VIDIOCGCHAN,&vc)3.ioctl(fd,VIDIOCSCHAN.&vc)这两个命令用来取得和设置电视卡的channel信息,例如使用那个输入源,制式等。vc 是一个video_channel结构,其定义为:struct video_capability{char name[32];int type;int channels; /* Num channels */int audios; /* Num audio devices */int maxwidth; /* Supported width */int maxheight; /* And height */int minwidth; /* Supported width */int minheight; /* And height */};struct video_channel{int channel;char name[32];int tuners;//number of tuners for this input__u32   flags;__u16   type; __u16 norm; };成员channel代表输入源,通常,0: television 1:composite1 2:s-videoname 表示该输入源的名称。norm 表示制式,通常,0:pal 1:ntsc 2:secam 3:auto4. ioctl(fd,VIDIOCGMBUF,*mbuf)获得电视卡缓存的信息,参数mbuf是video_mbuf结构。其定义如下:struct video_mbuf{int size; /* Total memory to map */int frames; /* Frames */int offsets[VIDEO_MAX_FRAME];};size是缓存的大小,frames表明该电视卡的缓存可以容纳的帧数,数组offsets则表明对应一帧的起始位置,0帧对应offsets[0],1帧对应offsets[1]....执行完该命令后,就可以用mmap函数将缓存映射到内存中了。大致用法可以参考以下的代码struct video_mbuf mbuf;unsigned char *buf1,*buf2;if(ioctl(fd,VIDIOCGMBUF,&mbuf){perror("VIDIOCGMBUF");return -1;}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{unsigned int frame; /* Frame (0 - n) for double buffer */int height,width;unsigned int format; /* should be VIDEO_PALETTE_* */};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){struct jpeg_compress_struct cinfo;struct jpeg_error_mgr jerr;FILE *fp;int i;unsigned char *line;int line_length;if (NULL == (fp = fopen(filename,"w"))) {fprintf(stderr,"grab: can't open %s: %s\n",filename,strerror(errno));return -1;}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 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(){unsigned char* buf;int i,j;int fd;int re;struct video_capability vcap;struct video_channel vc;struct video_mbuf    mbuf;struct video_mmap    mm;fd = open(V4L_DEVICE, O_RDWR);if(fd{   perror("open");     exit(1);}if(ioctl(fd, VIDIOCGCAP, &vcap){     perror("VIDIOCGCAP");     exit(1);}fprintf(stderr,"Video Capture Device Name : %s\n",vcap.name);for(i=0;i{     vc.channel = i;     if(ioctl(fd, VIDIOCGCHAN, &vc)     {   perror("VIDIOCGCHAN");   exit(1);     }     fprintf(stderr,"Video Source (%d) Name : %s\n",i, vc.name);}vc.channel =1;vc.norm=1;if(ioctl(fd, VIDIOCSCHAN, &vc) {     perror("VIDIOCSCHAN");     exit(1);}   if(ioctl(fd, VIDIOCGMBUF, &mbuf)    {perror("VIDIOCGMBUF");exit(1);   }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 {     perror("mmap");     exit(1);}mm.frame   = 0;mm.height = HEIGHT;mm.width   = WIDTH;mm.format = VIDEO_PALETTE_RGB24;if(ioctl(fd, VIDIOCMCAPTURE, &mm){     perror("VIDIOCMCAPTURE");exit(1);}if(ioctl(fd, VIDIOCSYNC, &mm.frame){     perror("VIDIOCSYNC");     exit(1);}if(-1 == (write_jpeg("./pic001.jpeg",buf,75,WIDTH,HEIGHT,0))){printf("write_jpeg error\n");exit(1);}munmap(buf,mbuf.size);close(fd);}

本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u3/99873/showart_2050884.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP