/* * Copyright (c) 1993-1995 The Regents of the University of California. * All rights reserved. * * 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 the Network Research * Group at Lawrence Berkeley National Laboratory. * 4. Neither the name of the University nor of the Laboratory may be used * to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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. * * Derived from code written by Eric Anderson, UCSD Computer Systems Lab, * 4/92 and hacked on by Jon Kay, Vach Kompella, Kevin Fall. * Ported to vic 1/94, Steven McCanne (mccanne@ee.lbl.gov) March 1993. */ /* * (c) Copyright 1994 HEWLETT-PACKARD COMPANY * * To anyone who acknowledges that this file is provided * "AS IS" without any express or implied warranty: * permission to use, copy, modify, and distribute this * file for any purpose is hereby granted without fee, * provided that the above copyright notice and this * notice appears in all copies, and that the name of * Hewlett-Packard Company not be used in advertising or * publicity pertaining to distribution of the software * without specific, written prior permission. Hewlett- * Packard Company makes no representations about the * suitability of this software for any purpose. * */ /* * Apply this patch to the extensions/xv/lib/Xv.c file: *** Xv.c~ Thu Mar 31 11:13:47 1994 --- Xv.c Fri May 27 11:38:33 1994 *************** *** 192,197 **** --- 192,198 ---- return(XvBadAlloc); } (void)strncpy(name, u.string, size); + name[size] = '\0'; pa->name = name; u.buffer += (size + 3) & ~3; *************** *** 351,356 **** --- 352,358 ---- return(XvBadAlloc); } strncpy(name, u.string, size); + name[size] = '\0'; pe->name = name; pe++; * It fixes a problem with strings NOT being null terminated. */ #ifndef lint static char rcsid[] = "@(#) $Header: /cs/research/mice/starship/src/local/CVS_repository/vic/video/grabber-xv.cpp,v 1.1 1999/09/09 12:52:58 piers Exp $ (LBL)"; #endif #include #include #include #include #include #include #include #include #include #include #include extern "C" { #ifdef _AIX #include #else #include #endif } #include "grabber.h" #include "crdef.h" #include "module.h" #include "vic_tcl.h" #include "device-input.h" #include "rgb-converter.h" #include "vw.h" #define NTSC_WIDTH 640 #define NTSC_HEIGHT 480 #define PAL_WIDTH 768 #define PAL_HEIGHT 576 #define CIF_WIDTH 352 #define CIF_HEIGHT 288 class XvWindow : public CaptureWindow { public: XvWindow(const char* name, XVisualInfo*, XvPortID); virtual ~XvWindow(); virtual void setsize(int w, int h); protected: XvPortID grabID_; }; class XvGrabber : public Grabber { public: XvGrabber(); virtual ~XvGrabber(); virtual int command(int argc, const char*const* argv); protected: virtual void setsize(); void setattr(Atom attr, int value); void setport(const char *port); int getattr(Atom attr); int getgrabber(); virtual int grab(); XvEncodingInfo *lookup_encoding_by_id(XvEncodingID id); XvEncodingInfo *lookup_encoding_by_name(char *name); Visual* visual_; XvPortID grabID_; XvWindow* capwin_; char grabber_name[80]; Atom XAbrightness, XAcontrast, XAhue, XAsaturation, XAencoding; u_int nencodings; XvEncodingInfo *encoding; int decimate_; XvEncodingID encodingid_; XVisualInfo vinfo_; }; class XvCIFGrabber : public XvGrabber { protected: virtual void setsize(); }; class Xv411Grabber : public XvGrabber { protected: virtual void setsize(); }; class XvDevice : public InputDevice { public: XvDevice(const char* s); int command(int argc, const char*const* argv); }; static XvDevice xv_device("xv"); XvDevice::XvDevice(const char* s) : InputDevice(s) { /*XXX port & 411*/ attributes_ = "format { 422 411 } size { small large cif }"; } int XvDevice::command(int argc, const char*const* argv) { #if 0 printf("XvDevice::command: %d: ", argc); for (int i=0; iname()); } else if (strcmp(argv[2], "cif") == 0) { TclObject* o = new XvCIFGrabber; tcl.result(o->name()); } return (TCL_OK); } } return (InputDevice::command(argc, argv)); } XvWindow::XvWindow(const char* name, XVisualInfo* vinfo, XvPortID grabID) : CaptureWindow(name, vinfo), grabID_(grabID) { /* * Xv doesn't have a way to query the signal type, and * hence the input video geometry. * XXX should make this configurable. */ #define NTSC_WIDTH 640 #define NTSC_HEIGHT 480 base_width_ = NTSC_WIDTH; base_height_ = NTSC_HEIGHT; } XvWindow::~XvWindow() { if (image_ != 0) XvStopVideo(dpy_, grabID_, Tk_WindowId(tk_)); } void XvWindow::setsize(int w, int h) { CaptureWindow::setsize(w, h); /* Start the video display */ Tk_MakeWindowExist(tk_); XvPutVideo(dpy_, grabID_, Tk_WindowId(tk_), gc_, 0, 0, base_width_, base_height_, 0, 0, width_, height_); } XvGrabber::XvGrabber() : capwin_(0), decimate_(0) { Tcl& tcl = Tcl::instance(); if (getgrabber() < 0) { status_ = -1; return; } Display* dpy = Tk_Display(Tcl::instance().tkmain()); if (XvGrabPort(dpy, grabID_, CurrentTime) != Success) { tcl.result("Unable to reserve grabber."); fprintf(stderr, "Unable to grab port\n"); status_ = -1; return; } } XvGrabber::~XvGrabber() { if (status_ >= 0) { Display* dpy = Tk_Display(Tcl::instance().tkmain()); XvUngrabPort(dpy, grabID_, CurrentTime); } } int XvGrabber::command(int argc, const char*const* argv) { Tcl& tcl = Tcl::instance(); 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; setsize(); } return (TCL_OK); } else if (strcmp(argv[1], "port") == 0) { setport(argv[2]); return (TCL_OK); } else if (strcmp(argv[1], "contrast") == 0) { setattr(XAcontrast, atoi(argv[2])); return (TCL_OK); } else if (strcmp(argv[1], "brightness") == 0) { setattr(XAbrightness, atoi(argv[2])); return (TCL_OK); } else if (strcmp(argv[1], "hue") == 0) { setattr(XAhue, atoi(argv[2])); return (TCL_OK); } else if (strcmp(argv[1], "saturation") == 0) { setattr(XAsaturation, atoi(argv[2])); return (TCL_OK); } else if (strcmp(argv[1], "create-capwin") == 0) { capwin_ = new XvWindow(argv[2], &vinfo_, grabID_); tcl.result(capwin_->name()); return (TCL_OK); } } else if (argc == 2) { if (strcmp(argv[1], "need-capwin") == 0) { tcl.result("1"); return (TCL_OK); } } return (Grabber::command(argc, argv)); } XvEncodingInfo *XvGrabber::lookup_encoding_by_id(XvEncodingID id) { int i; for (i=0; ibasewidth() / decimate_; int h = capwin_->baseheight() / decimate_; capwin_->setsize(w, h); capwin_->converter(RGB_Converter_422::instance()); set_size_422(capwin_->width(), capwin_->height()); allocref(); } void XvCIFGrabber::setsize() { int w = 2 * 352 / decimate_; int h = 2 * 288 / decimate_; capwin_->setsize(w, h); capwin_->converter(RGB_Converter_411::instance()); set_size_411(w, h); allocref(); } void Xv411Grabber::setsize() { int w = capwin_->basewidth() / decimate_; int h = capwin_->baseheight() / decimate_; capwin_->setsize(w, h); capwin_->converter(RGB_Converter_411::instance()); set_size_411(w, h); allocref(); } int XvGrabber::grab() { capwin_->capture(frame_); suppress(frame_); saveblks(frame_); YuvFrame f(media_ts(), frame_, crvec_, outw_, outh_); return (target_->consume(&f)); } int XvGrabber::getgrabber() { Tk_Window tk = Tcl::instance().tkmain(); Display* dpy = Tk_Display(tk); int majop, eventbase, errbase; if (XQueryExtension(dpy, "XVideo", &majop, &eventbase, &errbase) == False) return (-1); Window root = DefaultRootWindow(dpy); u_int ngrabbers; XvAdaptorInfo* grabbers; if (XvQueryAdaptors(dpy, root, &ngrabbers, &grabbers) != Success || ngrabbers == 0) return (-1); if (ngrabbers > 1) fprintf(stderr, "vic: warning: more than one frame grabber\n"); strncpy(grabber_name, grabbers[0].name, sizeof(grabber_name)); grabID_ = grabbers[0].base_id; XvFreeAdaptorInfo(grabbers); XvQueryEncodings(dpy, grabID_, &nencodings, &encoding); #if 0 printf("Encodings(%d): ", nencodings); for (int i=0; i