#include #include #include #include int main(int argc, char **argv) { Display *display; Screen *screen; Window root, window; GC gc; XvAdaptorInfo *info; unsigned int num_adaptors; XvPortID port; XvImage *image; int sw = 320, sh = 320, dw = 320, dh = 320; int id, byte_order, bpp; Atom xv_colorkey; int colorkey; int i, offset, pitch; char *src, *dst; int len1, len2; display = XOpenDisplay(NULL); if (display == NULL) { return 1; } screen = DefaultScreenOfDisplay(display); root = RootWindowOfScreen(screen); if (XvQueryAdaptors(display, root, &num_adaptors, &info) != Success) { XCloseDisplay(display); return 1; } bpp = 0; for (i = 1; i < argc; ++i) { bpp = strtol(argv[i], NULL, 0); if (bpp == 16 || bpp == 24 || bpp == 32) { break; } } for (i = 0; i < num_adaptors; ++i) { int j; if ((info[i].type & (XvInputMask | XvImageMask)) != (XvInputMask | XvImageMask)) { continue; } for (j = 0; j < info[i].num_ports; ++j) { XvImageFormatValues *formats; int num_formats, k; port = info[i].base_id + j; formats = XvListImageFormats(display, port, &num_formats); for (k = 0; k < num_formats; ++k) { if (formats[k].type == XvRGB && formats[k].format == XvPacked && (bpp == 0 || bpp == formats[k].bits_per_pixel) && XvGrabPort(display, port, CurrentTime) == Success) { id = formats[k].id; byte_order = formats[k].byte_order; bpp = formats[k].bits_per_pixel / 8; XFree(formats); XvFreeAdaptorInfo(info); goto found; } } XFree(formats); } } XvFreeAdaptorInfo(info); XCloseDisplay(display); return 1; found: xv_colorkey = XInternAtom(display, "XV_COLORKEY", False); if (XvGetPortAttribute(display, port, xv_colorkey, &colorkey) != Success) { XvUngrabPort(display, port, CurrentTime); XCloseDisplay(display); return 1; } image = XvCreateImage(display, port, id, NULL, sw, sh); image->data = malloc(image->data_size); if (image->data == NULL) { XFree(image); XvUngrabPort(display, port, CurrentTime); XCloseDisplay(display); return 1; } sw = image->width; sh = image->height; offset = *image->offsets; pitch = *image->pitches; len2 = bpp * sw; len1 = len2 / 2; len2 -= len1; dst = image->data + offset; memset(dst, 0xff, len1); dst += len1; memset(dst, 0, len2); dst = image->data + offset + pitch * sh / 2; memset(dst, 0, len1); dst += len1; memset(dst, 0xff, len2); src = image->data + offset; dst = src + pitch; for (i = 1; i < sh / 2; ++i) { memcpy(dst, src, pitch); dst += pitch; } src = image->data + offset + pitch * sh / 2; dst = src + pitch; for (i = sh / 2 + 1; i < sh; ++i) { memcpy(dst, src, pitch); dst += pitch; } window = XCreateSimpleWindow(display, root, 0, 0, dw, dh, 4, BlackPixelOfScreen(screen), colorkey); gc = XCreateGC(display, window, 0, NULL); XSelectInput(display, window, KeyPressMask | ButtonPressMask | ExposureMask | StructureNotifyMask); XMapWindow(display, window); while (1) { XEvent event; XNextEvent(display, &event); switch (event.type) { case Expose: if (event.xexpose.count == 0) { XClearWindow(display, window); XvPutImage(display, port, window, gc, image, 0, 0, sw, sh, 0, 0, dw, dh); } continue; case ConfigureNotify: dw = event.xconfigure.width; dh = event.xconfigure.height; XClearWindow(display, window); XvPutImage(display, port, window, gc, image, 0, 0, sw, sh, 0, 0, dw, dh); continue; case KeyPress: case ButtonPress: break; default: continue; } break; } free(image->data); XFree(image); XvUngrabPort(display, port, CurrentTime); XFreeGC(display, gc); XDestroyWindow(display, window); XCloseDisplay(display); return 0; }