/* pseudo grabber device Chris Greenhalgh cmg@cs.nott.ac.uk 14/3/2002 This shoudl be copied to vic/video and included in the makefile */ #include #include #include #include "config.h" //#include //#include #include "grabber.h" #include "device-input.h" #include "module.h" #include "rgb-converter.h" /* 0=ok; decimation already included in size */ typedef int (*GrabberCallback)(char *frame, int width, int height, int bpp, int decimation, void *closure); static GrabberCallback s_callback = NULL; static void *s_closure = NULL; extern "C" { #ifdef WIN32 __declspec(dllexport) #endif int SetGrabberCallback(GrabberCallback cb, void *cl) { s_callback = cb; s_closure = cl; return 0; } } extern "C" HINSTANCE TkWinGetAppInstance(); class CmgGrabber : public Grabber { public: CmgGrabber(const char *format); virtual ~CmgGrabber(); virtual int command(int argc, const char*const* argv); protected: virtual void start(); virtual void stop(); virtual int grab(); virtual void setsize(); int frametype; int basewidth, baseheight; int w, h; int framenumber; Converter *converter_; u_int decimate_; /* division of base sizes */ }; CmgGrabber::CmgGrabber(const char *format) { debug_msg("new CmgGrabber - format %s\n", format); frametype = 0; if (strcmp(format, "422")==0) { frametype = FT_YUV_422; converter_ = new RGB_Converter_422(32,NULL,0); } else if (strcmp(format, "411")==0) { frametype = FT_YUV_411; converter_ = new RGB_Converter_411(32,NULL,0); } else if (strcmp(format, "cif")==0) { frametype = FT_YUV_CIF; converter_ = new RGB_Converter_411(32,NULL,0); } else { debug_msg("unknown format - \"%s\"\n", format); converter_ = NULL; } // CIF basewidth = 704; baseheight = 576; framenumber = 0; decimate_ = 1; } CmgGrabber::~CmgGrabber() { debug_msg("delete CmgGrabber\n"); if (converter_ != NULL) delete converter_; } int CmgGrabber::command(int argc, const char*const* argv) { Tcl& tcl = Tcl::instance(); #ifdef DEBUG debug_msg("CmgGrabber::command argc=%d ", argc); int i; for (i = 0; i < argc; i++) debug_msg("\"%s\" ", argv[i]); debug_msg("\n"); #endif /* DEBUG */ if (argc == 3) { if (strcmp(argv[1], "q") == 0) { // ? from grabber-still return TCL_OK; } else if (strcmp(argv[1], "decimate") == 0) { u_int dec = (u_int)atoi(argv[2]); Tcl& tcl = Tcl::instance(); if (dec <= 0) { tcl.resultf("%s: divide by zero", argv[0]); return (TCL_ERROR); } debug_msg("CmgGrabber::command: decimate=%d (dec)=%d\n", dec, decimate_); if (dec != decimate_) { decimate_ = dec; if (running_) { stop(); setsize(); start(); } else setsize(); } return (TCL_OK); } } return (Grabber::command(argc, argv)); } void CmgGrabber::start() { setsize(); frameclock_ = gettimeofday(); timeout(); } void CmgGrabber::stop() { Grabber::stop(); } void CmgGrabber::setsize() { debug_msg("CmgGrabber::setsize\n"); w = basewidth/decimate_; h = baseheight/decimate_; if (frametype==FT_YUV_411) set_size_411(w, h); else if (frametype==FT_YUV_422) set_size_422(w, h); else if (frametype==FT_YUV_CIF) set_size_cif(w, h); allocref(); } int CmgGrabber::grab() { if (converter_ == NULL) return TCL_ERROR; u_int32_t *last_frame_ = (u_int32_t*)new u_char[4*framesize_]; if (s_callback!=NULL) (*s_callback)((char *)last_frame_, outw_, outh_, 32, decimate_, s_closure); else { memset(last_frame_, 0, 4*framesize_); // make it up - rgb(a), 32 bit, decimated int line = outw_;//uin32s int x, y; int fn = ++framenumber; u_int32_t *p = last_frame_; for (x=0; x<256; x++) { if (fn & 1) for (y=0; y<8; y++) { p[line*y] = (((((x+8)>>3) & 1) ? 0xff0000 : 0) | ((((x+8)>>3) & 2) ? 0x00ff00 : 0) | ((((x+8)>>3) & 4) ? 0x0000ff : 0)); } p++; if ((x & 7)==7) fn = fn >> 1; } } converter_->convert((u_int8_t*)last_frame_, outw_, outh_, frame_, outw_, outh_, TRUE); delete [] last_frame_; YuvFrame f(media_ts(), frame_, crvec_, outw_, outh_); return target_->consume(&f); } class CmgDevice : public InputDevice { public: CmgDevice(const char* name); ~CmgDevice(); virtual int command(int argc, const char*const* argv); protected: // .... }; static CmgDevice cmgDevice("cmg"); CmgDevice::CmgDevice(const char* name) : InputDevice(name) { debug_msg("CmgDevice: \"%s\"\n", name); attributes_ = "format { 422 411 } size { small large cif }"; } CmgDevice::~CmgDevice() { } int CmgDevice::command(int argc, const char*const* argv) { Tcl& tcl = Tcl::instance(); if ((argc == 3) && (strcmp(argv[1], "open") == 0)) { TclObject* o = 0; if (strcmp(argv[2], "422") == 0 || strcmp(argv[2], "411") == 0 || strcmp(argv[2], "cif") == 0) o = new CmgGrabber(argv[2]); if (o != 0) Tcl::instance().result(o->name()); return (TCL_OK); } return (InputDevice::command(argc, argv)); } /* EOF */