xcaptest.c
上传用户:aoeyumen
上传日期:2007-01-06
资源大小:3329k
文件大小:15k
源码类别:

DVD

开发平台:

Unix_Linux

  1. /* X Window Video Capture Testing Tool
  2.  *
  3.  * For testing a Video for Linux Two video capture driver
  4.  *
  5.  * This program was written by Bill Dirks.
  6.  * This program is in the public domain.
  7.  *
  8.  * gcc -o xcaptest -L/usr/X11R6/lib/ -lXt -lXaw -Wall xcaptest.c
  9.  *
  10.  * ./xcaptest [-b] [device-node]
  11.  *
  12.  * -b The X Window screen is 32 bits-per-pixel. */
  13. /*  This program does not properly detect when the X Windows desktop is
  14.  *  32 bits per pixel. (Some X functions use a value of 24 for the depth
  15.  *  when it is really 32 for reasons I don't understand.) As a workaround,
  16.  *  if you are running a 32-bpp X Windows screen, use -b on the command
  17.  *  line, or uncomment this line:  */
  18. //#define X_DEPTH  32
  19. /*  Set these according to your capture device set-up */
  20. #define MY_DEVICE "/dev/video0"
  21. //#define MY_STD   "NTSC" /*-> "PAL" or "NTSC" */
  22. #define MY_WIDTH  704
  23. #define MY_HEIGHT 240
  24. #define MY_INPUT  0
  25. /*  MY_PIXELFORMAT should match your X Window screen mode  */
  26. /*  If MY_PIXELFORMAT is not defined, capturing will be set to the
  27.     screen format automatically (I hope)  */
  28. //#define MY_PIXELFORMAT V4L2_PIX_FMT_BGR32
  29. /* V4L2_PIX_FMT_YUYV */
  30. /* V4L2_PIX_FMT_GREY */
  31. /* V4L2_PIX_FMT_YUV420 */
  32. /* V4L2_PIX_FMT_RGB555 */
  33. /* V4L2_PIX_FMT_RGB565 */
  34. /* V4L2_PIX_FMT_BGR24 */
  35. /* V4L2_PIX_FMT_BGR32 */
  36. /*  Uncomment the following to test stuff  */
  37. #define TEST_INPUTS      /* enumerate the inputs */
  38. #define TEST_FORMATS     /* enumerate the image formats */
  39. #define TEST_CONTROLS    /* enumerate the controls */
  40. #define TEST_CAPTURE     /* test video capture */
  41. #define TEST_STREAMING   /* test streaming capture */
  42. //#define TEST_FRAMERATE 400000  /* 10million / frames-per-second */
  43. #define STREAMBUFS 2
  44. #include <sys/time.h>
  45. #include <sys/types.h>
  46. #include <sys/stat.h>
  47. #include <sys/ioctl.h>
  48. #include <fcntl.h>
  49. #include <unistd.h>
  50. #include <stdlib.h>
  51. #include <stdio.h>
  52. #include <sys/mman.h>
  53. #include <errno.h>
  54. #define max(a,b) ((a) > (b) ? (a) : (b))
  55. /* These are needed to use the Videum driver */
  56. #include <linux/fs.h>
  57. #include <linux/kernel.h>
  58. #include <linux/videodev2.h>  /* Video for Linux Two */
  59. #include <X11/StringDefs.h>
  60. #include <X11/Intrinsic.h>
  61. #include <X11/Xaw/Box.h>
  62. #include <X11/Xaw/Command.h>
  63. #include <X11/Xaw/Porthole.h>
  64. #include <X11/Xaw/MenuButton.h>
  65. #include <X11/Xaw/SimpleMenu.h>
  66. #include <X11/Xaw/SmeBSB.h>
  67. typedef struct tag_vimage
  68. {
  69. struct v4l2_buffer vidbuf;
  70. char *data;
  71. XImage *ximage;
  72. } VIMAGE;
  73. VIMAGE vimage[STREAMBUFS];
  74. int vid;
  75. int x_depth;
  76. XtAppContext app;
  77. Widget w_toplevel;
  78. Widget w_topbox;
  79. Widget w_menubox;
  80. Widget w_quit;
  81. Widget w_viewport;
  82. Widget w_stdbutton;
  83. Widget w_stdmenu;
  84. struct v4l2_format fmt;
  85. void resize_window(Widget widget, XtPointer client_data, XEvent *event, Boolean *d);
  86. __u32 frame_buffer_format(Display *d, Window w)
  87. {
  88. int x;
  89. int y;
  90. int width;
  91. int height;
  92. int depth;
  93. int border;
  94. Window root;
  95. __u32 fbf = V4L2_PIX_FMT_RGB565;
  96. if (x_depth == 0)
  97. {
  98. #ifdef X_DEPTH
  99. x_depth = X_DEPTH;
  100. #else
  101. XWindowAttributes wa;
  102. XGetGeometry(d, w, &root, &x, &y, &width, &height, &border, &depth);
  103. XGetWindowAttributes(d, w, &wa);
  104. x_depth = wa.depth;
  105. #endif
  106. }
  107. if (x_depth == 15)
  108. fbf = V4L2_PIX_FMT_RGB555;
  109. else if (x_depth == 16)
  110. fbf = V4L2_PIX_FMT_RGB565;
  111. else if (x_depth == 24)
  112. fbf = V4L2_PIX_FMT_BGR24;
  113. else if (x_depth == 32)
  114. fbf = V4L2_PIX_FMT_BGR32;
  115. else
  116. {
  117. printf("Unrecognized display depth. You may get an "
  118.        "X Windows error.n");
  119. }
  120. return fbf;
  121. }
  122. void stop_capturing()
  123. {
  124. #ifdef TEST_STREAMING
  125. int i;
  126. #endif
  127. if (vid >= 0)
  128. {
  129. #ifdef TEST_STREAMING
  130. ioctl(vid, VIDIOC_STREAMOFF, V4L2_BUF_TYPE_CAPTURE);
  131. for (i = 0; i < STREAMBUFS; ++i)
  132. {
  133. if (vimage[i].data)
  134. munmap(vimage[i].data, 
  135.        vimage[i].vidbuf.length);
  136. vimage[i].data = NULL;
  137. if (vimage[i].ximage)
  138. // memory leak, but XDestroyImage always segfaults...
  139. // XDestroyImage(vimage[i].ximage);
  140. vimage[i].ximage = NULL;
  141. }
  142. #else
  143. if (vimage[0].data)
  144. free(vimage[0].data);
  145. vimage[0].data = NULL;
  146. if (vimage[0].ximage)
  147. // memory leak, but XDestroyImage always segfaults...
  148. // XDestroyImage(vimage[0].ximage);
  149. vimage[0].ximage = NULL;
  150. #endif
  151. }
  152. }
  153. int start_capturing(int width, int height)
  154. {
  155. struct v4l2_requestbuffers req;
  156. int err;
  157. int i;
  158. Arg arg[2];
  159. #ifdef MY_PIXELFORMAT
  160. fmt.pixelformat = MY_PIXELFORMAT;
  161. #else
  162. fmt.pixelformat = frame_buffer_format(XtDisplay(w_viewport),
  163. DefaultRootWindow(XtDisplay(w_viewport)));
  164. #endif
  165. fmt.width = width;
  166. fmt.height = height;
  167. err = ioctl(vid, VIDIOC_S_FMT, &fmt);
  168. if (err)
  169. {
  170. printf("S_FMT returned error %dn",errno);
  171. return 1;
  172. }
  173. fprintf(stderr, "new width = %d->%d height %d->%dn", width, fmt.width, height, fmt.height);
  174. #ifdef NEVER
  175. fmt.width = width & ~3;
  176. fmt.height = height & ~1;
  177. err = ioctl(vid, VIDIOC_S_FMT, &fmt);
  178. if (err)
  179. {
  180. printf("S_FMT returned error %dn",errno);
  181. return 1;
  182. }
  183. #endif
  184. req.count = 1;
  185. #ifdef TEST_STREAMING
  186. req.count = STREAMBUFS;
  187. req.type = V4L2_BUF_TYPE_CAPTURE;
  188. err = ioctl(vid, VIDIOC_REQBUFS, &req);
  189. if (err < 0 || req.count < 1)
  190. {
  191. printf("REQBUFS returned error %d, count %dn",
  192.        errno,req.count);
  193. return 1;
  194. }
  195. for (i = 0; i < req.count; ++i)
  196. {
  197. vimage[i].vidbuf.index = i;
  198. vimage[i].vidbuf.type = V4L2_BUF_TYPE_CAPTURE;
  199. err = ioctl(vid, VIDIOC_QUERYBUF, &vimage[i].vidbuf);
  200. if (err < 0)
  201. {
  202. printf("QUERYBUF returned error %dn",errno);
  203. return 1;
  204. }
  205. vimage[i].data = mmap(0, vimage[i].vidbuf.length, PROT_READ,
  206.       MAP_SHARED, vid, 
  207.       vimage[i].vidbuf.offset);
  208. if ((int)vimage[i].data == -1)
  209. {
  210. printf("mmap() returned error %dn", errno);
  211. return 1;
  212. }
  213. }
  214. #else
  215. vimage[0].data = malloc(fmt.sizeimage);
  216. if (vimage[0].data == NULL)
  217. {
  218. printf("malloc(%d) failedn", fmt.sizeimage);
  219. return 1;
  220. }
  221. #endif
  222. #ifdef TEST_STREAMING
  223. for (i = 0; i < req.count; ++i)
  224. if ((err = ioctl(vid, VIDIOC_QBUF, &vimage[i].vidbuf)))
  225. {
  226. printf("QBUF returned error %dn",errno);
  227. return 1;
  228. }
  229. err = ioctl(vid, VIDIOC_STREAMON, vimage[0].vidbuf.type);
  230. if (err)
  231. printf("STREAMON returned error %dn",errno);
  232. #endif
  233. fprintf(stderr, "default visual=%xn", DefaultVisual(XtDisplay(w_viewport), 0));
  234. for (i = 0; i < req.count; ++i)
  235. {
  236. vimage[i].ximage = XCreateImage(
  237. XtDisplay(w_viewport),
  238. DefaultVisual(XtDisplay(w_viewport), 0),
  239. (x_depth == 32) ? 24 : x_depth,
  240. ZPixmap,
  241. 0, vimage[i].data,
  242. #ifndef NEVER
  243. fmt.width, fmt.height, 
  244. #else
  245. 704, 240,
  246. #endif
  247. 16, 0);
  248. if (vimage[i].ximage == NULL)
  249. {
  250. printf("No XImagen");
  251. return 1;
  252. }
  253. }
  254. #ifdef NEVER
  255. XtSetArg(arg[0], XtNwidth, max(160, fmt.width));
  256. XtSetArg(arg[1], XtNheight, max(120, fmt.height));
  257. #endif
  258. XtSetArg(arg[0], XtNwidth, max(720, fmt.width));
  259. XtSetArg(arg[1], XtNheight, max(240, fmt.height));
  260. XtSetValues(w_viewport, arg, 2);
  261. XtSetValues(XtParent(w_viewport), arg, 2);
  262. #ifdef NEVER
  263. fmt.width = width & ~3;
  264. fmt.height = height & ~1;
  265. err = ioctl(vid, VIDIOC_S_FMT, &fmt);
  266. #endif
  267. return 0;
  268. }
  269. void quit(Widget w, XtPointer client, XtPointer call)
  270. {
  271. struct v4l2_performance perf;
  272. if (vid >= 0)
  273. {
  274. if (ioctl(vid, VIDIOC_G_PERF, &perf) != 0)
  275. printf("G_PERF returned error code %dn",errno);
  276. else
  277. printf("Captured %d framesn", perf.frames);
  278. stop_capturing();
  279. close(vid);
  280. }
  281. exit(0);
  282. }
  283. typedef struct
  284. {
  285. Widget w_item;
  286. struct v4l2_standard std;
  287. } StdMenuItem;
  288. #define MAXSTDS 10
  289. StdMenuItem stditem[MAXSTDS];
  290. void
  291. std_menu_callback(Widget w, XtPointer client, XtPointer call)
  292. {
  293. StdMenuItem *smi = (StdMenuItem *)client;
  294. stop_capturing();
  295. ioctl(vid, VIDIOC_S_STD, &smi->std);
  296. start_capturing(fmt.width, fmt.height);
  297. }
  298. void printctrl(struct v4l2_queryctrl *qc)
  299. {
  300. printf("  %-12s %-6s %8d %8d %7d %8d  %sn",
  301.        qc->name,
  302.        (qc->type == V4L2_CTRL_TYPE_MENU) ? "(menu)" : 
  303.        (qc->type == V4L2_CTRL_TYPE_BOOLEAN) ? "(bool)" :
  304.        "(int)",
  305.        qc->minimum, qc->maximum, qc->step, qc->default_value,
  306.        qc->catname);
  307. }
  308. int
  309. main(int argc, char *argv[])
  310. {
  311. char my_device[64];
  312. int err;
  313. int i;
  314. struct v4l2_capability cap;
  315. struct v4l2_captureparm parm;
  316. #ifdef MY_STD
  317. struct v4l2_standard std;
  318. #endif
  319. int input;
  320. #ifdef TEST_CONTROLS
  321. struct v4l2_queryctrl qc;
  322. #endif
  323. #ifdef TEST_STREAMING
  324. fd_set rdset;
  325. struct timeval timeout;
  326. int n;
  327. #endif
  328. GC imagegc;
  329. struct v4l2_buffer tempbuf;
  330. int argi;
  331. /*-> Put in the device node name */
  332. strcpy(my_device, MY_DEVICE);
  333. for (argi = 1; argi < argc; ++argi)
  334. {
  335. if (strcmp(argv[argi], "-b") == 0)
  336. {
  337. x_depth = 32;
  338. continue;
  339. }
  340. strcpy(my_device, argv[argi]);
  341. }
  342. vid = open(my_device, O_RDONLY);
  343. if (vid < 0)
  344. {
  345. printf("No video device "%s"n", my_device);
  346. return 1;
  347. }
  348. err = ioctl(vid, VIDIOC_QUERYCAP, &cap);
  349. if (err)
  350. {
  351. printf("QUERYCAP returned error %dn", errno);
  352. return 1;
  353. }
  354. printf("Device node:  %sn", my_device);
  355. printf("Device:       %sn", cap.name);
  356. printf("Capabilities:");
  357. if (cap.flags & V4L2_FLAG_READ)       printf(" capture via read();");
  358. if (cap.flags & V4L2_FLAG_STREAMING)  printf(" streaming capture;");
  359. if (cap.flags & V4L2_FLAG_PREVIEW)    printf(" automatic preview;");
  360. if (cap.flags & V4L2_FLAG_SELECT)     printf(" select() call;");
  361. if (cap.flags & V4L2_FLAG_TUNER)      printf(" tuner;");
  362. if (cap.flags & V4L2_FLAG_MONOCHROME) printf(" monochrome only;");
  363. printf("n");
  364. if (cap.type != V4L2_TYPE_CAPTURE)
  365. {
  366. printf("Not a capture device.n");
  367. return 1;
  368. }
  369. #ifdef TEST_INPUTS
  370. printf("Video inputs on this device:n");
  371. for (i = 0, err = 0; err == 0; ++i)
  372. {
  373. struct v4l2_input inp;
  374. inp.index = i;
  375. err = ioctl(vid, VIDIOC_ENUMINPUT, &inp);
  376. if (!err)
  377. printf("  %d: "%s" is a%s, %s audion", i,
  378.        inp.name,
  379.        (inp.type == V4L2_INPUT_TYPE_TUNER) ?
  380.        " TV tuner" : "n analog input",
  381.        (inp.capability & V4L2_INPUT_CAP_AUDIO) ? 
  382.        "has" : "no"
  383. );
  384. }
  385. #ifdef MY_INPUT
  386. input = MY_INPUT;
  387. err = ioctl(vid, VIDIOC_S_INPUT, input);
  388. if (err)
  389. printf("S_INPUT returned error %dn",errno);
  390. #endif
  391. #endif
  392. printf("Video standards supported:");
  393. for (i = 0, err = 0; err == 0; ++i)
  394. {
  395. struct v4l2_enumstd estd;
  396. estd.index = i;
  397. err = ioctl(vid, VIDIOC_ENUMSTD, &estd);
  398. if (!err)
  399. {
  400. printf("%c %s", i?',':' ', estd.std.name);
  401. #ifdef MY_STD
  402. if (strcmp(MY_STD, estd.std.name) == 0)
  403. std = estd.std;
  404. #endif
  405. }
  406. }
  407. printf("n");
  408. #ifdef TEST_FORMATS
  409. printf("Video capture image formats supported:n");
  410. for (i = 0, err = 0; err == 0; ++i)
  411. {
  412. struct v4l2_fmtdesc fmtd;
  413. fmtd.index = i;
  414. err = ioctl(vid, VIDIOC_ENUM_CAPFMT, &fmtd);
  415. if (!err)
  416. printf("  %d: %s  (%s)n", i,
  417.        fmtd.description,
  418.        (fmtd.flags & V4L2_FMT_FLAG_COMPRESSED) ?
  419. "compressed" : "uncompressed");
  420. }
  421. #endif
  422. #ifdef TEST_CONTROLS
  423. printf("Controls supported:n");
  424. printf("  Label        type    Minimum  Maximum    Step  Default"
  425.        "  Categoryn");
  426. qc.id = V4L2_CID_BRIGHTNESS;
  427. if (ioctl(vid, VIDIOC_QUERYCTRL, &qc) == 0)
  428. printctrl(&qc);
  429. qc.id = V4L2_CID_CONTRAST;
  430. if (ioctl(vid, VIDIOC_QUERYCTRL, &qc) == 0)
  431. printctrl(&qc);
  432. qc.id = V4L2_CID_SATURATION;
  433. if (ioctl(vid, VIDIOC_QUERYCTRL, &qc) == 0)
  434. printctrl(&qc);
  435. qc.id = V4L2_CID_HUE;
  436. if (ioctl(vid, VIDIOC_QUERYCTRL, &qc) == 0)
  437. printctrl(&qc);
  438. #endif
  439. #ifndef TEST_CAPTURE
  440. return 0;
  441. #endif
  442. #ifdef TEST_STREAMING
  443. if (!(cap.flags & V4L2_FLAG_STREAMING))
  444. {
  445. printf("Device does not support streaming capture.n");
  446. return 1;
  447. }
  448. #else
  449. if (!(cap.flags & V4L2_FLAG_READ))
  450. {
  451. printf("Device does not support the read() call.n");
  452. return 1;
  453. }
  454. #endif
  455. ioctl(vid, VIDIOC_G_PARM, &parm);
  456. #ifdef TEST_FRAMERATE
  457. parm.capturemode |= V4L2_CAP_TIMEPERFRAME;
  458. parm.timeperframe = TEST_FRAMERATE;
  459. #endif
  460. err = ioctl(vid, VIDIOC_S_PARM, &parm);
  461. if (err)
  462. printf("S_PARM returned error %dn",errno);
  463. #ifdef MY_STD
  464. err = ioctl(vid, VIDIOC_S_STD, &std);
  465. if (err)
  466. printf("S_STD returned error %dn",errno);
  467. #endif
  468. ioctl(vid, VIDIOC_G_FMT, &fmt);
  469. w_toplevel = XtAppInitialize(&app, "xvideum", NULL, 0,
  470.      &argc, argv, NULL, NULL, 0);
  471. w_topbox = XtVaCreateManagedWidget(
  472. "topbox",
  473. boxWidgetClass, w_toplevel,
  474. XtNorientation, XtorientVertical,
  475. XtNborderWidth, 0,
  476. XtNhSpace, 0,
  477. XtNvSpace, 0,
  478. NULL);
  479. w_menubox = XtVaCreateManagedWidget(
  480. "menubox",
  481. boxWidgetClass, w_topbox,
  482. XtNorientation, XtorientHorizontal,
  483. XtNborderWidth, 0,
  484. XtNhSpace, 4,
  485. XtNvSpace, 1,
  486. NULL);
  487. w_stdbutton = XtVaCreateManagedWidget(
  488. "menubutton",
  489. menuButtonWidgetClass, w_menubox,
  490. XtNlabel, "Standard...",
  491. XtNmenuName, "standard",
  492. XtNborderWidth, 0,
  493. NULL);
  494. w_stdmenu = XtVaCreatePopupShell(
  495. "standard", /* same as XtNmenuName and static */
  496. simpleMenuWidgetClass, w_stdbutton,
  497. NULL);
  498. for (i = 0; ; ++i)
  499. {
  500. struct v4l2_enumstd estd;
  501. estd.index = i;
  502. err = ioctl(vid, VIDIOC_ENUMSTD, &estd);
  503. if (err)
  504. break;
  505. stditem[i].std = estd.std;
  506. stditem[i].w_item = XtVaCreateManagedWidget(
  507. estd.std.name,
  508. smeBSBObjectClass, w_stdmenu,
  509. XtNlabel, estd.std.name,
  510. NULL);
  511. XtAddCallback(stditem[i].w_item,
  512.       XtNcallback, std_menu_callback,
  513.       &stditem[i]);
  514. }
  515. w_quit = XtVaCreateManagedWidget(
  516. "Quit!",
  517. commandWidgetClass, w_menubox,
  518. XtNborderWidth, 0,
  519. NULL);
  520. XtAddCallback(w_quit, XtNcallback, quit, NULL);
  521. w_viewport = XtVaCreateManagedWidget(
  522. "port",
  523. portholeWidgetClass, w_topbox,
  524. XtNwidth, MY_WIDTH,
  525. XtNheight, MY_HEIGHT,
  526. NULL);
  527. XtAddEventHandler(XtParent(w_viewport), StructureNotifyMask, True, resize_window, NULL);
  528. XtRealizeWidget(w_toplevel);
  529. imagegc = XCreateGC(
  530. XtDisplay(w_viewport),
  531. XtWindow(w_viewport),
  532. 0, NULL);
  533. if (imagegc == NULL)
  534. {
  535. printf("XCreateGC failed.n");
  536. return 1;
  537. }
  538. if (start_capturing(MY_WIDTH, MY_HEIGHT))
  539. {
  540. return 1;
  541. }
  542. printf("Capturing %dx%dx%d "%4.4s" imagesn", 
  543.        fmt.width, fmt.height,
  544.        fmt.depth, (char *)&fmt.pixelformat);
  545. printf("Images are %d bytes eachn", fmt.sizeimage);
  546. for (;;)
  547. {
  548. XEvent event;
  549. err = 0;
  550. if (XtIsRealized(w_viewport))
  551. {
  552. #if defined(TEST_STREAMING) || defined (TEST_SELECT)
  553. FD_ZERO(&rdset);
  554. FD_SET(vid, &rdset);
  555. timeout.tv_sec = 1;
  556. timeout.tv_usec = 0;
  557. n = select(vid + 1, &rdset, NULL, NULL, &timeout);
  558. err = -1;
  559. if (n == -1)
  560. fprintf(stderr, "select error.n");
  561. else if (n == 0)
  562. fprintf(stderr, "select timeoutn");
  563. else if (FD_ISSET(vid, &rdset))
  564. err = 0;
  565. #endif
  566. if (err == 0)
  567. {
  568. #ifdef TEST_STREAMING
  569. tempbuf.type = vimage[0].vidbuf.type;
  570. err = ioctl(vid, VIDIOC_DQBUF, &tempbuf);
  571. if (err)
  572. printf("DQBUF returned error %dn",
  573.        errno);
  574. #else
  575. tempbuf.index = 0;
  576. read(vid, vimage[0].data, fmt.sizeimage);
  577. #endif
  578. XPutImage(XtDisplay(w_viewport),
  579.   XtWindow(w_viewport),
  580.   imagegc,
  581.   vimage[tempbuf.index].ximage,
  582.   0, 0,
  583.   0, 0,
  584.   fmt.width, fmt.height);
  585. #ifdef TEST_STREAMING
  586. err = ioctl(vid, VIDIOC_QBUF, &tempbuf);
  587. if (err)
  588. printf("QBUF returned error %dn",
  589.        errno);
  590. #endif
  591. XFlush(XtDisplay(w_viewport));
  592. }
  593. }
  594. else
  595. {
  596. XtAppPeekEvent(app, &event);
  597. }
  598. while (XtAppPending(app))
  599. {
  600. XtAppNextEvent(app, &event);
  601. switch (event.type)
  602. {
  603. default:
  604. break;
  605. }
  606. XtDispatchEvent(&event);
  607. }
  608. }
  609. return 0;
  610. }
  611. void
  612. resize_window(Widget widget, XtPointer client_data, XEvent *event, Boolean *d)
  613. {
  614. switch(event->type) {
  615. case ConfigureNotify:
  616. fprintf(stderr, "window size = %d x %dn",
  617. event->xconfigure.width,
  618. event->xconfigure.height);
  619. stop_capturing();
  620. start_capturing(event->xconfigure.width, event->xconfigure.height);
  621. break;
  622. }
  623. }