⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ov511_test.c

📁 OV511和zc301的视频采集程序
💻 C
字号:
/*OV511
 * CAMIF test
 *
 */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <ctype.h>
#include <errno.h>
#include <sys/mman.h>
#include <sys/time.h>
#include <sys/ioctl.h>
#include <linux/videodev.h>
 #include <sys/time.h>    /* gettimeofday() */  
#include <linux/videodev2.h>

static int cam_fp = -1;
static char *cam_mmap = NULL;


static inline int camera_init(void)
{
	int dev_fp = -1;

	dev_fp  = open("/dev/video0",O_RDWR);
	if (dev_fp < 0) {
		printf("open /dev/video0 error\n");
		return -1;
	}
	printf("video device opened (%d)\n",dev_fp);
	return dev_fp;
}
 double      ms_time (void)     //返回值单位为毫秒
 {  
     static struct timeval tod;  
     gettimeofday (&tod, NULL); //gttimeofday()会把目前的时间由tod所指的结构返回,//时区的信息则放到NULL所指的结构中
     return ((double)tod.tv_sec * 1000.0 + (double)tod.tv_usec / 1000.0);  
       
 }  

int main(int argc, char *argv[])
{     double  ms_time0, ms_time1;       typedef struct v4l_struct {             int fd;//设备名           struct video_capability  cap; //video_capability包含设备的基本信息(设备名称、支持的最大最小分辨率、信号源信息等)。name[32] 设备名称,maxwidth,                                     /* maxheight,minwidth,minheight,Channels 信号源个数,type 是否能capture,彩色还是黑白,是否能裁剪等等。值如VID_TYPE_CAPTURE等*/           struct video_picture pict;//摄像头缓冲区内图像信息   设备采集图象的各种属性           struct video_window window;//窗口信息           struct video_capture v_capture;               struct video_mmap  v_mmap;            //video_mmap 用于mmap,利用mmap进行映射的帧信息,实际上是/*输入到摄像头存储器缓冲中的帧信息          struct video_mbuf  v_mbuf;           //video_mbuf 利用mmap进行映射的帧的信息。映射区长度,Frames 最多支持的帧数,Offsets 每帧相对基址的偏移          unsigned char *map;//用于存储映射得到的图片的首地址    }v4l_device;
	int frame = 0;   
	int ret;
	int i,size;        int framestate[2]={0,0};
       int width,height;          width = atoi(argv[1]);     height = atoi(argv[2]);    
	FILE *filedata;
	v4l_device  *vd;       vd=(v4l_device *)malloc(sizeof(v4l_device));


	
	// write to file
	filedata = fopen("OV511.YUV", "ab+");   //fopen是C的库函数,返回的是一个指向文件结构的指针。
	if(!filedata){
		printf("picmmap.yuv open error\n");
		return 0;
	}
	printf("file.yuv opened \n");


	if ((cam_fp = camera_init()) < 0)  //open
		goto err;

///                                          //Get capabilities

       ret = ioctl(cam_fp,VIDIOCGCAP,&vd->cap);   //通过ioctl函数的VIDIOCGCAP控制命令,来获取关于视频采集设备所能显示的最大图像大小,信号源的通道数
	if(ret<0) {                  perror("v4l_get_capability:");                   return   -1;             }
		printf("cap:ch=%d,max=%d:%d,min=%d:%d\n",
			vd->cap.channels, 
			vd->cap.maxwidth,vd->cap.maxheight,
			vd->cap.minwidth, vd->cap.minheight);
		printf("cap:[%s]\n",vd->cap.name);
		printf("cap:0x%X\n",vd->cap.type);
	

///	
ret = ioctl(cam_fp,VIDIOCGCAPTURE,&vd->v_capture);
 if(ret<0) {                  perror("v4l_get_capture:");                   return   -1;             }
		printf("capture:offset:%d:%d.\n",vd->v_capture.x, vd->v_capture.y);
		printf("w=%d,h=%d\n",vd->v_capture.width,vd-> v_capture.height);
		printf("decimation=0x%x\n",vd->v_capture.decimation);
		printf("flags=%d\n",vd->v_capture.flags); 
	

	
	vd->v_capture.x = 0;
	vd->v_capture.y = 0;
	vd->v_capture.width =   width;
	vd->v_capture.height = height;            
	vd->v_capture.flags = VIDEO_CAPTURE_ODD;	//在videodev.h中有宏定义 #define  VIDEO_CAPTURE_ODD   0 
	vd->v_capture.decimation = VIDEO_CAPTURE_ODD;
	ret = ioctl(cam_fp,VIDIOCSCAPTURE,&vd->v_capture);      // Set subcapture 
	if(ret<0){            perror("v4l_set_capture:") ;            return  -1;               }	
	
	ret = ioctl(cam_fp,VIDIOCGCAPTURE,&vd->v_capture);   //Get subcapture
 if(ret<0) {                  perror("v4l_get_capture:");                   return   -1;                }
		printf("capture:offset:%d:%d.\n",vd->v_capture.x,vd-> v_capture.y);
		printf("w=%d,h=%d\n",vd->v_capture.width,vd-> v_capture.height);
		printf("decimation=0x%x\n",vd->v_capture.decimation);
		printf("flags=%d\n",vd->v_capture.flags); 
	
///	
            //Get picture properties 
	ret = ioctl(cam_fp,VIDIOCGPICT,&vd->pict);        //通过ioctl函数的VIDIOCGPICT来获取一些关于图像的亮度,对比度等信息. 	if(ret<0) {                  perror("v4l_get_picture:");                   return   -1;             }             printf("pict:brightness=%d:hue=%d.\n",vd->pict.brightness,vd->pict.hue);
	printf(":color=%d,contrast=%d\n",vd->pict.colour,vd->pict.contrast);
	printf(":whiteness=%d,depth=%d\n",vd->pict.whiteness,vd->pict.depth);
	printf(":palette=0x%X\n",vd->pict.palette);

      vd-> pict.brightness=19968;   //新加的,改变亮度
      vd-> pict.colour=65535;   //
      vd-> pict.depth=16; 
	vd->pict.palette = VIDEO_PALETTE_YUV420;         //采用VIDEO_PALETTE_YUV420格式
	ret = ioctl(cam_fp,VIDIOCSPICT,&vd->pict);            // Set picture properties 
   if(ret<0) {                  perror("v4l_set_picture:");                   return   -1;             }
	//ret = ioctl(cam_fp,VIDIOCGPICT,&vd->pict);    // 否则会再次恢复默认值
	printf("pict:brightness=%d:hue=%d.\n",vd->pict.brightness,vd->pict.hue);
	printf(":color=%d,contrast=%d\n",vd->pict.colour,vd->pict.contrast);
	printf(":whiteness=%d,depth=%d\n",vd->pict.whiteness,vd->pict.depth);
	printf(":palette=0x%X\n",vd->pict.palette);

	                      // get mbuf attribute      Memory map buffer info            ret=ioctl(cam_fp,VIDIOCGMBUF,&vd->v_mbuf);
	if ( ret< 0)    {
		printf("get mbuf attribute error, ret(%d)\n",ret);
		goto err;
	    } 	
	printf("video_mbuf:size=%d frames=%d\n",vd->v_mbuf.size,vd->v_mbuf.frames);   
        printf("video_mbuf:offsets[0]=%d offsets[1]=%d\n",vd->v_mbuf. offsets[0],vd->v_mbuf .offsets[1]);   
                         //mmap 将视频设备的文件映射进内存
	cam_mmap = (char*)mmap(0, vd->v_mbuf.size, 
			PROT_READ | PROT_WRITE,      //页内容可以被读取,可以被写入
			MAP_SHARED, cam_fp, 0);     //MAP_SHARED与其它所有映射这个对象的进程共享映射空间
 if(cam_mmap < 0){
		printf("mmap() video error\n");
		return -1;
	}
	size=width*height*3/2;
	i = atoi(argv[3]);   //把字符串转换成整型数
	while(i){                   ms_time0 = ms_time(); /* milli seconds */  
		//v_mmap.frame = 0;   //对于单帧采集只需设置v_mmap.frame=0,即采集其中的第一帧
		vd->v_mmap.frame = frame;
		vd->v_mmap.width = width;     //设置内存区里图片的属性,与video_capture匹配 
		vd->v_mmap.height =height;
		vd->v_mmap.format = VIDEO_PALETTE_YUV420;
		printf("i=%d\n",i);
		            if(framestate[frame]==0){	     	if ((ret =ioctl(cam_fp,VIDIOCMCAPTURE,&vd->v_mmap)) < 0)     //Grab frames真正开始视频截取。将图像映射到内存中,
                                  //  若调用成功,开始一帧的截取,是非阻塞的,是否截取完毕留给VIDIOCSYNC来判断
		             {
			        printf("get capture error, ret(%d)\n",ret);
			       goto err;
		            }                      framestate[frame]=1;               }        
		             if(framestate[frame]==1){
		     while(ioctl(cam_fp, VIDIOCSYNC, &vd->v_mmap.frame) < 0){      //Sync with mmap grabbing     !!
                                                    //若成功,表明一帧截取已完成。可以开始做下一次 VIDIOCMCAPTURE
                                                     //frame是当前截取的帧的序号
			        sleep(1);    //执行挂起1秒                     等待一帧映射结束;
			       printf("sleep 1s\n");
		        }                      framestate[frame]=0;             }
		
     fwrite((cam_mmap + vd->v_mbuf.offsets[frame]),size, 1,filedata);                     
			printf("a picture ok\n");		                  ms_time1 = ms_time () - ms_time0;   //统计采集一帧的时间,单位ms                 printf("%f\n",ms_time1);
		
		frame = (frame == 0)?1:0; //next frame     或者frame=frame^ 1    取异或
		i--;
	}
	

err:
	fclose(filedata);

	if(cam_mmap)
		munmap(cam_mmap, vd->v_mbuf.size);   //解除内存映射
	
	if(cam_fp)
		close(cam_fp);

	printf("done.\n");
	return 0;
}

⌨️ 快捷键说明

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