best.c

来自「linux下」· C语言 代码 · 共 307 行

C
307
字号
#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  WIDTH  320
#define  HEIGHT 240

#ifndef VIDEO_PALETTE_JPEG
#define VIDEO_PALETTE_JPEG 21
#endif

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){
    if(ioctl(v->fd,VIDIOCSPICT,&(v->picture))<0)
        return -1;
    else 	
        return 0;
}

/*设置capture area的信息,window(不知道用不用设置这个)*/
int V4L_set_window(struct video_struct *v){
	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_JPEG; 
	v->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){
		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){
		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){
		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);
} 

int main(){
     char *address = NULL;
     FILE *  fp;
     char *filename;       //文件名
     
     int frame = 0;
     int count = 0;
     struct video_struct *vd=&VD;    
     	int file_no=0;
	char buf[3];
     bzero(vd,sizeof(struct video_struct));
     filename=(char *)malloc(100*sizeof(char));  
     
    if(V4L_open(vd,PATH,WIDTH,HEIGHT,VIDEO_PALETTE_JPEG) == 0)
		printf("open success\n");
	else{ 
		printf("open failure and open again\n");
        sleep(1);    //也许设备没有准备好,等一下
		if(V4L_open(vd,PATH,WIDTH,HEIGHT,VIDEO_PALETTE_JPEG)<0){   
			perror("open failure");
            exit(-1); 
		}
        else 
		    printf("open sucess at second time\n");
    }

    if(V4L_get_capability(vd)<0){
		perror("Couldn't get videodevice capability");
		exit(-1);
	}
	
	if(V4L_get_picture(vd)<0){
		perror("Couldn't get videodevice picture");
		exit(-1);
	}

if(V4L_set_picture(vd)<0){
		perror("Couldn't set videopict with VIDIOCSPICT");
		exit(-1);
	}
	
	if(V4L_set_window(vd)<0){
		perror("Couldn't set videowein with VIDIOCSWEIN");
		exit(-1);
	}

	if(V4L_get_mbuf(vd)<0){
		perror("init VIDIOCGMBUF FAILED");
		exit(-1);
	}

	if(V4L_memory_map(vd, vd->mbuf.size)<0){
		perror(" memory map FAILED");
		exit(-1);
	}

	if(V4L_set_mmap(vd) != 0){
		perror("set mmap FAILED");
		exit(-1);
	}

	if((V4L_start_get(vd,frame)<0)){
		perror("get image FAILED");
		exit(-1);
	}


	perror("start now!!!!!!");
	while(1){   //循环获得图片
		bzero(filename,15*sizeof(char)); 
		V4L_sync(vd,frame);
		
		if(file_no>9)
			file_no=0;
		sprintf(buf,"%d",file_no);
		strcat(filename,buf);
		strcat(filename,".jpg");
		fp=fopen(filename,"w");

		address = V4L_get_mapaddress(vd,frame);
		if( address==(char *)NULL){  
		   perror(" get mapaddress Failed!");
		   exit(-1);
		}

		if(-1 == (write_jpeg(filename,address,50,WIDTH,HEIGHT,0)))
		{
			printf("write_jpeg error\n");
			exit(1);
		}

		frame = (frame+1)%2;  //下一帧
		V4L_start_get(vd,frame);
		file_no++;
	}
    free(filename);
	V4L_close(vd);
	return 0;
}



⌨️ 快捷键说明

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