现在的位置: 首页 > 综合 > 正文

V4L用MMAP模式抓取摄像头图片

2017年10月12日 ⁄ 综合 ⁄ 共 1557字 ⁄ 字号 评论关闭

 

调试了一个晚上,终于把V4L的MMAP模式抓取图片的代码改好,并成功获取图片 /tmp/1.jpg 
本来下午搞定了在mini2440上用READ模式抓取图片的程序,以为切换为MMAP模式会是很简单的工作,没想到根本不是一回事...
一开是还想投机取巧,上网搜了N多资料,没一个有实质性帮助的。实在没辙,便自己静下来一步步摸索。
已经忘了交叉编译了几次代码了,现在记下一些关键点,一来对今晚的工作做个总结,二来可以帮助到广大对V4L视频采集有兴趣的朋友,不能说指点迷津,一起探讨~

1.首先,我对照了READ模式跟MMAP模式的代码区别,(之前有看过很多这方面的资料)发现一个很重要的线     索,MMAP是通过两个设备文件的IO控制来获取图像的开始帧和结束帧的,一个是VIDIOCMCAPTURE,另一个是VIDIOCSYNC。通过两个函数调用:
  if ((ioctl (vd->fd, VIDIOCMCAPTURE, &(vd->vmmap))) < 0)
    {
      perror ("cmcapturecaotao");
    }
   if (ioctl (vd->fd, VIDIOCSYNC, &vd->vmmap.frame) < 0)
    {
      perror ("cvsync err\n");
      erreur = -1;
    }
返回没错误的话,便成功抓取了一张图片(JPEG格式)。

2.然后通过下面这个函数调用来获取图片的存储信息:
jpegsize= convertframe(vd->ptframe,    vd->pFramebuffer + vd->videombuf.offsets[vd->vmmap.frame],            vd->hdrwidth,vd->hdrheight,vd->formatIn,vd->framesizeIn);
其中,ptframe是指向事先分配好的用来存储图片的内存的头指针,pFramebuffer是获取到的图片的第一个落脚内存的地方,framesizeln是抓取到的图片的大小。

3.之后这一步也是拦了我一晚上的最郁闷的一步,之前真的是没想到。我们刚刚获取的图片信息:jpegsize只是告知系统获取一张图片成功而已!仅此而已!并没有把图片保存到FLASH的任何地方,所以我们必须调用下面的write函数来进行写FLASH:
   jpegsize= convertframe(vd->ptframe,    vd->pFramebuffer + vd->videombuf.offsets[vd->vmmap.frame],      vd->hdrwidth,vd->hdrheight,vd->formatIn,vd->framesizeIn);
    fp = fopen(filename, "w");
    if(!fp) return -1;
    fwrite(vd->ptframe, jpegsize, 1, fp);
    fclose(fp);
    return 0;

结合之前的一系列程序,已经成功在路径:/tmp/下获得一张图片1.jpg。

************
双缓存模式:
1.MMAP映射到两个BUF
VIDIOCMCAPTURE(0)
while (whatever) {
   VIDIOCMCAPTURE(1)
   VIDIOCSYNC(0)
   // process frame 0 while the hardware captures frame 1
   VIDIOCMCAPTURE(0)
   VIDIOCSYNC(1)
   // process frame 1 while the hardware captures frame 0
}
注意:一定要先VIDIOCMCAPTURE(0)即从第0个BUF开始打开视频设备文件。否则会报错。

抱歉!评论已关闭.