xcaptest.c
上传用户:aoeyumen
上传日期:2007-01-06
资源大小:3329k
文件大小:15k
- /* X Window Video Capture Testing Tool
- *
- * For testing a Video for Linux Two video capture driver
- *
- * This program was written by Bill Dirks.
- * This program is in the public domain.
- *
- * gcc -o xcaptest -L/usr/X11R6/lib/ -lXt -lXaw -Wall xcaptest.c
- *
- * ./xcaptest [-b] [device-node]
- *
- * -b The X Window screen is 32 bits-per-pixel. */
- /* This program does not properly detect when the X Windows desktop is
- * 32 bits per pixel. (Some X functions use a value of 24 for the depth
- * when it is really 32 for reasons I don't understand.) As a workaround,
- * if you are running a 32-bpp X Windows screen, use -b on the command
- * line, or uncomment this line: */
- //#define X_DEPTH 32
- /* Set these according to your capture device set-up */
- #define MY_DEVICE "/dev/video0"
- //#define MY_STD "NTSC" /*-> "PAL" or "NTSC" */
- #define MY_WIDTH 704
- #define MY_HEIGHT 240
- #define MY_INPUT 0
- /* MY_PIXELFORMAT should match your X Window screen mode */
- /* If MY_PIXELFORMAT is not defined, capturing will be set to the
- screen format automatically (I hope) */
- //#define MY_PIXELFORMAT V4L2_PIX_FMT_BGR32
- /* V4L2_PIX_FMT_YUYV */
- /* V4L2_PIX_FMT_GREY */
- /* V4L2_PIX_FMT_YUV420 */
- /* V4L2_PIX_FMT_RGB555 */
- /* V4L2_PIX_FMT_RGB565 */
- /* V4L2_PIX_FMT_BGR24 */
- /* V4L2_PIX_FMT_BGR32 */
- /* Uncomment the following to test stuff */
- #define TEST_INPUTS /* enumerate the inputs */
- #define TEST_FORMATS /* enumerate the image formats */
- #define TEST_CONTROLS /* enumerate the controls */
- #define TEST_CAPTURE /* test video capture */
- #define TEST_STREAMING /* test streaming capture */
- //#define TEST_FRAMERATE 400000 /* 10million / frames-per-second */
- #define STREAMBUFS 2
- #include <sys/time.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <sys/ioctl.h>
- #include <fcntl.h>
- #include <unistd.h>
- #include <stdlib.h>
- #include <stdio.h>
- #include <sys/mman.h>
- #include <errno.h>
- #define max(a,b) ((a) > (b) ? (a) : (b))
- /* These are needed to use the Videum driver */
- #include <linux/fs.h>
- #include <linux/kernel.h>
- #include <linux/videodev2.h> /* Video for Linux Two */
- #include <X11/StringDefs.h>
- #include <X11/Intrinsic.h>
- #include <X11/Xaw/Box.h>
- #include <X11/Xaw/Command.h>
- #include <X11/Xaw/Porthole.h>
- #include <X11/Xaw/MenuButton.h>
- #include <X11/Xaw/SimpleMenu.h>
- #include <X11/Xaw/SmeBSB.h>
- typedef struct tag_vimage
- {
- struct v4l2_buffer vidbuf;
- char *data;
- XImage *ximage;
- } VIMAGE;
- VIMAGE vimage[STREAMBUFS];
- int vid;
- int x_depth;
- XtAppContext app;
- Widget w_toplevel;
- Widget w_topbox;
- Widget w_menubox;
- Widget w_quit;
- Widget w_viewport;
- Widget w_stdbutton;
- Widget w_stdmenu;
- struct v4l2_format fmt;
- void resize_window(Widget widget, XtPointer client_data, XEvent *event, Boolean *d);
- __u32 frame_buffer_format(Display *d, Window w)
- {
- int x;
- int y;
- int width;
- int height;
- int depth;
- int border;
- Window root;
- __u32 fbf = V4L2_PIX_FMT_RGB565;
- if (x_depth == 0)
- {
- #ifdef X_DEPTH
- x_depth = X_DEPTH;
- #else
- XWindowAttributes wa;
- XGetGeometry(d, w, &root, &x, &y, &width, &height, &border, &depth);
- XGetWindowAttributes(d, w, &wa);
- x_depth = wa.depth;
- #endif
- }
- if (x_depth == 15)
- fbf = V4L2_PIX_FMT_RGB555;
- else if (x_depth == 16)
- fbf = V4L2_PIX_FMT_RGB565;
- else if (x_depth == 24)
- fbf = V4L2_PIX_FMT_BGR24;
- else if (x_depth == 32)
- fbf = V4L2_PIX_FMT_BGR32;
- else
- {
- printf("Unrecognized display depth. You may get an "
- "X Windows error.n");
- }
- return fbf;
- }
- void stop_capturing()
- {
- #ifdef TEST_STREAMING
- int i;
- #endif
- if (vid >= 0)
- {
- #ifdef TEST_STREAMING
- ioctl(vid, VIDIOC_STREAMOFF, V4L2_BUF_TYPE_CAPTURE);
- for (i = 0; i < STREAMBUFS; ++i)
- {
- if (vimage[i].data)
- munmap(vimage[i].data,
- vimage[i].vidbuf.length);
- vimage[i].data = NULL;
- if (vimage[i].ximage)
- // memory leak, but XDestroyImage always segfaults...
- // XDestroyImage(vimage[i].ximage);
- vimage[i].ximage = NULL;
- }
- #else
- if (vimage[0].data)
- free(vimage[0].data);
- vimage[0].data = NULL;
- if (vimage[0].ximage)
- // memory leak, but XDestroyImage always segfaults...
- // XDestroyImage(vimage[0].ximage);
- vimage[0].ximage = NULL;
- #endif
- }
- }
- int start_capturing(int width, int height)
- {
- struct v4l2_requestbuffers req;
- int err;
- int i;
- Arg arg[2];
- #ifdef MY_PIXELFORMAT
- fmt.pixelformat = MY_PIXELFORMAT;
- #else
- fmt.pixelformat = frame_buffer_format(XtDisplay(w_viewport),
- DefaultRootWindow(XtDisplay(w_viewport)));
- #endif
- fmt.width = width;
- fmt.height = height;
- err = ioctl(vid, VIDIOC_S_FMT, &fmt);
- if (err)
- {
- printf("S_FMT returned error %dn",errno);
- return 1;
- }
- fprintf(stderr, "new width = %d->%d height %d->%dn", width, fmt.width, height, fmt.height);
- #ifdef NEVER
- fmt.width = width & ~3;
- fmt.height = height & ~1;
- err = ioctl(vid, VIDIOC_S_FMT, &fmt);
- if (err)
- {
- printf("S_FMT returned error %dn",errno);
- return 1;
- }
- #endif
- req.count = 1;
- #ifdef TEST_STREAMING
- req.count = STREAMBUFS;
- req.type = V4L2_BUF_TYPE_CAPTURE;
- err = ioctl(vid, VIDIOC_REQBUFS, &req);
- if (err < 0 || req.count < 1)
- {
- printf("REQBUFS returned error %d, count %dn",
- errno,req.count);
- return 1;
- }
- for (i = 0; i < req.count; ++i)
- {
- vimage[i].vidbuf.index = i;
- vimage[i].vidbuf.type = V4L2_BUF_TYPE_CAPTURE;
- err = ioctl(vid, VIDIOC_QUERYBUF, &vimage[i].vidbuf);
- if (err < 0)
- {
- printf("QUERYBUF returned error %dn",errno);
- return 1;
- }
- vimage[i].data = mmap(0, vimage[i].vidbuf.length, PROT_READ,
- MAP_SHARED, vid,
- vimage[i].vidbuf.offset);
- if ((int)vimage[i].data == -1)
- {
- printf("mmap() returned error %dn", errno);
- return 1;
- }
- }
- #else
- vimage[0].data = malloc(fmt.sizeimage);
- if (vimage[0].data == NULL)
- {
- printf("malloc(%d) failedn", fmt.sizeimage);
- return 1;
- }
- #endif
- #ifdef TEST_STREAMING
- for (i = 0; i < req.count; ++i)
- if ((err = ioctl(vid, VIDIOC_QBUF, &vimage[i].vidbuf)))
- {
- printf("QBUF returned error %dn",errno);
- return 1;
- }
- err = ioctl(vid, VIDIOC_STREAMON, vimage[0].vidbuf.type);
- if (err)
- printf("STREAMON returned error %dn",errno);
- #endif
- fprintf(stderr, "default visual=%xn", DefaultVisual(XtDisplay(w_viewport), 0));
- for (i = 0; i < req.count; ++i)
- {
- vimage[i].ximage = XCreateImage(
- XtDisplay(w_viewport),
- DefaultVisual(XtDisplay(w_viewport), 0),
- (x_depth == 32) ? 24 : x_depth,
- ZPixmap,
- 0, vimage[i].data,
- #ifndef NEVER
- fmt.width, fmt.height,
- #else
- 704, 240,
- #endif
- 16, 0);
- if (vimage[i].ximage == NULL)
- {
- printf("No XImagen");
- return 1;
- }
- }
- #ifdef NEVER
- XtSetArg(arg[0], XtNwidth, max(160, fmt.width));
- XtSetArg(arg[1], XtNheight, max(120, fmt.height));
- #endif
- XtSetArg(arg[0], XtNwidth, max(720, fmt.width));
- XtSetArg(arg[1], XtNheight, max(240, fmt.height));
- XtSetValues(w_viewport, arg, 2);
- XtSetValues(XtParent(w_viewport), arg, 2);
- #ifdef NEVER
- fmt.width = width & ~3;
- fmt.height = height & ~1;
- err = ioctl(vid, VIDIOC_S_FMT, &fmt);
- #endif
- return 0;
- }
- void quit(Widget w, XtPointer client, XtPointer call)
- {
- struct v4l2_performance perf;
- if (vid >= 0)
- {
- if (ioctl(vid, VIDIOC_G_PERF, &perf) != 0)
- printf("G_PERF returned error code %dn",errno);
- else
- printf("Captured %d framesn", perf.frames);
- stop_capturing();
- close(vid);
- }
- exit(0);
- }
- typedef struct
- {
- Widget w_item;
- struct v4l2_standard std;
- } StdMenuItem;
- #define MAXSTDS 10
- StdMenuItem stditem[MAXSTDS];
- void
- std_menu_callback(Widget w, XtPointer client, XtPointer call)
- {
- StdMenuItem *smi = (StdMenuItem *)client;
- stop_capturing();
- ioctl(vid, VIDIOC_S_STD, &smi->std);
- start_capturing(fmt.width, fmt.height);
- }
- void printctrl(struct v4l2_queryctrl *qc)
- {
- printf(" %-12s %-6s %8d %8d %7d %8d %sn",
- qc->name,
- (qc->type == V4L2_CTRL_TYPE_MENU) ? "(menu)" :
- (qc->type == V4L2_CTRL_TYPE_BOOLEAN) ? "(bool)" :
- "(int)",
- qc->minimum, qc->maximum, qc->step, qc->default_value,
- qc->catname);
- }
- int
- main(int argc, char *argv[])
- {
- char my_device[64];
- int err;
- int i;
- struct v4l2_capability cap;
- struct v4l2_captureparm parm;
- #ifdef MY_STD
- struct v4l2_standard std;
- #endif
- int input;
- #ifdef TEST_CONTROLS
- struct v4l2_queryctrl qc;
- #endif
- #ifdef TEST_STREAMING
- fd_set rdset;
- struct timeval timeout;
- int n;
- #endif
- GC imagegc;
- struct v4l2_buffer tempbuf;
- int argi;
- /*-> Put in the device node name */
- strcpy(my_device, MY_DEVICE);
- for (argi = 1; argi < argc; ++argi)
- {
- if (strcmp(argv[argi], "-b") == 0)
- {
- x_depth = 32;
- continue;
- }
- strcpy(my_device, argv[argi]);
- }
- vid = open(my_device, O_RDONLY);
- if (vid < 0)
- {
- printf("No video device "%s"n", my_device);
- return 1;
- }
- err = ioctl(vid, VIDIOC_QUERYCAP, &cap);
- if (err)
- {
- printf("QUERYCAP returned error %dn", errno);
- return 1;
- }
- printf("Device node: %sn", my_device);
- printf("Device: %sn", cap.name);
- printf("Capabilities:");
- if (cap.flags & V4L2_FLAG_READ) printf(" capture via read();");
- if (cap.flags & V4L2_FLAG_STREAMING) printf(" streaming capture;");
- if (cap.flags & V4L2_FLAG_PREVIEW) printf(" automatic preview;");
- if (cap.flags & V4L2_FLAG_SELECT) printf(" select() call;");
- if (cap.flags & V4L2_FLAG_TUNER) printf(" tuner;");
- if (cap.flags & V4L2_FLAG_MONOCHROME) printf(" monochrome only;");
- printf("n");
- if (cap.type != V4L2_TYPE_CAPTURE)
- {
- printf("Not a capture device.n");
- return 1;
- }
- #ifdef TEST_INPUTS
- printf("Video inputs on this device:n");
- for (i = 0, err = 0; err == 0; ++i)
- {
- struct v4l2_input inp;
- inp.index = i;
- err = ioctl(vid, VIDIOC_ENUMINPUT, &inp);
- if (!err)
- printf(" %d: "%s" is a%s, %s audion", i,
- inp.name,
- (inp.type == V4L2_INPUT_TYPE_TUNER) ?
- " TV tuner" : "n analog input",
- (inp.capability & V4L2_INPUT_CAP_AUDIO) ?
- "has" : "no"
- );
- }
- #ifdef MY_INPUT
- input = MY_INPUT;
- err = ioctl(vid, VIDIOC_S_INPUT, input);
- if (err)
- printf("S_INPUT returned error %dn",errno);
- #endif
- #endif
- printf("Video standards supported:");
- for (i = 0, err = 0; err == 0; ++i)
- {
- struct v4l2_enumstd estd;
- estd.index = i;
- err = ioctl(vid, VIDIOC_ENUMSTD, &estd);
- if (!err)
- {
- printf("%c %s", i?',':' ', estd.std.name);
- #ifdef MY_STD
- if (strcmp(MY_STD, estd.std.name) == 0)
- std = estd.std;
- #endif
- }
- }
- printf("n");
- #ifdef TEST_FORMATS
- printf("Video capture image formats supported:n");
- for (i = 0, err = 0; err == 0; ++i)
- {
- struct v4l2_fmtdesc fmtd;
- fmtd.index = i;
- err = ioctl(vid, VIDIOC_ENUM_CAPFMT, &fmtd);
- if (!err)
- printf(" %d: %s (%s)n", i,
- fmtd.description,
- (fmtd.flags & V4L2_FMT_FLAG_COMPRESSED) ?
- "compressed" : "uncompressed");
- }
- #endif
- #ifdef TEST_CONTROLS
- printf("Controls supported:n");
- printf(" Label type Minimum Maximum Step Default"
- " Categoryn");
- qc.id = V4L2_CID_BRIGHTNESS;
- if (ioctl(vid, VIDIOC_QUERYCTRL, &qc) == 0)
- printctrl(&qc);
- qc.id = V4L2_CID_CONTRAST;
- if (ioctl(vid, VIDIOC_QUERYCTRL, &qc) == 0)
- printctrl(&qc);
- qc.id = V4L2_CID_SATURATION;
- if (ioctl(vid, VIDIOC_QUERYCTRL, &qc) == 0)
- printctrl(&qc);
- qc.id = V4L2_CID_HUE;
- if (ioctl(vid, VIDIOC_QUERYCTRL, &qc) == 0)
- printctrl(&qc);
- #endif
- #ifndef TEST_CAPTURE
- return 0;
- #endif
- #ifdef TEST_STREAMING
- if (!(cap.flags & V4L2_FLAG_STREAMING))
- {
- printf("Device does not support streaming capture.n");
- return 1;
- }
- #else
- if (!(cap.flags & V4L2_FLAG_READ))
- {
- printf("Device does not support the read() call.n");
- return 1;
- }
- #endif
- ioctl(vid, VIDIOC_G_PARM, &parm);
- #ifdef TEST_FRAMERATE
- parm.capturemode |= V4L2_CAP_TIMEPERFRAME;
- parm.timeperframe = TEST_FRAMERATE;
- #endif
- err = ioctl(vid, VIDIOC_S_PARM, &parm);
- if (err)
- printf("S_PARM returned error %dn",errno);
- #ifdef MY_STD
- err = ioctl(vid, VIDIOC_S_STD, &std);
- if (err)
- printf("S_STD returned error %dn",errno);
- #endif
- ioctl(vid, VIDIOC_G_FMT, &fmt);
- w_toplevel = XtAppInitialize(&app, "xvideum", NULL, 0,
- &argc, argv, NULL, NULL, 0);
- w_topbox = XtVaCreateManagedWidget(
- "topbox",
- boxWidgetClass, w_toplevel,
- XtNorientation, XtorientVertical,
- XtNborderWidth, 0,
- XtNhSpace, 0,
- XtNvSpace, 0,
- NULL);
- w_menubox = XtVaCreateManagedWidget(
- "menubox",
- boxWidgetClass, w_topbox,
- XtNorientation, XtorientHorizontal,
- XtNborderWidth, 0,
- XtNhSpace, 4,
- XtNvSpace, 1,
- NULL);
- w_stdbutton = XtVaCreateManagedWidget(
- "menubutton",
- menuButtonWidgetClass, w_menubox,
- XtNlabel, "Standard...",
- XtNmenuName, "standard",
- XtNborderWidth, 0,
- NULL);
- w_stdmenu = XtVaCreatePopupShell(
- "standard", /* same as XtNmenuName and static */
- simpleMenuWidgetClass, w_stdbutton,
- NULL);
- for (i = 0; ; ++i)
- {
- struct v4l2_enumstd estd;
- estd.index = i;
- err = ioctl(vid, VIDIOC_ENUMSTD, &estd);
- if (err)
- break;
- stditem[i].std = estd.std;
- stditem[i].w_item = XtVaCreateManagedWidget(
- estd.std.name,
- smeBSBObjectClass, w_stdmenu,
- XtNlabel, estd.std.name,
- NULL);
- XtAddCallback(stditem[i].w_item,
- XtNcallback, std_menu_callback,
- &stditem[i]);
- }
- w_quit = XtVaCreateManagedWidget(
- "Quit!",
- commandWidgetClass, w_menubox,
- XtNborderWidth, 0,
- NULL);
- XtAddCallback(w_quit, XtNcallback, quit, NULL);
- w_viewport = XtVaCreateManagedWidget(
- "port",
- portholeWidgetClass, w_topbox,
- XtNwidth, MY_WIDTH,
- XtNheight, MY_HEIGHT,
- NULL);
- XtAddEventHandler(XtParent(w_viewport), StructureNotifyMask, True, resize_window, NULL);
- XtRealizeWidget(w_toplevel);
- imagegc = XCreateGC(
- XtDisplay(w_viewport),
- XtWindow(w_viewport),
- 0, NULL);
- if (imagegc == NULL)
- {
- printf("XCreateGC failed.n");
- return 1;
- }
- if (start_capturing(MY_WIDTH, MY_HEIGHT))
- {
- return 1;
- }
- printf("Capturing %dx%dx%d "%4.4s" imagesn",
- fmt.width, fmt.height,
- fmt.depth, (char *)&fmt.pixelformat);
- printf("Images are %d bytes eachn", fmt.sizeimage);
- for (;;)
- {
- XEvent event;
- err = 0;
- if (XtIsRealized(w_viewport))
- {
- #if defined(TEST_STREAMING) || defined (TEST_SELECT)
- FD_ZERO(&rdset);
- FD_SET(vid, &rdset);
- timeout.tv_sec = 1;
- timeout.tv_usec = 0;
- n = select(vid + 1, &rdset, NULL, NULL, &timeout);
- err = -1;
- if (n == -1)
- fprintf(stderr, "select error.n");
- else if (n == 0)
- fprintf(stderr, "select timeoutn");
- else if (FD_ISSET(vid, &rdset))
- err = 0;
- #endif
- if (err == 0)
- {
- #ifdef TEST_STREAMING
- tempbuf.type = vimage[0].vidbuf.type;
- err = ioctl(vid, VIDIOC_DQBUF, &tempbuf);
- if (err)
- printf("DQBUF returned error %dn",
- errno);
- #else
- tempbuf.index = 0;
- read(vid, vimage[0].data, fmt.sizeimage);
- #endif
- XPutImage(XtDisplay(w_viewport),
- XtWindow(w_viewport),
- imagegc,
- vimage[tempbuf.index].ximage,
- 0, 0,
- 0, 0,
- fmt.width, fmt.height);
- #ifdef TEST_STREAMING
- err = ioctl(vid, VIDIOC_QBUF, &tempbuf);
- if (err)
- printf("QBUF returned error %dn",
- errno);
- #endif
- XFlush(XtDisplay(w_viewport));
- }
- }
- else
- {
- XtAppPeekEvent(app, &event);
- }
- while (XtAppPending(app))
- {
- XtAppNextEvent(app, &event);
- switch (event.type)
- {
- default:
- break;
- }
- XtDispatchEvent(&event);
- }
- }
- return 0;
- }
- void
- resize_window(Widget widget, XtPointer client_data, XEvent *event, Boolean *d)
- {
- switch(event->type) {
- case ConfigureNotify:
- fprintf(stderr, "window size = %d x %dn",
- event->xconfigure.width,
- event->xconfigure.height);
- stop_capturing();
- start_capturing(event->xconfigure.width, event->xconfigure.height);
- break;
- }
- }