/* * Copyright (c) 1993-1994 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 University of * California, Berkeley and the Network Research Group at * Lawrence Berkeley 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. */ #ifndef lint static char rcsid[] = "@(#) $Header: /cs/research/mice/starship/src/local/CVS_repository/vic/video/grabber-mme.cpp,v 1.1 1999/09/09 12:52:53 piers Exp $ (LBL)"; #endif #include #include #include #include #ifndef __DECCXX #include #endif #include #include extern "C" { /*XXX*/ #undef VOID #include } #include "inet.h" #include "vic_tcl.h" #include "rtp.h" #include "grabber.h" #include "iohandler.h" #include "device-input.h" #include "crdef.h" #include "module.h" #define NTSC_WIDTH 640 #define NTSC_HEIGHT 480 extern "C" { #include #include #include #include } class MmeGrabber : public Grabber, public IOHandler { public: MmeGrabber(); virtual ~MmeGrabber(); virtual int command(int argc, const char*const* argv); virtual void fps(int); virtual void start(); virtual void stop(); protected: virtual void SetComp() = 0; void setport(const char *port); void setstandard(const char *standard); virtual void dispatch(int mask); virtual void timeout(); virtual int consume(const u_char* dmabuf, int length) = 0; virtual const char* type() const; virtual void startup(); virtual void shutdown(); virtual int grab(); inline int mme_error(MMRESULT, const char* msg) const; static int server_; /* fd of server socket */ HVIDEO handle_; /* handle for video connection */ int x_decimate_; /* horizontal downsampling factor */ int y_decimate_; /* vertical downsampling factor */ struct info { EXBMINFOHEADER b; JPEGINFOHEADER jpeg; } *bmh; private: void init(); VIDEOHDR* vh_; static void mme_callback(HVIDEO handle, DWORD code, DWORD instance, LPARAM p1, LPARAM p2); int callback(int code, VIDEOHDR* vh); void waitgrab(); int port_; int standard_; int fps_; int delay_; int last_grab_; volatile int outstanding_; volatile int running_; volatile int valid_; volatile int wantgrab_; int buffers_; }; class MmeJpegGrabber : public MmeGrabber { public: MmeJpegGrabber(); virtual ~MmeJpegGrabber(); virtual int command(int argc, const char*const* argv); protected: int consume(const u_char* buffer, int length); virtual void SetComp(); private: int q_; int nq_; }; class MmeYuvGrabber : public MmeGrabber { public: MmeYuvGrabber(); virtual void SetComp(); virtual int consume(const u_char* buffer, int length); protected: void suppress(const u_char* devbuf, const u_char* lumbuf); virtual void saveblks(const u_char* in) = 0; virtual void setsize(int w, int h) = 0; }; class Mme422Grabber : public MmeYuvGrabber { protected: virtual void saveblks(const u_char* in); void saveblk(const u_char* in, u_char* yp, u_char* up, u_char* vp, int stride); void setsize(int w, int h); }; class MmeCIFGrabber : public MmeYuvGrabber { protected: virtual void saveblks(const u_char* in); void saveblk(const u_char* in, u_char* yp, u_char* up, u_char* vp, int stride, int istride); void setsize(int w, int h); }; class Mme411Grabber : public MmeCIFGrabber { protected: virtual void setsize(int xsize, int ysize); }; class MmeDevice : public InputDevice { public: MmeDevice(const char* name); virtual int command(int argc, const char*const* argv); static int havedev(); }; /***********************************************************************/ static MmeDevice mme_device("mme"); int MmeDevice::havedev() { /* tfm - need to do a more thorough check here */ if( videoGetNumDevs() > 0 ) return (1); else return (0); } MmeDevice::MmeDevice(const char* name) : InputDevice(name) { /* fprintf(stderr, "vic: Called MmeDevice::MmeDevice\n"); */ if (havedev()) attributes_ = "format { 422 jpeg } size { small large cif } port {Comp-1 Comp-2 S-Video525 S-Video625}"; else attributes_ = "disabled"; } int MmeDevice::command(int argc, const char*const* argv) { Tcl& tcl = Tcl::instance(); if (argc == 3) { if(strcmp(argv[1], "open") == 0) { const char* fmt = argv[2]; TclObject* o = 0; /* fprintf(stderr, "vic: Called MmeDevice::command with %s %s\n", argv[1],argv[2]); */ if (strcmp(fmt, "jpeg") == 0) o = new MmeJpegGrabber; else if (strcmp(fmt, "422") == 0) o = new Mme422Grabber; else if (strcmp(fmt, "411") == 0) o = new Mme411Grabber; else if (strcmp(fmt, "cif") == 0) o = new MmeCIFGrabber; if (o != 0) { Tcl::instance().result(o->name()); return (TCL_OK); } } } return (InputDevice::command(argc, argv)); } /***********************************************************************/ MmeGrabber* mmeMaster; MmeGrabber::MmeGrabber() { /* fprintf(stderr, "vic: Called MmeGrabber constructor\n"); */ mmeMaster = this; /*XXX defer videoOpen until start? */ if (videoGetNumDevs() <= 0 || videoOpen(&handle_, 0, VIDEO_IN) != DV_ERR_OK) { valid_ = 0; fprintf(stderr,"vic : Failed to open video device\n"); return; } port_=1; standard_=VIDEO_STANDARD_NTSC; valid_ = 1; running_ = 0; wantgrab_ = 0; buffers_ = 1; fps(5); init(); } MmeGrabber::~MmeGrabber() { /* fprintf(stderr, "vic: Called MmeGrabber::~MmeGrabber\n"); */ if (valid_) { if (running_) stop(); mmeFreeMem(vh_); videoClose(handle_); } } const char* MmeGrabber::type() const { return ("mme"); } int MmeGrabber::server_ = -1; void MmeGrabber::init() { int size; MMRESULT s; /* fprintf(stderr, "vic: Called MmeGrabber::init\n"); */ /* * Allocate & zero some memory for the video header and bitmap * info header. We allocate it as a single block to keep it * all in one shared memory segment. * (Make sure everything's aligned on quadword boundaries) */ size = ((sizeof(*bmh)+sizeof(void*)-1) / sizeof(void*)) * sizeof(void*); bmh = (info*)mmeAllocMem(size+sizeof(*vh_)); if (bmh == 0) { fprintf(stderr, "vic: cannot allocate mme memory\n"); valid_ = 0; return; } memset(bmh, 0, size+sizeof(*vh_)); vh_ = (VIDEOHDR*)((char*)bmh+size); if (server_ < 0) { server_ = mmeServerFileDescriptor(); link(server_, TK_READABLE); } return; bail: mmeFreeMem(bmh); bmh = 0; videoClose(handle_); vh_ = 0; valid_ = 0; /*XXX*/ } /* Override Grabber's timeout method with an empty method */ void MmeGrabber::timeout() { } int MmeGrabber::command(int argc, const char*const* argv) { Tcl& tcl = Tcl::instance(); if (argc == 3) { if(strcmp(argv[1], "decimate") == 0) { int d = atoi(argv[2]); /* fprintf(stderr, "vic: Called MmeGrabber::command with %s %s\n", argv[1],argv[2]); */ if (d == 0) { tcl.resultf("%s: divide by zero", argv[0], 0); return (TCL_ERROR); } x_decimate_ = d; y_decimate_ = d; if(running_) { shutdown(); SetComp(); startup(); } else SetComp(); return (TCL_OK); } else if (strcmp(argv[1], "port") == 0) { setport(argv[2]); return(TCL_OK); } else if (strcmp(argv[1], "type") == 0) { setstandard(argv[2]); return(TCL_OK); } } return (Grabber::command(argc, argv)); } void MmeGrabber::start() { /* fprintf(stderr, "vic: Called MmeGrabber::start\n"); */ startup(); Grabber::start(); } void MmeGrabber::stop() { /* fprintf(stderr, "vic: Called MmeGrabber::stop\n"); */ shutdown(); Grabber::stop(); } void MmeGrabber::fps(int f) { /* fprintf(stderr, "vic: Called MmeGrabber::fps\n"); */ fps_ = f; delay_ = 1000 / f; Grabber::fps(f); } void MmeGrabber::setport(const char *port) { if(port) { if(strcmp(port,"Comp-1") == 0) port_=1; else if(strcmp(port,"Comp-2") == 0) port_=2; else if(strcmp(port,"S-Video525") == 0) { port_ = 0; standard_ = VIDEO_STANDARD_SVIDEO525; } else if(strcmp(port,"S-Video625") == 0) { port_ = 0; standard_ = VIDEO_STANDARD_SVIDEO625; } } } void MmeGrabber::setstandard(const char *standard) { if(standard) { if(strcmp(standard,"ntsc") == 0) { standard_=VIDEO_STANDARD_NTSC; if(!port_) port_=1; } else if(strcmp(standard,"pal") == 0) { standard_=VIDEO_STANDARD_PAL; if(!port_) port_=1; } else if(strcmp(standard,"secam") == 0) { standard_=VIDEO_STANDARD_SECAM; if(!port_) port_=1; } else if(strcmp(standard,"svideo525") == 0) standard_=VIDEO_STANDARD_SVIDEO525; else if(strcmp(standard,"svideo625") == 0) standard_=VIDEO_STANDARD_SVIDEO625; } } void MmeGrabber::startup() { MMRESULT s; int size; /* fprintf(stderr, "vic: Called MmeGrabber::startup\n"); */ if (running_) return; if(port_) { s=videoSetPortNum(handle_,port_); if (mme_error(s, "couldn't configure mme")) goto bail; } if(standard_) { s=videoSetStandard(handle_,standard_); if (mme_error(s, "couldn't configure mme")) goto bail; } s = videoConfigure(handle_, DVM_FORMAT, VIDEO_CONFIGURE_GET|VIDEO_CONFIGURE_MIN, 0, bmh, sizeof(*bmh), 0, 0); size = bmh->b.bmi.biSizeImage;/*XXX ridiculously large*/ s = videoConfigure(handle_, DVM_FORMAT, VIDEO_CONFIGURE_SET, 0, bmh, sizeof(*bmh), 0, 0); if (mme_error(s, "couldn't configure mme")) goto bail; #ifdef notdef size = 320 * 240 * 3; #endif vh_->lpData = (LPSTR)mmeAllocBuffer(size); if (vh_->lpData == 0) { fprintf(stderr, "vic: couldn't allocate mme frame memory\n"); goto bail; } vh_->dwBufferLength = size; s = videoStreamInit(handle_, 1000000 /*10fps - ignored */, mme_callback, 0, CALLBACK_FUNCTION); if (mme_error(s, "couldn't initialize mme stream\n")) return; s = videoStreamPrepareHeader(handle_, vh_, sizeof(*vh_)); if (mme_error(s, "couldn't prepare mme video hdr")) return; s = videoStreamStart(handle_); if (mme_error(s, "couldn't start mme video stream\n")) return; running_ = 1; frameclock_ = gettimeofday(); outstanding_ = 0; last_grab_ = 0; grab(); return; bail: mmeFreeMem(bmh); bmh = 0; videoClose(handle_); vh_ = 0; valid_ = 0; } void MmeGrabber::shutdown() { MMRESULT s; /* fprintf(stderr, "vic: Called MmeGrabber::shutdown\n"); */ if (!running_) return; wantgrab_ = 0; running_ = 0; s = videoStreamReset(handle_); (void)mme_error(s, "couldn't reset mme stream"); while(outstanding_) { mmeWaitForCallbacks(); mmeProcessCallbacks(); } s = videoStreamUnprepareHeader(handle_, vh_, sizeof(*vh_)); (void)mme_error(s, "couldn't unprepare mme video header"); s = videoStreamFini(handle_); (void)mme_error(s, "couldn't shutdown mme stream"); running_ = 0; mmeFreeBuffer(vh_->lpData); } /*XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX*/ inline int MmeGrabber::mme_error(MMRESULT code, const char* msg) const { if (code != DV_ERR_OK) { char *buffer; if(buffer=(char *)mmeAllocMem(MAXERRORLENGTH)) { videoGetErrorText(handle_,code,buffer,MAXERRORLENGTH); fprintf(stderr, "vic: %s - %s (%d)\n", msg, buffer, code); mmeFreeMem(buffer); } return (1); } return (0); } extern "C" { void MmeGrabber::mme_callback(HVIDEO handle, DWORD code, DWORD instance, LPARAM vh, LPARAM p2) { #ifdef notyet MmeGrabber* p = (MmeGrabber*)instance; fprintf(stderr, "vic: Called MmeGrabber::mme_callback\n"); p->callback(); #else (void)mmeMaster->callback(code, (VIDEOHDR*)vh); #endif } } int MmeGrabber::callback(int code, VIDEOHDR *vh) { int n; /* fprintf(stderr, "vic: Called MmeGrabber::callback\n"); */ /* Nothing to do for open or close - just dismiss */ if (code == MM_DRVM_OPEN || code == MM_DRVM_CLOSE) return (1); if (code != MM_DRVM_DATA) { fprintf(stderr,"vic: mme callback code %d\n", code); return (0); } if (vh->lpData != vh_->lpData) fprintf(stderr,"vic: buffer address changed in callback\n"); if ((vh->dwFlags & VHDR_DONE) == 0 && running_) { fprintf(stderr, "vic: mme callback: done bit = 0\n"); } /* Check for wraparound */ if( vh->dwTimeCaptured < last_grab_ ) last_grab_ = last_grab_ - sizeof(vh->dwTimeCaptured)*8; /* ** See if we want to keep this frame ** The capture overhead is low enough that we just capture them all ** then throw away the ones we don't want */ if(vh->dwTimeCaptured - last_grab_ > delay_ ) { last_grab_ = vh->dwTimeCaptured; int length = vh->dwBytesUsed; u_char* p = (u_char*)vh->lpData; n = consume(p, length ); delay_ = (int)(tick(n)/1000); } outstanding_--; wantgrab_ = 1; return (1); } int MmeGrabber::grab() { MMRESULT s; if(outstanding_ >= buffers_ ) /* fprintf(stderr, " skipping grab\n") */ ; else { /* fprintf(stderr, " grab - outstanding = %d ",outstanding_); */ /* tfm - add multibuffer code here */ if(s = videoStreamAddBuffer(handle_, vh_, sizeof(*vh_))) (void)mme_error(s, "couldn't queue mme buffer"); else outstanding_++; } return TRUE; } void MmeGrabber::dispatch(int mask) { /* fprintf(stderr, "vic: Called MmeGrabber::dispatch\n"); */ while (mmeCheckForCallbacks()) mmeProcessCallbacks(); if (wantgrab_ && running_ ) { wantgrab_ = 0; mmeMaster->grab(); } } /***********************************************************************/ MmeJpegGrabber::MmeJpegGrabber() : q_(80) { /* fprintf(stderr, "vic: Called MmeJpegGrabber constructor\n"); */ } MmeJpegGrabber::~MmeJpegGrabber() { /* fprintf(stderr, "vic: Called MmeJpegGrabber destructor\n"); */ } int MmeJpegGrabber::command(int argc, const char*const* argv) { /* fprintf(stderr, "vic: Called MmeJpegGrabber::command\n"); */ if (argc == 3) { /* fprintf(stderr, "vic: Called MmeGrabber::command with %s %s\n", argv[1],argv[2]); */ if (strcmp(argv[1], "q") == 0) { /* assume value is in range */ nq_ = atoi(argv[2]); if (nq_ != q_) { q_ = nq_; MMRESULT s = videoSetQuality(handle_, 10000 * q_ / 100 ); (void)mme_error(s, "couldn't set quality\n"); } return (TCL_OK); } } return (MmeGrabber::command(argc, argv)); } int MmeJpegGrabber::consume(const u_char* p, int length) { /* fprintf(stderr, "vic: Called MmeJpegGrabber::consume()\n"); */ /* * We should get a better timestamp XXX */ JpegFrame f(media_ts(), (u_char*)p, length, q_, 0, inw_, inh_); return (target_->consume(&f)); } void MmeJpegGrabber::SetComp() { /* fprintf(stderr,"vic: Called MmeJpegGrabber::SetComp()\n"); */ inw_ = NTSC_WIDTH / x_decimate_; inh_ = NTSC_HEIGHT / y_decimate_; if( bmh == 0 ) fprintf(stderr,"Bitmap infoheader pointer is null\n"); memset(bmh, 0, sizeof(*bmh)); bmh->b.bmi.biSize = sizeof(*bmh); bmh->b.bmi.biWidth = inw_; bmh->b.bmi.biHeight = inh_; bmh->b.bmi.biPlanes = 1; bmh->b.bmi.biBitCount = 24; bmh->b.bmi.biCompression = MJPG_DIB; bmh->b.biExtDataOffset = sizeof(bmh->b); bmh->jpeg.JPEGSize = sizeof(bmh->jpeg); bmh->jpeg.JPEGProcess = JPEG_PROCESS_BASELINE; bmh->jpeg.JPEGColorSpaceID = JPEG_YCbCr; bmh->jpeg.JPEGBitsPerSample = 8; bmh->jpeg.JPEGHSubSampling = 2; bmh->jpeg.JPEGVSubSampling = 1; } /***********************************************************************/ MmeYuvGrabber::MmeYuvGrabber() { /* fprintf(stderr, "vic: Called MmeYuvGrabber constructor\n"); */ } int MmeYuvGrabber::consume(const u_char* buffer, int length) { suppress(buffer, frame_); saveblks(buffer); YuvFrame f(media_ts(), frame_, crvec_, outw_, outh_); return (target_->consume(&f)); } /* * define these for REPLENISH macro used below */ #define DIFF4(in, frm, v) \ v += (in)[0] - (frm)[0]; \ v += (in)[2] - (frm)[1]; \ v += (in)[4] - (frm)[2]; \ v += (in)[6] - (frm)[3]; #define DIFFLINE(in, frm, left, center, right) \ DIFF4(in, frm, left); \ DIFF4(in + 1*8, frm + 1*4, center); \ DIFF4(in + 2*8, frm + 2*4, center); \ DIFF4(in + 3*8, frm + 3*4, right); \ if (right < 0) \ right = -right; \ if (left < 0) \ left = -left; \ if (center < 0) \ center = -center; void MmeYuvGrabber::suppress(const u_char* devbuf, const u_char* lumbuf) { const u_char* start = frame_ + 16 * vstart_ * outw_ + 16 * hstart_; REPLENISH(devbuf, start, inw_ << 1, 2, hstart_, hstop_, vstart_, vstop_); } void MmeYuvGrabber::SetComp() { /* fprintf(stderr,"vic: Called MmeYUVGrabber::SetComp()\n"); */ int w = NTSC_WIDTH / x_decimate_; int h = NTSC_HEIGHT / y_decimate_; if (w != inw_ || h != inh_) { setsize(w, h); } if( bmh == 0 ) fprintf(stderr,"Bitmap infoheader pointer is null\n"); /* Uh oh! */ else { memset(bmh, 0, sizeof(*bmh)); bmh->b.bmi.biSize = sizeof(BITMAPINFOHEADER); bmh->b.bmi.biWidth = inw_; bmh->b.bmi.biHeight = inh_; bmh->b.bmi.biPlanes = 1; bmh->b.bmi.biBitCount = 16; bmh->b.bmi.biCompression = BICOMP_DECYUVDIB; } } /***********************************************************************/ /* ** Take YUV 4:2:2 packed data and unpack it into YUV 4:2:2 with each ** component in a separate block of memory */ inline void Mme422Grabber::saveblk(const u_char* in, u_char* yp, u_char* up, u_char* vp, int stride) { int is = stride << 1; int cs = stride >> 1; for (int i = 16; --i >= 0; ) { /* * Each iteration of this loop grabs 16 Ys & 8 U/Vs. */ register u_int y0, y1, u, v; u = in[1] | in[5] << 8 | in[9] << 16 | in[13] << 24; v = in[3] | in[7] << 8 | in[11] << 16 | in[15] << 24; y0 = in[0] | in[2] << 8 | in[4] << 16 | in[6] << 24; y1 = in[8] | in[10] << 8 | in[12] << 16 | in[14] << 24; ((u_int*)yp)[0] = y0; ((u_int*)yp)[1] = y1; *(u_int*)up = u; *(u_int*)vp = v; u = in[16+1] | in[16+5] << 8 | in[16+9] << 16 | in[16+13] << 24; v = in[16+3] | in[16+7] << 8 | in[16+11] << 16 | in[16+15] << 24; y0 = in[16+0] | in[16+2] << 8 | in[16+4] << 16 | in[16+6] << 24; y1 = in[16+8] | in[16+10] << 8 | in[16+12] << 16 | in[16+14] << 24; ((u_int*)yp)[2] = y0; ((u_int*)yp)[3] = y1; ((u_int*)up)[1] = u; ((u_int*)vp)[1] = v; in += is; yp += stride; up += cs; vp += cs; } } void Mme422Grabber::saveblks(const u_char* in) { u_char* crv = crvec_; u_char* lum = frame_; int off = framesize_; u_char* chm = lum + off; off >>= 1; int stride = 15 * inw_; for (int y = 0; y < blkh_; ++y) { for (int x = 0; x < blkw_; ++x) { int s = *crv++; if ((s & CR_SEND) != 0) saveblk(in, lum, chm, chm + off, outw_); in += 32; lum += 16; chm += 8; } lum += stride; chm += stride >> 1; in += stride << 1; } } void Mme422Grabber::setsize(int w, int h) { set_size_422(w, h); } /***********************************************************************/ void MmeCIFGrabber::setsize(int w, int h) { set_size_cif(w, h); } /* ** Take YUV 4:2:2 packed data and unpack it into YUV 4:1:1 with each ** components in a separate block of memory. ** ** NB: The chroma is subsampled with no prefiltering. The samples are ** cosited with the first of the pair of scan lines rather than ** being positioned between them as specified for true CIF */ inline void MmeCIFGrabber::saveblk(const u_char* in, u_char* yp, u_char* up, u_char* vp, int stride, int is) { int cs = stride >> 1; for (int i = 8; --i >= 0; ) { /* * Each iteration of this loop grabs 16 Ys & 8 U/Vs. */ register u_int y0, y1, u, v; u = in[1] | in[5] << 8 | in[9] << 16 | in[13] << 24; v = in[3] | in[7] << 8 | in[11] << 16 | in[15] << 24; y0 = in[0] | in[2] << 8 | in[4] << 16 | in[6] << 24; y1 = in[8] | in[10] << 8 | in[12] << 16 | in[14] << 24; ((u_int*)yp)[0] = y0; ((u_int*)yp)[1] = y1; *(u_int*)up = u; *(u_int*)vp = v; u = in[16+1] | in[16+5] << 8 | in[16+9] << 16 | in[16+13] << 24; v = in[16+3] | in[16+7] << 8 | in[16+11] << 16 | in[16+15] << 24; y0 = in[16+0] | in[16+2] << 8 | in[16+4] << 16 | in[16+6] << 24; y1 = in[16+8] | in[16+10] << 8 | in[16+12] << 16 | in[16+14] << 24; ((u_int*)yp)[2] = y0; ((u_int*)yp)[3] = y1; ((u_int*)up)[1] = u; ((u_int*)vp)[1] = v; in += is; yp += stride; up += cs; vp += cs; /* do the 2nd (y only instead of yuv) line */ y0 = in[0] | in[2] << 8 | in[4] << 16 | in[6] << 24; y1 = in[8] | in[10] << 8 | in[12] << 16 | in[14] << 24; ((u_int*)yp)[0] = y0; ((u_int*)yp)[1] = y1; y0 = in[16+0] | in[16+2] << 8 | in[16+4] << 16 | in[16+6] << 24; y1 = in[16+8] | in[16+10] << 8 | in[16+12] << 16 | in[16+14] << 24; ((u_int*)yp)[2] = y0; ((u_int*)yp)[3] = y1; in += is; yp += stride; } } void MmeCIFGrabber::saveblks(const u_char* in) { int is = 2 * inw_; u_char* crv = crvec_; u_char* lum = frame_; u_char* chm = frame_ + framesize_; u_int off = framesize_ >> 2; crv += vstart_ * blkw_ + hstart_; lum += vstart_ * outw_ * 16 + hstart_ * 16; chm += vstart_ * (outw_ >> 1) * 8 + hstart_ * 8; int skip = hstart_ + (blkw_ - hstop_); for (int y = vstart_; y < vstop_; ++y) { const u_char* nin = in; for (int x = hstart_; x < hstop_; ++x) { int s = *crv++; if ((s & CR_SEND) != 0) saveblk(in, lum, chm, chm + off, outw_, is); in += 32; lum += 16; chm += 8; } crv += skip; lum += 15 * outw_ + skip * 16; chm += 7 * (outw_ >> 1) + skip * 8; in = nin + 16 * is; } } /***********************************************************************/ void Mme411Grabber::setsize(int w, int h) { set_size_411(w, h); } /***********************************************************************/