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

📄 zc301_test.c

📁 OV511和zc301的视频采集程序
💻 C
字号:
/*     ZC301
 * 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() */  

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;      int width,height;          width = atoi(argv[1]);     height = atoi(argv[2]);         typedef struct v4l_struct {             int fd;//设备名           struct video_capability  cap;            struct video_picture  pict; //设备采集图象的各种属性             struct video_mmap  v_mmap;              struct  video_channel  channel;          struct video_mbuf  v_mbuf;           //video_mbuf 利用mmap进行映射的帧的信息。映射区长度,Frames 最多支持的帧数,Offsets 每帧相对基址的偏移    }v4l_device;
	int frame = 0;   
	int ret;
	int i,size;        int framestate[2]={0,0};
	
	FILE *filedata;
	v4l_device  *vd;       vd=(v4l_device *)calloc(1,sizeof(*vd));

	// write to file
	filedata = fopen("ZC301.YUV", "ab+");   
	if(!filedata){
		printf("pile.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));   //获取关于视频采集设备所能显示的最大图像大小,信号源的通道数
	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_name:[%s]\n",vd->cap.name);
		printf("cap_tyep:0x%X\n",vd->cap.type);   // VID_TYPE_CAPTURE
	
   ret=ioctl(cam_fp,VIDIOCGCHAN,&(vd->channel));     if(ret<0) {                    perror("v4l_get_channel  ERROR: ");                   return   -1;             }     printf("channels= %d, name= %s,type=%d\n",               vd->channel.channel,vd->channel.name,vd->channel.type); //type: VIDEO_TYPE_CAMERA       2
ret = ioctl(cam_fp,VIDIOCGPICT,&vd->pict);        	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=9968;   //新加的,改变亮度
      vd-> pict.colour=65535;   //
      vd-> pict.depth=16; 
	vd->pict.palette = VIDEO_PALETTE_YUV420P;         //采用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与其它所有映射这个对象的进程共享映射空间
    printf("%p\n",cam_mmap); if(cam_mmap < 0){
		printf("mmap() video error\n");
		return -1;
	}
	size=width*height*3/2;            // VIDEO_PALETTE_YUV420P  每个像素占1.5个字节
	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_YUV420P;
		printf("i=%d\n",i);
		            if(framestate[frame]==0){	     	if ((ret =ioctl(cam_fp,VIDIOCMCAPTURE,&vd->v_mmap)) < 0)    
		             {
			        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){                                   
			        sleep(1);    
			       printf("sleep 1s\n");
		        }                      framestate[frame]=0;             }
		
     fwrite((cam_mmap + vd->v_mbuf.offsets[frame]),size, 1,filedata);                 printf("%p\n",(cam_mmap+vd->v_mbuf.offsets[frame]));        
		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 + -