📄 zc301_test.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 + -