www.pudn.com > usb_camera.rar > videodemo.c
/****************************************Copyright (c)************************************************** ** Guangzhou ZHIYUAN electronics Co.,LTD. ** ** http://www.zyinside.com ** **--------------File Info------------------------------------------------------------------------------- ** File Name: videotest.c ** Last modified Date: 2006-01-14 ** Last Version: v1.0 ** Description: ** Note: **------------------------------------------------------------------------------------------------------ ** Created By: 周立山 ** Created date: 2006-01-01 ** Version: v1.0 ** Descriptions: ** **------------------------------------------------------------------------------------------------------ ** Modified by: ** Modified date: ** Version: ** Description: ** ********************************************************************************************************/ // arm-linux-gcc -s -Wall -I/zylinux/kernel/include -Wstrict-prototypes videodemo.c -o videodemo #include#include #include #include #include #include #include #include #define ERR_FRAME_BUFFER 1 #define ERR_VIDEO_OPEN 2 #define ERR_VIDEO_GCAP 3 #define ERR_VIDEO_GPIC 4 #define ERR_VIDEO_SPIC 5 #define ERR_SYNC 6 #define ERR_FRAME_USING 7 #define ERR_GET_FRAME 8 typedef struct _fb_v4l { // FrameBuffer 信息 int fbfd ; // FrameBuffer设备句柄 struct fb_var_screeninfo vinfo; // FrameBuffer屏幕可变的信息 struct fb_fix_screeninfo finfo; // FrameBuffer固定不变的信息 char *fbp; // FrameBuffer 内存指针 // video4linux信息 int fd; // struct video_capability capability; // struct video_buffer buffer; // struct video_window window; // struct video_channel channel[8]; // struct video_picture picture; // struct video_tuner tuner; // struct video_audio audio[8]; // struct video_mmap mmap; // struct video_mbuf mbuf; // unsigned char *map; int frame_current; int frame_using[VIDEO_MAX_FRAME]; }fb_v41; #define DEFAULT_PALETTE VIDEO_PALETTE_RGB565 #define FB_FILE "/dev/fb/0" #define V4L_FILE "/dev/video0" /********************************************************************************************************* ** Function name: get_grab_frame ** Descriptions: 获取图像帧,该函数调用了VIDIOCMCAPTURE的ioctl,获取一帧图片 ** Input: *vd,参数指针 ** frame,帧号 ** Output : 无 ** Created by: ** Created Date: **------------------------------------------------------------------------------------------------------- ** Modified by: ** Modified Date: **------------------------------------------------------------------------------------------------------ ********************************************************************************************************/ int get_grab_frame(fb_v41 *vd, int frame) { if (vd->frame_using[frame]) { fprintf(stderr, "get_grab_frame: frame %d is already used.\n", frame); return ERR_FRAME_USING; } vd->mmap.frame = frame; if (ioctl(vd->fd, VIDIOCMCAPTURE, &(vd->mmap)) < 0) { perror("v4l_grab_frame"); return ERR_GET_FRAME; } vd->frame_using[frame] = 1; vd->frame_current = frame; return 0; } /********************************************************************************************************* ** Function name: get_next_frame ** Descriptions: 获取下一帧的图像 ** Input: *vd ,参数指针 ** Output : 无 ** Created by: ** Created Date: **------------------------------------------------------------------------------------------------------- ** Modified by: ** Modified Date: **------------------------------------------------------------------------------------------------------ ********************************************************************************************************/ int get_first_frame(fb_v41 *vd) { int ret; vd->frame_current = 0; ret = get_grab_frame( vd, 0 ); if ( ret<0 ) return ret; // 等待帧同步 if (ioctl(vd->fd, VIDIOCSYNC, &(vd->frame_current)) < 0) { perror("v4l_grab_sync"); return ERR_SYNC; } vd->frame_using[vd->frame_current] = 0 ; return (0); } /********************************************************************************************************* ** Function name: get_next_frame ** Descriptions: 获取下一帧的图像 ** Input: *vd ,参数指针 ** Output : 返回0表示正常完成返回。 ** Created by: ** Created Date: **------------------------------------------------------------------------------------------------------- ** Modified by: ** Modified Date: **------------------------------------------------------------------------------------------------------ ********************************************************************************************************/ int get_next_frame(fb_v41 *vd) { int ret; vd->frame_current ^= 1; ret = get_grab_frame( vd,vd->frame_current); // 获取图像数据 if( ret < 0 ) return ret; if (ioctl(vd->fd, VIDIOCSYNC, &(vd->frame_current)) < 0) // 等待帧同步 { perror("v4l_grab_sync"); return ERR_SYNC; } vd->frame_using[vd->frame_current] = 0 ; return 0; } /********************************************************************************************************* ** Function name: get_frame_address ** Descriptions: 获取帧地址.调用该函数可以获取当前帧的缓冲地址 ** Input: *vd ,参数指针 ** Output : 返回帧图像数据的指针地址. ** Created by: ** Created Date: **------------------------------------------------------------------------------------------------------- ** Modified by: ** Modified Date: **------------------------------------------------------------------------------------------------------ ********************************************************************************************************/ unsigned char *get_frame_address(fb_v41 *vd) { return (vd->map + vd->mbuf.offsets[vd->frame_current]); // 从MAP内存中找到当前帧的起始指针 } /********************************************************************************************************* ** Function name: rgb_to_framebuffer ** Descriptions: 写图像数据到Framebuffer,使用该函数前必须成功执行open_framebuffer函数. ** Input: *vd ,参数指针 ** width,图像的宽度vd->mmap.width ** height,图像高度 ** xoffset,图在Framebuffer X轴偏移量vd->vinfo.xoffset ** yoffset,图在Framebuffer Y轴偏移量 ** *img_ptr,将写进FrameBuffer缓冲区指针 ** Output : 无 ** Created by: ** Created Date: **------------------------------------------------------------------------------------------------------- ** Modified by: ** Modified Date: **------------------------------------------------------------------------------------------------------ ********************************************************************************************************/ void rgb_to_framebuffer( fb_v41 *vd, // int width,int height, // 图像大小 int xoffset,int yoffset, // 图像在Framebuffer偏移位置 unsigned short *img_ptr ) // 图像数据指针 { int x,y; int location; unsigned short *loca_ptr; // Figure out where in memory to put the pixel for ( y = 0; y < height; y++ ) // 纵扫描 { location = xoffset * 2 + (y + yoffset) * vd->finfo.line_length; loca_ptr = (unsigned short *) (vd->fbp + location); for ( x = 0; x < width; x++ ) // 行扫描 { *(loca_ptr + x) = *img_ptr++; } } } /* void rgb_to_framebuffer( fb_v41 *vd, // int width,int height, // 图像大小 int xoffset,int yoffset, // 图像在Framebuffer偏移位置 unsigned short int *img_ptr ) // 图像数据指针 { int x,y; int location; // Figure out where in memory to put the pixel for ( y = 0; y < height; y++ ) // 纵扫描 { for ( x = 0; x < width; x++ ) // 行扫描 { location = (x + xoffset) * 2 + (y + yoffset) * vd->finfo.line_length; *((unsigned short int*)(vd->fbp + location )) = *img_ptr++; } } } */ /********************************************************************************************************* ** Function name: open_framebuffer ** Descriptions: 该函数用于初始化FrameBuffer设备,在该函数中打开FrameBuffer设备,并将设备影射到内存 ** Input: *ptr,打开Framebuffer设备路径指针 ** *vd ,参数指针 ** Output : 返回非0值表示出错 ** Created by: ** Created Date: **------------------------------------------------------------------------------------------------------- ** Modified by: ** Modified Date: **------------------------------------------------------------------------------------------------------ ********************************************************************************************************/ int open_framebuffer(char *ptr,fb_v41 *vd) { int fbfd,screensize; // Open the file for reading and writing fbfd = open( ptr, O_RDWR); if (fbfd < 0) { printf("Error: cannot open framebuffer device.%x\n",fbfd); return ERR_FRAME_BUFFER; } printf("The framebuffer device was opened successfully.\n"); vd->fbfd = fbfd; // 保存打开FrameBuffer设备的句柄 // Get fixed screen information 获取FrameBuffer固定不变的信息 if (ioctl(fbfd, FBIOGET_FSCREENINFO, &vd->finfo)) { printf("Error reading fixed information.\n"); return ERR_FRAME_BUFFER; } // Get variable screen information 获取FrameBuffer屏幕可变的信息 if (ioctl(fbfd, FBIOGET_VSCREENINFO, &vd->vinfo)) { printf("Error reading variable information.\n"); return ERR_FRAME_BUFFER; } printf("%dx%d, %dbpp, xoffset=%d ,yoffset=%d \n", vd->vinfo.xres, vd->vinfo.yres, vd->vinfo.bits_per_pixel,vd->vinfo.xoffset,vd->vinfo.yoffset ); // Figure out the size of the screen in bytes screensize = vd->vinfo.xres * vd->vinfo.yres * vd->vinfo.bits_per_pixel / 8; // Map the device to memory vd->fbp = (char *)mmap(0,screensize,PROT_READ|PROT_WRITE,MAP_SHARED,fbfd,0); // 影射Framebuffer设备到内存 if ((int)vd->fbp == -1) { printf("Error: failed to map framebuffer device to memory.\n"); return ERR_FRAME_BUFFER; } printf("The framebuffer device was mapped to memory successfully.\n"); return 0; } /********************************************************************************************************* ** Function name: open_video ** Descriptions: 通过该函数初始化视频设备 ** Input: *fileptr,打开的文件名指针 ** *vd,参数指针 ** dep,像素深度 ** pal,调色板 ** width,宽度 ** height,高度 ** Output : 无 ** Created by: ** Created Date: **------------------------------------------------------------------------------------------------------- ** Modified by: ** Modified Date: **------------------------------------------------------------------------------------------------------ ********************************************************************************************************/ int open_video( char *fileptr,fb_v41 *vd ,int dep,int pal,int width,int height) { // 打开视频设备 if ((vd->fd = open(fileptr, O_RDWR)) < 0) { perror("v4l_open:"); return ERR_VIDEO_OPEN; } // 获取设备 if (ioctl(vd->fd, VIDIOCGCAP, &(vd->capability)) < 0) { perror("v4l_get_capability:"); return ERR_VIDEO_GCAP; } // 获取图象 if (ioctl(vd->fd, VIDIOCGPICT, &(vd->picture)) < 0) { perror("v4l_get_picture"); return ERR_VIDEO_GPIC; } // 设置图象 vd->picture.palette = pal; // 调色板 vd->picture.depth = dep; // 像素深度 vd->mmap.format =pal; if (ioctl(vd->fd, VIDIOCSPICT, &(vd->picture)) < 0) { perror("v4l_set_palette"); return ERR_VIDEO_SPIC; } // vd->mmap.width = width; // width; vd->mmap.height = height; // height; vd->mmap.format = vd->picture.palette; vd->frame_current = 0; vd->frame_using[0] = 0; vd->frame_using[1] = 0; // 获取缓冲影射信息 if (ioctl(vd->fd, VIDIOCGMBUF, &(vd->mbuf)) < 0) { perror("v4l_get_mbuf"); return -1; } // 建立设备内存影射 vd->map = mmap(0, vd->mbuf.size, PROT_READ|PROT_WRITE, MAP_SHARED, vd->fd, 0); if ( vd->map < 0) { perror("v4l_mmap_init:mmap"); return -1; } printf("The video device was opened successfully.\n"); // return get_first_frame(vd); return 0; } /************************************************************************************************************** ** ** ***************************************************************************************************************/ int main( void ) { fb_v41 vd; int ret,i; unsigned short *imageptr; unsigned short tempbuf[640*480]; ret = open_framebuffer(FB_FILE,&vd); // 打开FrameBuffer设备 if( 0!= ret ) // 打开FrameBuffer设备 { goto err; } for(i=0;i<640*480;i++) tempbuf[i] = 0xffff; rgb_to_framebuffer(&vd,640,480,0,0,tempbuf); // 填充FrameBuffer颜色 ret = open_video( V4L_FILE, &vd , 16, // 像素深度 VIDEO_PALETTE_RGB565, // 设置调包板 320,240 ); if( 0!= ret ) // 打开视频设备失败 { goto err; } printf(vd.capability.name);printf(", Type:%d\n",vd.capability.type); printf("Maxwidth:%d,Maxheight:%d\n",vd.capability.maxwidth ,vd.capability.maxheight); printf("Minwidth:%d,Minheight:%d\n",vd.capability.minwidth,vd.capability.minheight); printf("Channels:%d,Audios:%d\n",vd.capability.channels,vd.capability.audios); while(1) { imageptr = (unsigned short *) get_frame_address( &vd ); // rgb_to_framebuffer(&vd,vd.mmap.width,vd.mmap.height, 160,120,imageptr); // if(get_next_frame( &vd ) !=0 ) { // 获取图像数据出错 goto err; } } // exit(0); err: if(vd.fbfd) close(vd.fbfd); // 关闭FrameBuffer设备 if(vd.fd) close(vd.fd); exit(0); return 0; }