你好,游客 登录 注册 搜索
背景:
阅读新闻

V4L(Video for Linux)使用摄像头实验笔记

[日期:2012-12-31] 来源:Linux社区  作者:ddddwant [字体: ]

前言

学习Linux快1个月了,Linux教学视频看完了,然后在虚拟机上装了个CentOS6.3把该做的实验大多也做了。突然就想玩玩刚买来的蓝魔USB摄像头(型号M2200),我给自己定了个计划,先写个摄像头驱动再写个应用层上面与图像有关的随便什么程序。

正文

1,先是驱动,我在想USB摄像头的话USB总线协议部分Linux应该已经有了,我只要基于这个USB总线协议上增加一层摄像头的通信协议就可以了。于是我就想把我的摄像头拆了看看里面用的是什么芯片,结果没有舍得拆,于是我干脆先到淘宝网物品信息部分看看有没有我的M2200所用芯片信息,结果查出了芯片供应商是中星微但具体芯片型号没有,我舍不得拆,怎么办。我突然想起来我的摄像头是免驱的,既然windows都自带它的驱动,就说明芯片那边使用的协议一定也是符合某个标准的。上于是在网上捣鼓了一下,我靠,有好多论文和论坛都在讲关于USB摄像头驱动,居然有这么多人在玩摄像头,看来我落伍了。看着看着我渐渐的明白了,原来有个V4L(video for Linux)协议,果不其然。既然Linux都已经自带了摄像头驱动,那我就不写了。但是我要看看我的CentOS6.3有没有集成摄像头驱动,我把摄像头插上,windows给我自动安装程序,安装完了,好像又安装了一个vmware usb device什么东东。不管它(后来才知道windows关机后再启动虚拟机就不会安装vmware usb device了,要设置下:虚拟机->可移动设备->usb设备上钩一下),然后再lsmod | grep video下就能看到uvcvideo、videodev之类的模块如图1,用ll /dev命令也就能看到video0这个设备文件了如图2。

图1

图2

2,应用层,上网搜一搜,天啦,也有好多程序,很给力,看来我有了很好的学习材料,先给出一些传送门http://www.linuxidc.com/Linux/2012-12/77159.htm(这位叫d_south的朋友总结了网上的USB摄像头程序然后给出了自己的想法和源程序,我就是借鉴的这个,稍微改一下能通过gcc编译),还有人把网上的程序搜集到一块了,比如http://www.linuxidc.com/Linux/2012-12/77160.htm,好多好多,我不一一例举了。我把d_south的程序一个字母一个字母的用gedit编译器敲进去,形成了如下的程序。

v4l.h头文件

#ifndef _V4L_H_
#define _V4L_H_

#include <stdio.h>
#include <stdlib.h> //stdio.h and stdlib.h are needed by perror function
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h> //O_RDWR
#include <unistd.h>
#include <sys/mman.h> //unistd.h and sys/mman.h are needed by mmap function
#include <stdbool.h>//false and true
#include <sys/ioctl.h>
#include <linux/videodev.h>//v4l API

typedef struct _v4l_struct
{
 int fd;
 struct video_capability capability;
 struct video_picture picture;
 struct video_mmap mmap;
 struct video_mbuf mbuf;
 unsigned char *map;
 int frame_current;
 int frame_using[VIDEO_MAX_FRAME];
}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_get_picture(v4l_device*);
extern int v4l_get_mbuf(v4l_device*);
extern int v4l_set_picture(v4l_device*,int,int,int,int,int);
extern int v4l_grab_picture(v4l_device*,unsigned int);
extern int v4l_mmap_init(v4l_device*);
extern int v4l_grab_init(v4l_device*,int,int);
extern int v4l_grab_frame(v4l_device*,int);
extern int v4l_grab_sync(v4l_device*);

#define DEFAULT_DEVICE "/dev/video0"

int v4l_open(char *dev,v4l_device *vd)
{
 if(!dev)
 dev=DEFAULT_DEVICE;
 if((vd->fd=open(dev,O_RDWR))<0)
 {
  perror("v4l_open fail");
  return -1;
 
 }
 if(v4l_get_capability(vd))
  return -1;
 printf("video capture device name:%s\n",vd->capability.name);
 if(v4l_get_picture(vd))
  return -1;
 printf("frames number is %d\n",vd->mbuf.frames);
 return 0;
}

int v4l_close(v4l_device *vd)
{
 munmap(vd->map,vd->mbuf.size);
 close(vd->fd);
 return 0;
}

int v4l_get_capability(v4l_device *vd)
{
 if(ioctl(vd->fd,VIDIOCGCAP,&vd->capability)<0)
 { 
  perror("v4l_get_capability fail");
  return -1;
 }
 return 0; 
}

int v4l_get_picture(v4l_device *vd)
{
 if(ioctl(vd->fd,VIDIOCGPICT,&vd->picture)<0)
 {
  perror("v4l_get_picture fail");
  return -1;
 }
 return 0;
}

int v4l_get_mbuf(v4l_device *vd)
{
 if(ioctl(vd->fd,VIDIOCGMBUF,&vd->mbuf)<0)
 {
  perror("v4l_get_mbuf fail");
  return -1;
 }
 return 0;
}

int v4l_set_picture(v4l_device *vd,int br,int hue,int col,int cont,int white)
{
 if(br)
  vd->picture.brightness=br;
 if(hue)
  vd->picture.hue=hue;
 if(col) 
  vd->picture.colour=col;
 if(cont)
  vd->picture.contrast=cont;
 if(white)
  vd->picture.whiteness=white;
 if(ioctl(vd->fd,VIDIOCSPICT,&vd->picture)<0)
 {
  perror("v4l_set_picture fail");
  return -1;
 }
 return 0;
}

int v4l_grab_picture(v4l_device *vd,unsigned int size)
{
 if(read(vd->fd,vd->map,size)==0)
 return -1;
 return 0;
}

int v4l_mmap_init(v4l_device *vd)
{
 if(v4l_get_mbuf(vd)<0)
  return -1;
 if((vd->map=(unsigned char*)mmap(0,vd->mbuf.size,PROT_READ|PROT_WRITE,MAP_SHARED,vd->fd,0))<0)
 {
  perror("v4l_mmap_init fail");
  return -1;
 }
 return 0;
}

int v4l_grab_init(v4l_device *vd,int width,int height)
{
 vd->mmap.width=width;
 vd->mmap.height=height;
 vd->mmap.format=vd->picture.palette;
 vd->frame_current=0;
 vd->frame_using[0]=false;
 vd->frame_using[1]=false;
 return v4l_grab_frame(vd,0);
}

int v4l_grab_frame(v4l_device *vd,int frame)
{
 if(vd->frame_using[frame])
 {
  fprintf(stderr,"v4l_grab_frame %d is already used\n",frame);
  return -1;
 }
 vd->mmap.frame=frame;
 if(ioctl(vd->fd,VIDIOCMCAPTURE,&vd->mmap)<0)
 {
 
  perror("v4l_grab_frame fail");
 
  return -1;
 
 }
 vd->frame_using[frame]=true;
 vd->frame_current=frame;
 return 0;
}

int v4l_grab_sync(v4l_device *vd)
{
 if(ioctl(vd->fd,VIDIOCSYNC,&vd->frame_current)<0)
 { 
  perror("v4l_grab_sync fail");
  return -1;
 }
 vd->frame_using[vd->frame_current]=false;
 return 0;
}

#endif

linux
相关资讯       V4L  Video for Linux  video4linux 
本文评论   查看全部评论 (0)
表情: 表情 姓名: 字数

       

评论声明
  • 尊重网上道德,遵守中华人民共和国的各项有关法律法规
  • 承担一切因您的行为而直接或间接导致的民事或刑事法律责任
  • 本站管理人员有权保留或删除其管辖留言中的任意内容
  • 本站有权在网站内转载或引用您的评论
  • 参与本评论即表明您已经阅读并接受上述条款