⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 grab.c

📁 v4l usb摄像头捕捉图片 linux arm9
💻 C
字号:
#include <stdio.h>
#include <stdlib.h>
#include <error.h>#include <errno.h>
#include <assert.h>
#include <fcntl.h>               
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <unistd.h>
#include <linux/videodev.h>
#include <sys/ioctl.h>#include <string.h>#include <time.h>#include   <jpeglib.h>  
/************可以定义一些常量*********************/

#define PATH "/dev/video0"//#define VIDEO_PALETTE_RGB24 24
#define  WIDTH  320
#define  HEIGHT 240

struct video_struct{
	int fd;                      //////////打开文件的返回值
	unsigned char *map;          /////////映射区的内存起始地址
	struct video_capability capability;
  struct video_picture   picture;
	struct video_window  window;
	struct video_mbuf   mbuf;
	struct video_mmap  mmap;
	int framestat[2];
	int vformat;
	int vheight;
	int vwidth;
}VD;


//参数是路径,打开函数
int V4L_open(struct video_struct *v,char *path,int width,int height,int format);
int V4L_get_capability(struct video_struct *v);
int V4L_get_picture(struct video_struct *v);
int V4L_set_picture(struct video_struct *v);
int V4L_set_window(struct video_struct *v);
int V4L_get_mbuf(struct video_struct *v);
int V4L_set_mmap(struct video_struct *v);
int V4L_memory_map(struct video_struct *v,int);
int V4L_start_get(struct video_struct *,int );
int V4L_sync(struct video_struct *,int );
char *  V4L_get_mapaddress(struct video_struct *v, int );int write_jpeg(char *filename, unsigned char * img, int width, int height, int quality, int gray);
void V4L_close(struct video_struct *);char *gettime(int t);


/*fd是打开设备返回的文件描述符,打开错误返回-1*/
int V4L_open(struct video_struct *v,char *path,int width,int height,int format){ 
	if(v == NULL)
		return -1;
	if(width == 0||height == 0)
		return -1;
      if((v->fd=open(path,O_RDWR,10705))<0)
            return -1;
	v->vformat = format;
	v->vheight = height;
	v->vwidth = width; 
      return 0;
}

/*获取摄像头的基本信息*/
int V4L_get_capability(struct video_struct *v){
	if(ioctl(v->fd ,VIDIOCGCAP, &(v->capability))<0)
       return -1;
    else
       return 0;   
}

/*获取设备采集图像的各种属性 */
int V4L_get_picture(struct video_struct *v){   
    if(ioctl(v->fd,VIDIOCGPICT,&(v->picture))<0)	
        return -1;
    else
        return 0;
}

/*设置设备的属性*/ //先为分量赋新值,再调用VIDIOCSPICT
int V4L_set_picture(struct video_struct *v){
//	v->picture.colour = 65535;
//	v->picture.hue = 0;//////;//	v->picture.depth = 8;
	/*
    __u16	brightness;
	__u16	hue;
	__u16	colour;
	__u16	contrast;
	__u16	whiteness;	// Black and white only 
	__u16	depth;		// Capture depth 
	__u16   palette;
	*/
    if(ioctl(v->fd,VIDIOCSPICT,&(v->picture))<0)
        return -1;
    else 	
        return 0;
}

/*设置capture area的信息,window(不知道用不用设置这个)*/
int V4L_set_window(struct video_struct *v){
    /*
	__u32	x,y;		// Position of window 
	__u32	width,height;		// Its size 
	__u32	chromakey;
	__u32	flags;
	*/	v->window.width = WIDTH;	v->window.height = HEIGHT;
	if(ioctl(v->fd, VIDIOCSWIN, &(v->window))<0)
		return -1;
	else
		return 0;
}

/*查询实际可用的缓存数*/
int V4L_get_mbuf(struct video_struct *v){   
    if(ioctl(v->fd, VIDIOCGMBUF, &(v->mbuf))<0)
        return -1;
    else  
        return 0;
}

/*修改video_mmap中的设置*/
int V4L_set_mmap(struct video_struct *v){    
	  v->mmap.width = WIDTH;//v->window.width;
    v->mmap.height = HEIGHT;//v->window.height;
    v->mmap.format = VIDEO_PALETTE_RGB24;      v->mmap.frame = 0;
	  /*
    unsigned	int frame;		// Frame (0 - n) for double buffer 
	int		height,width;
	unsigned	int format;		// should be VIDEO_PALETTE_* 
      */
  //    mmap->frame=0;
      return 0;            //返回0时设置成功
}

/*设备文件映射到内存*/
int V4L_memory_map(struct video_struct *v,int size){ //size should be VIDEO_MBUF.size
     v->map=(unsigned char *)mmap(NULL,size,PROT_READ|PROT_WRITE,MAP_SHARED,v->fd,0);
    if(v->map==MAP_FAILED)    //MAP_FAILEN == -1 ,错误原因在errno中
         return -1;
    else  
         return 0;
}


//开始捕获影像数据
int V4L_start_get(struct video_struct *v,int frame){
	v->mmap.frame = frame;
	if(ioctl(v->fd,VIDIOCMCAPTURE,&(v->mmap))<0){printf("kkkkkkkkkkkkkkkkkkkkkkk\n");
		exit(-1);
		return -1;
		
	}
	v->framestat[frame] = 1;
	return 0;
}
//同步
int V4L_sync(struct video_struct *v,int frame){
	if(ioctl(v->fd, VIDIOCSYNC, &frame)<0){printf("sync##########################\n");//;asldjfal;sdjfl;asjdfl;ajsdl;jflajsdfjin
		exit(-1);
		return -1;
	}
	v->framestat[frame] = 0;
	return 0;
}

/*获取mmap的地址*/

 char* V4L_get_mapaddress(struct video_struct *v,int frame){    
     char *frameaddress=NULL;
     frameaddress=v->map+v->mbuf.offsets[frame];
     if(frameaddress>0){
      printf("frameadress is %p\n",frameaddress);
      return  frameaddress;
     }
   else 
       return NULL;
}   
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 ((fp = fopen(filename,"w")) == NULL )    {                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 < height; i++, line += line_length)        jpeg_write_scanlines(&cinfo, &line, 1);       jpeg_finish_compress(&(cinfo));    jpeg_destroy_compress(&(cinfo));    fclose(fp);    return 0;}
/*关闭*/
void V4L_close(struct video_struct *v){
	munmap(v->map,v->mbuf.size);//删除内存的映射
	close(v->fd);
//	fclose(fp);
//	fclose(FP);
} char * gettime(int t){	int dec, sign; //用于ecvt();	char temp[2] = "0";	char *fn;	if(t<10){          fn=(char *)ecvt((float)t,1,&dec,&sign);        }      else{          fn=(char *)ecvt((float)t,2,&dec,&sign);        }      if(strlen(fn)==1){          strcat(temp,fn);          *fn = *temp;          *(fn+1) = *(temp+1);        }      return fn;}		


int main(){
     char *address = NULL;     FILE *  fp;
     char *filename;       //文件名////////下面三个变量是给图片文件起名用的,文件用时间来命名     char *hour;	         //小时     char *min;            //分钟     char *sec;            //秒///下面的2个变量是为了获取系统时间     time_t tval;
     struct tm *now;
     
          
     int frame = 0;
     int count = 0;     struct video_struct *vd=&VD;              bzero(vd,sizeof(struct video_struct));
     filename=(char *)malloc(15*sizeof(char));   //文件名的格式是 小时:分钟:秒 共需要6位 和字符串结束符共7     
    if(V4L_open(vd,PATH,WIDTH,HEIGHT,VIDEO_PALETTE_RGB24) == 0)
		printf("open success\n");
	else{ 
		printf("open failure and open again\n");
        sleep(1);    //也许设备没有准备好,等一下
		if(V4L_open(vd,PATH,WIDTH,HEIGHT,VIDEO_PALETTE_RGB24)<0){   
			perror(" open failure");
            exit(-1); 
          }
        else 
		    printf("open sucess at second time\n");
    }

    printf("----------- Go to get capability-----------\n");

    if(V4L_get_capability(vd)<0){
		perror("Couldn't get videodevice capability");
		exit(-1);
	}
	else
		printf(" \tget video_capability SUCCESS!\n");



	printf("------------Go to get picture--------------\n");

	if(V4L_get_picture(vd)<0){
		perror("Couldn't get videodevice picture");
		exit(-1);
	}
	else
		printf("\tget video_picture SUCCESS!\n");



	printf("------------GO to set picture--------------\n");

      if(V4L_set_picture(vd)<0){
		perror("Couldn't set videopict with VIDIOCSPICT");
		exit(-1);
	}
	else
		printf("\tset video_picture SUCCESS!\n");


	printf("------------GO to set window---------------\n");

	if(V4L_set_window(vd)<0){
		perror("Couldn't set videowein with VIDIOCSWEIN");
		exit(-1);
	}
	else
		printf("\tset videowein SUCCESS!\n");


    printf("\t\n----------------GO to get mbuf-----------------\n");

	if(V4L_get_mbuf(vd)<0){
		perror("init VIDIOCGMBUF FAILED");
		exit(-1);
	}
    else
		printf("\tget mbuf SUCCESS!\n");


	


	printf("-------------------GO to memory map----------------\n");

	if(V4L_memory_map(vd, vd->mbuf.size)<0){
		perror(" memory map FAILED");
		exit(-1);
	}
	else
		printf("\tmemory map SUCCESS!\n");

      printf("--------------------GO to set mmap----------------\n");

	if(V4L_set_mmap(vd) == 0)
		printf("\tset mmap SUCCESS!\n");
	else{
		perror("set mmap FAILED");
		exit(-1);
	}

	printf("-------------------GO TO start capture image-------\n");
printf("------------------------1-----------------\n");

	if((V4L_start_get(vd,frame)<0)){		printf("**********************\n");		perror("get image FAILED");
		exit(-1);
	}printf("0000000000000000000\n");	
	while(count<4){   //循环获得图片	sleep(1);printf("1111111111111111111111\n");	bzero(filename,15*sizeof(char)); 
	V4L_sync(vd,frame);	tval=time(NULL);	now=localtime(&tval);	hour = gettime(now->tm_hour);	strcat(filename,hour);	printf("2222222222222222222222\n");	min = gettime(now->tm_min);	strcat(filename,min);	sec = gettime(now->tm_sec);	strcat(filename,sec);	puts(sec);
printf("3333333333333333333333\n");//打开文件      
    fp=fopen(filename,"w");
	 if(fp==NULL){
		 perror("open file failure");
		 exit(-1);
	 }

      fprintf(fp,"P6\n%d %d\n255\n",WIDTH,HEIGHT);  //文件的头     
	address = V4L_get_mapaddress(vd,frame);
	if( address==(char *)NULL){  
       perror(" get mapaddress Failed!");
	   exit(-1);
	}
    else   
       printf(" get mapaddress SUCCESS!\n");

	fwrite(address,WIDTH,3*HEIGHT,fp);      fclose(fp);      strcat(filename,".jpg");   if(-1 == (write_jpeg(filename,address,75,WIDTH,HEIGHT,0)))   {        printf("write_jpeg error\n");        exit(1);   }
	
	frame = (frame+1)%2;  //下一帧
	V4L_start_get(vd,frame);	count++;
	}
      free(filename);
	V4L_close(vd);

	return 0;
}


⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -