v4l2摄像头驱动

来源:互联网 发布:松江的主机怎么编程 编辑:程序博客网 时间:2024/06/04 18:55

环境:

硬件:radxa rock开发板,蓝色妖姬T998无驱摄像头

系统:lubuntu 3月15号固件,v4l2


其实我只是把草根老师的博客代码改了些参数:

1.摄像头的模式由O_RDWR | O_NONBLOCK改为O_RDWR,若不改,会报DQ_BUF的bug

2.视频的参数改为YUYV422

3.n_buffer中途会莫名其妙改变,所以在程序中人为赋值


程序运行后,会保存count个bin文件在选定目录下。文件内容是YUYV422的图像数据。


参考文档:

1.http://blog.chinaunix.net/uid-26833883-id-3249346.html 

2.http://wenku.baidu.com/view/2f92ce8c680203d8ce2f247f.html


#include <stdio.h>#include <string.h>#include <errno.h>#include <stdlib.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <sys/mman.h>#include <assert.h>#include <linux/videodev2.h>#include <sys/ioctl.h>#include "unistd.h"typedef struct{void *start;int length;}BUFTYPE;BUFTYPE user_buf_real;BUFTYPE *user_buf=&user_buf_real;int n_buffer = 0;//鎵撳紑鎽勫儚澶磋澶?int open_camer_device(){int fd;//if((fd = open("/dev/video0",O_RDWR | O_NONBLOCK)) < 0)if((fd = open("/dev/video0",O_RDWR)) < 0){perror("Fail to open");exit(EXIT_FAILURE);} printf("open camer %d \n",fd);return fd;}int init_mmap(int fd){        printf("init_mmap \n");int i = 0;struct v4l2_requestbuffers reqbuf;bzero(&reqbuf,sizeof(reqbuf));reqbuf.count = 1;  //changedreqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;reqbuf.memory = V4L2_MEMORY_MMAP;//鐢宠瑙嗛缂撳啿鍖?杩欎釜缂撳啿鍖轰綅浜庡唴鏍哥┖闂达紝闇€瑕侀€氳繃mmap鏄犲皠)//杩欎竴姝ユ搷浣滃彲鑳戒細淇敼reqbuf.count鐨勫€硷紝淇敼涓哄疄闄呮垚鍔熺敵璇风紦鍐插尯涓暟if(-1 == ioctl(fd,VIDIOC_REQBUFS,&reqbuf)){perror("Fail to ioctl 'VIDIOC_REQBUFS'");exit(EXIT_FAILURE);}n_buffer = reqbuf.count; //mark reatch hereprintf("n_buffer = %d\n",n_buffer);//test_yz = calloc(reqbuf.count,sizeof(BUFTYPE));//////test       //user_buf->start =(void*)calloc(reqbuf.count,sizeof(*user_buf)); //mark-err        user_buf->start = calloc(reqbuf.count,sizeof(*user_buf));       //user_buf = (BUFTYPE*)(calloc(reqbuf.count,sizeof(*user_buf))); //mark-err//printf("start \n");printf("start %d \n",user_buf->start);//////////if(user_buf == NULL){fprintf(stderr,"Out of memory\n");exit(EXIT_FAILURE);}//灏嗗唴鏍哥紦鍐插尯鏄犲皠鍒扮敤鎴疯繘绋嬬┖闂?for(i = 0; i < reqbuf.count; i ++){struct v4l2_buffer buf;bzero(&buf,sizeof(buf));buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;buf.memory = V4L2_MEMORY_MMAP;buf.index = i;       printf("index %d \n",i);//鏌ヨ鐢宠鍒板唴鏍哥紦鍐插尯鐨勪俊鎭?if(-1 == ioctl(fd,VIDIOC_QUERYBUF,&buf)){  perror("Fail to ioctl : VIDIOC_QUERYBUF");exit(EXIT_FAILURE);}user_buf[i].length = buf.length;user_buf[i].start = mmap(NULL,/*start anywhere*/buf.length,PROT_READ | PROT_WRITE,MAP_SHARED,fd,buf.m.offset);////////////////testprintf("user_buf: %d \t start addr:%d \n",i,user_buf->start);////////////////if(MAP_FAILED == user_buf[i].start){perror("Fail to mmap");exit(EXIT_FAILURE);}}return 0;}//鍒濆鍖栬棰戣澶?int init_camer_device(int fd){ printf("init_camer_device \n");struct v4l2_fmtdesc fmt;struct v4l2_capability cap;struct v4l2_format stream_fmt;int ret;//褰撳墠瑙嗛璁惧鏀寔鐨勮棰戞牸寮?memset(&fmt,0,sizeof(fmt));fmt.index = 0;fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;while((ret = ioctl(fd,VIDIOC_ENUM_FMT,&fmt)) == 0){fmt.index ++ ;printf("{pixelformat = %c%c%c%c},description = '%s'\n",fmt.pixelformat & 0xff,(fmt.pixelformat >> 8)&0xff,(fmt.pixelformat >> 16) & 0xff,(fmt.pixelformat >> 24)&0xff,fmt.description);}//鏌ヨ瑙嗛璁惧椹卞姩鐨勫姛鑳?ret = ioctl(fd,VIDIOC_QUERYCAP,&cap);if(ret < 0){perror("FAIL to ioctl VIDIOC_QUERYCAP");exit(EXIT_FAILURE);}printf("catability : \n");printf("driver = %s \n",cap.driver);printf("card = %s \n",cap.card);//鍒ゆ柇鏄惁鏄竴涓棰戞崟鎹夎澶?if(!(cap.capabilities & V4L2_BUF_TYPE_VIDEO_CAPTURE)){printf("The Current device is not a video capture device\n");exit(EXIT_FAILURE);}//鍒ゆ柇鏄惁鏀寔瑙嗛娴佸舰寮?if(!(cap.capabilities & V4L2_CAP_STREAMING)){printf("The Current device does not support streaming i/o\n");exit(EXIT_FAILURE);}//璁剧疆鎽勫儚澶撮噰闆嗘暟鎹牸寮忥紝濡傝缃噰闆嗘暟鎹殑//闀?瀹斤紝鍥惧儚鏍煎紡(JPEG,YUYV,MJPEG绛夋牸寮?stream_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;stream_fmt.fmt.pix.width = 640;stream_fmt.fmt.pix.height = 480;stream_fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;stream_fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;if(-1 == ioctl(fd,VIDIOC_S_FMT,&stream_fmt)){perror("Fail to ioctl");exit(EXIT_FAILURE);}//鍒濆鍖栬棰戦噰闆嗘柟寮?mmap)init_mmap(fd);return 0;}int start_capturing(int fd){        printf("start_capturing \n");unsigned int i;enum v4l2_buf_type type;//testprintf("n_buffer = %d \n",n_buffer);//n_buffer = 1;////////////////灏嗙敵璇风殑鍐呮牳缂撳啿鍖烘斁鍏ヤ竴涓槦鍒椾腑for(i = 0;i < n_buffer;i ++){struct v4l2_buffer buf;printf("index %d \n",i);bzero(&buf,sizeof(buf));buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;buf.memory = V4L2_MEMORY_MMAP;buf.index = i;if(-1 == ioctl(fd,VIDIOC_QBUF,&buf)){perror("Fail to ioctl 'VIDIOC_QBUF'");exit(EXIT_FAILURE);}}//寮€濮嬮噰闆嗘暟鎹?type = V4L2_BUF_TYPE_VIDEO_CAPTURE;if(-1 == ioctl(fd,VIDIOC_STREAMON,&type)){printf("i = %d.\n",i);perror("Fail to ioctl 'VIDIOC_STREAMON'");exit(EXIT_FAILURE);}return 0;}//灏嗛噰闆嗗ソ鐨勬暟鎹斁鍒版枃浠朵腑int process_image(void *addr,int length){printf("process_image \n");FILE *fp;static int num = 0;char picture_name[20];char temp;sprintf(picture_name,"picture%d.bin",num ++);if((fp = fopen(picture_name,"w")) == NULL){perror("Fail to fopen");exit(EXIT_FAILURE);}fwrite(addr,length,1,fp);usleep(500);fclose(fp);return 0;}int read_frame(int fd){        printf("read_frame \n");struct v4l2_buffer buf;unsigned int i;//memset(&buf,0,sizeof(struct v4l2_buffer));      bzero(&buf,sizeof(buf));       buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;buf.memory = V4L2_MEMORY_MMAP;printf("haha \n");//浠庨槦鍒椾腑鍙栫紦鍐插尯if(-1 == ioctl(fd,VIDIOC_DQBUF,&buf)){perror("Fail to ioctl 'VIDIOC_DQBUF'");exit(EXIT_FAILURE);}assert(buf.index < n_buffer);//璇诲彇杩涚▼绌洪棿鐨勬暟鎹埌涓€涓枃浠朵腑printf("buf.index: %d \n",buf.index);process_image(user_buf[buf.index].start,user_buf[buf.index].length);//process_image(user_buf->start,user_buf->length);if(-1 == ioctl(fd,VIDIOC_QBUF,&buf)){perror("Fail to ioctl 'VIDIOC_QBUF'");exit(EXIT_FAILURE);}return 1;}int mainloop(int fd){ int count = 20;while(count -- > 0){for(;;){fd_set fds;struct timeval tv;int r;FD_ZERO(&fds);FD_SET(fd,&fds);/*Timeout*/tv.tv_sec = 2;tv.tv_usec = 0;r = select(fd + 1,&fds,NULL,NULL,&tv);if(-1 == r){if(EINTR == errno)continue;perror("Fail to select");exit(EXIT_FAILURE);}if(0 == r){fprintf(stderr,"select Timeout\n");exit(EXIT_FAILURE);}if(read_frame(fd))  break;}}return 0;}void stop_capturing(int fd){        printf("stop capturing \n");enum v4l2_buf_type type;type = V4L2_BUF_TYPE_VIDEO_CAPTURE;if(-1 == ioctl(fd,VIDIOC_STREAMOFF,&type)){perror("Fail to ioctl 'VIDIOC_STREAMOFF'");exit(EXIT_FAILURE);}return;}void uninit_camer_device(){unsigned int i;printf("uninit_camer_device \n");printf("n_buffer %d \n",n_buffer);for(i = 0;i < n_buffer;i ++){if(-1 == munmap(user_buf[i].start,user_buf[i].length)){printf("munmap err: \n");exit(EXIT_FAILURE);}}//free(user_buf);printf("start addr: %d \n",user_buf->start);free(user_buf->start);return;}void close_camer_device(int fd){printf("close_camer_device \n");if(-1 == close(fd)){perror("Fail to close fd");exit(EXIT_FAILURE);}return;}int main(){int fd;                                fd = open_camer_device();       init_camer_device(fd);      start_capturing(fd);mainloop(fd);stop_capturing(fd);uninit_camer_device();close_camer_device(fd);return 0;}


0 0
原创粉丝点击