?? camera.c
字號:
#include <unistd.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <stdio.h>#include <sys/ioctl.h>#include <sys/mman.h>#include <stdlib.h>#include <linux/types.h>#include <linux/videodev.h>#include "jpeglib.h"#include <setjmp.h>#include "SDL.h"#include <string.h>#include <signal.h>#include <errno.h>#define USB_VIDEO "/dev/video0"SDL_Surface *screen,*img;int cam_fd;int width,height;const int bpp = 24;struct video_mmap cam_mm;struct video_capability cam_cap;struct video_picture cam_pic;struct video_mbuf cam_mbuf;struct video_window win;char *cam_data = NULL;int nframe;void errexit(char *msg){ fputs(msg,stderr); exit(-1);}void e_sig(int signum){ printf("\nERROR:signal %d\n",signum); exit(-1);}void setup_sighandler(){ signal(SIGTERM,&e_sig); signal(SIGINT,&e_sig); signal(SIGSEGV,&e_sig); signal(SIGILL,&e_sig); signal(SIGFPE,&e_sig);}void init_video(int w,int h,int bpp); /* bpp == bits per pixel, 暫時無效*/void init_screen(int w,int h,int bpp); /* like above*/void read_video(char *pixels);void show_img(char *pixels);void window_loop();void exchange_r_b( char * f,long size);void compress_to_jpeg_file( FILE *outfile, char * image_buffer,int w,int h, int quality);void save_snapshot();void free_dev(){ printf("free device\n"); close(cam_fd);}int main(int argc,char *argv[]){ int i; width = 320; height = 240; printf("cc1\n"); atexit( &free_dev ); printf("cc2\n"); init_video(width,height,bpp); init_screen(width,height,bpp); setup_sighandler(); window_loop(); getchar(); munmap(cam_data,cam_mbuf.size); exit(0);}void config_vid_pic(){ int ret; if (ioctl(cam_fd, VIDIOCGPICT, &cam_pic) < 0) { errexit("ERROR:VIDIOCGPICT\n"); } cam_pic.palette = VIDEO_PALETTE_RGB24; cam_pic.brightness = 44464; cam_pic.hue = 36000; cam_pic.colour = 0; cam_pic.contrast = 43312; cam_pic.whiteness = 13312; cam_pic.depth = 24; ret = ioctl( cam_fd, VIDIOCSPICT,&cam_pic ); if( ret<0 ) { close(cam_fd); errexit("ERROR: VIDIOCSPICT,Can't set video_picture format\n"); } }void init_video(int w,int h,int bpp) { int ret; printf("open the video\n"); cam_fd = open( USB_VIDEO, O_RDWR ); if( cam_fd<0 ) errexit("Can't open video device\n"); ret = ioctl( cam_fd,VIDIOCGCAP,&cam_cap ); if( ret<0 ) { errexit("Can't get device information: VIDIOCGCAP\n"); } printf("Device name:%s\nWidth:%d ~ %d\nHeight:%d ~ %d\n",cam_cap.name, cam_cap.maxwidth, cam_cap.minwidth, cam_cap.maxheight, cam_cap.minheight); if( ioctl(cam_fd,VIDIOCGWIN,&win)<0 ) { errexit("ERROR:VIDIOCGWIN\n"); } win.x = 0; win.y = 0; win.width=width; win.height=height; if (ioctl(cam_fd, VIDIOCSWIN, &win) < 0) { errexit("ERROR:VIDIOCSWIN\n"); } config_vid_pic(); ret = ioctl(cam_fd,VIDIOCGMBUF,&cam_mbuf); if( ret<0 ) { errexit("ERROR:VIDIOCGMBUF,Can't get video_mbuf\n"); } printf("Frames:%d\n",cam_mbuf.frames); nframe = cam_mbuf.frames; cam_data = (char*)mmap(0, cam_mbuf.size, PROT_READ|PROT_WRITE,MAP_SHARED,cam_fd,0); if( cam_data == MAP_FAILED ) { errexit("ERROR:mmap\n"); } printf("Buffer size:%d\nOffset:%d\n",cam_mbuf.size,cam_mbuf.offsets[0]);}void init_screen(int w,int h,int bpp) // like above{ if ( SDL_Init(SDL_INIT_AUDIO|SDL_INIT_VIDEO) < 0 ) { fprintf(stderr, "無法初始化SDL: %s\n", SDL_GetError()); exit(1); } img = SDL_CreateRGBSurface(SDL_SWSURFACE, width, height, bpp, 0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000); screen = SDL_SetVideoMode(width, height, bpp, SDL_SWSURFACE); if ( screen == NULL ) { fprintf(stderr, "無法設置視頻模式:%s\n", SDL_GetError()); exit(1); } atexit(SDL_Quit);}void read_video(char *pixels){ int ret; int frame=0; cam_mm.height = height; cam_mm.width = width; cam_mm.frame = 0; cam_mm.format=VIDEO_PALETTE_RGB24; ret = ioctl(cam_fd,VIDIOCMCAPTURE,&cam_mm); if( ret<0 ) { errexit("ERROR: VIDIOCMCAPTURE\n"); } ret = ioctl(cam_fd,VIDIOCSYNC,&frame); if( ret<0 ) { errexit("ERROR: VIDIOCSYNC\n"); }}void show_img(char *pixels){ int row_stride = width*3; char *pbuf = (char*)img->pixels; int row; for(row=0; row<height; row++) { memcpy(pbuf, pixels, row_stride); pbuf += img->pitch; pixels += row_stride; } SDL_BlitSurface(img, NULL, screen, NULL); SDL_UpdateRect(screen,0,0,width,height);}void window_loop(){ SDL_Event event; int keystat = 0; Uint32 ticks = 0; SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY,1000); while ( 1 ) { SDL_PollEvent(&event); switch (event.type) { case SDL_QUIT: exit(0); case SDL_KEYDOWN: if( event.key.keysym.sym == SDLK_F8 && keystat == 0 ) save_snapshot(); if( event.key.keysym.sym == SDLK_F9 && keystat == 0 ) config_vid_pic(); keystat = 1; break; case SDL_KEYUP: keystat = 0; break; default: break; } if( (SDL_GetTicks()-ticks)<100 ) continue; read_video(NULL); show_img( cam_data ); ticks = SDL_GetTicks(); }}void compress_to_jpeg_file( FILE *outfile, char * image_buffer,int w,int h, int quality){ struct jpeg_compress_struct cinfo; struct jpeg_error_mgr jerr; JSAMPROW row_pointer[1]; /* pointer to JSAMPLE row[s] */ int row_stride; /* physical row width in image buffer */ int image_width; int image_height; cinfo.err = jpeg_std_error(&jerr); jpeg_create_compress(&cinfo); jpeg_stdio_dest(&cinfo, outfile); image_width = w; image_height = h; cinfo.image_width = image_width; /* image width and height, in pixels */ cinfo.image_height = image_height; cinfo.input_components = 3; /* # of color components per pixel */ cinfo.in_color_space = JCS_RGB; /* colorspace of input image */ jpeg_set_defaults(&cinfo); jpeg_set_quality(&cinfo, quality, TRUE /* limit to baseline-JPEG values */); jpeg_start_compress(&cinfo, TRUE); row_stride = image_width * 3; /* JSAMPLEs per row in image_buffer */ while (cinfo.next_scanline < cinfo.image_height) { row_pointer[0] = (JSAMPROW)& image_buffer[cinfo.next_scanline * row_stride]; (void) jpeg_write_scanlines(&cinfo, row_pointer, 1); } jpeg_finish_compress(&cinfo); jpeg_destroy_compress(&cinfo); }void exchange_r_b( char * f,long size){ char r,b; long i; for( i = 0; i < size ; i++) { r = *f; b = *( f + 2); *f = b; *(f + 2) = r; f = f +3; }}void save_snapshot(){ char *basepath = "/mnt/usb"; char *basename = "/snapsot"; char *extname = ".jpg"; char filename[100]; int i = 0; FILE *fo; for(;;) { sprintf(filename,"%s%s%d%s",basepath,basename,i,extname); fo = fopen(filename,"rb"); if( fo==NULL ) break; else fclose(fo); i += 1; } printf("snapshot:%s\n",filename); fo = fopen(filename,"wb"); exchange_r_b( cam_data, width*height ); compress_to_jpeg_file( fo, cam_data, width, height, 90 ); fclose(fo);}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -