完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
查看摄像头支持格式和分辨率清单 [root@ok3568:~/test]# v4l2-ctl -d/dev/video9 --list-formats-ext ioctl: VIDIOC_ENUM_FMT Type: Video Capture [0]: 'MJPG' (Motion-JPEG, compressed) Size: Discrete 1920x1080 Interval: Discrete0.033s (30.000 fps) Interval: Discrete0.040s (25.000 fps) Interval: Discrete0.050s (20.000 fps) Interval: Discrete0.200s (5.000 fps) Size: Discrete 160x120 Interval: Discrete0.033s (30.000 fps) Interval: Discrete0.040s (25.000 fps) Interval: Discrete0.050s (20.000 fps) Interval: Discrete0.200s (5.000 fps) Size: Discrete 176x144 Interval: Discrete0.033s (30.000 fps) Interval: Discrete0.040s (25.000 fps) Interval: Discrete0.050s (20.000 fps) Interval: Discrete0.200s (5.000 fps) Size: Discrete 320x240 Interval: Discrete0.033s (30.000 fps) Interval: Discrete0.040s (25.000 fps) Interval: Discrete0.050s (20.000 fps) Interval: Discrete0.200s (5.000 fps) Size: Discrete 352x288 Interval: Discrete0.033s (30.000 fps) Interval: Discrete0.040s (25.000 fps) Interval: Discrete0.050s (20.000 fps) Interval: Discrete0.200s (5.000 fps) Size: Discrete 640x360 Interval: Discrete0.033s (30.000 fps) Interval: Discrete0.040s (25.000 fps) Interval: Discrete0.050s (20.000 fps) Interval: Discrete0.200s (5.000 fps) Size: Discrete 640x480 Interval: Discrete0.033s (30.000 fps) Interval: Discrete0.040s (25.000 fps) Interval: Discrete0.050s (20.000 fps) Interval: Discrete0.200s (5.000 fps) Size: Discrete 800x600 Interval: Discrete0.033s (30.000 fps) Interval: Discrete0.040s (25.000 fps) Interval: Discrete0.050s (20.000 fps) Interval: Discrete0.200s (5.000 fps) Size: Discrete 848x480 Interval: Discrete0.033s (30.000 fps) Interval: Discrete0.040s (25.000 fps) Interval: Discrete0.050s (20.000 fps) Interval: Discrete0.200s (5.000 fps) Size: Discrete 1024x768 Interval: Discrete0.033s (30.000 fps) Interval: Discrete0.040s (25.000 fps) Interval: Discrete0.050s (20.000 fps) Interval: Discrete0.200s (5.000 fps) Size: Discrete 1280x800 Interval: Discrete0.033s (30.000 fps) Interval: Discrete0.040s (25.000 fps) Interval: Discrete0.050s (20.000 fps) Interval: Discrete0.200s (5.000 fps) Size: Discrete 1280x720 Interval: Discrete0.033s (30.000 fps) Interval: Discrete0.040s (25.000 fps) Interval: Discrete0.050s (20.000 fps) Interval: Discrete0.200s (5.000 fps) Size: Discrete 600x1080 Interval: Discrete0.033s (30.000 fps) Interval: Discrete0.040s (25.000 fps) Interval: Discrete0.050s (20.000 fps) Interval: Discrete0.200s (5.000 fps) Size: Discrete 1280x1024 Interval: Discrete 0.033s (30.000 fps) Interval: Discrete0.040s (25.000 fps) Interval: Discrete0.050s (20.000 fps) Interval: Discrete0.200s (5.000 fps) [1]: 'YUYV' (YUYV 4:2:2) Size: Discrete 1920x1080 Interval: Discrete0.200s (5.000 fps) Size: Discrete 160x120 Interval: Discrete0.033s (30.000 fps) Interval: Discrete 0.040s(25.000 fps) Interval: Discrete0.050s (20.000 fps) Interval: Discrete0.067s (15.000 fps) Size: Discrete 176x144 Interval: Discrete0.033s (30.000 fps) Interval: Discrete0.040s (25.000 fps) Interval: Discrete0.050s (20.000 fps) Interval: Discrete0.067s (15.000 fps) Size: Discrete 320x240 Interval: Discrete0.033s (30.000 fps) Interval: Discrete0.040s (25.000 fps) Interval: Discrete0.050s (20.000 fps) Interval: Discrete0.067s (15.000 fps) Size: Discrete 352x288 Interval: Discrete0.033s (30.000 fps) Interval: Discrete0.040s (25.000 fps) Interval: Discrete0.050s (20.000 fps) Interval: Discrete0.067s (15.000 fps) Size: Discrete 640x360 Interval: Discrete0.033s (30.000 fps) Interval: Discrete0.040s (25.000 fps) Interval: Discrete0.050s (20.000 fps) Interval: Discrete0.067s (15.000 fps) Size: Discrete 640x480 Interval: Discrete0.033s (30.000 fps) Interval: Discrete0.040s (25.000 fps) Interval: Discrete0.050s (20.000 fps) Interval: Discrete0.067s (15.000 fps) Size: Discrete 800x600 Interval: Discrete0.050s (20.000 fps) Interval: Discrete0.100s (10.000 fps) Interval: Discrete0.200s (5.000 fps) Size: Discrete 848x480 Interval: Discrete0.050s (20.000 fps) Interval: Discrete0.100s (10.000 fps) Interval: Discrete0.200s (5.000 fps) Size: Discrete 1024x768 Interval: Discrete0.100s (10.000 fps) Interval: Discrete0.200s (5.000 fps) Size: Discrete 1280x800 Interval: Discrete0.100s (10.000 fps) Interval: Discrete0.200s (5.000 fps) Size: Discrete 1280x720 Interval: Discrete0.100s (10.000 fps) Interval: Discrete 0.200s (5.000 fps) Size: Discrete 600x1080 Interval: Discrete0.100s (10.000 fps) Size: Discrete 1280x1024 Interval: Discrete0.200s (5.000 fps) [root@ok3568:~/test]# 查看对应的摄像头设备 [root@ok3568:~/test]# v4l2-ctl--list-devices rkisp-statistics (platform: rkisp): /dev/video7 /dev/video8 rkisp_mainpath (platform:rkisp-vir0): /dev/video0 /dev/video1 /dev/video2 /dev/video3 /dev/video4 /dev/video5 /dev/video6 SY 1080P camera: SY 1080P camer(usb-fd800000.usb-1): /dev/video9 /dev/video10 [root@ok3568:~/test]# ./camera /dev/video9 -----------------------设备信息--------------------- DriverName :uvcvideo Card Name :SY 1080P camera: SY 1080P camer Bus info :usb-fd800000.usb-1 DriverVersion:4.19.206 -----------------------支持格式--------------------- Supportformat: 1.Motion-JPEG 2.YUYV 4:2:2 ------------------------帧信息---------------------- Currentdata format information: width:1920 height:1080 format:Motion-JPEG --------------------设置当前格式-------------------- set image size: width = 800 height = 600 --------------------设置当前帧率-------------------- set fps : 60 --------------------设置曝光模式-------------------- set exposure mode : 手动 val : 12 ---------------------申请缓冲区--------------------- count : 5 -----------------获取缓冲区地址,长度--------------- -----------------将申请到的缓冲帧放入队------------- --------------------开始采集数据------------------- --------------------获取一帧并处里------------------ ----------------------结束采集数据------------------ [root@ok3568:~/test]# ls camera go.mod hello.go jpg webgo.go [root@ok3568:~/test]# ls jpg/ 000.jpg 001.jpg [root@ok3568:~/test]# sz jpg/001.jpg rz Starting zmodem transfer. Press Ctrl+C to cancel. Transferring 001.jpg... 100% 355 KB 11 KB/sec 00:00:32 0 Errors [root@ok3568:~/test]# #include #include #include #include #include #include #include #include #include #define NB_BUFFER 5 #define DBG_DIR "jpg/" #define VIDEO_L_MASK 0x01 #define VIDEO_R_MASK 0x02 #if 1 /* 头文件 : 函数 :int ioctl(intfd, int request, struct v4l2_capability *argp); struct v4l2_capability 设备的功能 { __u8 driver[16]; // 驱动名字 __u8 card[32]; // 设备名字 __u8 bus_info[32]; // 设备在系统中的位置 __u32 version; // 驱动版本号 __u32 capabilities;// 设备支持的操作 __u32 reserved[4]; // 保留字段 }; VIDIOC_QUERYCAP //查询驱动功能 */ /* fd:文件描述符 */ int showCapability(int fd) { printf("-----------------------设备信息---------------------n"); struct v4l2_capability cap; if(ioctl(fd,VIDIOC_QUERYCAP,&cap) < 0) { perror("error ioctl VIDIOC_QUERYCAP !"); return -1; } printf("DriverName :%snCard Name :%snBus info :%snDriverVersion:%u.%u.%un" ,cap.driver ,cap.card ,cap.bus_info ,(cap.version>>16)&0xff ,(cap.version>>8)&0xff ,cap.version&0xff); return 0; } #endif #if 1 /* 函数 :int ioctl(intfd, int request, struct v4l2_fmtdesc *argp); struct v4l2_fmtdesc { __u32 index; // 要查询的格式序号,应用程序设置 enum v4l2_buf_type type; // 帧类型,应用程序设置 __u32 flags; // 是否为压缩格式 __u8 description[32]; // 格式名称 __u32 pixelformat; // 格式 __u32 reserved[4]; // 保留 }; VIDIOC_ENUM_FMT //指令含义:获取当前驱动支持的视频格式 */ /* fd:文件描述符 */ int showFmtdesc(int fd) { printf("-----------------------支持格式---------------------n"); struct v4l2_fmtdesc dis_fmtdesc; dis_fmtdesc.index=0; dis_fmtdesc.type=V4L2_BUF_TYPE_VIDEO_CAPTURE; printf("Supportformat:n"); while(ioctl(fd,VIDIOC_ENUM_FMT,&dis_fmtdesc)!=-1) { printf("t%d.%sn",dis_fmtdesc.index+1,dis_fmtdesc.description); dis_fmtdesc.index++; } return 0; } #endif #if 1 /* 函数 :int ioctl(intfd, int request, struct v4l2_format *argp); struct v4l2_format 帧的格式 { enum v4l2_buf_type type; //帧类型,应用程序设置 union fmt { structv4l2_pix_format pix; //视频设备使用 structv4l2_window win; structv4l2_vbi_format vbi; structv4l2_sliced_vbi_format sliced; __u8raw_data[200]; }; }; VIDIOC_G_FMT: //指令含义:读取当前驱动的捕获格式 VIDIOC_S_FMT: //指令含义:设置当前驱动的捕获格式 VIDIOC_ENUM_FMT: //指令含义:获取当前驱动支持的视频格式 */ /* fd:文件描述符 */ int showFormat(int fd) { printf("------------------------帧信息----------------------n"); struct v4l2_format dis_fmt; dis_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; ioctl(fd,VIDIOC_G_FMT,&dis_fmt); printf("Currentdata format information:ntwidth:%dntheight:%dn" ,dis_fmt.fmt.pix.width ,dis_fmt.fmt.pix.height); struct v4l2_fmtdesc fmtdesc; fmtdesc.index=0; fmtdesc.type=V4L2_BUF_TYPE_VIDEO_CAPTURE; while(ioctl(fd,VIDIOC_ENUM_FMT,&fmtdesc)!=-1) { if(fmtdesc.pixelformat & dis_fmt.fmt.pix.pixelformat) { printf("tformat:%sn",fmtdesc.description); break; } fmtdesc.index++; } return 0; } #endif #if 1 /* V4L2_FIELD_ANY //指令含义: V4L2_PIX_FMT_MJPEG //指令含义:MJPEG格式 V4L2_PIX_FMT_UYVY //指令含义:YUYV格式 VIDIOC_S_PARM //指令格式:检查格式和设置 */ /* fd : 文件描述符 w :宽 h:高 */ int setFormat(int fd ,int w,int h) { printf("--------------------设置当前格式--------------------n"); struct v4l2_format fmt = { .type = V4L2_BUF_TYPE_VIDEO_CAPTURE, .fmt = { .pix = { .width = w, //帧宽 .height = h, //帧高 .pixelformat = V4L2_PIX_FMT_MJPEG, //帧格式 .field = V4L2_FIELD_ANY, } }, }; //检查格式 和 设置是否成功 if(ioctl(fd,VIDIOC_S_PARM,&fmt) < 0){ perror("error ioctl VIDIOC_S_PARM !"); return -1; }else{ printf("set image size:ntwidth = %dntheight = %dn",w,h); } return 0; } #endif #if 1 /* fd :文件描述符 fps:帧率 numerator:这里固定为1 */ int setFps(int fd ,int fps) { printf("--------------------设置当前帧率--------------------n"); struct v4l2_streamparm setfps = { .type = V4L2_BUF_TYPE_VIDEO_CAPTURE, .parm = { .capture = { .timeperframe = { .numerator=1, .denominator = fps, //帧率时间长度为 = numerator/denominator } } }, }; if (ioctl(fd, VIDIOC_S_PARM, &setfps) < 0) { perror("error SETFPS failed !"); return -1; }else{ printf("tset fps : %dn",fps); } return 0; } #endif #if 1 /* fd :文件描述符 val:曝光值 */ int setExposure(int fd,int val) { printf("--------------------设置曝光模式--------------------n"); struct v4l2_control con_setup = { //设置手动曝光 .id = V4L2_CID_EXPOSURE_AUTO, .value = V4L2_EXPOSURE_MANUAL, }; if(ioctl(fd,VIDIOC_S_CTRL,&con_setup)<0){ perror("set exposure failed !"); } struct v4l2_control con_set = { //设置曝光绝对值 .id = V4L2_CID_EXPOSURE_ABSOLUTE, .value = val, }; if(ioctl(fd,VIDIOC_S_CTRL,&con_set)<0){ perror("set exposure failed !"); }else{ printf("set exposurentmode : 手动ntval : %dn",val); } return 0; } #endif #if 1 /* fd :文件描述符 val:焦距 */ int setFocus(int fd ,int val) { printf("--------------------设置对焦模式--------------------n"); struct v4l2_control con_setup = { //关闭自动对焦 .id = V4L2_CID_FOCUS_AUTO, .value = 0, }; if(ioctl(fd,VIDIOC_S_CTRL,&con_setup) < 0){ perror("focus set failed !"); }else{ printf("focus off;n"); } struct v4l2_control con_set = { //设置焦点值 .id = V4L2_CID_FOCUS_ABSOLUTE, .value = val, }; if(ioctl(fd,VIDIOC_S_CTRL,&con_set) < 0){ perror("focus set failed !"); }else{ printf("focus on;ntval : %dn",val); } return 0; } #endif #if 1 /* 申请和管理缓冲区,应用程序和设备有三种交换数据的方法,直接read/write ,内存映射(memorymapping) ,用户指针。这里只讨论 memorymapping. 函数 :int ioctl(intfd, int request, struct v4l2_requestbuffers *argp); struct v4l2_requestbuffers 申请帧缓冲 { __u32 count; // 缓冲区内缓冲帧的数目 enum v4l2_buf_type type;// 缓冲帧数据格式 enum v4l2_memorymemory; // 区别是内存映射还是用户指针方式 __u32 reserved[2]; }; VIDIOC_REQBUFS //指令含义:分配内存 */ /* fd :文件描述符 */ int requestBuffers(int fd) { printf("---------------------申请缓冲区---------------------n"); struct v4l2_requestbuffers rb = { .count = NB_BUFFER, //缓冲帧个数 .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,//数据类型:流类型,永远都是 .memory = V4L2_MEMORY_MMAP, //存储类型:V4L2_MEMORY_MMAP或V4L2_MEMORY_USERPTR }; if (ioctl(fd, VIDIOC_REQBUFS, &rb) < 0){ perror("error VIDIOC_REQBUFS !"); return -1; } printf("count : %dn",NB_BUFFER); return 0; } #endif #if 1 /* 函数 :int ioctl(intfd, int request, struct v4l2_buffer *argp); struct v4l2_buffer { __u32 index; //buffer 序号 enum v4l2_buf_type type; //buffer 类型 __u32 byteused; //buffer 中已使用的字节数 __u32 flags; //区分是MMAP 还是USERPTR enum v4l2_fieldfield; struct timeval timestamp; //获取第一个字节时的系统时间 struct v4l2_timecode timecode; __u32 sequence; //队列中的序号 enum v4l2_memory memory; //IO 方式,被应用程序设置 union m { __u32 offset; //缓冲帧地址,只对MMAP 有效 unsigned longuserptr; }; __u32 length; //缓冲帧长度 __u32 input; __u32 reserved; }; VIDIOC_QUERYBUF //把VIDIOC_REQBUFS中分配的数据缓存转换成物理地址 */ /* MMAP:定义一个结构体来映射每个缓冲帧 */ struct buffer{ void *start; unsigned int length; } *buffers; /* #include void *mmap(void*addr, size_t length, int prot, int flags, int fd, off_t offset); //addr 映射起始地址,一般为NULL ,让内核自动选择 //length 被映射内存块的长度 //prot 标志映射后能否被读写,其值为PROT_EXEC,PROT_READ,PROT_WRITE,PROT_NONE //flags 确定此内存映射能否被其他进程共享,MAP_SHARED,MAP_PRIVATE //fd,offset, 确定被映射的内存地址 成功:返回成功映射后的地址,不成功:返回MAP_FAILED ((void*)-1); int munmap(void*addr, size_t length);// 断开映射 //addr 为映射后的地址,length 为映射后的内存长度 */ /* fd :文件描述符 addr:二级指针,用来存放开辟的buffers地址 */ int getBufLenAndAddr(int fd,struct buffer **addr) { printf("-----------------获取缓冲区地址,长度---------------n"); buffers = (struct buffer*)calloc(NB_BUFFER,sizeof(*buffers)); *addr = buffers; //记录开辟的空间首地址,便于free if(!buffers){ //将n_buffers个以申请到的缓冲帧映射到引用程序,用buffers指针记录 perror("error calloc failed !"); return -1; } unsigned int n_buffers; for(n_buffers=0;n_buffers memset(&buf,0,sizeof(buf)); buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; buf.memory = V4L2_MEMORY_MMAP; buf.index = n_buffers; // 查询序号为n_buffers 的缓冲区,得到其起始物理地址和大小 if (-1 == ioctl(fd, VIDIOC_QUERYBUF, &buf)){ perror("error VIDIOC_QUERYBUF failed !"); return -1; } buffers[n_buffers].length = buf.length; //映射内存 buffers[n_buffers].start = mmap(NULL,buf.length,PROT_READ,MAP_SHARED,fd,buf.m.offset); if (MAP_FAILED == buffers[n_buffers].start){ //MAP_FAILED判断返回是否错误 perror("error mmap failed !"); return -1; } } return 0; } #endif #if 1 /* VIDIOC_STREAMON 指令含义:开始采集 VIDIOC_STREAMOFF 指令含义:结束采集 */ /* fd :文件描述符 */ int putQueue(int fd) { printf("-----------------将申请到的缓冲帧放入队-------------n"); unsigned int i; for(i=0;i buf.type =V4L2_BUF_TYPE_VIDEO_CAPTURE; buf.memory =V4L2_MEMORY_MMAP; buf.index = i; if(ioctl(fd,VIDIOC_QBUF, &buf) < 0) { perror("error VIDIOC_QBUF failed !"); return -1; }; } return 0; } #endif #if 1 /* fd :文件描述符 */ int videoOn(int fd) { printf("--------------------开始采集数据-------------------n"); enum v4l2_buf_type type; type = V4L2_BUF_TYPE_VIDEO_CAPTURE; int temp = ioctl(fd,VIDIOC_STREAMON,&type); if(temp < 0){ perror("video on failed !n"); } return 0; } #endif #if 1 /* fd :文件描述符 */ int handleDate(int fd) { printf("--------------------获取一帧并处里------------------n"); struct v4l2_buffer buf; memset(&buf,0,sizeof(buf)); buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; buf.memory = V4L2_MEMORY_MMAP; ioctl (fd,VIDIOC_DQBUF, &buf); // 从缓冲区取出一个缓冲帧 char jpgName[32]; sprintf(jpgName,DBG_DIR "%03d.jpg",buf.index); FILE *fSource = fopen(jpgName,"wb"); fwrite(buffers[buf.index].start,1,(size_t)buf.bytesused,fSource); fclose(fSource); ioctl (fd, VIDIOC_QBUF,&buf); // 将取出的缓冲帧放回缓冲区 } #endif #if 1 /* fd :文件描述符 */ int videoOff(int fd) { printf("----------------------结束采集数据------------------n"); int type_off = V4L2_BUF_TYPE_VIDEO_CAPTURE; if(ioctl(fd,VIDIOC_STREAMOFF,&type_off)){ perror("error STREAMOFF failed"); return -1; } return 0; } #endif int main(int argc, char *argv[]) { int fd; struct buffer *ptr; int i; if((fd = open(argv[1], O_RDWR)) == -1) { perror("error open !"); return -1; } mkdir(DBG_DIR,0777); showCapability(fd); showFmtdesc(fd); showFormat(fd); setFormat(fd,800,600); setFps(fd,60); setExposure(fd,12); // setFocus(fd,12); 焦距的设置因摄像头而定,如果不支持这去掉这个为默认状态 requestBuffers(fd); getBufLenAndAddr(fd,&ptr); putQueue(fd); videoOn(fd); handleDate(fd); videoOff(fd); free(ptr); close(fd); return 0; } |
|
相关推荐
|
|
只有小组成员才能发言,加入小组>>
[技术] 【飞凌嵌入式OK3576-C开发板体验】llama2.c部署
5170 浏览 0 评论
5955 浏览 0 评论
【飞凌嵌入式OK3576-C开发板体验】ssh连接与文件传输
6122 浏览 0 评论
7509 浏览 0 评论
【飞凌嵌入式OK527N-C开发板体验】6.制作h264播放器
7107 浏览 0 评论
6740浏览 2评论
3205浏览 2评论
11028浏览 1评论
5152浏览 1评论
82435浏览 1评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-6 05:40 , Processed in 0.596452 second(s), Total 62, Slave 44 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号