capture.c.xml 19 KB

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