V4L2拍照循环采集

差等生up 2016-08-23 12:46:25
采用V4L2根据步骤采集图片,可循环保存2400左右图片,到2400之后系统就开始调用oom killer,将进程杀死了。但采集视频流是可以进行循环采集,请问各位大神这是什么原因。
...全文
2009 3 打赏 收藏 转发到动态 举报
写回复
用AI写文章
3 条回复
切换为时间正序
请发表友善的回复…
发表回复
差等生up 2016-08-23
  • 打赏
  • 举报
回复
#include "ImageProc.h" #include <string.h> // 定义一个 Camera的指针 Camera *camera=NULL; int n_buffers=0; char * g_buffer=NULL; static unsigned char *jpeg=NULL; static long unsigned int size=0; static struct buffer *fram_buf=NULL; int xioctl(int fd, int request, void *arg) { int r = 0; do { r = ioctl(fd, request, arg); } while (-1 == r && EINTR == errno); return r; } //初始化设备 int init_camera( Camera *cam) { struct v4l2_capability *cap = &(cam->v4l2_cap); struct v4l2_cropcap *cropcap = &(cam->v4l2_cropcap); struct v4l2_crop *crop = &(cam->crop); struct v4l2_format *fmt = &(cam->v4l2_fmt); unsigned int min; int ret =0; struct v4l2_fmtdesc fmtdesc; //VIDIOC_QUERYCAP 命令 来获得当前设备的各个属性 if (!(cap->capabilities & V4L2_CAP_STREAMING)) { LOGE( "%s does not support streaming i/o\n",cam->device_name); return ERROR_DEVICE_CAP_ERROR; } //获得设备对 Image Cropping 和 Scaling 的支持 CLEAR (*cropcap); cropcap->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; crop->c.width = cam->width; crop->c.height = cam->height; crop->c.left = 0; crop->c.top = 0; crop->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; //设置图形格式 fmt->fmt.pix.field = V4L2_FIELD_INTERLACED; //隔行扫描 //检查流权限 if (-1 == xioctl(cam->fd, VIDIOC_S_FMT, fmt)){ LOGE("%s error %d, %s\n", "VIDIOC_S_FMT", errno, strerror(errno)); return ERROR_DEVICE_CAP_ERROR; } return initmmap (cam); } //I/O模式选择 int initmmap( Camera *cam) { struct v4l2_requestbuffers req; CLEAR (req); LOGI("initmap\n"); req.count = 1; //最大不能超过5 req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; req.memory = V4L2_MEMORY_MMAP; //static buffers *fram_buf; if (-1 == xioctl (cam->fd, VIDIOC_REQBUFS, &req)) { if (EINVAL == errno) { LOGE("%s does not support memory mapping", cam->device_name); return ERROR_LOCAL; } else { return ERROR_REQBUFS; } } fram_buf =(struct buffer *) calloc (req.count, sizeof (* (fram_buf))); if (!fram_buf) { LOGE("Out of memory"); return ERROR_LOCAL; } for (n_buffers = 0; n_buffers < req.count; n_buffers++) { struct v4l2_buffer buf; CLEAR (buf); buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; buf.memory = V4L2_MEMORY_MMAP; buf.index = n_buffers; //查询序号 if (-1 == xioctl (cam->fd, VIDIOC_QUERYBUF, &buf)) return ERROR_VIDIOC_QUERYBUF; LOGI("MMAP_SIZE=%d\n",buf.length); fram_buf[n_buffers].length = buf.length; fram_buf[n_buffers].start = //映射起始地址 //映射到用户空间层 mmap (NULL , buf.length, PROT_READ | PROT_WRITE, MAP_SHARED, cam->fd, buf.m.offset); //缓冲区长度(buf.length)和偏移地址(fd,buf.m.offset) if (MAP_FAILED == fram_buf[n_buffers].start) return ERROR_MMAP_FAILD; } return SUCCESSED; } //映射到用户空间2个 int startcapturing(Camera *cam) { unsigned int i; for (i = 0; i < n_buffers; i++) { struct v4l2_buffer buf; CLEAR (buf); buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; buf.memory = V4L2_MEMORY_MMAP; buf.index = i; //数据放入缓存输入队列 printf("--------------%d---------buf.index\n",buf.index); if (-1 == xioctl (cam->fd, VIDIOC_QBUF, &buf)) return ERROR_VIDIOC_QBUF; } enum v4l2_buf_type type; type = V4L2_BUF_TYPE_VIDEO_CAPTURE; if (-1 == xioctl (cam->fd, VIDIOC_STREAMON, &type)) return ERROR_VIDIOC_STREAMON; return SUCCESSED; } int readframeonce(Camera *cam,unsigned char *buf ,long unsigned int * size) { for (;;) { fd_set fds; struct timeval tv; int r; FD_ZERO (&fds); FD_SET (cam->fd,&fds); tv.tv_sec = 30; tv.tv_usec = 0; r = select (cam->fd + 1, &fds, NULL, NULL, &tv); if (-1 == r) { if (EINTR == errno) // continue; return ERROR_SELECT; } if (0 == r) { LOGE("select timeout"); return ERROR_LOCAL; } if (readframe (cam,buf,size)==1) break; } return SUCCESSED; } int file_save(int i) { int fd2; printf("pic_num=%d\n",i); char picpath[100]; sprintf(pic_name,"./pic_name%d.jpg",i); strcat(picpath,pic_name); fd2 = open(picpath,O_RDWR | O_CREAT); if(fd2 < 0){ perror("open "); } return fd2; } int yuyv_2_rgb888(char *pointer) { int i,j; unsigned char y1,y2,u,v; int r1,g1,b1,r2,g2,b2; for(i=0;i<IMG_HEIGHT;i++) { for(j=0;j<IMG_WIDTH/2;j++)//每次取4个字节,也就是两个像素点,转换rgb,6个字节,还是两个像素点 { y1 = *( pointer + (i*IMG_WIDTH/2+j)*4); u = *( pointer + (i*IMG_WIDTH/2+j)*4 + 1); y2 = *( pointer + (i*IMG_WIDTH/2+j)*4 + 2); v = *( pointer + (i*IMG_WIDTH/2+j)*4 + 3); r1 = y1 + 1.042*(v-128); g1 = y1 - 0.34414*(u-128) - 0.71414*(v-128); b1 = y1 + 1.772*(u-128); r2 = y2 + 1.042*(v-128); g2 = y2 - 0.34414*(u-128) - 0.71414*(v-128); b2 = y2 + 1.772*(u-128); if(r1>255) r1 = 255; else if(r1<0) r1 = 0; if(b1>255) b1 = 255; else if(b1<0) b1 = 0; if(g1>255) g1 = 255; else if(g1<0) g1 = 0; if(r2>255) r2 = 255; else if(r2<0) r2 = 0; if(b2>255) b2 = 255; else if(b2<0) b2 = 0; if(g2>255) g2 = 255; else if(g2<0) g2 = 0; *(frame_buffer + (i*IMG_WIDTH/2+j)*6 ) = (unsigned char)b1; *(frame_buffer + (i*IMG_WIDTH/2+j)*6 + 1) = (unsigned char)g1; *(frame_buffer + (i*IMG_WIDTH/2+j)*6 + 2) = (unsigned char)r1; *(frame_buffer + (i*IMG_WIDTH/2+j)*6 + 3) = (unsigned char)b2; *(frame_buffer + (i*IMG_WIDTH/2+j)*6 + 4) = (unsigned char)g2; *(frame_buffer + (i*IMG_WIDTH/2+j)*6 + 5) = (unsigned char)r2; } } printf("change to RGB OK \n"); } //编码格式 long encode_jpeg(char *lpbuf,int width,int height) { struct jpeg_compress_struct cinfo ; struct jpeg_error_mgr jerr ; JSAMPROW row_pointer[0] ;//一行图像数据 int row_stride ; cinfo.err = jpeg_std_error(&jerr); jpeg_create_compress(&cinfo); jpeg_mem_dest(&cinfo,&jpeg,&size); cinfo.image_width = width; cinfo.image_height = height; cinfo.input_components = 3; cinfo.in_color_space = JCS_RGB; jpeg_set_defaults(&cinfo); jpeg_set_quality(&cinfo, 80,TRUE); jpeg_start_compress(&cinfo, TRUE); row_stride = width * 3; while (cinfo.next_scanline < height) { row_pointer[0] = &lpbuf[cinfo.next_scanline * row_stride]; jpeg_write_scanlines (&cinfo, row_pointer, 1);//critical } jpeg_finish_compress(&cinfo); jpeg_abort_compress(&cinfo); return size; } int readframe(Camera *cam,unsigned char *buffer,long unsigned int *size){ //获取一帧并处理 struct v4l2_buffer buf; static int picnum=0; CLEAR (buf); buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; buf.memory = V4L2_MEMORY_MMAP; if ( xioctl (cam->fd, VIDIOC_DQBUF, &buf)>=0) //驱动填充用户空间的buffer switch (errno) { case EAGAIN: return 0; case EIO: default: return ERROR_VIDIOC_DQBUF; } assert(buf.index < n_buffers); yuyv_2_rgb888(fram_buf[buf.index].start); *size = encode_jpeg(frame_buffer,IMG_WIDTH,IMG_HEIGHT); //RGB24 to Jpeg printf("the pic jpeg size is %ld\n",*size); printf("save JPEG OK\n"); int fd=file_save(picnum++); write(fd,jpeg,*size); close(fd); //将缓冲帧入列 if (-1 == xioctl (cam->fd, VIDIOC_QBUF, &buf)) return ERROR_VIDIOC_QBUF; return 1; } int main(int argc,char *argv[]){ if(argc<2){ perror("argc <2\n"); exit(-1); } int ret; camera = ( Camera *) malloc( sizeof( Camera ) ); sprintf(camera->device_name,"/dev/video%d",atoi(argv[1])); camera->width = 640; camera->height = 480; ret = open_camera(camera); if(ret !=0 ){ return ret;//open_fail! } ret = init_camera(camera); LOGE("init_camera return %d\n",ret); if(ret == SUCCESSED){ ret = startcapturing(camera); LOGE("startcapturing return %d\n",ret); } if(ret != SUCCESSED){ stopcapturing(camera); uninitdevice (camera); closedevice (camera); LOGE("device CLOSED!\n"); } //获取一 int n=0;//帧率30 while(1){ int i= readframeonce(camera,jpeg,&size); if(i<0){ perror("read frame error!"); break; } n++; } stopcapturing(camera); sleep(1); uninitdevice (camera); sleep(1); closedevice (camera); free(camera); return SUCCESSED; } 这是我的采集代码,前面打开设备就忽略了。出队列入队列,释放什么的都有做为什么还存在内存泄漏。检查可好久了,望各位能指点一下。谢谢啦
fly 100% 2016-08-23
  • 打赏
  • 举报
回复
内存耗尽了吧
91program 2016-08-23
  • 打赏
  • 举报
回复
Out of Memory (OOM) killer,OOM killer 的作用是:杀掉某个进程以腾出内存留给系统用,不致于让系统立刻崩溃。 所以,可能你的程序有内存泄露。

19,500

社区成员

发帖
与我相关
我的任务
社区描述
硬件/嵌入开发 嵌入开发(WinCE)
社区管理员
  • 嵌入开发(WinCE)社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧