diff options
author | Jordan K. Hubbard <jkh@FreeBSD.org> | 1998-06-24 07:54:40 +0000 |
---|---|---|
committer | Jordan K. Hubbard <jkh@FreeBSD.org> | 1998-06-24 07:54:40 +0000 |
commit | b39ac6d642143a74bf5bb26fac58f657db08b199 (patch) | |
tree | 1523ca6cffccae4139a05ac293033f80578138ed /multimedia/vic/files/patch-am | |
parent | This patch contains an update to the audio-voxware.cc module in vat (diff) |
These patches implement the following features in vic:
* an x11 grabber similar to the one present in nv. Extremely useful
for interactive work (i'd say better than a camera in many cases).
* add video controls to the meteor grabber (brightness etc.)
* add tuner control when used with the meteor grabber (require a
small modification to the kernel to let tuner be controlled
via the grabber fd);
Submitted by: luigi
PR: 6814
Notes
Notes:
svn path=/head/; revision=11502
Diffstat (limited to '')
-rw-r--r-- | multimedia/vic/files/patch-am | 1335 |
1 files changed, 1335 insertions, 0 deletions
diff --git a/multimedia/vic/files/patch-am b/multimedia/vic/files/patch-am new file mode 100644 index 000000000000..a29a780aa006 --- /dev/null +++ b/multimedia/vic/files/patch-am @@ -0,0 +1,1335 @@ +--- grabber-x11.cc Sat May 30 14:55:30 1998 ++++ /home/old_wd0f/ports/mbone/vic/work.luigi/vic-2.8-luigi/grabber-x11.cc Fri Apr 10 21:32:11 1998 +@@ -0,0 +1,1332 @@ ++/* ++ * Copyright (c) 1998 Luigi Rizzo ++ * grabber-x11.cc for vic ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. All advertising materials mentioning features or use of this software ++ * must display the following acknowledgement: ++ * This product includes software developed by Jim Lowe ++ * 4. The name of the author may not be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR ++ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ++ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, ++ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR ++ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, ++ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ++ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++ * POSSIBILITY OF SUCH DAMAGE. ++ */ ++ ++#include <stdio.h> ++#include <stdlib.h> ++#include <unistd.h> ++#include <fcntl.h> ++#include <sys/types.h> ++#include <sys/ioctl.h> ++#include <sys/mman.h> ++ ++#include "grabber.h" ++#include "Tcl.h" ++#include "device-input.h" ++#include "module.h" ++ ++#include <X11/Xlib.h> ++#include <X11/Xutil.h> ++#include <X11/Xatom.h> ++#include <X11/cursorfont.h> ++#include <tk.h> ++/*** #include "sized_types.h" ***/ ++ ++/* ++ Netvideo version 3.3 ++ Written by Ron Frederick <frederick@parc.xerox.com> ++ ++ Machine-specific sized integer type definitions ++ Video utility definitions ++*/ ++ ++/* ++ * Copyright (c) Xerox Corporation 1992. All rights reserved. ++ * ++ * License is granted to copy, to use, and to make and to use derivative ++ * works for research and evaluation purposes, provided that Xerox is ++ * acknowledged in all documentation pertaining to any such copy or derivative ++ * work. Xerox grants no other licenses expressed or implied. The Xerox trade ++ * name should not be used in any advertising without its written permission. ++ * ++ * XEROX CORPORATION MAKES NO REPRESENTATIONS CONCERNING EITHER THE ++ * MERCHANTABILITY OF THIS SOFTWARE OR THE SUITABILITY OF THIS SOFTWARE ++ * FOR ANY PARTICULAR PURPOSE. The software is provided "as is" without ++ * express or implied warranty of any kind. ++ * ++ * These notices must be retained in any copies of any part of this software. ++ */ ++ ++typedef signed char int8; /* 8 bit signed int */ ++typedef short int16; /* 16 bit signed int */ ++typedef int int32; /* 32 bit signed int */ ++#if defined(__alpha) ++typedef long int64; /* 64 bit signed int */ ++#endif ++ ++typedef unsigned char uint8; /* 8 bit unsigned int */ ++typedef unsigned short uint16; /* 16 bit unsigned int */ ++typedef unsigned int uint32; /* 32 bit unsigned int */ ++#if defined(__alpha) ++typedef unsigned long uint64; /* 64 bit unsigned int */ ++#endif ++ ++/* Mildly gross but moderately portable test for littleendian machines */ ++#define LITTLEENDIAN (ntohl(0x12345678) != 0x12345678) ++ ++typedef struct { ++ XImage *image; ++ void *shminfo; ++} ximage_t; ++ ++/*************************/ ++ ++#define VID_SMALL 0x01 ++#define VID_MEDIUM 0x02 ++#define VID_LARGE 0x04 ++#define VID_SIZEMASK 0x07 ++ ++#define VID_GREYSCALE 0x08 ++#define VID_COLOR 0x10 ++ ++#define X11GRAB_FIXED 0 ++#define X11GRAB_POINTER 1 ++#define X11GRAB_WINDOW 2 ++ ++ ++/*XXX*/ ++#define NTSC_WIDTH 320 ++#define NTSC_HEIGHT 240 ++#define PAL_WIDTH 384 ++#define PAL_HEIGHT 288 ++#define CIF_WIDTH 352 ++#define CIF_HEIGHT 288 ++ ++ ++class X11Grabber : public Grabber { ++ public: ++ X11Grabber(const char* name, const char* format); ++ virtual ~X11Grabber(); ++ virtual void start(); ++ virtual void stop(); ++ protected: ++ virtual int command(int argc, const char*const* argv); ++ virtual int capture(); ++ virtual int grab(); ++ void format(); ++ void setsize(); ++ ++ void X11Grab_ComputeYUVTable(void) ; ++ int X11Grab_MSBWhite1(void); ++ int X11Grab_LSBWhite1(void); ++ int X11Grab_MSBBlack1(void); ++ int X11Grab_LSBBlack1(void); ++ int X11Grab_Pseudo8(void); ++ int X11Grab_RGB16(void); ++ int X11Grab_TrueXBGR24(void); ++ ++ int X11Grab_Initialize(Window rw, int w, int h); ++ int (X11Grabber::*c_grab)(void); ++ ++ uint8 *rgb2y_ ; ++ int8 *rgb2u_ ; ++ int8 *rgb2v_ ; ++ ++ ximage_t *ximage_ ; ++ ++ Display *dpy_ ; ++ int mode_; /* input mode */ ++ Window theroot_ ; ++ ++// Tcl_Interp *interp_=NULL; ++ ++ int screen, xerror ; ++ Window vRoot_ ; ++ Window rootwin_ ; ++ Colormap colormap; ++ Visual *root_vis; ++ XVisualInfo root_visinfo; ++ ++ int ncolors_ ; ++ int black, white; ++ XColor *color ; ++ uint8 *col2y_ ; ++ uint16 *col2rgb16_ ; ++ ++ u_int basewidth_; /* Height of frame to be captured */ ++ u_int baseheight_; /* Width of frame to be captured */ ++ u_int decimate_; /* division of base sizes */ ++ ++ int x_origin_, y_origin_, width_, height_; ++ int root_depth_, root_width, root_height; ++}; ++ ++class X11Device : public InputDevice { ++ public: ++ X11Device(const char* nickname); ++ virtual int command(int argc, const char*const* argv); ++ protected: ++ const char* name_; ++}; ++ ++static X11Device find_x11_devices("x11"); ++ ++X11Device::X11Device(const char* nickname): ++ InputDevice(nickname), name_(nickname) ++{ ++ if (free) ++ attributes_ = "\ ++size {large normal small cif} \ ++format {422}" ; ++ else ++ attributes_ = "disabled"; ++} ++ ++extern "C" { ++/*** most of this taken from nv:x11-grab.c ***/ ++extern ximage_t *VidUtil_AllocXImage(Display *dpy, Visual *vis, int depth, ++ int width, int height, int readonly); ++ ++#if 0 /* debugging stuff */ ++static int my_Tcl_Eval(Tcl_Interp *interp, char *cmd) ++{ ++ fprintf(stderr,"Tcl_Eval <%s>\n", cmd); ++ Tcl_Eval(interp, cmd); ++} ++#define Tcl_Eval my_Tcl_Eval ++#endif ++ ++static Window ++VirtualRootWindow(Display *dpy, int screen) ++{ ++ static Display *last_dpy=(Display *)NULL; ++ static int last_screen = -1; ++ static Window vRoot=None; ++ ++ Atom __SWM_VROOT=None; ++ Window rw, p, *child; ++ unsigned int i, nChildren; ++ ++ if ((dpy != last_dpy) || (screen != last_screen)) { ++ vRoot = RootWindow(dpy, screen); ++ ++ /* go look for a virtual root */ ++ __SWM_VROOT = XInternAtom(dpy, "__SWM_VROOT", False); ++ XQueryTree(dpy, vRoot, &rw, &p, &child, &nChildren); ++ for (i=0; i<nChildren; i++) { ++ Atom actual_type; ++ int actual_format; ++ unsigned long nitems, bytesafter; ++ Window *newRoot=NULL; ++ ++ if ((XGetWindowProperty(dpy, child[i], __SWM_VROOT, 0, 1, False, ++ XA_WINDOW, &actual_type, &actual_format, ++ &nitems, &bytesafter, ++ (unsigned char **)&newRoot) == Success) ++ && (newRoot != NULL)) { ++ vRoot = *newRoot; ++ XFree((void *)newRoot); ++ break; ++ } ++ } ++ XFree((void *)child); ++ ++ last_dpy = dpy; ++ last_screen = screen; ++ } ++ ++ return vRoot; ++} ++ ++} /* end extern C */ ++ ++void ++X11Grabber::X11Grab_ComputeYUVTable(void) ++{ ++ int i; ++ ++ switch (root_visinfo.c_class) { ++ case StaticColor: ++ case PseudoColor: ++ case StaticGray: ++ case GrayScale: ++ for (i=0; i<ncolors_; i++) color[i].pixel = i; ++ XQueryColors(dpy_, colormap, color, ncolors_); ++ for (i=0; i<ncolors_; i++) { ++ color[i].red = (color[i].red & 0xf800) ; ++ color[i].green = (color[i].green & 0xfc00) >> 5 ; ++ color[i].blue = (color[i].blue & 0xf800) >> 11 ; ++ col2rgb16_[i] = color[i].red + color[i].green + color[i].blue; ++ col2y_[i] = rgb2y_[col2rgb16_[i]]; ++ } ++ break; ++ case TrueColor: ++ fprintf(stderr, "TrueColor...\n"); ++ break; ++ case DirectColor: ++ fprintf(stderr, "DirectColor...\n"); ++ break; ++ } ++} ++ ++/* ++ * these are the grabbing functions for the various video formats ++ */ ++ ++int ++X11Grabber::X11Grab_MSBWhite1() ++{ ++ int x, y, row; ++ uint8 *data=(uint8 *)ximage_->image->data, *yp= frame_; ++ ++ for (y=0; y<height_; y++) { ++ for (x=0; x<width_; x+=8) { ++ row = *data++; ++ ++ yp[0] = 255 * ((row & 0x80)>>7); ++ yp[1] = 255 * ((row & 0x40)>>6); ++ yp[2] = 255 * ((row & 0x20)>>5); ++ yp[3] = 255 * ((row & 0x10)>>4); ++ yp[4] = 255 * ((row & 0x08)>>3); ++ yp[5] = 255 * ((row & 0x04)>>2); ++ yp[6] = 255 * ((row & 0x02)>>1); ++ yp[7] = 255 * (row & 0x01); ++ yp += 8; ++ } ++ } ++ ++ return 1; ++} ++ ++int ++X11Grabber::X11Grab_MSBBlack1() ++{ ++ int x, y, row; ++ uint8 *data=(uint8 *)ximage_->image->data, *yp= frame_; ++ ++ for (y=0; y<height_; y++) { ++ for (x=0; x<width_; x+=8) { ++ row = *data++; ++ ++ yp[0] = 255 - 255 * ((row & 0x80)>>7); ++ yp[1] = 255 - 255 * ((row & 0x40)>>6); ++ yp[2] = 255 - 255 * ((row & 0x20)>>5); ++ yp[3] = 255 - 255 * ((row & 0x10)>>4); ++ yp[4] = 255 - 255 * ((row & 0x08)>>3); ++ yp[5] = 255 - 255 * ((row & 0x04)>>2); ++ yp[6] = 255 - 255 * ((row & 0x02)>>1); ++ yp[7] = 255 - 255 * (row & 0x01); ++ yp += 8; ++ } ++ } ++ ++ return 1; ++} ++ ++int ++X11Grabber::X11Grab_LSBWhite1() ++{ ++ int x, y, row; ++ uint8 *data=(uint8 *)ximage_->image->data, *yp= frame_ ; ++ ++ for (y=0; y<height_; y++) { ++ for (x=0; x<width_; x+=8) { ++ row = *data++; ++ ++ yp[7] = 255 * ((row & 0x80)>>7); ++ yp[6] = 255 * ((row & 0x40)>>6); ++ yp[5] = 255 * ((row & 0x20)>>5); ++ yp[4] = 255 * ((row & 0x10)>>4); ++ yp[3] = 255 * ((row & 0x08)>>3); ++ yp[2] = 255 * ((row & 0x04)>>2); ++ yp[1] = 255 * ((row & 0x02)>>1); ++ yp[0] = 255 * (row & 0x01); ++ yp += 8; ++ } ++ } ++ ++ return 1; ++} ++ ++int ++X11Grabber::X11Grab_LSBBlack1() ++{ ++ int x, y, row; ++ uint8 *data=(uint8 *)ximage_->image->data, *yp= frame_; ++ ++ for (y=0; y<height_; y++) { ++ for (x=0; x<width_; x+=8) { ++ row = *data++; ++ ++ yp[7] = 255 - 255 * ((row & 0x80)>>7); ++ yp[6] = 255 - 255 * ((row & 0x40)>>6); ++ yp[5] = 255 - 255 * ((row & 0x20)>>5); ++ yp[4] = 255 - 255 * ((row & 0x10)>>4); ++ yp[3] = 255 - 255 * ((row & 0x08)>>3); ++ yp[2] = 255 - 255 * ((row & 0x04)>>2); ++ yp[1] = 255 - 255 * ((row & 0x02)>>1); ++ yp[0] = 255 - 255 * (row & 0x01); ++ yp += 8; ++ } ++ } ++ ++ return 1; ++} ++ ++int ++X11Grabber::X11Grab_Pseudo8() ++{ ++ int x, y, p0, p1, p2, p3 ; ++ uint8 *data=(uint8 *)ximage_->image->data, *yp=frame_ ; ++ uint8 *up= (uint8 *)yp + framesize_ ; ++ uint8 *vp= up + (framesize_ >> 2) ; ++ ++ X11Grab_ComputeYUVTable(); ++ ++ for (y=0; y<height_; y += 2) { ++ for (x=0; x<width_ ; x += 2) { ++ yp[0] = col2y_[data[0]]; ++ p0 = col2rgb16_[data[0]]; ++ yp[1] = col2y_[data[1]]; ++ p1 = col2rgb16_[data[1]]; ++ ++ p2 = col2rgb16_[data[width_]]; ++ p3 = col2rgb16_[data[width_ + 1]]; ++#if 0 /* average */ ++ p0 = ( (p0 >> 1) & 0x7bef ) + ( (p1 >> 1) & 0x7bef ) ; ++ p2 = ( (p2 >> 1) & 0x7bef ) + ( (p3 >> 1) & 0x7bef ) ; ++ p0 = ( (p0 >> 1) & 0x7bef ) + ( (p2 >> 1) & 0x7bef ) ; ++#else /* take the darkest... */ ++ if (yp[1] < yp[0]) p0 = p1 ; ++ if (rgb2y_[p2] < rgb2y_[p0]) p0 = p2 ; ++ if (rgb2y_[p3] < rgb2y_[p0]) p0 = p3 ; ++#endif ++ *up++ = rgb2u_[ p0 ]; ++ *vp++ = rgb2v_[ p0 ]; ++ ++ data += 2; ++ yp += 2 ; ++ } ++ for (x=0; x<width_; x += 8) { ++ yp[0] = col2y_[data[0]]; ++ yp[1] = col2y_[data[1]]; ++ yp[2] = col2y_[data[2]]; ++ yp[3] = col2y_[data[3]]; ++ yp[4] = col2y_[data[4]]; ++ yp[5] = col2y_[data[5]]; ++ yp[6] = col2y_[data[6]]; ++ yp[7] = col2y_[data[7]]; ++ data += 8; ++ yp += 8 ; ++ } ++ } ++ ++ return 1; ++} ++ ++int ++X11Grabber::X11Grab_RGB16(void) ++{ ++ int x, y; ++ uint8 *yp= (uint8 *)frame_ ; ++ uint8 *up= (uint8 *)yp + framesize_ ; ++ uint8 *vp= up + (framesize_ >> 2) ; ++ uint16 *data=(uint16 *)ximage_->image->data, p0, p1, p2, p3; ++ ++ for (y=0; y<height_; y+=2) { ++ for (x=0; x<width_; x += 2) { ++ p0 = data[0] ; ++ p1 = data[1] ; ++ p2 = data[ width_] ; ++ p3 = data[ width_ + 1] ; ++ data += 2 ; ++ yp[0] = rgb2y_[ p0 ] ; /* in 565 format */ ++ yp[1] = rgb2y_[ p1 ] ; /* in 565 format */ ++#if 0 ++ /* average the four pixels... */ ++ p0 = ( (p0 >> 1) & 0x7bef ) + ( (p1 >> 1) & 0x7bef ) ; ++ p2 = ( (p2 >> 1) & 0x7bef ) + ( (p3 >> 1) & 0x7bef ) ; ++ p0 = ( (p0 >> 1) & 0x7bef ) + ( (p2 >> 1) & 0x7bef ) ; ++#else /* take the darkest... */ ++ if (yp[1] < yp[0]) p0 = p1 ; ++ if (rgb2y_[p2] < rgb2y_[p0]) p0 = p2 ; ++ if (rgb2y_[p3] < rgb2y_[p0]) p0 = p3 ; ++#endif ++ *up++ = rgb2u_[ p0 ]; ++ *vp++ = rgb2v_[ p0 ]; ++ yp += 2 ; ++ } ++ for (x=0; x<width_; x += 8) { ++ yp[0] = rgb2y_[data[0] ]; ++ yp[1] = rgb2y_[data[1] ]; ++ yp[2] = rgb2y_[data[2] ]; ++ yp[3] = rgb2y_[data[3] ]; ++ yp[4] = rgb2y_[data[4] ]; ++ yp[5] = rgb2y_[data[5] ]; ++ yp[6] = rgb2y_[data[6] ]; ++ yp[7] = rgb2y_[data[7] ]; ++ yp += 8 ; ++ data += 8 ; ++ } ++ } ++ ++ return 1; ++} ++ ++int ++X11Grabber::X11Grab_TrueXBGR24() ++{ ++ int x, y; ++ uint8 *yp= (uint8 *)frame_ ; ++ uint8 *up= (uint8 *)yp + framesize_ ; ++ uint8 *vp= up + (framesize_ >> 2) ; ++ uint16 p0, p1 ; ++ uint32 *data=(uint32 *)ximage_->image->data, d ; ++ ++ for (y=0; y<height_; y += 2) { ++ for (x=0; x<width_; x+=2) { ++ d = *data++ ; ++ p0 = ((d<<8) & 0xf100) | ((p0>>5) & 0x7e0) | ((p0>>19) & 0x1f); ++ *yp++ = rgb2y_[ p0 ]; ++ ++ d = *data++ ; ++ p1 = ((d<<8) & 0xf100) | ((p0>>5) & 0x7e0) | ((p0>>19) & 0x1f); ++ *yp++ = rgb2y_[ p1 ]; ++ ++ /* average the two pixels... */ ++ p0 = ( (p0 >> 1) & 0x7bef ) + ( (p1 >> 1) & 0x7bef ) ; ++ *up++ = rgb2u_[ p0 ]; ++ } ++ for (x=0; x<width_; x+=2) { ++ d = *data++ ; ++ p0 = ((d<<8) & 0xf100) | ((p0>>5) & 0x7e0) | ((p0>>19) & 0x1f); ++ *yp++ = rgb2y_[ p0 ]; ++ ++ d = *data++ ; ++ p1 = ((d<<8) & 0xf100) | ((p0>>5) & 0x7e0) | ((p0>>19) & 0x1f); ++ *yp++ = rgb2y_[ p1 ]; ++ ++ /* average the two pixels... */ ++ p0 = ( (p0 >> 1) & 0x7bef ) + ( (p1 >> 1) & 0x7bef ) ; ++ *vp++ = rgb2v_[ p0 ]; ++ } ++ } ++ ++ return 1; ++} ++ ++/* ++ * initialization of frame grabber... ++ */ ++int ++X11Grabber::X11Grab_Initialize(Window rw, int w, int h) ++{ ++ int config = 0 ; ++ XWindowAttributes wattr; ++ ++ if (theroot_ != rw) { ++ theroot_ = rw; ++ XGetWindowAttributes(dpy_, theroot_, &wattr); ++ screen = XScreenNumberOfScreen(wattr.screen); ++ colormap = DefaultColormapOfScreen(wattr.screen); ++ ncolors_ = CellsOfScreen(wattr.screen); ++ black = BlackPixelOfScreen(wattr.screen); ++ white = WhitePixelOfScreen(wattr.screen); ++ root_depth_ = wattr.depth; ++ root_width = wattr.width; ++ root_height = wattr.height; ++ root_vis = wattr.visual; ++ vRoot_ = VirtualRootWindow(dpy_, screen); ++ ++ if (color != NULL) { ++ free(color); ++ free(col2y_); ++ free(col2rgb16_); ++ } ++ color = (XColor *) malloc(ncolors_*sizeof(XColor)); ++ col2y_ = (uint8 *) malloc(ncolors_*sizeof(uint8)); ++ col2rgb16_ = (uint16 *) malloc(ncolors_*sizeof(uint16)); ++ ++ XMatchVisualInfo(dpy_, screen, root_depth_, root_vis->c_class, ++ &root_visinfo); ++ switch (root_depth_) { ++ case 1: ++ if (white == 1) { ++ c_grab = (LITTLEENDIAN) ? X11Grab_LSBWhite1 : X11Grab_MSBWhite1; ++ } else { ++ c_grab = (LITTLEENDIAN) ? X11Grab_LSBBlack1 : X11Grab_MSBBlack1; ++ } ++ config = VID_GREYSCALE; ++ break; ++ ++ case 8: ++ switch (root_visinfo.c_class) { ++ case PseudoColor: ++ case GrayScale: ++ case StaticColor: ++ case StaticGray: ++ c_grab = X11Grab_Pseudo8; ++ break; ++ default: ++ c_grab = NULL; ++ break; ++ } ++ config = VID_GREYSCALE|VID_COLOR; ++ break; ++ ++ case 16: ++ c_grab = X11Grab_RGB16; ++ break ; ++ ++ case 24: ++ if ((root_visinfo.c_class == TrueColor) && ++ (root_visinfo.green_mask = 0xff00) && ++#ifdef __FreeBSD__ ++ (root_visinfo.red_mask == 0xff0000) && ++ (root_visinfo.blue_mask == 0xff)) ++#else ++ (root_visinfo.red_mask == 0xff) && ++ (root_visinfo.blue_mask == 0xff0000)) ++#endif ++ { ++ c_grab = X11Grab_TrueXBGR24; ++ } else ++ c_grab = NULL; ++ config = VID_GREYSCALE|VID_COLOR; ++ break; ++ ++ default: ++ fprintf(stderr, "don't know how to grab %d bits\n", ++ root_depth_); ++ c_grab = NULL; ++ break; ++ } ++ } ++ ++ if ((ximage_ == NULL) || (width_ != w) || (height_ != h)) { ++ width_ = w; ++ height_ = h; ++ if (ximage_ != NULL) ++ VidUtil_DestroyXImage(dpy_, ximage_); ++ ximage_ = VidUtil_AllocXImage(dpy_, root_vis, root_depth_, w, h, False); ++ } ++ return (c_grab == NULL) ? 0 : config|VID_SMALL|VID_MEDIUM|VID_LARGE; ++} ++ ++extern "C" { ++extern void VidUtil_Init(Display *dpy); ++extern void VidUtil_DestroyXImage(Display *dpy, ximage_t *ximage); ++ ++#ifdef UNUSED /* not yet... */ ++static int ++ErrHandler1(ClientData clientData, XErrorEvent *errevp) ++{ ++ xerror = 1; ++ return 0; ++} ++ ++static int ++X11Grab_MakeBox(unsigned int x1, unsigned int y1, ++ unsigned int x2, unsigned int y2, ++ int *xp, int *yp, int *wp, int *hp) ++{ ++ int w, h; ++ ++ w = x2-x1; ++ if (w < 0) { ++ *xp = x2; ++ *wp = -w; ++ } else { ++ *xp = x1; ++ *wp = w; ++ } ++ ++ h = y2-y1; ++ if (h < 0) { ++ *yp = y2; ++ *hp = -h; ++ } else { ++ *yp = y1; ++ *hp = h; ++ } ++} ++ ++static int ++X11Grab_UpdatePos(Window rw, int x, int y, int w, int h) ++{ ++ static char cmd[256]; ++ ++ if (w < 8) w = 8; ++ if (h < 8) h = 8; ++ ++ if (w > root_width/8*8) w = root_width/8*8; ++ if (h > root_height/8*8) h = root_height/8*8; ++ ++ w = (w+7)/8*8; ++ h = (h+7)/8*8; ++ ++ if (x < 0) x = 0; ++ if (y < 0) y = 0; ++ ++ if (x > root_width-w) x = root_width-w; ++ if (y > root_height-h) y = root_height-h; ++ ++ sprintf(cmd, "x11grabUpdatePos %d %d %d %d", x, y, w, h); ++ (void) Tcl_Eval(interp, cmd); ++ ++ x_origin = x; ++ y_origin = y; ++ ++ if ((root != rw) || (width != w) || (height != h)) { ++ X11Grab_Initialize(rw, w, h); ++ return 0; ++ } else ++ return 1; ++} ++ ++static int ++X11Grab_FollowPointer(void) ++{ ++ Window rw, cw; ++ int x, y, wx, wy; ++ unsigned int mask; ++ ++ XQueryPointer(dpy, root, &rw, &cw, &x, &y, &wx, &wy, &mask); ++ ++ if (x < x_origin+width/4) ++ x = x-width/4; ++ else if (x >= x_origin+3*width/4) ++ x = x-3*width/4; ++ else ++ x = x_origin; ++ ++ if (y < y_origin+height/4) ++ y = y-height/4; ++ else if (y >= y_origin+3*height/4) ++ y = y-3*height/4; ++ else ++ y = y_origin; ++ ++ return X11Grab_UpdatePos(rw, x, y, width, height); ++} ++ ++static int ++X11Grab_FollowWindow(void) ++{ ++ int x, y, w, h; ++ XWindowAttributes wattr, vRoot_wattr; ++ Tk_ErrorHandler handler; ++ ++ handler = Tk_CreateErrorHandler(dpy, -1, -1, -1, ErrHandler1, NULL); ++ xerror = 0; ++ XGetWindowAttributes(dpy, target, &wattr); ++ XSync(dpy, False); ++ Tk_DeleteErrorHandler(handler); ++ if ((target == None) || xerror) { ++ target = None; ++ (void) Tcl_Eval(interp, ++ ".grabControls.x11grab.row1.mode.window config -state disabled"); ++ (void) Tcl_Eval(interp, "set x11grabMode fixed"); ++ return 1; ++ } else { ++ XGetWindowAttributes(dpy, vRoot, &vRoot_wattr); ++ x = wattr.x+vRoot_wattr.x; ++ y = wattr.y+vRoot_wattr.y; ++ w = wattr.width+2*wattr.border_width; ++ h = wattr.height+2*wattr.border_width; ++ ++ return X11Grab_UpdatePos(root, x, y, w, h); ++ } ++} ++#endif /* UNUSED ... */ ++ ++ ++#ifdef UNUSED ++/*ARGSUSED*/ ++static int ++X11Grab_SetXCmd(ClientData clientData, Tcl_Interp *interp, ++ int argc, char *argv[]) ++{ ++ int x; ++ ++ if (argc != 2) { ++ Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], ++ " x\"", NULL); ++ return TCL_ERROR; ++ } ++ ++ x = atoi(argv[1]); ++ (void) X11Grab_UpdatePos(root, x, y_origin, width, height); ++ ++ return TCL_OK; ++} ++ ++/*ARGSUSED*/ ++static int ++X11Grab_SetYCmd(ClientData clientData, Tcl_Interp *interp, ++ int argc, char *argv[]) ++{ ++ int y; ++ ++ if (argc != 2) { ++ Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], ++ " y\"", NULL); ++ return TCL_ERROR; ++ } ++ ++ y = atoi(argv[1]); ++ (void) X11Grab_UpdatePos(root, x_origin, y, width, height); ++ ++ return TCL_OK; ++} ++ ++/*ARGSUSED*/ ++static int X11Grab_SetWCmd(ClientData clientData, Tcl_Interp *interp, ++ int argc, char *argv[]) ++{ ++ int w; ++ ++ if (argc != 2) { ++ Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], ++ " width\"", NULL); ++ return TCL_ERROR; ++ } ++ ++ w = atoi(argv[1]); ++ (void) X11Grab_UpdatePos(root, x_origin, y_origin, w, height); ++ ++ return TCL_OK; ++} ++ ++/*ARGSUSED*/ ++static int ++X11Grab_SetHCmd(ClientData clientData, Tcl_Interp *interp, ++ int argc, char *argv[]) ++{ ++ int h; ++ ++ if (argc != 2) { ++ Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], ++ " height\"", NULL); ++ return TCL_ERROR; ++ } ++ ++ h = atoi(argv[1]); ++ (void) X11Grab_UpdatePos(root, x_origin, y_origin, width, h); ++ ++ return TCL_OK; ++} ++ ++/*ARGSUSED*/ ++static int ++X11Grab_SetRegionCmd(ClientData clientData, Tcl_Interp *interp, ++ int argc, char *argv[]) ++{ ++ unsigned int rootx, rooty; ++ int x, y, w, h, boxDrawn=0; ++ GC xorGC; ++ Cursor cursor; ++ XEvent event; ++ ++ cursor = XCreateFontCursor(dpy, XC_cross); ++ ++ if (XGrabPointer(dpy, root, False, ButtonPressMask, GrabModeAsync, ++ GrabModeAsync, root, cursor, CurrentTime)!=GrabSuccess) { ++ Tcl_AppendResult(interp, argv[0], ": can't grab mouse", NULL); ++ return TCL_ERROR; ++ } ++ ++ xorGC = XCreateGC(dpy, root, 0, NULL); ++ XSetSubwindowMode(dpy, xorGC, IncludeInferiors); ++ XSetForeground(dpy, xorGC, -1); ++ XSetFunction(dpy, xorGC, GXxor); ++ ++ XMaskEvent(dpy, ButtonPressMask, &event); ++ rootx = event.xbutton.x_root; ++ rooty = event.xbutton.y_root; ++ ++ XChangeActivePointerGrab(dpy, ButtonMotionMask|ButtonReleaseMask, cursor, ++ CurrentTime); ++ ++ while (1) { ++ XNextEvent(dpy, &event); ++ switch (event.type) { ++ case MotionNotify: ++ if (boxDrawn) { ++ XDrawRectangle(dpy, root, xorGC, x, y, w, h); ++ boxDrawn = 0; ++ } ++ while (XCheckTypedEvent(dpy, MotionNotify, &event)) ; ++ X11Grab_MakeBox(rootx, rooty, event.xbutton.x_root, ++ event.xbutton.y_root, &x, &y, &w, &h); ++ XDrawRectangle(dpy, root, xorGC, x, y, w, h); ++ boxDrawn = 1; ++ break; ++ case ButtonRelease: ++ if (boxDrawn) { ++ XDrawRectangle(dpy, root, xorGC, x, y, w, h); ++ boxDrawn = 0; ++ } ++ XFlush(dpy); ++ X11Grab_MakeBox(rootx, rooty, event.xmotion.x_root, ++ event.xmotion.y_root, &x, &y, &w, &h); ++ XUngrabPointer(dpy, CurrentTime); ++ XFreeGC(dpy, xorGC); ++ XFreeCursor(dpy, cursor); ++ (void) Tcl_Eval(interp, "set x11grabMode fixed"); ++ (void) X11Grab_UpdatePos(root, x, y, w, h); ++ return TCL_OK; ++ } ++ } ++} ++ ++/*ARGSUSED*/ ++static int X11Grab_SetWindowCmd(ClientData clientData, Tcl_Interp *interp, ++ int argc, char *argv[]) ++{ ++ int buttons=0; ++ Cursor cursor; ++ XEvent event; ++ ++ cursor = XCreateFontCursor(dpy, XC_crosshair); ++ target = None; ++ ++ if (XGrabPointer(dpy, vRoot, False, ButtonPressMask|ButtonReleaseMask, ++ GrabModeSync, GrabModeAsync, root, cursor, ++ CurrentTime) != GrabSuccess) { ++ Tcl_AppendResult(interp, argv[0], ": can't grab mouse", NULL); ++ return TCL_ERROR; ++ } ++ ++ while ((target == None) || (buttons != 0)) { ++ XAllowEvents(dpy, SyncPointer, CurrentTime); ++ XWindowEvent(dpy, vRoot, ButtonPressMask|ButtonReleaseMask, &event); ++ switch (event.type) { ++ case ButtonPress: ++ if (target == None) target = event.xbutton.subwindow; ++ buttons++; ++ break; ++ case ButtonRelease: ++ if (buttons > 0) buttons--; ++ break; ++ } ++ } ++ ++ XUngrabPointer(dpy, CurrentTime); ++ XFreeCursor(dpy, cursor); ++ ++ (void) Tcl_Eval(interp, ++ ".grabControls.x11grab.row1.mode.window config -state normal"); ++ (void) Tcl_Eval(interp, "set x11grabMode window"); ++ (void) X11Grab_FollowWindow(); ++ return TCL_OK; ++} ++ ++int ++X11Grab_Probe(Tk_Window tkMainWin) ++{ ++ Window rw; ++ interp = Tcl_CreateInterp(); ++ ++ if (tkMainWin == NULL) return 0; ++ ++ Tcl_TraceVar(interp, "x11grabMode", TCL_TRACE_WRITES, X11Grab_TraceMode, ++ NULL); ++ Tcl_CreateCommand(interp, "x11grabSetX", X11Grab_SetXCmd, 0, NULL); ++ Tcl_CreateCommand(interp, "x11grabSetY", X11Grab_SetYCmd, 0, NULL); ++ Tcl_CreateCommand(interp, "x11grabSetW", X11Grab_SetWCmd, 0, NULL); ++ Tcl_CreateCommand(interp, "x11grabSetH", X11Grab_SetHCmd, 0, NULL); ++ Tcl_CreateCommand(interp, "x11grabSetRegion", X11Grab_SetRegionCmd, 0, ++ NULL); ++ Tcl_CreateCommand(interp, "x11grabSetWindow", X11Grab_SetWindowCmd, 0, ++ NULL); ++ dpy = Tk_Display(tkMainWin); ++ rootwin = rw = RootWindow(dpy, Tk_ScreenNumber(tkMainWin)); ++ VidUtil_Init(dpy); ++ return X11Grab_Initialize(rw, width, height); ++} ++#endif /* UNUSED */ ++ ++} /* end extern "C" block */ ++ ++ ++int ++X11Device::command(int argc, const char*const* argv) ++{ ++ Tcl& tcl = Tcl::instance(); ++ ++ if ((argc == 3) && (strcmp(argv[1], "open") == 0)) { ++ TclObject* o = new X11Grabber(name_, argv[2]); ++ if (o != 0) ++ tcl.result(o->name()); ++ return (TCL_OK); ++ } ++ return (InputDevice::command(argc, argv)); ++} ++ ++X11Grabber::X11Grabber(const char* name, const char* format) ++{ ++ c_grab = NULL ; /* XXX */ ++ theroot_ = None ; /* XXX */ ++ ximage_ = NULL ; ++ color = NULL ; ++ col2y_ = NULL ; ++ col2rgb16_ = NULL ; ++ ++ width_ = 320 ; ++ height_ = 240 ; ++ x_origin_ = y_origin_ = 0 ; /* XXX */ ++ ++ if (strcmp(format, "422") && strcmp(format, "cif")) { ++ fprintf(stderr, ++ "vic: x11Grabber: unsupported format: %s\n", ++ format); ++ abort(); ++ } ++ ++ Tk_Window tkMainWin = Tcl::instance().tkmain() ; ++ Window rw ; ++ ++ dpy_ = Tk_Display(tkMainWin); ++ rootwin_ = rw = RootWindow(dpy_, Tk_ScreenNumber(tkMainWin)); ++ ++ /* Initialize the RGB565 to YUV tables */ ++ int i, r, g, b, y, u, v; ++ ++ rgb2y_ = new uint8[65536] ; ++ rgb2u_ = new uint8[65536] ; ++ rgb2v_ = new uint8[65536] ; ++ ++ i = 0; ++ for (r=4; r<256; r+=8) { ++ for (g=3; g<256; g+=4) { /* XXX */ ++ for (b=4; b<256; b+=8) { ++ y = (38*r+75*g+15*b+64)/128; ++ u = 74*(b-y)/128; ++ if (u > 127) u = 127 ; ++ else if (u< -128) u = -128 ; ++ v = (93*(r-y)/128); ++ if (v > 127) v = 127 ; ++ else if (v< -128) v = -128 ; ++ rgb2y_[i] = y ; ++ rgb2u_[i] = u ^ 0x80 ; /* was u */ ++ rgb2v_[i] = v ^ 0x80 ; ++ i++; ++ } ++ } ++ } ++ ++ X11Grab_Initialize(rw, width_, height_); ++ ++ mode_ = X11GRAB_FIXED; /* XXX */ ++ decimate_ = 1; /* XXX */ ++ basewidth_ = PAL_WIDTH * 2; ++ baseheight_ = PAL_HEIGHT * 2; ++ ++} ++ ++X11Grabber::~X11Grabber() ++{ ++ if (ximage_ != NULL) ++ VidUtil_DestroyXImage(dpy_, ximage_); ++ free(rgb2y_); ++ free(rgb2u_); ++ free(rgb2v_); ++} ++ ++void ++X11Grabber::setsize() ++{ ++ int rows, columns; ++ ++ rows = (baseheight_ / decimate_) &~0xf; /* 0xf, ugh! */ ++ columns = (basewidth_ / decimate_) &~0xf; ++ ++ /* XXX set size of captured window ? */ ++ ++ set_size_422(columns, rows); /* was 422... */ ++ X11Grab_Initialize(rootwin_, columns, rows); /* XXX */ ++ ++ allocref(); /* allocate reference frame */ ++} ++ ++void ++X11Grabber::format() ++{ ++ ++ baseheight_ = CIF_HEIGHT * 2; ++ basewidth_ = CIF_WIDTH * 2; ++ ++ setsize(); ++} ++ ++ ++void ++X11Grabber::start() ++{ ++ format(); ++ /* XXX prepare for continuous capture */ ++ Grabber::start(); ++} ++ ++void ++X11Grabber::stop() ++{ ++ /* XXX stop capture */ ++ VidUtil_DestroyXImage(dpy_, ximage_); ++ ximage_ = NULL ; ++ Grabber::stop(); ++} ++ ++int ++X11Grabber::command(int argc, const char*const* argv) ++{ ++ if (argc >= 3) { ++ if (strcmp(argv[1], "decimate") == 0) { ++ int dec = atoi(argv[2]); ++ Tcl& tcl = Tcl::instance(); ++ if (dec <= 0) { ++ tcl.resultf("%s: divide by zero", argv[0]); ++ return (TCL_ERROR); ++ } ++ if (dec != decimate_) { ++ decimate_ = dec; ++ if(running_) { ++ stop(); ++ setsize(); ++ start(); ++ } ++ } ++ return (TCL_OK); ++ } else if (strcmp(argv[1], "fixed") == 0) { ++ mode_ = X11GRAB_FIXED; ++ ++ int x = atoi(argv[2]); ++ int y = atoi(argv[3]); ++ if (x >= 0 && *argv[2] != '-' && x + width_ <= root_width) ++ x_origin_ = x ; ++ else if ( x <= 0 && -x + width_ <= root_width ) ++ x_origin_ = root_width + x - width_ ; ++ if (y >= 0 && *argv[3] != '-' && y + height_ <= root_height) ++ y_origin_ = y ; ++ else if (y <= 0 && -y + height_ <= root_height ) ++ y_origin_ = root_height + y - height_ ; ++ fprintf(stderr, "x11 fixed %d %d (root %dx%d)\n", ++ x_origin_, y_origin_, root_width, root_height); ++ return (TCL_OK); ++ } else if (!strcmp(argv[2], "pointer")) { ++ mode_ = X11GRAB_POINTER; ++ return (TCL_OK); ++ } else if (!strcmp(argv[2], "window")) { ++ mode_ = X11GRAB_WINDOW; ++ return (TCL_OK); ++ } else if (strcmp(argv[1], "format") == 0 || ++ strcmp(argv[1], "type") == 0) { ++ if (running_) ++ format(); ++ return (TCL_OK); ++ } else if (strcmp(argv[1], "contrast") == 0) { ++ contrast(atof(argv[2])); ++ return (TCL_OK); ++ } ++ } else if (argc == 2) { ++ if (strcmp(argv[1], "format") == 0 || ++ strcmp(argv[1], "type") == 0) { ++ return (TCL_OK); ++ } ++ } ++ return (Grabber::command(argc, argv)); ++} ++ ++/* ++ * captures in CIF or 411 -- color info is half the luma info. ++ */ ++int ++X11Grabber::capture() ++{ ++ int dograb = 0 ; ++ ++#define MY_T uint8 ++ ++ ++ switch (mode_) { ++ case X11GRAB_FIXED: ++ dograb = 1; ++ break; ++#if 0 /* not yet... */ ++ case X11GRAB_POINTER: ++ dograb = X11Grab_FollowPointer(); ++ break; ++ case X11GRAB_WINDOW: ++ dograb = X11Grab_FollowWindow(); ++ break; ++#endif ++ } ++ ++ if (1 || dograb) { ++ XImage *image=ximage_->image; ++ ++#ifdef USE_SHM ++ if (ximage_->shminfo != NULL) ++ XShmGetImage(dpy_, theroot_, image, x_origin_, y_origin_,AllPlanes); ++ else ++#endif ++ XGetSubImage(dpy_, theroot_, x_origin_, y_origin_, ++ image->width, image->height, AllPlanes, ++ ZPixmap, image, 0, 0); ++ c_grab(); ++ return 1 ; ++ } else ++ return 0; ++} ++ ++int X11Grabber::grab() ++{ ++ if (capture() == 0) ++ return (0); ++ suppress(frame_); ++ saveblks(frame_); ++ YuvFrame f(media_ts(), frame_, crvec_, outw_, outh_); ++ return (target_->consume(&f)); ++} ++ ++extern "C" { ++ ++#include <sys/ipc.h> ++#ifdef USE_SHM ++#include <sys/shm.h> ++#if defined(sun) && !defined(__svr4__) ++int shmget(key_t, int, int); ++char *shmat(int, char*, int); ++int shmdt(char*); ++int shmctl(int, int, struct shmid_ds*); ++#endif ++#ifdef __osf__ ++int XShmGetEventBase(struct _XDisplay *); ++#else ++int XShmGetEventBase(Display *); ++#endif ++#ifdef sgi ++#define XShmAttach __XShmAttach__ ++#define XShmDetach __XShmDetach__ ++#define XShmPutImage __XShmPutImage__ ++#endif ++#include <X11/extensions/XShm.h> ++#ifdef sgi ++#undef XShmAttach ++#undef XShmDetach ++#undef XShmPutImage ++int XShmAttach(Display*, XShmSegmentInfo*); ++int XShmDetach(Display*, XShmSegmentInfo*); ++int XShmPutImage(Display*, Drawable, GC, XImage*, int, int, int, int, ++ int, int, int); ++#endif ++#endif ++ ++ ++/*ARGSUSED*/ ++static int ++ErrHandler(ClientData clientData, XErrorEvent *errevp) ++{ ++ return 0; ++} ++ ++ximage_t * ++VidUtil_AllocXImage(Display *dpy, Visual *vis, int depth, int width, ++ int height, int readonly) ++{ ++ ximage_t *ximage; ++ int ximage_size; ++ Tk_ErrorHandler handler; ++ ++ ximage = (ximage_t *) malloc(sizeof(ximage_t)); ++ if (ximage == NULL) ++ return NULL; ++ ++#ifdef USE_SHM ++ if (1) { ++ XShmSegmentInfo *shminfo; ++ ++ ximage->shminfo = shminfo = ++ (XShmSegmentInfo *) malloc(sizeof(XShmSegmentInfo)); ++ ++ ximage->image = XShmCreateImage(dpy, vis, depth, ZPixmap, 0, shminfo, ++ width, height); ++ ximage_size = ximage->image->bytes_per_line * ximage->image->height; ++ ++ shminfo->shmid = shmget(IPC_PRIVATE, ximage_size, IPC_CREAT|0777); ++ if (shminfo->shmid != -1) { ++ shminfo->shmaddr = ximage->image->data = ++ (char *) shmat(shminfo->shmid, 0, 0); ++ shminfo->readOnly = readonly; ++ ++ handler = Tk_CreateErrorHandler(dpy, -1, -1, -1, ErrHandler, NULL); ++ XShmAttach(dpy, shminfo); ++ XSync(dpy, False); ++ shmctl(shminfo->shmid, IPC_RMID, 0); /* so it goes away on exit */ ++ Tk_DeleteErrorHandler(handler); ++ if (0) { /* so it goes away on exit... */ ++ shmdt(shminfo->shmaddr); ++ shmctl(shminfo->shmid, IPC_RMID, 0); ++ XDestroyImage(ximage->image); ++ free(shminfo); ++ } ++ return ximage; ++ } else { ++ XDestroyImage(ximage->image); ++ free(shminfo); ++ ximage->shminfo = NULL ; ++ /* XXX hmmm... something more ? */ ++ } ++ } ++#endif ++ { ++ ximage->image = XCreateImage(dpy, vis, depth, ZPixmap, 0, NULL, width, ++ height, (depth == 24) ? 32 : depth, 0); ++ ximage_size = ximage->image->bytes_per_line * ximage->image->height; ++ ximage->image->data = (char *) malloc(ximage_size); ++ ++ ximage->shminfo = NULL; ++ } ++ ++ return ximage; ++} ++ ++void ++VidUtil_DestroyXImage(Display *dpy, ximage_t *ximage) ++{ ++#ifdef USE_SHM ++ if (ximage->shminfo != NULL) { ++ XShmSegmentInfo *shminfo=(XShmSegmentInfo *)ximage->shminfo; ++ ++ XShmDetach(dpy, shminfo); ++ shmdt(shminfo->shmaddr); ++ shmctl(shminfo->shmid, IPC_RMID, 0); ++ free(shminfo); ++ } ++ ximage->shminfo = NULL ; ++#endif ++ ++ XDestroyImage(ximage->image); ++ free(ximage); ++} ++ ++ ++} /* end extern "C" block */ |