capture.c
上传用户:ledjyj
上传日期:2014-08-27
资源大小:2639k
文件大小:16k
源码类别:

驱动编程

开发平台:

Unix_Linux

  1. /*
  2.  *  V4L2 video capture example
  3.  *
  4.  *  This program can be used and distributed without restrictions.
  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 <asm/types.h>          /* for videodev2.h */
  20. #include <linux/videodev2.h>
  21. #define CLEAR(x) memset (&(x), 0, sizeof (x))
  22. typedef enum {
  23. IO_METHOD_READ,
  24. IO_METHOD_MMAP,
  25. IO_METHOD_USERPTR,
  26. } io_method;
  27. struct buffer {
  28.         void *                  start;
  29.         size_t                  length;
  30. };
  31. static char *           dev_name        = NULL;
  32. static io_method io = IO_METHOD_MMAP;
  33. static int              fd              = -1;
  34. struct buffer *         buffers         = NULL;
  35. static unsigned int     n_buffers       = 0;
  36. static void
  37. errno_exit                      (const char *           s)
  38. {
  39.         fprintf (stderr, "%s error %d, %sn",
  40.                  s, errno, strerror (errno));
  41.         exit (EXIT_FAILURE);
  42. }
  43. static int
  44. xioctl                          (int                    fd,
  45.                                  int                    request,
  46.                                  void *                 arg)
  47. {
  48.         int r;
  49.         do r = ioctl (fd, request, arg);
  50.         while (-1 == r && EINTR == errno);
  51.         return r;
  52. }
  53. static void
  54. process_image                   (const void *           p)
  55. {
  56.         fputc ('.', stdout);
  57.         fflush (stdout);
  58. }
  59. static int
  60. read_frame (void)
  61. {
  62.         struct v4l2_buffer buf;
  63. unsigned int i;
  64. switch (io) {
  65. case IO_METHOD_READ:
  66.      if (-1 == read (fd, buffers[0].start, buffers[0].length)) {
  67.              switch (errno) {
  68.              case EAGAIN:
  69.                      return 0;
  70. case EIO:
  71. /* Could ignore EIO, see spec. */
  72. /* fall through */
  73. default:
  74. errno_exit ("read");
  75. }
  76. }
  77.      process_image (buffers[0].start);
  78. break;
  79. case IO_METHOD_MMAP:
  80. CLEAR (buf);
  81.              buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  82.              buf.memory = V4L2_MEMORY_MMAP;
  83.      if (-1 == xioctl (fd, VIDIOC_DQBUF, &buf)) {
  84.              switch (errno) {
  85.              case EAGAIN:
  86.                      return 0;
  87. case EIO:
  88. /* Could ignore EIO, see spec. */
  89. /* fall through */
  90. default:
  91. errno_exit ("VIDIOC_DQBUF");
  92. }
  93. }
  94.                 assert (buf.index < n_buffers);
  95.         process_image (buffers[buf.index].start);
  96. if (-1 == xioctl (fd, VIDIOC_QBUF, &buf))
  97. errno_exit ("VIDIOC_QBUF");
  98. break;
  99. case IO_METHOD_USERPTR:
  100. CLEAR (buf);
  101.      buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  102.      buf.memory = V4L2_MEMORY_USERPTR;
  103. if (-1 == xioctl (fd, VIDIOC_DQBUF, &buf)) {
  104. switch (errno) {
  105. case EAGAIN:
  106. return 0;
  107. case EIO:
  108. /* Could ignore EIO, see spec. */
  109. /* fall through */
  110. default:
  111. errno_exit ("VIDIOC_DQBUF");
  112. }
  113. }
  114. for (i = 0; i < n_buffers; ++i)
  115. if (buf.m.userptr == (unsigned long) buffers[i].start
  116.     && buf.length == buffers[i].length)
  117. break;
  118. assert (i < n_buffers);
  119.      process_image ((void *) buf.m.userptr);
  120. if (-1 == xioctl (fd, VIDIOC_QBUF, &buf))
  121. errno_exit ("VIDIOC_QBUF");
  122. break;
  123. }
  124. return 1;
  125. }
  126. static void
  127. mainloop                        (void)
  128. {
  129. unsigned int count;
  130.         count = 100;
  131.         while (count-- > 0) {
  132.                 for (;;) {
  133.                         fd_set fds;
  134.                         struct timeval tv;
  135.                         int r;
  136.                         FD_ZERO (&fds);
  137.                         FD_SET (fd, &fds);
  138.                         /* Timeout. */
  139.                         tv.tv_sec = 2;
  140.                         tv.tv_usec = 0;
  141.                         r = select (fd + 1, &fds, NULL, NULL, &tv);
  142.                         if (-1 == r) {
  143.                                 if (EINTR == errno)
  144.                                         continue;
  145.                                 errno_exit ("select");
  146.                         }
  147.                         if (0 == r) {
  148.                                 fprintf (stderr, "select timeoutn");
  149.                                 exit (EXIT_FAILURE);
  150.                         }
  151. if (read_frame ())
  152.                      break;
  153. /* EAGAIN - continue select loop. */
  154.                 }
  155.         }
  156. }
  157. static void
  158. stop_capturing                  (void)
  159. {
  160.         enum v4l2_buf_type type;
  161. switch (io) {
  162. case IO_METHOD_READ:
  163. /* Nothing to do. */
  164. break;
  165. case IO_METHOD_MMAP:
  166. case IO_METHOD_USERPTR:
  167. type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  168. if (-1 == xioctl (fd, VIDIOC_STREAMOFF, &type))
  169. errno_exit ("VIDIOC_STREAMOFF");
  170. break;
  171. }
  172. }
  173. static void
  174. start_capturing                 (void)
  175. {
  176.         unsigned int i;
  177.         enum v4l2_buf_type type;
  178. switch (io) {
  179. case IO_METHOD_READ:
  180. /* Nothing to do. */
  181. break;
  182. case IO_METHOD_MMAP:
  183. for (i = 0; i < n_buffers; ++i) {
  184.              struct v4l2_buffer buf;
  185.          CLEAR (buf);
  186.          buf.type        = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  187.          buf.memory      = V4L2_MEMORY_MMAP;
  188.          buf.index       = i;
  189.          if (-1 == xioctl (fd, VIDIOC_QBUF, &buf))
  190.                      errno_exit ("VIDIOC_QBUF");
  191. }
  192. type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  193. if (-1 == xioctl (fd, VIDIOC_STREAMON, &type))
  194. errno_exit ("VIDIOC_STREAMON");
  195. break;
  196. case IO_METHOD_USERPTR:
  197. for (i = 0; i < n_buffers; ++i) {
  198.              struct v4l2_buffer buf;
  199.          CLEAR (buf);
  200.          buf.type        = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  201.          buf.memory      = V4L2_MEMORY_USERPTR;
  202. buf.index       = i;
  203. buf.m.userptr = (unsigned long) buffers[i].start;
  204. buf.length      = buffers[i].length;
  205. if (-1 == xioctl (fd, VIDIOC_QBUF, &buf))
  206.                      errno_exit ("VIDIOC_QBUF");
  207. }
  208. type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  209. if (-1 == xioctl (fd, VIDIOC_STREAMON, &type))
  210. errno_exit ("VIDIOC_STREAMON");
  211. break;
  212. }
  213. }
  214. static void
  215. uninit_device                   (void)
  216. {
  217.         unsigned int i;
  218. switch (io) {
  219. case IO_METHOD_READ:
  220. free (buffers[0].start);
  221. break;
  222. case IO_METHOD_MMAP:
  223. for (i = 0; i < n_buffers; ++i)
  224. if (-1 == munmap (buffers[i].start, buffers[i].length))
  225. errno_exit ("munmap");
  226. break;
  227. case IO_METHOD_USERPTR:
  228. for (i = 0; i < n_buffers; ++i)
  229. free (buffers[i].start);
  230. break;
  231. }
  232. free (buffers);
  233. }
  234. static void
  235. init_read (unsigned int buffer_size)
  236. {
  237.         buffers = calloc (1, sizeof (*buffers));
  238.         if (!buffers) {
  239.                 fprintf (stderr, "Out of memoryn");
  240.                 exit (EXIT_FAILURE);
  241.         }
  242. buffers[0].length = buffer_size;
  243. buffers[0].start = malloc (buffer_size);
  244. if (!buffers[0].start) {
  245.      fprintf (stderr, "Out of memoryn");
  246.              exit (EXIT_FAILURE);
  247. }
  248. }
  249. static void
  250. init_mmap (void)
  251. {
  252. struct v4l2_requestbuffers req;
  253.         CLEAR (req);
  254.         req.count               = 4;
  255.         req.type                = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  256.         req.memory              = V4L2_MEMORY_MMAP;
  257. if (-1 == xioctl (fd, VIDIOC_REQBUFS, &req)) {
  258.                 if (EINVAL == errno) {
  259.                         fprintf (stderr, "%s does not support "
  260.                                  "memory mappingn", dev_name);
  261.                         exit (EXIT_FAILURE);
  262.                 } else {
  263.                         errno_exit ("VIDIOC_REQBUFS");
  264.                 }
  265.         }
  266.         if (req.count < 2) {
  267.                 fprintf (stderr, "Insufficient buffer memory on %sn",
  268.                          dev_name);
  269.                 exit (EXIT_FAILURE);
  270.         }
  271.         buffers = calloc (req.count, sizeof (*buffers));
  272.         if (!buffers) {
  273.                 fprintf (stderr, "Out of memoryn");
  274.                 exit (EXIT_FAILURE);
  275.         }
  276.         for (n_buffers = 0; n_buffers < req.count; ++n_buffers) {
  277.                 struct v4l2_buffer buf;
  278.                 CLEAR (buf);
  279.                 buf.type        = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  280.                 buf.memory      = V4L2_MEMORY_MMAP;
  281.                 buf.index       = n_buffers;
  282.                 if (-1 == xioctl (fd, VIDIOC_QUERYBUF, &buf))
  283.                         errno_exit ("VIDIOC_QUERYBUF");
  284.                 buffers[n_buffers].length = buf.length;
  285.                 buffers[n_buffers].start =
  286.                         mmap (NULL /* start anywhere */,
  287.                               buf.length,
  288.                               PROT_READ | PROT_WRITE /* required */,
  289.                               MAP_SHARED /* recommended */,
  290.                               fd, buf.m.offset);
  291.                 if (MAP_FAILED == buffers[n_buffers].start)
  292.                         errno_exit ("mmap");
  293.         }
  294. }
  295. static void
  296. init_userp (unsigned int buffer_size)
  297. {
  298. struct v4l2_requestbuffers req;
  299.         CLEAR (req);
  300.         req.count               = 4;
  301.         req.type                = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  302.         req.memory              = V4L2_MEMORY_USERPTR;
  303.         if (-1 == xioctl (fd, VIDIOC_REQBUFS, &req)) {
  304.                 if (EINVAL == errno) {
  305.                         fprintf (stderr, "%s does not support "
  306.                                  "user pointer i/on", dev_name);
  307.                         exit (EXIT_FAILURE);
  308.                 } else {
  309.                         errno_exit ("VIDIOC_REQBUFS");
  310.                 }
  311.         }
  312.         buffers = calloc (4, sizeof (*buffers));
  313.         if (!buffers) {
  314.                 fprintf (stderr, "Out of memoryn");
  315.                 exit (EXIT_FAILURE);
  316.         }
  317.         for (n_buffers = 0; n_buffers < 4; ++n_buffers) {
  318.                 buffers[n_buffers].length = buffer_size;
  319.                 buffers[n_buffers].start = malloc (buffer_size);
  320.                 if (!buffers[n_buffers].start) {
  321.      fprintf (stderr, "Out of memoryn");
  322.              exit (EXIT_FAILURE);
  323. }
  324.         }
  325. }
  326. static void
  327. init_device                     (void)
  328. {
  329.         struct v4l2_capability cap;
  330.         struct v4l2_cropcap cropcap;
  331.         struct v4l2_crop crop;
  332.         struct v4l2_format fmt;
  333. unsigned int min;
  334.         if (-1 == xioctl (fd, VIDIOC_QUERYCAP, &cap)) {
  335.                 if (EINVAL == errno) {
  336.                         fprintf (stderr, "%s is no V4L2 devicen",
  337.                                  dev_name);
  338.                         exit (EXIT_FAILURE);
  339.                 } else {
  340.                         errno_exit ("VIDIOC_QUERYCAP");
  341.                 }
  342.         }
  343.         if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) {
  344.                 fprintf (stderr, "%s is no video capture devicen",
  345.                          dev_name);
  346.                 exit (EXIT_FAILURE);
  347.         }
  348. switch (io) {
  349. case IO_METHOD_READ:
  350. if (!(cap.capabilities & V4L2_CAP_READWRITE)) {
  351. fprintf (stderr, "%s does not support read i/on",
  352.  dev_name);
  353. exit (EXIT_FAILURE);
  354. }
  355. break;
  356. case IO_METHOD_MMAP:
  357. case IO_METHOD_USERPTR:
  358. if (!(cap.capabilities & V4L2_CAP_STREAMING)) {
  359. fprintf (stderr, "%s does not support streaming i/on",
  360.  dev_name);
  361. exit (EXIT_FAILURE);
  362. }
  363. break;
  364. }
  365.         /* Select video input, video standard and tune here. */
  366. CLEAR (cropcap);
  367.         cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  368.         if (0 == xioctl (fd, VIDIOC_CROPCAP, &cropcap)) {
  369.                 crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  370.                 crop.c = cropcap.defrect; /* reset to default */
  371.                 if (-1 == xioctl (fd, VIDIOC_S_CROP, &crop)) {
  372.                         switch (errno) {
  373.                         case EINVAL:
  374.                                 /* Cropping not supported. */
  375.                                 break;
  376.                         default:
  377.                                 /* Errors ignored. */
  378.                                 break;
  379.                         }
  380.                 }
  381.         } else {
  382.                 /* Errors ignored. */
  383.         }
  384.         CLEAR (fmt);
  385.         fmt.type                = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  386.         fmt.fmt.pix.width       = 640; 
  387.         fmt.fmt.pix.height      = 480;
  388.         fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
  389.         fmt.fmt.pix.field       = V4L2_FIELD_INTERLACED;
  390.         if (-1 == xioctl (fd, VIDIOC_S_FMT, &fmt))
  391.                 errno_exit ("VIDIOC_S_FMT");
  392.         /* Note VIDIOC_S_FMT may change width and height. */
  393. /* Buggy driver paranoia. */
  394. min = fmt.fmt.pix.width * 2;
  395. if (fmt.fmt.pix.bytesperline < min)
  396. fmt.fmt.pix.bytesperline = min;
  397. min = fmt.fmt.pix.bytesperline * fmt.fmt.pix.height;
  398. if (fmt.fmt.pix.sizeimage < min)
  399. fmt.fmt.pix.sizeimage = min;
  400. switch (io) {
  401. case IO_METHOD_READ:
  402. init_read (fmt.fmt.pix.sizeimage);
  403. break;
  404. case IO_METHOD_MMAP:
  405. init_mmap ();
  406. break;
  407. case IO_METHOD_USERPTR:
  408. init_userp (fmt.fmt.pix.sizeimage);
  409. break;
  410. }
  411. }
  412. static void
  413. close_device                    (void)
  414. {
  415.         if (-1 == close (fd))
  416.         errno_exit ("close");
  417.         fd = -1;
  418. }
  419. static void
  420. open_device                     (void)
  421. {
  422.         struct stat st; 
  423.         if (-1 == stat (dev_name, &st)) {
  424.                 fprintf (stderr, "Cannot identify '%s': %d, %sn",
  425.                          dev_name, errno, strerror (errno));
  426.                 exit (EXIT_FAILURE);
  427.         }
  428.         if (!S_ISCHR (st.st_mode)) {
  429.                 fprintf (stderr, "%s is no devicen", dev_name);
  430.                 exit (EXIT_FAILURE);
  431.         }
  432.         fd = open (dev_name, O_RDWR /* required */ | O_NONBLOCK, 0);
  433.         if (-1 == fd) {
  434.                 fprintf (stderr, "Cannot open '%s': %d, %sn",
  435.                          dev_name, errno, strerror (errno));
  436.                 exit (EXIT_FAILURE);
  437.         }
  438. }
  439. static void
  440. usage                           (FILE *                 fp,
  441.                                  int                    argc,
  442.                                  char **                argv)
  443. {
  444.         fprintf (fp,
  445.                  "Usage: %s [options]nn"
  446.                  "Options:n"
  447.                  "-d | --device name   Video device name [/dev/video]n"
  448.                  "-h | --help          Print this messagen"
  449.                  "-m | --mmap          Use memory mapped buffersn"
  450.                  "-r | --read          Use read() callsn"
  451.                  "-u | --userp         Use application allocated buffersn"
  452.                  "",
  453.  argv[0]);
  454. }
  455. static const char short_options [] = "d:hmru";
  456. static const struct option
  457. long_options [] = {
  458.         { "device",     required_argument,      NULL,           'd' },
  459.         { "help",       no_argument,            NULL,           'h' },
  460.         { "mmap",       no_argument,            NULL,           'm' },
  461.         { "read",       no_argument,            NULL,           'r' },
  462.         { "userp",      no_argument,            NULL,           'u' },
  463.         { 0, 0, 0, 0 }
  464. };
  465. int
  466. main                            (int                    argc,
  467.                                  char **                argv)
  468. {
  469.         dev_name = "/dev/video";
  470.         for (;;) {
  471.                 int index;
  472.                 int c;
  473.                 
  474.                 c = getopt_long (argc, argv,
  475.                                  short_options, long_options,
  476.                                  &index);
  477.                 if (-1 == c)
  478.                         break;
  479.                 switch (c) {
  480.                 case 0: /* getopt_long() flag */
  481.                         break;
  482.                 case 'd':
  483.                         dev_name = optarg;
  484.                         break;
  485.                 case 'h':
  486.                         usage (stdout, argc, argv);
  487.                         exit (EXIT_SUCCESS);
  488.                 case 'm':
  489.                         io = IO_METHOD_MMAP;
  490. break;
  491.                 case 'r':
  492.                         io = IO_METHOD_READ;
  493. break;
  494.                 case 'u':
  495.                         io = IO_METHOD_USERPTR;
  496. break;
  497.                 default:
  498.                         usage (stderr, argc, argv);
  499.                         exit (EXIT_FAILURE);
  500.                 }
  501.         }
  502.         open_device ();
  503.         init_device ();
  504.         start_capturing ();
  505.         mainloop ();
  506.         stop_capturing ();
  507.         uninit_device ();
  508.         close_device ();
  509.         exit (EXIT_SUCCESS);
  510.         return 0;
  511. }