主题 : Tinny4412使用usb摄像头 复制链接 | 浏览器收藏 | 打印
级别: 新手上路
UID: 118746
精华: 0
发帖: 4
金钱: 20 两
威望: 4 点
综合积分: 8 分
注册时间: 2015-09-06
最后登录: 2015-12-20
楼主  发表于: 2015-12-10 22:37

 Tinny4412使用usb摄像头

      使用Tinny做usb摄像头的开发,在开发板上能正确识别设备、能打开设备、能设置参数、能获取设备信息、就是不能获取数据。直接使用VIDIOC_DQBUF系统就死机,使用select函数则报“select timeout”错误(select函数返回值为22即EINVA),但在linux(内核版本为2.6.29)下能运行正常。
       刚学ARM开发,请各位大神解救小弟啊!
              我使用的是开发板自带的内核,也做了v4l的配置,如下:
Device Drivers --->
    <*> Multimedia support --->
        <*> Video For Linux
        [*] Enable Video For Linux API 1 (DEPRECATED)
        [*] Video capture adapters --->
            [*] V4L USB devices --->
                <*> USB Video Class (UVC)
                [*] UVC input events device support
                [*] GSPCA based webcams --->
测试程序用的是官方 v4l2 video capture example
复制代码
  1. /*
  2.  *  V4L2 video capture example
  3.  *
  4.  *  This program can be used and distributed without restrictions.
  5.  *
  6.  *      This program is provided with the V4L2 API
  7.  * see http://linuxtv.org/docs.php for more information
  8.  */
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11. #include <string.h>
  12. #include <assert.h>
  13. #include <getopt.h>             /* getopt_long() */
  14. #include <fcntl.h>              /* low-level i/o */
  15. #include <unistd.h>
  16. #include <errno.h>
  17. #include <sys/stat.h>
  18. #include <sys/types.h>
  19. #include <sys/time.h>
  20. #include <sys/mman.h>
  21. #include <sys/ioctl.h>
  22. #include <linux/videodev2.h>
  23. #define CLEAR(x) memset(&(x), 0, sizeof(x))
  24. enum io_method {
  25.         IO_METHOD_READ,
  26.         IO_METHOD_MMAP,
  27.         IO_METHOD_USERPTR,
  28. };
  29. struct buffer {
  30.         void   *start;
  31.         size_t  length;
  32. };
  33. static char            *dev_name;
  34. static enum io_method   io = IO_METHOD_MMAP;
  35. static int              fd = -1;
  36. struct buffer          *buffers;
  37. static unsigned int     n_buffers;
  38. static int              out_buf;
  39. static int              force_format;
  40. static int              frame_count = 70;
  41. static void errno_exit(const char *s)
  42. {
  43.         fprintf(stderr, "%s error %d, %s\n", s, errno, strerror(errno));
  44.         exit(EXIT_FAILURE);
  45. }
  46. static int xioctl(int fh, int request, void *arg)
  47. {
  48.         int r;
  49.         do {
  50.                 r = ioctl(fh, request, arg);
  51.         } while (-1 == r && EINTR == errno);
  52.         return r;
  53. }
  54. static int read_frame(void)
  55. {
  56.         struct v4l2_buffer buf;
  57.         unsigned int i;
  58.         switch (io) {
  59.         case IO_METHOD_READ: 
  60.               //省略直接读的代码
  61.                 break;
  62.         case IO_METHOD_MMAP:
  63.                 CLEAR(buf);
  64.                 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  65.                 buf.memory = V4L2_MEMORY_MMAP;
  66.                 if (-1 == xioctl(fd, VIDIOC_DQBUF, &buf)) {
  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("VIDIOC_DQBUF");
  75.                         }
  76.                 }
  77.                 assert(buf.index < n_buffers);
  78.                 process_image(buffers[buf.index].start, buf.bytesused);
  79.                 if (-1 == xioctl(fd, VIDIOC_QBUF, &buf))
  80.                         errno_exit("VIDIOC_QBUF");
  81.                 break;
  82.         case IO_METHOD_USERPTR: 
  83.            //这种模式的也不用
  84.                 break;
  85.         }
  86.         return 1;
  87. }
  88. /* two operations
  89.  * step1 : delay
  90.  * step2 : read frame
  91.  */
  92. static void mainloop(void)
  93. {
  94.         unsigned int count;
  95.         count = frame_count;
  96.         while (count-- > 0) {
  97.                 for (;;) {
  98.                         fd_set fds;
  99.                         struct timeval tv;
  100.                         int r;
  101.                         FD_ZERO(&fds);
  102.                         FD_SET(fd, &fds);
  103.                         /* Timeout. */
  104.                         tv.tv_sec = 2;
  105.                         tv.tv_usec = 0;
  106.                         r = select(fd + 1, &fds, NULL, NULL, &tv);
  107.                         if (-1 == r) {
  108.                                 if (EINTR == errno)
  109.                                         continue;
  110.                                 errno_exit("select");
  111.                         }
  112.                         if (0 == r) {
  113.                                 fprintf(stderr, "select timeout\n");
  114.                                 exit(EXIT_FAILURE);
  115.                         }
  116.                         if (read_frame())
  117.                                 break;
  118.                         /* EAGAIN - continue select loop. */
  119.                 }
  120.         }
  121. }
  122. /*
  123.  * one operation
  124.  * step1 : VIDIOC_STREAMOFF
  125.  */
  126. static void stop_capturing(void)
  127. {
  128.         enum v4l2_buf_type type;
  129.         switch (io) {
  130.         case IO_METHOD_READ:
  131.                 /* Nothing to do. */
  132.                 break;
  133.         case IO_METHOD_MMAP:
  134.         case IO_METHOD_USERPTR:
  135.                 type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  136.                 if (-1 == xioctl(fd, VIDIOC_STREAMOFF, &type))
  137.                         errno_exit("VIDIOC_STREAMOFF");
  138.                 break;
  139.         }
  140. }
  141. /* tow operations
  142.  * step1 : VIDIOC_QBUF(insert buffer to queue)
  143.  * step2 : VIDIOC_STREAMOFF
  144.  */
  145. static void start_capturing(void)
  146. {
  147.         unsigned int i;
  148.         enum v4l2_buf_type type;
  149.         switch (io) {
  150.         case IO_METHOD_READ:
  151.                 /* Nothing to do. */
  152.                 break;
  153.         case IO_METHOD_MMAP:
  154.                 for (i = 0; i < n_buffers; ++i) {
  155.                         struct v4l2_buffer buf;
  156.                         CLEAR(buf);
  157.                         buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  158.                         buf.memory = V4L2_MEMORY_MMAP;
  159.                         buf.index = i;
  160.                         if (-1 == xioctl(fd, VIDIOC_QBUF, &buf))
  161.                                 errno_exit("VIDIOC_QBUF");
  162.                 }
  163.                 type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  164.                 if (-1 == xioctl(fd, VIDIOC_STREAMON, &type))
  165.                         errno_exit("VIDIOC_STREAMON");
  166.                 break;
  167.         case IO_METHOD_USERPTR: 
  168.               //省略
  169.                 break;
  170.         }
  171. }
  172. /* two operations
  173.  * step1 : munmap buffers
  174.  * steo2 : free buffers
  175.  */
  176. static void uninit_device(void)
  177. {
  178.         unsigned int i;
  179.         switch (io) {
  180.         case IO_METHOD_READ:
  181.                 free(buffers[0].start);
  182.                 break;
  183.         case IO_METHOD_MMAP:
  184.                 for (i = 0; i < n_buffers; ++i)
  185.                         if (-1 == munmap(buffers[i].start, buffers[i].length))
  186.                                 errno_exit("munmap");
  187.                 break;
  188.         case IO_METHOD_USERPTR: 
  189.                  //省略
  190.                 break;
  191.         }
  192.         free(buffers);
  193. }
  194. static void init_read(unsigned int buffer_size)
  195.          //省略
  196. }
  197. static void init_mmap(void)
  198. {
  199.         struct v4l2_requestbuffers req;
  200.         CLEAR(req);
  201.         req.count = 4;
  202.         req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  203.         req.memory = V4L2_MEMORY_MMAP;
  204.         if (-1 == xioctl(fd, VIDIOC_REQBUFS, &req)) {
  205.                 if (EINVAL == errno) {
  206.                         fprintf(stderr, "%s does not support "
  207.                                  "memory mapping\n", dev_name);
  208.                         exit(EXIT_FAILURE);
  209.                 } else {
  210.                         errno_exit("VIDIOC_REQBUFS");
  211.                 }
  212.         }
  213.         if (req.count < 2) {
  214.                 fprintf(stderr, "Insufficient buffer memory on %s\n",
  215.                          dev_name);
  216.                 exit(EXIT_FAILURE);
  217.         }
  218.         buffers = calloc(req.count, sizeof(*buffers));
  219.         if (!buffers) {
  220.                 fprintf(stderr, "Out of memory\n");
  221.                 exit(EXIT_FAILURE);
  222.         }
  223.         for (n_buffers = 0; n_buffers < req.count; ++n_buffers) {
  224.                 struct v4l2_buffer buf;
  225.                 CLEAR(buf);
  226.                 buf.type        = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  227.                 buf.memory      = V4L2_MEMORY_MMAP;
  228.                 buf.index       = n_buffers;
  229.                 if (-1 == xioctl(fd, VIDIOC_QUERYBUF, &buf))
  230.                         errno_exit("VIDIOC_QUERYBUF");
  231.                 buffers[n_buffers].length = buf.length;
  232.                 buffers[n_buffers].start =
  233.                         mmap(NULL /* start anywhere */,
  234.                               buf.length,
  235.                               PROT_READ | PROT_WRITE /* required */,
  236.                               MAP_SHARED /* recommended */,
  237.                               fd, buf.m.offset);
  238.                 if (MAP_FAILED == buffers[n_buffers].start)
  239.                         errno_exit("mmap");
  240.         }
  241. }
  242. static void init_userp(unsigned int buffer_size)
  243.           //省略
  244. }
  245. /* five operations
  246.  * step1 : cap :query camera's capability and check it(is a video device? is it support read? is it support streaming?)
  247.  * step2 : cropcap:set cropcap's type and get cropcap by VIDIOC_CROPCAP
  248.  * step3 : set crop parameter by VIDIOC_S_CROP (such as frame type and angle)
  249.  * step4 : set fmt
  250.  * step5 : mmap
  251.  */
  252. static void init_device(void)
  253. {
  254.         struct v4l2_capability cap;
  255.         struct v4l2_cropcap cropcap;
  256.         struct v4l2_crop crop;
  257.         struct v4l2_format fmt;
  258.         unsigned int min;
  259.         if (-1 == xioctl(fd, VIDIOC_QUERYCAP, &cap)) {
  260.                 if (EINVAL == errno) {
  261.                         fprintf(stderr, "%s is no V4L2 device\n",
  262.                                  dev_name);
  263.                         exit(EXIT_FAILURE);
  264.                 } else {
  265.                         errno_exit("VIDIOC_QUERYCAP");
  266.                 }
  267.         }
  268.         if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) {
  269.                 fprintf(stderr, "%s is no video capture device\n",
  270.                          dev_name);
  271.                 exit(EXIT_FAILURE);
  272.         }
  273.         switch (io) {
  274.         case IO_METHOD_READ:
  275.                 if (!(cap.capabilities & V4L2_CAP_READWRITE)) {
  276.                         fprintf(stderr, "%s does not support read i/o\n",
  277.                                  dev_name);
  278.                         exit(EXIT_FAILURE);
  279.                 }
  280.                 break;
  281.         case IO_METHOD_MMAP:
  282.         case IO_METHOD_USERPTR:
  283.                 if (!(cap.capabilities & V4L2_CAP_STREAMING)) {
  284.                         fprintf(stderr, "%s does not support streaming i/o\n",
  285.                                  dev_name);
  286.                         exit(EXIT_FAILURE);
  287.                 }
  288.                 break;
  289.         }
  290.         /* Select video input, video standard and tune here. */
  291.         CLEAR(cropcap);
  292.         cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  293.         /* if device support cropcap's type then set crop */
  294.         if (0 == xioctl(fd, VIDIOC_CROPCAP, &cropcap)) {
  295.                 crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  296.                 crop.c = cropcap.defrect; /* reset to default */
  297.                 if (-1 == xioctl(fd, VIDIOC_S_CROP, &crop)) {
  298.                         switch (errno) {
  299.                         case EINVAL:
  300.                                 /* Cropping not supported. */
  301.                                 break;
  302.                         default:
  303.                                 /* Errors ignored. */
  304.                                 break;
  305.                         }
  306.                 }
  307.         } else {
  308.                 /* Errors ignored. */
  309.         }
  310.         CLEAR(fmt);
  311.         fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  312.         if (force_format) {
  313.                 fmt.fmt.pix.width       = 640;
  314.                 fmt.fmt.pix.height      = 480;
  315.                 fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
  316.                 fmt.fmt.pix.field       = V4L2_FIELD_INTERLACED;
  317.                 if (-1 == xioctl(fd, VIDIOC_S_FMT, &fmt))
  318.                         errno_exit("VIDIOC_S_FMT");
  319.                 /* Note VIDIOC_S_FMT may change width and height. */
  320.         } else {
  321.                 /* Preserve original settings as set by v4l2-ctl for example */
  322.                 if (-1 == xioctl(fd, VIDIOC_G_FMT, &fmt))
  323.                         errno_exit("VIDIOC_G_FMT");
  324.         }
  325.         /* Buggy driver paranoia. */
  326.         min = fmt.fmt.pix.width * 2;
  327.         if (fmt.fmt.pix.bytesperline < min)
  328.                 fmt.fmt.pix.bytesperline = min;
  329.         min = fmt.fmt.pix.bytesperline * fmt.fmt.pix.height;
  330.         if (fmt.fmt.pix.sizeimage < min)
  331.                 fmt.fmt.pix.sizeimage = min;
  332.         switch (io) {
  333.         case IO_METHOD_READ:
  334.                 init_read(fmt.fmt.pix.sizeimage);
  335.                 break;
  336.         case IO_METHOD_MMAP:
  337.                 init_mmap();
  338.                 break;
  339.         case IO_METHOD_USERPTR:
  340.                 init_userp(fmt.fmt.pix.sizeimage);
  341.                 break;
  342.         }
  343. }
  344. /*
  345.  * close (fd)
  346.  */
  347. static void close_device(void)
  348. {
  349.         if (-1 == close(fd))
  350.                 errno_exit("close");
  351.         fd = -1;
  352. }
  353. /* three operations
  354.  * step 1 : check dev_name and st_mode
  355.  * step 2 : open(device)
  356.  */
  357. static void open_device(void)
  358. {
  359.         struct stat st;
  360.         if (-1 == stat(dev_name, &st)) {
  361.                 fprintf(stderr, "Cannot identify '%s': %d, %s\n",
  362.                          dev_name, errno, strerror(errno));
  363.                 exit(EXIT_FAILURE);
  364.         }
  365.         if (!S_ISCHR(st.st_mode)) {
  366.                 fprintf(stderr, "%s is no device\n", dev_name);
  367.                 exit(EXIT_FAILURE);
  368.         }
  369.         fd = open(dev_name, O_RDWR /* required */ | O_NONBLOCK, 0);
  370.         if (-1 == fd) {
  371.                 fprintf(stderr, "Cannot open '%s': %d, %s\n",
  372.                          dev_name, errno, strerror(errno));
  373.                 exit(EXIT_FAILURE);
  374.         }
  375. }
  376. static void usage(FILE *fp, int argc, char **argv)
  377. {
  378.         fprintf(fp,
  379.                  "Usage: %s [options]\n\n"
  380.                  "Version 1.3\n"
  381.                  "Options:\n"
  382.                  "-d | --device name   Video device name [%s]\n"
  383.                  "-h | --help          Print this message\n"
  384.                  "-m | --mmap          Use memory mapped buffers [default]\n"
  385.                  "-r | --read          Use read() calls\n"
  386.                  "-u | --userp         Use application allocated buffers\n"
  387.                  "-o | --output        Outputs stream to stdout\n"
  388.                  "-f | --format        Force format to 640x480 YUYV\n"
  389.                  "-c | --count         Number of frames to grab [%i]\n"
  390.                  "",
  391.                  argv[0], dev_name, frame_count);
  392. }
  393. static const char short_options[] = "d:hmruofc:";
  394. static const struct option
  395. long_options[] = {
  396.         { "device", required_argument, NULL, 'd' },
  397.         { "help",   no_argument,       NULL, 'h' },
  398.         { "mmap",   no_argument,       NULL, 'm' },
  399.         { "read",   no_argument,       NULL, 'r' },
  400.         { "userp",  no_argument,       NULL, 'u' },
  401.         { "output", no_argument,       NULL, 'o' },
  402.         { "format", no_argument,       NULL, 'f' },
  403.         { "count",  required_argument, NULL, 'c' },
  404.         { 0, 0, 0, 0 }
  405. };
  406. int main(int argc, char **argv)
  407. {
  408.         dev_name = "/dev/video4";
  409.         for (;;) {
  410.                 int idx;
  411.                 int c;
  412.                 c = getopt_long(argc, argv,
  413.                                 short_options, long_options, &idx);
  414.                 if (-1 == c)
  415.                         break;
  416.                 switch (c) {
  417.                 case 0: /* getopt_long() flag */
  418.                         break;
  419.                 case 'd':
  420.                         dev_name = optarg;
  421.                         break;
  422.                 case 'h':
  423.                         usage(stdout, argc, argv);
  424.                         exit(EXIT_SUCCESS);
  425.                 case 'm':
  426.                         io = IO_METHOD_MMAP;
  427.                         break;
  428.                 case 'r':
  429.                         io = IO_METHOD_READ;
  430.                         break;
  431.                 case 'u':
  432.                         io = IO_METHOD_USERPTR;
  433.                         break;
  434.                 case 'o':
  435.                         out_buf++;
  436.                         break;
  437.                 case 'f':
  438.                         force_format++;
  439.                         break;
  440.                 case 'c':
  441.                         errno = 0;
  442.                         frame_count = strtol(optarg, NULL, 0);
  443.                         if (errno)
  444.                                 errno_exit(optarg);
  445.                         break;
  446.                 default:
  447.                         usage(stderr, argc, argv);
  448.                         exit(EXIT_FAILURE);
  449.                 }
  450.         }
  451.         open_device();
  452.         init_device();
  453.         start_capturing();
  454.         mainloop();
  455.         stop_capturing();
  456.         uninit_device();
  457.         close_device();
  458.         fprintf(stderr, "\n");
  459.         return 0;
  460. }