📄 grab.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 + -