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 + -
显示快捷键?