/* * Copyright (c) 1993-1995 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. * * Contributed by Bob Olson (olson@mcs.anl.gov) September 1995. */ #ifndef lint static char rcsid[] = "@(#) $Header: /cs/research/mice/starship/src/local/CVS_repository/vic/video/grabber-sunrise.cpp,v 1.1 1999/09/09 12:52:55 piers Exp $ (LBL)"; #endif #include #include #include #include #include #include #include "inet.h" #include "vic_tcl.h" #include "rtp.h" #include "grabber.h" #include "crdef.h" #include "device-input.h" #include "transmitter.h" #include "module.h" #include #include #define UMS_Success(rc) (rc == UMSVideoIO_Success) #define NTSC_FULL_WIDTH 640 #define NTSC_FULL_HEIGHT 480 #define N_RING_BUFFERS 4 class SunriseGrabber : public Grabber { protected: SunriseGrabber(); public: virtual ~SunriseGrabber(); virtual int command(int argc, const char* const * argv); virtual void fps(int); protected: _IDL_SEQUENCE_UMSVideoIO_RingBufferElement ring_buffer; void allocate_ring_buffers(long n_buffers, long buffer_size); int decimate_; long width_; long height_; string port_; virtual void setsize() = 0; virtual void set_port(); Environment *ev; }; class SunriseJpegGrabber : public SunriseGrabber { public: SunriseJpegGrabber(); virtual ~SunriseJpegGrabber(); virtual int command(int argc, const char* const * argv); void setsize(); protected: void start(); void stop(); private: int q_; int grab(); }; class SunriseYuvCore : public SunriseGrabber { public: SunriseYuvCore(); virtual ~SunriseYuvCore(); protected: virtual void start(); virtual void stop(); virtual int command(int argc, const char * const * argv); u_char* frame_; _IDL_SEQUENCE_octet colormap; }; class SunriseYuvGrabber : public SunriseYuvCore { public: SunriseYuvGrabber(); virtual int command(int argc, const char * const * argv); virtual int grab(); void setsize(); protected: }; class SunriseCIFGrabber : public SunriseYuvCore { public: SunriseCIFGrabber(); virtual int command(int argc, const char * const * argv); virtual int grab(); void setsize(); protected: }; class SunriseDevice : public InputDevice { public: // SunriseDevice(const char* s); SunriseDevice(const char* s, const char *which); virtual int command(int argc, const char * const * argv); virtual Grabber* yuv_grabber(); virtual Grabber* jpeg_grabber(); virtual Grabber* cif_grabber(); UMSVideoIO *video; SunriseDevice *next; const char *myname; char *device; int open_video(); void close_video(); protected: Environment *ev; }; class SunriseDeviceMaker { public: SunriseDeviceMaker(); ~SunriseDeviceMaker(); protected: SunriseDevice *devices; void trydev(string dev); Environment *ev; }; static SunriseDeviceMaker maker; static SunriseDevice *sunrise_device = NULL; SunriseDeviceMaker::SunriseDeviceMaker() { string devnames[] = { "/dev/sr1", "/dev/sr0", NULL }; int i; string devname; struct stat statbuf; SunriseDevice *dev; ev = somGetGlobalEnvironment(); devices = NULL; for (i = 0; devnames[i] != NULL; i++) { devname = devnames[i]; if (stat(devname, &statbuf) == 0) { if (statbuf.st_mode & (S_IWUSR | S_IRUSR)) { char *s; if (s = rindex(devname, '/')) s++; else s = devname; char *name = new char[strlen(s) + 10]; sprintf(name, "Sunrise_%s", s); dev = new SunriseDevice(name, devname); #ifdef DEBUG printf("Creating %s %x\n", s, dev); #endif dev->next = devices; devices = dev; } } } } SunriseDeviceMaker::~SunriseDeviceMaker() { } SunriseDevice::SunriseDevice(const char* s, const char *dev = "/dev/sr0") : InputDevice(s), myname(s) { attributes_ = "format { 422 jpeg } size { small large cif } port { composite svideo }"; #ifdef DEBUG printf("SunriseDevice::SunriseDevice name=%s\n", s); #endif /* DEBUG */ ev = somGetGlobalEnvironment(); video = new UMSVideoIO; device = new char[strlen(dev) + 1]; strcpy(device, dev); } int SunriseDevice::command(int argc, const char*const* argv) { if (argc == 3 && strcmp(argv[1], "open") == 0) { const char* fmt = argv[2]; TclObject* o = 0; if (strcmp(fmt, "jpeg") == 0) o = jpeg_grabber(); else if (strcmp(fmt, "422") == 0) o = yuv_grabber(); else if (strcmp(fmt, "cif") == 0) o = cif_grabber(); /* else if (strcmp(fmt, "411") == 0) o = new Jv411Grabber; */ if (o != 0) Tcl::instance().result(o->name()); return (TCL_OK); } return (InputDevice::command(argc, argv)); } int SunriseDevice::open_video() { UMSVideoIO_ReturnCode rc; #ifdef DEBUG printf("%x %s open_video\n", this, device); #endif if ((rc = video->open(ev, (string) device)) != UMSVideoIO_Success) { #ifdef DEBUG printf("error %d opening video device %s\n", rc, device); #endif return 0; } #ifdef DEBUG printf("opened device %s\n", device); #endif /* DEBUG */ return 1; } void SunriseDevice::close_video() { UMSVideoIO_ReturnCode rc; #ifdef DEBUG printf("%x %s close_video\n", this, device); #endif if ((rc = video->close(ev)) != UMSVideoIO_Success) { #ifdef DEBUG printf("error %d closing video device %s\n", rc, device); #endif } else { #ifdef DEBUG printf("closed device %s\n", device); #endif } } Grabber* SunriseDevice::jpeg_grabber() { #ifdef DEBUG printf("Asking device %s for new jpeg grabber\n", myname); #endif if (open_video()) { #ifdef DEBUG printf("Open succeeded\n"); #endif sunrise_device = this; return (new SunriseJpegGrabber()); } else { #ifdef DEBUG printf("open failed\n"); #endif return NULL; } } Grabber* SunriseDevice::yuv_grabber() { #ifdef DEBUG printf("Asking device %s for new jpeg grabber\n", myname); #endif if (open_video()) { #ifdef DEBUG printf("Open succeeded\n"); #endif sunrise_device = this; return (new SunriseYuvGrabber()); } else { #ifdef DEBUG printf("open failed\n"); #endif return NULL; } } Grabber* SunriseDevice::cif_grabber() { #ifdef DEBUG printf("Asking device %s for new jpeg grabber\n", myname); #endif if (open_video()) { #ifdef DEBUG printf("Open succeeded\n"); #endif sunrise_device = this; return (new SunriseCIFGrabber()); } else { #ifdef DEBUG printf("open failed\n"); #endif return NULL; } } SunriseGrabber::SunriseGrabber() : port_(INPUT_COMPOSITE) { ev = somGetGlobalEnvironment(); ring_buffer._buffer = (UMSVideoIO_RingBufferElement *) NULL; } SunriseGrabber::~SunriseGrabber() { #ifdef DEBUG printf("grabber destroy\n"); #endif sunrise_device->close_video(); sunrise_device = NULL; } void SunriseGrabber::fps(int val) { UMSVideoIO_ReturnCode rc; double capture_rate = val; int was_running; was_running = running_; if (was_running) stop(); rc = sunrise_device->video->set_capture_rate(ev, &capture_rate); #ifdef DEBUG if (!UMS_Success(rc)) { printf("set_capture_rate failed with rc=%d\n", rc); } else printf("set capture rate to %lf\n", capture_rate); #endif /* DEBUG */ if (was_running) start(); Grabber::fps(val); } int SunriseGrabber::command(int argc, const char * const * argv) { int i; Tcl& tcl = Tcl::instance(); #ifdef DEBUG printf("SunriseGrabber::command argc=%d ", argc); for (i = 0; i < argc; i++) printf("\"%s\" ", argv[i]); printf("\n"); #endif /* DEBUG */ if (argc == 3) { if (strcmp(argv[1], "port") == 0) { string new_port = ""; if (strcmp(argv[2], "composite") == 0) new_port = INPUT_COMPOSITE; else new_port = INPUT_SVIDEO; if (strcmp(port_, new_port) != 0) { port_ = new_port; set_port(); } } } return (Grabber::command(argc, argv)); } void SunriseGrabber::set_port() { int was_running = running_; UMSVideoIO_ReturnCode rc; if (was_running) stop(); rc = sunrise_device->video->set_video_input_connector(ev, port_); if (!UMS_Success(rc) && rc != UMSVideoIO_ValueChanged) { #ifdef DEBUG printf("set_video_input_connector %s failed with rc=%d\n", port_, rc); #endif /* DEBUG */ } if (was_running) start(); } SunriseJpegGrabber::SunriseJpegGrabber() : q_(50) { decimate_ = 2; // setsize(); } void SunriseJpegGrabber::setsize() { UMSVideoIO_ReturnCode rc; long w, h; int was_running; #ifdef DEBUG printf("SunriseJpegGrabber::setsize()\n"); #endif /* DEBUG */ was_running = running_; if (was_running) stop(); w = 640 / decimate_; if (decimate_ == 4 || decimate_ == 2) h = 240; else h = 120; #ifdef DEBUG printf("set_input_image_size %dx%d\n", w, h); #endif /* DEBUG */ rc = sunrise_device->video->set_input_image_size(ev, &w, &h); if (!UMS_Success(rc) && rc != UMSVideoIO_ValueChanged) { #ifdef DEBUG printf("set_input_image_size %dx%d failed with rc=%d\n", w, h, rc); #endif /* DEBUG */ } #ifdef DEBUG printf("after set_input_image_size w=%d h=%d rc=%d\n", w, h, rc); #endif /* DEBUG */ width_ = w; height_ = h; double capture_rate = fps_; rc = sunrise_device->video->set_capture_rate(ev, &capture_rate); #ifdef DEBUG if (!UMS_Success(rc)) printf("set_capture_rate failed with rc=%d\n", rc); #endif /* DEBUG */ allocate_ring_buffers(N_RING_BUFFERS, w * h); long q = q_; rc = sunrise_device->video->set_quality_factor(ev, &q); if (!UMS_Success(rc)) { #ifdef DEBUG printf("set_quality_factor failed with rc=%d\n", rc); #endif /* DEBUG */ return; } q_ = q; rc = sunrise_device->video->setup_compressed_capture_buffers(ev, &ring_buffer); if (!UMS_Success(rc)) { #ifdef DEBUG printf("setup_compressed_capture failed with rc=%d\n", rc); #endif /* DEBUG */ return; } if (was_running) start(); } void SunriseJpegGrabber::start() { UMSVideoIO_ReturnCode rc; rc = sunrise_device->video->set_compression(ev, UMSVideoIO_On); if (!UMS_Success(rc)) { #ifdef DEBUG printf("set_compression failed with rc=%d\n", rc); #endif /* DEBUG */ return; } frameclock_ = gettimeofday(); /* * This sleep is VERY IMPORTANT. It lets the capture card * get ahead of vic, so that frames will be available when * vic tries to grab them. Otherwise, the grab will block * and vic will be permanently behind, locking out X events. * * Another fix might be to use nonblocking frame grabs. */ // sleep(1); timeout(); } void SunriseJpegGrabber::stop() { UMSVideoIO_ReturnCode rc; rc = sunrise_device->video->set_compression(ev, UMSVideoIO_Off); if (!UMS_Success(rc)) { #ifdef DEBUG printf("set_uncompression failed with rc=%d\n", rc); #endif /* DEBUG */ } cancel(); } int SunriseJpegGrabber::grab() { UMSVideoIO_RingBufferElement *frame; static UMSVideoIO_RingBufferElement *last_frame = NULL; long index; UMSVideoIO_ReturnCode rc; int frc; unsigned char *data; tx_->flush(); if (last_frame) last_frame->InUseByCaller = 0; rc = sunrise_device->video->get_compressed_frame(ev, &index, FALSE); if (!UMS_Success(rc)) { #ifdef DEBUG printf("get_compressed_frame failed with rc=%d\n", rc); #endif return 0; } frame = &(ring_buffer._buffer[index]); data = (unsigned char *) frame->Address; JpegFrame f(media_ts(), data, frame->SizeOfDataInBuffer, q_, 0, width_, height_); frc = target_->consume(&f); last_frame = frame; return frc; } int SunriseJpegGrabber::command(int argc, const char * const * argv) { int i; Tcl& tcl = Tcl::instance(); #ifdef DEBUG printf("SunriseJpegGrabber::command argc=%d ", argc); for (i = 0; i < argc; i++) printf("\"%s\" ", argv[i]); printf("\n"); #endif /* DEBUG */ if (argc == 3) { if (strcmp(argv[1], "q") == 0) { /* assume value is in range */ q_ = atoi(argv[2]); setsize(); return (TCL_OK); } else if (strcmp(argv[1], "decimate") == 0) { int d = atoi(argv[2]); Tcl& tcl = Tcl::instance(); if (d <= 0) { Tcl_AppendResult(tcl.interp(), "%s: divide by zero", argv[0], 0); return (TCL_ERROR); } decimate_ = d; setsize(); return(TCL_OK); } } return SunriseGrabber::command(argc, argv); } SunriseJpegGrabber::~SunriseJpegGrabber() { } SunriseYuvCore::SunriseYuvCore() : frame_(0) { } int SunriseYuvCore::command(int argc, const char * const * argv) { int i; Tcl& tcl = Tcl::instance(); #ifdef DEBUG printf("SunriseYuvCore::command argc=%d ", argc); for (i = 0; i < argc; i++) printf("\"%s\" ", argv[i]); printf("\n"); #endif /* DEBUG */ if (argc == 3) { if (strcmp(argv[1], "decimate") == 0) { int d = atoi(argv[2]); Tcl& tcl = Tcl::instance(); if (d <= 0) { Tcl_AppendResult(tcl.interp(), "%s: divide by zero", argv[0], 0); return (TCL_ERROR); } decimate_ = d; setsize(); return(TCL_OK); } } return SunriseGrabber::command(argc, argv); } SunriseYuvCore::~SunriseYuvCore() { } SunriseYuvGrabber::SunriseYuvGrabber() { decimate_ = 2; // setsize(); } void SunriseYuvGrabber::setsize() { long w, h, v; UMSVideoIO_ReturnCode rc; int was_running; was_running = running_; if (was_running) stop(); w = NTSC_FULL_WIDTH / decimate_; h = NTSC_FULL_HEIGHT / decimate_; rc = sunrise_device->video->set_output_image_format(ev, YUV422); if (!UMS_Success(rc)) { #ifdef DEBUG printf("set_output_image_format failed with rc=%d\n", rc); #endif /* DEBUG */ return; } long iw, ih; if (w > 320) iw = 640; else iw = 320; if (h > 240) ih = 480; else ih = 240; rc = sunrise_device->video->set_input_image_size(ev, &iw, &ih); if (!UMS_Success(rc) && rc != UMSVideoIO_ValueChanged) { #ifdef DEBUG printf("set_input_image_size failed with rc=%d\n", rc); #endif /* DEBUG */ return; } #ifdef DEBUG printf("after set_input iw=%d ih=%d rc=%d\n", iw, ih, rc); #endif /* DEBUG */ rc = sunrise_device->video->set_uncompressed_image_size(ev, &w, &h); if (!UMS_Success(rc) && rc != UMSVideoIO_ValueChanged) { #ifdef DEBUG printf("set_uncompressed_image_size failed with rc=%d\n", rc); #endif /* DEBUG */ return; } #ifdef DEBUG printf("after set_uncompressed_image_size w=%d h=%d rc=%d\n", w, h, rc); #endif /* DEBUG */ width_ = w; height_ = h; framesize_ = w * h; frame_ = new u_char[2 * framesize_]; crinit(w, h); allocref(); double capture_rate = fps_; rc = sunrise_device->video->set_capture_rate(ev, &capture_rate); #ifdef DEBUG if (!UMS_Success(rc)) { printf("set_capture_rate failed with rc=%d\n", rc); } else printf("set capture rate to %lf\n", capture_rate); #endif /* DEBUG */ allocate_ring_buffers(N_RING_BUFFERS, w * h * 2); rc = sunrise_device->video->setup_uncompressed_capture_buffers(ev, &ring_buffer); #ifdef DEBUG if (!UMS_Success(rc)) printf("setup_uncompressed_capture failed with rc=%d\n", rc); #endif /* DEBUG */ if (was_running) start(); } int SunriseYuvGrabber::command(int argc, const char * const * argv) { return (SunriseYuvCore::command(argc, argv)); } int SunriseYuvGrabber::grab() { UMSVideoIO_RingBufferElement *frame; long index; UMSVideoIO_ReturnCode rc; int grc; unsigned char *yptr, *uptr, *vptr; int i; rc = sunrise_device->video->get_uncompressed_frame(ev, &index, TRUE); if (!UMS_Success(rc)) { printf("get_uncompressed_frame failed with rc=%d\n", rc); return 0; } frame = &(ring_buffer._buffer[index]); /* * Pixel format: YYYYYYYY UUUUUUUU YYYYYYYY VVVVVVVV * U & V are shared for two pixels. */ struct pixel { unsigned char y1; unsigned char u; unsigned char y2; unsigned char v; } *p, *p_end; yptr = frame_; uptr = frame_ + framesize_; vptr = uptr + framesize_ / 2; p = (struct pixel *) frame->Address; p_end = (struct pixel *) (frame->Address + frame->SizeOfDataInBuffer); while (p < p_end) { yptr[0] = p->y1; yptr[1] = p->y2; uptr[0] = p->u; vptr[0] = p->v; yptr += 2; uptr++; vptr++; p++; } int overruns = frame->NumberOfOverruns; frame->InUseByCaller = 0; #if 0 if (overruns > 0) { printf("Got %d overruns, flushing\n", frame->NumberOfOverruns); rc = sunrise_device->video->flush_uncompressed_capture_buffers(ev); if (!UMS_Success(rc)) { printf("flush_uncompressed_capture_buffers failed with rc=%d\n", rc); } } #endif suppress(frame_); saveblks(frame_); YuvFrame f(media_ts(), frame_, crvec_, width_, height_); grc = target_->consume(&f); return grc; } void SunriseYuvCore::start() { UMSVideoIO_ReturnCode rc; if (running_) return; rc = sunrise_device->video->set_uncompression(ev, UMSVideoIO_On); if (!UMS_Success(rc)) { printf("set_uncompression failed with rc=%d\n", rc); return; } running_ = 1; frameclock_ = gettimeofday(); timeout(); } void SunriseYuvCore::stop() { UMSVideoIO_ReturnCode rc; if (!running_) return; rc = sunrise_device->video->set_uncompression(ev, UMSVideoIO_Off); if (!UMS_Success(rc)) { printf("set_uncompression failed with rc=%d\n", rc); } running_ = 0; cancel(); } void SunriseGrabber::allocate_ring_buffers(long n_buffers, long buffer_size) { unsigned char **Address; UMSVideoIO_RingBufferElement *rbuffer1; int i; Address = new unsigned char * [n_buffers]; ring_buffer._length = n_buffers; ring_buffer._maximum = n_buffers; #ifdef DEBUG printf("Allocating ring buffers: n_buffers=%d buffer_size=%d\n", n_buffers, buffer_size); #endif /* DEBUG */ if (ring_buffer._buffer != (struct UMSVideoIO_RingBufferElement *) NULL) delete ring_buffer._buffer; ring_buffer._buffer = new UMSVideoIO_RingBufferElement[n_buffers]; if (ring_buffer._buffer <= 0) { fprintf(stderr, "Cannot malloc somThis->ring_buffer._buffer\n"); exit(1); } /* Set up each ring buffer */ rbuffer1 = ring_buffer._buffer; for (i = 0; i < n_buffers; i++) { Address[i] = (unsigned char *) malloc(buffer_size + 4096); if (Address[i] <= 0) { fprintf(stderr, "Cannot malloc ring_buffer %d\n", i); free(ring_buffer._buffer); exit(1); } rbuffer1->Address = ( ((long) Address[i]) + 4096 - ( ((long) Address[i]) % 4096)); rbuffer1->AfterHeader = rbuffer1->Address; rbuffer1->SizeOfBuffer = buffer_size; rbuffer1->SizeOfDataInBuffer = 0; rbuffer1->InUseByCaller = 0; rbuffer1->NumberOfOverruns = 0; rbuffer1++; } } SunriseCIFGrabber::SunriseCIFGrabber() { #ifdef DEBUG printf("SunriseCIFGrabber::SunriseCIFGrabber\n"); #endif decimate_ = 2; // setsize(); } void SunriseCIFGrabber::setsize() { long w, h, v; UMSVideoIO_ReturnCode rc; #ifdef DEBUG printf("SunriseCIFGrabber::setsize()\n"); #endif w = 2 * 352 / decimate_; h = 2 * 288 / decimate_; rc = sunrise_device->video->set_output_image_format(ev, YUV422); if (!UMS_Success(rc)) { #ifdef DEBUG printf("set_output_image_format failed with rc=%d\n", rc); #endif return; } long iw, ih; if (w > 320) iw = 640; else iw = 320; if (h > 240) ih = 480; else ih = 240; rc = sunrise_device->video->set_input_image_size(ev, &iw, &ih); if (!UMS_Success(rc) && rc != UMSVideoIO_ValueChanged) { #ifdef DEBUG printf("set_input_image_size failed with rc=%d\n", rc); #endif return; } #ifdef DEBUG printf("after set_input iw=%d ih=%d rc=%d\n", iw, ih, rc); #endif rc = sunrise_device->video->set_uncompressed_image_size(ev, &w, &h); if (!UMS_Success(rc) && rc != UMSVideoIO_ValueChanged) { #ifdef DEBUG printf("set_uncompressed_image_size failed with rc=%d\n", rc); #endif return; } #ifdef DEBUG printf("after set_uncompressed_image_size w=%d h=%d rc=%d\n", w, h, rc); #endif width_ = w; height_ = h; framesize_ = w * h; frame_ = new u_char[framesize_ + framesize_ / 2]; crinit((int) w, (int) h); allocref(); double capture_rate = fps_; rc = sunrise_device->video->set_capture_rate(ev, &capture_rate); if (!UMS_Success(rc)) { #ifdef DEBUG printf("set_capture_rate failed with rc=%d\n", rc); #endif } else { #ifdef DEBUG printf("set capture rate to %lf\n", capture_rate); #endif } allocate_ring_buffers(N_RING_BUFFERS, w * h * 2); rc = sunrise_device->video->setup_uncompressed_capture_buffers(ev, &ring_buffer); if (!UMS_Success(rc)) { #ifdef DEBUG printf("setup_uncompressed_capture failed with rc=%d\n", rc); #endif return; } } int SunriseCIFGrabber::grab() { UMSVideoIO_RingBufferElement *frame; long index; UMSVideoIO_ReturnCode rc; int grc; unsigned char *yptr, *uptr, *vptr; int i, x, y; rc = sunrise_device->video->get_uncompressed_frame(ev, &index, TRUE); if (!UMS_Success(rc)) { printf("get_uncompressed_frame failed with rc=%d\n", rc); return 0; } frame = &(ring_buffer._buffer[index]); /* * Pixel format: YYYYYYYY UUUUUUUU YYYYYYYY VVVVVVVV * U & V are shared for two pixels. */ struct pixel { unsigned char y1; unsigned char u; unsigned char y2; unsigned char v; } *p, *p_end; yptr = frame_; uptr = frame_ + framesize_; vptr = uptr + framesize_ / 4; p = (struct pixel *) frame->Address; p_end = (struct pixel *) (frame->Address + frame->SizeOfDataInBuffer); for (y = 0; y < height_; y++) { for (x = 0; x < width_; x += 2) { yptr[0] = p->y1; yptr[1] = p->y2; yptr += 2; p++; if ((y & 1) == 0) { *uptr++ = p->u; *vptr++ = p->v; } } } frame->InUseByCaller = 0; suppress(frame_); saveblks(frame_); YuvFrame f(media_ts(), frame_, crvec_, width_, height_); grc = target_->consume(&f); return grc; } int SunriseCIFGrabber::command(int argc, const char * const * argv) { return (SunriseYuvCore::command(argc, argv)); }