Ubuntu10.04中利用V4L2读取摄像头数据并保存成文件【转】

简介:

转自:http://blog.chinaunix.net/uid-29339876-id-4042245.html

利用V4L2读取UVC摄像头数据并保存成视频文件,主要参考http://linuxtv.org/downloads/v4l-dvb-apis/index.html中的示例Appendix D. Video Capture Example将读取的文件保存在当前目录下的file.yuv中,修改后的完成代码如下:
    

点击(此处)折叠或打开

  1. /*
  2.  * V4L2 video capture example
  3.  * AUTHOT : WANGTISHENG
  4.  * DATA : 2013-12-18
  5.  */
  6. #include <stdio.h>
  7. #include <stdlib.h>
  8. #include <string.h>
  9. #include <assert.h>
  10. #include <getopt.h/* getopt_long(*/
  11. #include <fcntl.h/* low-level i/o */
  12. #include <unistd.h>
  13. #include <errno.h>
  14. #include <sys/stat.h>
  15. #include <sys/types.h>
  16. #include <sys/time.h>
  17. #include <sys/mman.h>
  18. #include <sys/ioctl.h>

  19. #include <linux/videodev2.h>

  20. #define CLEAR(x) memset(&(x), 0, sizeof(x))

  21. struct buffer {
  22.         void *start;
  23.         size_t length;
  24. };

  25. static char *dev_name;
  26. static int fd -1;        //DEVICE NUMBER
  27. struct buffer *buffers;
  28. static unsigned int n_buffers;
  29. static int frame_count = 70;
  30. FILE *fp;                                //FILE POINTOR

  31. static void errno_exit(const char *s)
  32. {
  33.         fprintf(stderr"%s error %d, %s\n", s, errno, strerror(errno));
  34.         exit(EXIT_FAILURE);
  35. }

  36. static int xioctl(int fhint request, void *arg)
  37. {
  38.         int r;
  39.         do {
  40.                 r = ioctl(fh, request, arg);
  41.         while (-1 == r && EINTR == errno);
  42.         return r;
  43. }
  44. //处理函数
  45. static void process_image(const void *pint size)
  46. {
  47.         fwrite(p,size, 1, fp)
  48. }

  49. static int read_frame(FILE *fp)
  50. {
  51.         struct v4l2_buffer buf;
  52.         CLEAR(buf);

  53.         buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  54.         buf.memory = V4L2_MEMORY_MMAP;
  55.         
  56.         if (-1 == xioctl(fd, VIDIOC_DQBUF&buf)
  57.                 errno_exit("VIDIOC_DQBUF");
  58.         
  59.         process_image(buffers[buf.index].start, buf.bytesused);

  60.         if (-1 == xioctl(fd, VIDIOC_QBUF&buf))
  61.             errno_exit("VIDIOC_QBUF")

  62.         return 1;
  63. }

  64. static void mainloop(void)
  65. {
  66.         unsigned int count;
  67.         count = frame_count;
  68.         while (count-> 0{
  69.             printf("No.%d\n",frame_count - count);        //显示当前帧数目
  70.             read_frame(fp);
  71.         }
  72.         printf("\nREAD AND SAVE DONE!\n");
  73. }

  74. static void stop_capturing(void)
  75. {
  76.         enum v4l2_buf_type type;

  77.         type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  78.         if (-1 == xioctl(fd, VIDIOC_STREAMOFF&type))
  79.             errno_exit("VIDIOC_STREAMOFF");
  80. }

  81. static void start_capturing(void)
  82. {
  83.         unsigned int i;
  84.         enum v4l2_buf_type type;

  85.         for (i = 0; i < n_buffers++i{
  86.                 struct v4l2_buffer buf;

  87.                 CLEAR(buf);
  88.                 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  89.                 buf.memory = V4L2_MEMORY_MMAP;
  90.                 buf.index = i;

  91.                 if (-1 == xioctl(fd, VIDIOC_QBUF&buf))
  92.                         errno_exit("VIDIOC_QBUF");
  93.         }
  94.         type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  95.         if (-1 == xioctl(fd, VIDIOC_STREAMON&type))
  96.                 errno_exit("VIDIOC_STREAMON");
  97. }

  98. static void uninit_device(void)
  99. {
  100.         unsigned int i;

  101.         for (i = 0; i < n_buffers++i)
  102.                 if (-1 == munmap(buffers[i].start, buffers[i].length))
  103.                         errno_exit("munmap");

  104.         free(buffers);
  105. }



  106. static void init_mmap(void)
  107. {
  108.         struct v4l2_requestbuffers req;

  109.         CLEAR(req);

  110.         req.count = 4;
  111.         req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  112.         req.memory = V4L2_MEMORY_MMAP;

  113.         if (-1 == xioctl(fd, VIDIOC_REQBUFS&req){
  114.                 if (EINVAL == errno{
  115.                         fprintf(stderr"%s does not support "
  116.                                  "memory mapping\n", dev_name);
  117.                         exit(EXIT_FAILURE);
  118.                 else {
  119.                         errno_exit("VIDIOC_REQBUFS");
  120.                 }
  121.         }

  122.         if (req.count < 2{
  123.                 fprintf(stderr"Insufficient buffer memory on %s\n",
  124.                          dev_name);
  125.                 exit(EXIT_FAILURE);
  126.         }

  127.         buffers = calloc(req.count, sizeof(*buffers));

  128.         if (!buffers{
  129.                 fprintf(stderr"Out of memory\n");
  130.                 exit(EXIT_FAILURE);
  131.         }

  132.         for (n_buffers = 0; n_buffers < req.count++n_buffers{
  133.                 struct v4l2_buffer buf;

  134.                 CLEAR(buf);

  135.                 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  136.                 buf.memory = V4L2_MEMORY_MMAP;
  137.                 buf.index = n_buffers;

  138.                 if (-1 == xioctl(fd, VIDIOC_QUERYBUF&buf))
  139.                         errno_exit("VIDIOC_QUERYBUF");

  140.                 buffers[n_buffers].length = buf.length;
  141.                 buffers[n_buffers].start =
  142.                         mmap(NULL /* start anywhere */,
  143.                               buf.length,
  144.                               PROT_READ | PROT_WRITE /* required */,
  145.                               MAP_SHARED /* recommended */,
  146.                               fd, buf.m.offset);

  147.                 if (MAP_FAILED == buffers[n_buffers].start)
  148.                         errno_exit("mmap");
  149.         }
  150. }


  151. static void init_device(void)
  152. {
  153.         struct v4l2_capability cap;
  154.         struct v4l2_format fmt;

  155.         if (-1 == xioctl(fd, VIDIOC_QUERYCAP&cap){        //测试参数
  156.                 if (EINVAL == errno{
  157.                         fprintf(stderr"%s is no V4L2 device\n",
  158.                                  dev_name);
  159.                         exit(EXIT_FAILURE);
  160.                 else {
  161.                         errno_exit("VIDIOC_QUERYCAP");
  162.                 }
  163.         }

  164.         if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE){
  165.                 fprintf(stderr"%s is no video capture device\n",
  166.                          dev_name);
  167.                 exit(EXIT_FAILURE);
  168.         }

  169.         if (!(cap.capabilities & V4L2_CAP_STREAMING){
  170.                 fprintf(stderr"%s does not support streaming i/o\n",
  171.                     dev_name);
  172.                 exit(EXIT_FAILURE);
  173.         }




  174.         CLEAR(fmt)
  175.         fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  176.         fmt.fmt.pix.width = 640;
  177.         fmt.fmt.pix.height = 480;
  178.         fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
  179.         fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;

  180.         if (-1 == xioctl(fd, VIDIOC_S_FMT&fmt))        //设置格式
  181.                 errno_exit("VIDIOC_S_FMT");        
  182.         init_mmap();
  183. }

  184. static void close_device(void)
  185. {
  186.         if (-1 == close(fd))
  187.                 errno_exit("close");

  188.         fd -1;
  189. }

  190. static void open_device(void)
  191. {
  192.         //加上O_NONBLOCK会出现如下错误
  193.         //VIDIOC_DQBUF error 11, Resource temporarily unavailable
  194.         fd = open(dev_name, O_RDWR /* required */*| O_NONBLOCK*/, 0);

  195.         if (-1 == fd{
  196.                 fprintf(stderr"Cannot open '%s': %d, %s\n",
  197.                          dev_name, errno, strerror(errno));
  198.                 exit(EXIT_FAILURE);
  199.         }
  200. }


  201. int main(int argc, char **argv)
  202. {
  203.         dev_name "/dev/video0";
  204.         
  205.         if(argc != 2)
  206.         {
  207.             printf("usage :%s filename\n", argv[0]);
  208.             exit(0);
  209.         }
  210.         if ((fp = fopen(argv[1]"w")=NULL
  211.             perror("Creat file failed")
  212.             exit(0)
  213.         
  214.         open_device();
  215.         init_device();
  216.         start_capturing();
  217.         mainloop();                //主要处理均在该函数中实现
  218.         fclose(fp);
  219.         stop_capturing();
  220.         uninit_device();
  221.         close_device();
  222.         //fprintf(stderr"\n");
  223.         return 0;
  224. }

Makefile   

点击(此处)折叠或打开

  1. v4l2_capture_example:v4l2_capture_example.c
  2.     gcc -Wall -o  @ <

  3. clean:
  4.     rm -rf v4l2_capture_example

make测试
    运行方法
        $ 
./v4l2_capture_example file.yuv
    
可完成摄像头数据的读取和保存。附上查看YUV格式的软件一枚~~~~~~~
YUV_Tools.rar









本文转自张昺华-sky博客园博客,原文链接:http://www.cnblogs.com/sky-heaven/p/7115061.html,如需转载请自行联系原作者


相关文章
|
7月前
|
Ubuntu Linux 时序数据库
|
2月前
|
Ubuntu 关系型数据库 MySQL
ubuntu使用aliyun源+mysql删除有外键约束的数据+查看特定目录的大小
ubuntu使用aliyun源+mysql删除有外键约束的数据+查看特定目录的大小
87 4
|
4月前
|
Ubuntu Unix Linux
在Ubuntu安装RPM文件
Ubuntu软件源包含数千个deb软件包,可以从Ubuntu软件中心或使用apt命令行安装。 Deb是所有基于Debian的Linux发行版,例如包括Ubuntu,Linux mint等发行版使用的安装包格式。 如果某些软件在Ubuntu软件源中不可用,可以通过启用适当的软件源来安装,然后使用APT命令安装。 在大多数情况下,当软件开发者不提供软件源时,他们都有一个下载页面,您可以在该页面下载并安装deb软件包,或者下载源码然后编译。 虽然不常见,但某些软件开发者可能会仅发布RPM包格式的文件。RPM是Red Hat及其衍生的Linux发行版,例如如CentOS,Fedora使用软件包
|
4月前
|
Windows
Windows——windows10下如何和子系统Ubuntu18.04互传文件
Windows——windows10下如何和子系统Ubuntu18.04互传文件
69 1
|
4月前
|
Ubuntu 网络安全
【ubuntu】目录下文件太多导致rm指令无法执行问题解决方法
【ubuntu】目录下文件太多导致rm指令无法执行问题解决方法
87 0
|
4月前
|
存储 NoSQL Ubuntu
在Ubuntu 14.04上如何备份和恢复Redis数据
在Ubuntu 14.04上如何备份和恢复Redis数据
44 0
|
7月前
|
Ubuntu Unix Linux
在Ubuntu安装RPM文件
Ubuntu使用`apt`和`alien`工具安装软件。`deb`是Ubuntu的标准包格式,但通过`alien`可转换及安装`RPM`包。首先确保启用`Universe`源,然后安装`alien`。转换RPM包为DEB包,运行`sudo alien package_name.rpm`,接着用`sudo apt install package_name.deb`安装。直接安装RPM包可使用`sudo alien -i package_name.rpm`,但这种方法不推荐,可能导致依赖性冲突和系统不稳定。
208 10
|
6月前
|
Ubuntu
蓝易云 - ubuntu系统如何将文件打包成tar.gz
这样,"example"目录就会被打包成"example.tar.gz"文件。
157 0
|
7月前
|
Ubuntu
蓝易云 - ubuntu下自启动设置,为了开机自启动launch文件
完成以上步骤后,每次开机时,Ubuntu系统就会自动启动你指定的launch文件了。
173 0
|
7月前
|
Linux 程序员 Shell
【Linux】详解core dump文件的作用以及用法&&ubuntu20.04下无法形成core dump文件的解决办法
【Linux】详解core dump文件的作用以及用法&&ubuntu20.04下无法形成core dump文件的解决办法
313 0