1
0
mirror of https://git.FreeBSD.org/ports.git synced 2024-10-19 19:59:43 +00:00

Add BT848 grabber support.

Submitted by:	Amancio Hasty <hasty@rah.star-gate.com>
This commit is contained in:
Bill Fenner 1997-12-19 02:50:52 +00:00
parent 61c8e9cd6e
commit 6832892b30
Notes: svn2git 2021-03-31 03:12:20 +00:00
svn path=/head/; revision=9131
2 changed files with 1450 additions and 0 deletions

725
mbone/vic/files/patch-af Normal file
View File

@ -0,0 +1,725 @@
--- grabber-meteor.cc.orig Sat May 18 11:44:54 1996
+++ grabber-meteor.cc Thu Dec 18 18:35:09 1997
@@ -43,7 +43,6 @@
*
*/
-/*#define FRAME_CNTS /* print frame counts and fps when device stops -- debug */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
@@ -51,14 +50,13 @@
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
-#ifdef FRAME_CNTS
-#include <sys/time.h>
-#endif
#include "grabber.h"
+#include "crdef.h"
#include "Tcl.h"
#include "device-input.h"
#include "module.h"
+#include "bsd-endian.h"
#include <machine/ioctl_meteor.h>
@@ -72,62 +70,85 @@
class MeteorGrabber : public Grabber {
- public:
- MeteorGrabber(const char* name, const char* format);
+ public:
+ MeteorGrabber(const char* name);
virtual ~MeteorGrabber();
+ virtual int command(int argc, const char*const* argv);
+ virtual void fps(int);
virtual void start();
virtual void stop();
- virtual void fps(int);
- protected:
- virtual int command(int argc, const char*const* argv);
- virtual int capture();
virtual int grab();
+ protected:
void format();
- void setsize();
+ virtual void setsize() = 0;
+ void suppress(const u_char* in, int istride);
+ virtual void saveblks(const u_char* in, int istride) = 0;
+ void set_size_meteor(int w, int h);
int video_format_; /* video input format: NTSC or PAL */
int dev_; /* device fd */
int port_; /* video input port */
- int coder_format_; /* 411, 422, or cif */
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 */
volatile u_int* pyuv_; /* pointer to yuv data */
-#ifdef FRAME_CNTS
- struct meteor_counts cnts_; /* pointer to counters */
- double start_time_;
-#endif
};
-static const int f_411 = 0; /* coder_format_s */
-static const int f_422 = 1;
-static const int f_cif = 2;
+class Meteor422Grabber : public MeteorGrabber {
+ public:
+ Meteor422Grabber(const char* name);
+ protected:
+ void setsize();
+ void saveblk(const u_char* in, u_char* yp, u_char* up, u_char* vp,
+ int stride, int istride);
+ void saveblks(const u_char* in, int istride);
+};
+
+class MeteorCIFGrabber : public MeteorGrabber {
+ public:
+ MeteorCIFGrabber(const char* name);
+ protected:
+ void setsize();
+ void saveblk(const u_char* in, u_char* yp, u_char* up, u_char* vp,
+ int stride, int istride);
+ void saveblks(const u_char* in, int istride);
+};
class MeteorDevice : public InputDevice {
- public:
+ public:
MeteorDevice(const char* nickname, const char* devname, int free);
virtual int command(int argc, const char*const* argv);
- protected:
+ protected:
const char* name_;
};
class MeteorScanner {
- public:
+ public:
MeteorScanner(const int n);
};
+
static MeteorScanner find_meteor_devices(4);
MeteorScanner::MeteorScanner(const int n)
{
char* devname_template = "/dev/meteor%d";
char* nickname_template = "Matrox Meteor %d";
+ char* devname_template1 = "/dev/bktr%d";
+ char* nickname_template1 = "BrookTree848 %d";
+
+
for(int i = 0; i < n; i++) {
char *devname = new char[strlen(devname_template) + 3];
char *nickname = new char[strlen(nickname_template) + 3];
+ char *devname1 = new char[strlen(devname_template1) + 3];
+ char *nickname1 = new char[strlen(nickname_template1) + 3];
sprintf(nickname, nickname_template, i + 1);
sprintf(devname, devname_template, i);
+
+ sprintf(nickname1, nickname_template1, i + 1);
+ sprintf(devname1, devname_template1, i);
if(access(devname, R_OK) == 0) {
int fd = open(devname, O_RDONLY);
if(fd < 0) {
@@ -140,7 +161,21 @@
delete nickname;
delete devname;
}
+
+ if(access(devname1, R_OK) == 0) {
+ int fd = open(devname1, O_RDONLY);
+ if(fd < 0) {
+ new MeteorDevice(nickname1, devname1, 0);
+ } else {
+ (void)close(fd);
+ new MeteorDevice(nickname1, devname1, 1);
+ }
+ } else {
+ delete nickname1;
+ delete devname1;
+ }
}
+
}
MeteorDevice::MeteorDevice(const char* nickname, const char *devname, int free):
@@ -160,7 +195,10 @@
Tcl& tcl = Tcl::instance();
if ((argc == 3) && (strcmp(argv[1], "open") == 0)) {
TclObject* o = 0;
- o = new MeteorGrabber(name_, argv[2]);
+ if (strcmp(argv[2], "422") == 0)
+ o = new Meteor422Grabber(name_);
+ else if (strcmp(argv[2], "cif") == 0)
+ o = new MeteorCIFGrabber(name_);
if (o != 0)
tcl.result(o->name());
return (TCL_OK);
@@ -168,19 +206,8 @@
return (InputDevice::command(argc, argv));
}
-MeteorGrabber::MeteorGrabber(const char* name, const char* format)
+MeteorGrabber::MeteorGrabber(const char* name)
{
- coder_format_ = -1;
- if(!strcmp(format, "411")) coder_format_ = f_411;
- if(!strcmp(format, "422")) coder_format_ = f_422;
- if(!strcmp(format, "cif")) coder_format_ = f_cif;
- if(coder_format_ == -1) {
- fprintf(stderr,
- "vic: MeteorGrabber: unsupported format: %s\n",
- format);
- abort();
- }
-
dev_ = open(name, O_RDONLY);
if (dev_ == -1) {
status_ = -1;
@@ -205,27 +232,27 @@
}
}
-void MeteorGrabber::setsize()
+void MeteorGrabber::set_size_meteor(int w, int h)
{
struct meteor_geomet geom;
- geom.rows = (baseheight_ / decimate_) &~0xf; /* 0xf, ugh! */
- geom.columns = (basewidth_ / decimate_) &~0xf;
+ geom.rows = h &~0xf; /* 0xf, ugh! */
+ geom.columns = w &~0xf;
geom.frames = 1;
- geom.oformat = METEOR_GEO_UNSIGNED;
- geom.oformat |= METEOR_GEO_YUV_422;
+ geom.oformat = METEOR_GEO_UNSIGNED | METEOR_GEO_YUV_PACKED;
/*
* If we can get by with only reading even fields, then by all
* means do so.
*/
unsigned short status;
ioctl(dev_, METEORSTATUS, &status);
- if(status & METEOR_STATUS_HCLK) { /* do we have a source? */
- /* No source, assume ntsc*/
+ if(status & METEOR_STATUS_HCLK) {
+ /* No source, assume ntsc */
if(geom.rows <= NTSC_HEIGHT && geom.columns <= NTSC_WIDTH)
geom.oformat |= METEOR_GEO_EVEN_ONLY;
} else {
- if(status & METEOR_STATUS_FIDT) { /* is it pal or ntsc? */
+ /* is it pal or ntsc? */
+ if(status & METEOR_STATUS_FIDT) {
/* 60 hz */
if(geom.rows<=NTSC_HEIGHT && geom.columns<=NTSC_WIDTH)
geom.oformat |= METEOR_GEO_EVEN_ONLY;
@@ -237,18 +264,6 @@
if(ioctl(dev_, METEORSETGEO, &geom) < 0)
perror("vic: METERSETGEO: ");
-
- switch(coder_format_) {
- case f_422:
- set_size_422(geom.columns, geom.rows);
- break;
- case f_cif:
- case f_411:
- set_size_411(geom.columns, geom.rows);
- break;
- }
-
- allocref(); /* allocate reference frame */
}
void MeteorGrabber::format()
@@ -285,11 +300,6 @@
baseheight_ = PAL_HEIGHT * 2;
basewidth_ = PAL_WIDTH * 2;
}
-
- if(coder_format_ == f_cif) {
- baseheight_ = CIF_HEIGHT * 2;
- basewidth_ = CIF_WIDTH * 2;
- }
setsize();
}
@@ -299,15 +309,6 @@
format();
int cmd = METEOR_CAP_SINGLE;
ioctl(dev_, METEORCAPTUR, (char*)&cmd);
-#ifdef FRAME_CNTS
- cnts_.fifo_errors = 0;
- cnts_.dma_errors = 0;
- cnts_.frames_captured = 0;
- cnts_.even_fields_captured = 0;
- cnts_.odd_fields_captured = 0;
- ioctl(dev_, METEORSCOUNT, &cnts_);
- start_time_ = gettimeofday();
-#endif
cmd = METEOR_CAP_CONTINOUS;
ioctl(dev_, METEORCAPTUR, (char*)&cmd);
@@ -319,19 +320,6 @@
int cmd = METEOR_CAP_STOP_CONT;
ioctl(dev_, METEORCAPTUR, (char*)&cmd);
-#ifdef FRAME_CNTS
- double endtime = gettimeofday() ;
- ioctl(dev_, METEORGCOUNT, &cnts_);
- int diff = (int)((endtime-start_time_) * 1e-6 + 0.5);
- printf("frames = %d, even fields = %d, odd fields = %d,\n\
-fifo errors = %d, dma errors = %d, seconds = %d",
- cnts_.frames_captured, cnts_.even_fields_captured,
- cnts_.odd_fields_captured, cnts_.fifo_errors, cnts_.dma_errors,
- diff);
- if(diff)
- printf(",fps = %d", cnts_.frames_captured/diff);
- printf("\n");
-#endif
Grabber::stop();
}
@@ -345,15 +333,15 @@
int MeteorGrabber::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_) {
+ if ((u_int)dec != decimate_) {
decimate_ = dec;
if(running_) {
stop();
@@ -362,7 +350,8 @@
}
}
return (TCL_OK);
- } else if (strcmp(argv[1], "port") == 0) {
+ }
+ if (strcmp(argv[1], "port") == 0) {
int p = port_;
if(!strcmp(argv[2], "RCA")) p = METEOR_INPUT_DEV0;
if(!strcmp(argv[2], "Port-1")) p = METEOR_INPUT_DEV1;
@@ -377,7 +366,8 @@
ioctl(dev_, METEORSINPUT, &port_);
}
return (TCL_OK);
- } else if (strcmp(argv[1], "format") == 0 ||
+ }
+ if (strcmp(argv[1], "format") == 0 ||
strcmp(argv[1], "type") == 0) {
if (strcmp(argv[2], "auto") == 0)
video_format_ = METEOR_FMT_AUTOMODE;
@@ -390,14 +380,35 @@
if (running_)
format();
return (TCL_OK);
- } else if (strcmp(argv[1], "contrast") == 0) {
- contrast(atof(argv[2]));
- return (TCL_OK);
+ }
+ if (strcmp(argv[1], "brightness") == 0) {
+ u_char val = atoi(argv[2]);
+ ioctl(dev_, METEORSBRIG, &val);
+ return (TCL_OK);
+ }
+ if (strcmp(argv[1], "contrast") == 0) {
+ u_char val = atoi(argv[2]);
+ ioctl(dev_, METEORSCONT, &val);
+ return (TCL_OK);
+ }
+ if (strcmp(argv[1], "hue") == 0) {
+ char val = atoi(argv[2]);
+ ioctl(dev_, METEORSHUE, &val);
+ return (TCL_OK);
+ }
+ if (strcmp(argv[1], "saturation") == 0) {
+ u_char val = atoi(argv[2]);
+ ioctl(dev_, METEORSCSAT, &val);
+ return (TCL_OK);
+ }
+ if (strcmp(argv[1], "uvgain") == 0) {
+ u_char val = atoi(argv[2]);
+ ioctl(dev_, METEORSCHCV, &val);
+ return (TCL_OK);
}
} else if (argc == 2) {
if (strcmp(argv[1], "format") == 0 ||
strcmp(argv[1], "type") == 0) {
- Tcl& tcl = Tcl::instance();
switch (video_format_) {
case METEOR_FMT_AUTOMODE:
@@ -423,54 +434,316 @@
return (TCL_OK);
}
+ if (strcmp(argv[1], "brightness") == 0) {
+ u_char val;
+ ioctl(dev_, METEORGBRIG, &val);
+ tcl.resultf("%d", (int)val);
+ return (TCL_OK);
+ }
+ if (strcmp(argv[1], "contrast") == 0) {
+ u_char val;
+ ioctl(dev_, METEORGCONT, &val);
+ tcl.resultf("%d", (int)val);
+ return (TCL_OK);
+ }
+ if (strcmp(argv[1], "hue") == 0) {
+ char val;
+ ioctl(dev_, METEORGHUE, &val);
+ tcl.resultf("%d", (int)val);
+ return (TCL_OK);
+ }
+ if (strcmp(argv[1], "saturation") == 0) {
+ u_char val;
+ ioctl(dev_, METEORGCSAT, &val);
+ tcl.resultf("%d", (int)val);
+ return (TCL_OK);
+ }
+ if (strcmp(argv[1], "uvgain") == 0) {
+ u_char val;
+ ioctl(dev_, METEORGCHCV, &val);
+ tcl.resultf("%d", (int)val);
+ return (TCL_OK);
+ }
}
return (Grabber::command(argc, argv));
}
-int MeteorGrabber::capture()
-{
- if(pyuv_ == 0) return 0;
-
- volatile u_int* py = pyuv_;
- volatile u_int* pu = (u_int *)((u_int)py + (u_int)framesize_);
- volatile u_int* pv = (u_int *)((u_int)pu + (framesize_ >> 1));
- u_int* lum = (u_int *)frame_;
- u_int* uoff = (u_int *)((u_int)lum + (u_int)framesize_);
- int f422 = coder_format_ == f_422;
- u_int* voff = (u_int *)((u_int)uoff +
- (u_int)(framesize_>>(f422?1:2)));
- int numc = ((basewidth_/decimate_) &~0xf) >> 3;
-
- for (int row = 0; row < (((baseheight_/decimate_)&~0xf) >> 1); row++) {
- for(int col = 0; col < numc; col++) {
- *lum++ = *py++;
- *lum++ = *py++;
- *uoff++ = *pu++;
- *voff++ = *pv++;
- }
- for(col = 0; col < numc; col++) {
- *lum++ = *py++;
- *lum++ = *py++;
- if(f422) { /* only copy odd in 4:2:2 format */
- *uoff++ = *pu++;
- *voff++ = *pv++;
-
- }
- }
- if(!f422) { /* skip odd if 4:1:1 or cif format */
- pu += numc;
- pv += numc;
- }
- }
- return 1;
+#define U 0
+#define Y0 1
+#define V 2
+#define Y1 3
+
+/*
+ * define these for REPLENISH macro used below
+ */
+#define DIFF4(in, frm, v) \
+ v += (in)[Y0] - (frm)[0]; \
+ v += (in)[Y1] - (frm)[1]; \
+ v += (in)[Y0+4] - (frm)[2]; \
+ v += (in)[Y1+4] - (frm)[3];
+
+#define DIFFLINE(in, frm, left, center, right) \
+ DIFF4(in + 0*8, frm + 0*4, 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 MeteorGrabber::suppress(const u_char* devbuf, int is)
+{
+ const u_char* start = frame_ + 16 * vstart_ * outw_ + 16 * hstart_;
+ REPLENISH(devbuf, start, is, 2,
+ hstart_, hstop_, vstart_, vstop_);
}
int MeteorGrabber::grab()
{
- if (capture() == 0)
- return (0);
- suppress(frame_);
- saveblks(frame_);
- YuvFrame f(media_ts(), frame_, crvec_, outw_, outh_);
+ if (pyuv_ == 0)
+ return 0;
+
+ int istride = inw_ * 2;
+ suppress((u_char*)pyuv_, istride);
+ saveblks((u_char*)pyuv_, istride);
+ u_int32_t ts = media_ts();
+ YuvFrame f(ts, frame_, crvec_, outw_, outh_);
return (target_->consume(&f));
+}
+
+Meteor422Grabber::Meteor422Grabber(const char* name)
+ : MeteorGrabber(name)
+{
+}
+
+MeteorCIFGrabber::MeteorCIFGrabber(const char* name)
+ : MeteorGrabber(name)
+{
+}
+
+void Meteor422Grabber::setsize()
+{
+ int w = basewidth_ / decimate_;
+ int h = baseheight_ / decimate_;
+ set_size_meteor(w, h);
+ set_size_422(w, h);
+}
+
+inline void
+Meteor422Grabber::saveblk(const u_char* in,
+ u_char* yp, u_char* up, u_char* vp, int stride, int istride)
+{
+ 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[U + 0*4] << SHIFT(24) |
+ in[U + 1*4] << SHIFT(16) |
+ in[U + 2*4] << SHIFT(8) |
+ in[U + 3*4] << SHIFT(0);
+ v = in[V + 0*4] << SHIFT(24) |
+ in[V + 1*4] << SHIFT(16) |
+ in[V + 2*4] << SHIFT(8) |
+ in[V + 3*4] << SHIFT(0);
+ y0 = in[Y0 + 0*4] << SHIFT(24) |
+ in[Y1 + 0*4] << SHIFT(16) |
+ in[Y0 + 1*4] << SHIFT(8) |
+ in[Y1 + 1*4] << SHIFT(0);
+ y1 = in[Y0 + 2*4] << SHIFT(24) |
+ in[Y1 + 2*4] << SHIFT(16) |
+ in[Y0 + 3*4] << SHIFT(8) |
+ in[Y1 + 3*4] << SHIFT(0);
+
+ ((u_int*)yp)[0] = y0;
+ ((u_int*)yp)[1] = y1;
+ ((u_int*)up)[0] = u;
+ ((u_int*)vp)[0] = v;
+
+ u = in[U + 4*4] << SHIFT(24) |
+ in[U + 5*4] << SHIFT(16) |
+ in[U + 6*4] << SHIFT(8) |
+ in[U + 7*4] << SHIFT(0);
+ v = in[V + 4*4] << SHIFT(24) |
+ in[V + 5*4] << SHIFT(16) |
+ in[V + 6*4] << SHIFT(8) |
+ in[V + 7*4] << SHIFT(0);
+ y0 = in[Y0 + 4*4] << SHIFT(24) |
+ in[Y1 + 4*4] << SHIFT(16) |
+ in[Y0 + 5*4] << SHIFT(8) |
+ in[Y1 + 5*4] << SHIFT(0);
+ y1 = in[Y0 + 6*4] << SHIFT(24) |
+ in[Y1 + 6*4] << SHIFT(16) |
+ in[Y0 + 7*4] << SHIFT(8) |
+ in[Y1 + 7*4] << SHIFT(0);
+
+ ((u_int*)yp)[2] = y0;
+ ((u_int*)yp)[3] = y1;
+ ((u_int*)up)[1] = u;
+ ((u_int*)vp)[1] = v;
+
+ in += istride;
+ yp += stride;
+ up += stride >> 1;
+ vp += stride >> 1;
+ }
+}
+
+void Meteor422Grabber::saveblks(const u_char* devbuf, int is)
+{
+ u_char* crv = crvec_;
+ int off = framesize_;
+ u_char* lum = frame_;
+ u_char* chm = lum + off;
+ off >>= 1;
+ int stride = 15 * outw_;
+ int istride = is * 15;
+ for (int y = 0; y < blkh_; ++y) {
+ for (int x = 0; x < blkw_; ++x) {
+ int s = *crv++;
+ if ((s & CR_SEND) != 0)
+ saveblk(devbuf, lum, chm, chm + off, outw_, is);
+
+ devbuf += 32;
+ lum += 16;
+ chm += 8;
+ }
+ lum += stride;
+ chm += stride >> 1;
+ devbuf += istride;
+ }
+}
+
+void MeteorCIFGrabber::setsize()
+{
+ int w = basewidth_ / decimate_;
+ int h = baseheight_ / decimate_;
+ set_size_meteor(w, h);
+ set_size_cif(w, h);
+}
+
+inline void
+MeteorCIFGrabber::saveblk(const u_char* in,
+ u_char* yp, u_char* up, u_char* vp, int stride, int istride)
+{
+ for (int i = 8; --i >= 0; ) {
+ /*
+ * Each iteration of this loop grabs 32 Ys & 16 U/Vs.
+ */
+ register u_int y0, y1, u, v;
+
+ u = in[U + 0*4] << SHIFT(24) |
+ in[U + 1*4] << SHIFT(16) |
+ in[U + 2*4] << SHIFT(8) |
+ in[U + 3*4] << SHIFT(0);
+ v = in[V + 0*4] << SHIFT(24) |
+ in[V + 1*4] << SHIFT(16) |
+ in[V + 2*4] << SHIFT(8) |
+ in[V + 3*4] << SHIFT(0);
+ y0 = in[Y0 + 0*4] << SHIFT(24) |
+ in[Y1 + 0*4] << SHIFT(16) |
+ in[Y0 + 1*4] << SHIFT(8) |
+ in[Y1 + 1*4] << SHIFT(0);
+ y1 = in[Y0 + 2*4] << SHIFT(24) |
+ in[Y1 + 2*4] << SHIFT(16) |
+ in[Y0 + 3*4] << SHIFT(8) |
+ in[Y1 + 3*4] << SHIFT(0);
+
+ ((u_int*)yp)[0] = y0;
+ ((u_int*)yp)[1] = y1;
+ ((u_int*)up)[0] = u;
+ ((u_int*)vp)[0] = v;
+
+ u = in[U + 4*4] << SHIFT(24) |
+ in[U + 5*4] << SHIFT(16) |
+ in[U + 6*4] << SHIFT(8) |
+ in[U + 7*4] << SHIFT(0);
+ v = in[V + 4*4] << SHIFT(24) |
+ in[V + 5*4] << SHIFT(16) |
+ in[V + 6*4] << SHIFT(8) |
+ in[V + 7*4] << SHIFT(0);
+ y0 = in[Y0 + 4*4] << SHIFT(24) |
+ in[Y1 + 4*4] << SHIFT(16) |
+ in[Y0 + 5*4] << SHIFT(8) |
+ in[Y1 + 5*4] << SHIFT(0);
+ y1 = in[Y0 + 6*4] << SHIFT(24) |
+ in[Y1 + 6*4] << SHIFT(16) |
+ in[Y0 + 7*4] << SHIFT(8) |
+ in[Y1 + 7*4] << SHIFT(0);
+
+ ((u_int*)yp)[2] = y0;
+ ((u_int*)yp)[3] = y1;
+ ((u_int*)up)[1] = u;
+ ((u_int*)vp)[1] = v;
+
+ in += istride;
+ yp += stride;
+ up += stride >> 1;
+ vp += stride >> 1;
+
+ /* do the 2nd (y only instead of yuv) line */
+
+ y0 = in[Y0 + 0*4] << SHIFT(24) |
+ in[Y1 + 0*4] << SHIFT(16) |
+ in[Y0 + 1*4] << SHIFT(8) |
+ in[Y1 + 1*4] << SHIFT(0);
+ y1 = in[Y0 + 2*4] << SHIFT(24) |
+ in[Y1 + 2*4] << SHIFT(16) |
+ in[Y0 + 3*4] << SHIFT(8) |
+ in[Y1 + 3*4] << SHIFT(0);
+
+ ((u_int*)yp)[0] = y0;
+ ((u_int*)yp)[1] = y1;
+
+ y0 = in[Y0 + 4*4] << SHIFT(24) |
+ in[Y1 + 4*4] << SHIFT(16) |
+ in[Y0 + 5*4] << SHIFT(8) |
+ in[Y1 + 5*4] << SHIFT(0);
+ y1 = in[Y0 + 6*4] << SHIFT(24) |
+ in[Y1 + 6*4] << SHIFT(16) |
+ in[Y0 + 7*4] << SHIFT(8) |
+ in[Y1 + 7*4] << SHIFT(0);
+
+ ((u_int*)yp)[2] = y0;
+ ((u_int*)yp)[3] = y1;
+
+ in += istride;
+ yp += stride;
+ }
+}
+
+void MeteorCIFGrabber::saveblks(const u_char* in, int is)
+{
+ u_char* crv = crvec_;
+ int off = framesize_;
+ u_char* lum = frame_;
+ u_char* chm = lum + off;
+ off >>= 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;
+ }
}

View File

@ -0,0 +1,725 @@
--- grabber-meteor.cc.orig Sat May 18 11:44:54 1996
+++ grabber-meteor.cc Thu Dec 18 18:35:09 1997
@@ -43,7 +43,6 @@
*
*/
-/*#define FRAME_CNTS /* print frame counts and fps when device stops -- debug */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
@@ -51,14 +50,13 @@
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
-#ifdef FRAME_CNTS
-#include <sys/time.h>
-#endif
#include "grabber.h"
+#include "crdef.h"
#include "Tcl.h"
#include "device-input.h"
#include "module.h"
+#include "bsd-endian.h"
#include <machine/ioctl_meteor.h>
@@ -72,62 +70,85 @@
class MeteorGrabber : public Grabber {
- public:
- MeteorGrabber(const char* name, const char* format);
+ public:
+ MeteorGrabber(const char* name);
virtual ~MeteorGrabber();
+ virtual int command(int argc, const char*const* argv);
+ virtual void fps(int);
virtual void start();
virtual void stop();
- virtual void fps(int);
- protected:
- virtual int command(int argc, const char*const* argv);
- virtual int capture();
virtual int grab();
+ protected:
void format();
- void setsize();
+ virtual void setsize() = 0;
+ void suppress(const u_char* in, int istride);
+ virtual void saveblks(const u_char* in, int istride) = 0;
+ void set_size_meteor(int w, int h);
int video_format_; /* video input format: NTSC or PAL */
int dev_; /* device fd */
int port_; /* video input port */
- int coder_format_; /* 411, 422, or cif */
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 */
volatile u_int* pyuv_; /* pointer to yuv data */
-#ifdef FRAME_CNTS
- struct meteor_counts cnts_; /* pointer to counters */
- double start_time_;
-#endif
};
-static const int f_411 = 0; /* coder_format_s */
-static const int f_422 = 1;
-static const int f_cif = 2;
+class Meteor422Grabber : public MeteorGrabber {
+ public:
+ Meteor422Grabber(const char* name);
+ protected:
+ void setsize();
+ void saveblk(const u_char* in, u_char* yp, u_char* up, u_char* vp,
+ int stride, int istride);
+ void saveblks(const u_char* in, int istride);
+};
+
+class MeteorCIFGrabber : public MeteorGrabber {
+ public:
+ MeteorCIFGrabber(const char* name);
+ protected:
+ void setsize();
+ void saveblk(const u_char* in, u_char* yp, u_char* up, u_char* vp,
+ int stride, int istride);
+ void saveblks(const u_char* in, int istride);
+};
class MeteorDevice : public InputDevice {
- public:
+ public:
MeteorDevice(const char* nickname, const char* devname, int free);
virtual int command(int argc, const char*const* argv);
- protected:
+ protected:
const char* name_;
};
class MeteorScanner {
- public:
+ public:
MeteorScanner(const int n);
};
+
static MeteorScanner find_meteor_devices(4);
MeteorScanner::MeteorScanner(const int n)
{
char* devname_template = "/dev/meteor%d";
char* nickname_template = "Matrox Meteor %d";
+ char* devname_template1 = "/dev/bktr%d";
+ char* nickname_template1 = "BrookTree848 %d";
+
+
for(int i = 0; i < n; i++) {
char *devname = new char[strlen(devname_template) + 3];
char *nickname = new char[strlen(nickname_template) + 3];
+ char *devname1 = new char[strlen(devname_template1) + 3];
+ char *nickname1 = new char[strlen(nickname_template1) + 3];
sprintf(nickname, nickname_template, i + 1);
sprintf(devname, devname_template, i);
+
+ sprintf(nickname1, nickname_template1, i + 1);
+ sprintf(devname1, devname_template1, i);
if(access(devname, R_OK) == 0) {
int fd = open(devname, O_RDONLY);
if(fd < 0) {
@@ -140,7 +161,21 @@
delete nickname;
delete devname;
}
+
+ if(access(devname1, R_OK) == 0) {
+ int fd = open(devname1, O_RDONLY);
+ if(fd < 0) {
+ new MeteorDevice(nickname1, devname1, 0);
+ } else {
+ (void)close(fd);
+ new MeteorDevice(nickname1, devname1, 1);
+ }
+ } else {
+ delete nickname1;
+ delete devname1;
+ }
}
+
}
MeteorDevice::MeteorDevice(const char* nickname, const char *devname, int free):
@@ -160,7 +195,10 @@
Tcl& tcl = Tcl::instance();
if ((argc == 3) && (strcmp(argv[1], "open") == 0)) {
TclObject* o = 0;
- o = new MeteorGrabber(name_, argv[2]);
+ if (strcmp(argv[2], "422") == 0)
+ o = new Meteor422Grabber(name_);
+ else if (strcmp(argv[2], "cif") == 0)
+ o = new MeteorCIFGrabber(name_);
if (o != 0)
tcl.result(o->name());
return (TCL_OK);
@@ -168,19 +206,8 @@
return (InputDevice::command(argc, argv));
}
-MeteorGrabber::MeteorGrabber(const char* name, const char* format)
+MeteorGrabber::MeteorGrabber(const char* name)
{
- coder_format_ = -1;
- if(!strcmp(format, "411")) coder_format_ = f_411;
- if(!strcmp(format, "422")) coder_format_ = f_422;
- if(!strcmp(format, "cif")) coder_format_ = f_cif;
- if(coder_format_ == -1) {
- fprintf(stderr,
- "vic: MeteorGrabber: unsupported format: %s\n",
- format);
- abort();
- }
-
dev_ = open(name, O_RDONLY);
if (dev_ == -1) {
status_ = -1;
@@ -205,27 +232,27 @@
}
}
-void MeteorGrabber::setsize()
+void MeteorGrabber::set_size_meteor(int w, int h)
{
struct meteor_geomet geom;
- geom.rows = (baseheight_ / decimate_) &~0xf; /* 0xf, ugh! */
- geom.columns = (basewidth_ / decimate_) &~0xf;
+ geom.rows = h &~0xf; /* 0xf, ugh! */
+ geom.columns = w &~0xf;
geom.frames = 1;
- geom.oformat = METEOR_GEO_UNSIGNED;
- geom.oformat |= METEOR_GEO_YUV_422;
+ geom.oformat = METEOR_GEO_UNSIGNED | METEOR_GEO_YUV_PACKED;
/*
* If we can get by with only reading even fields, then by all
* means do so.
*/
unsigned short status;
ioctl(dev_, METEORSTATUS, &status);
- if(status & METEOR_STATUS_HCLK) { /* do we have a source? */
- /* No source, assume ntsc*/
+ if(status & METEOR_STATUS_HCLK) {
+ /* No source, assume ntsc */
if(geom.rows <= NTSC_HEIGHT && geom.columns <= NTSC_WIDTH)
geom.oformat |= METEOR_GEO_EVEN_ONLY;
} else {
- if(status & METEOR_STATUS_FIDT) { /* is it pal or ntsc? */
+ /* is it pal or ntsc? */
+ if(status & METEOR_STATUS_FIDT) {
/* 60 hz */
if(geom.rows<=NTSC_HEIGHT && geom.columns<=NTSC_WIDTH)
geom.oformat |= METEOR_GEO_EVEN_ONLY;
@@ -237,18 +264,6 @@
if(ioctl(dev_, METEORSETGEO, &geom) < 0)
perror("vic: METERSETGEO: ");
-
- switch(coder_format_) {
- case f_422:
- set_size_422(geom.columns, geom.rows);
- break;
- case f_cif:
- case f_411:
- set_size_411(geom.columns, geom.rows);
- break;
- }
-
- allocref(); /* allocate reference frame */
}
void MeteorGrabber::format()
@@ -285,11 +300,6 @@
baseheight_ = PAL_HEIGHT * 2;
basewidth_ = PAL_WIDTH * 2;
}
-
- if(coder_format_ == f_cif) {
- baseheight_ = CIF_HEIGHT * 2;
- basewidth_ = CIF_WIDTH * 2;
- }
setsize();
}
@@ -299,15 +309,6 @@
format();
int cmd = METEOR_CAP_SINGLE;
ioctl(dev_, METEORCAPTUR, (char*)&cmd);
-#ifdef FRAME_CNTS
- cnts_.fifo_errors = 0;
- cnts_.dma_errors = 0;
- cnts_.frames_captured = 0;
- cnts_.even_fields_captured = 0;
- cnts_.odd_fields_captured = 0;
- ioctl(dev_, METEORSCOUNT, &cnts_);
- start_time_ = gettimeofday();
-#endif
cmd = METEOR_CAP_CONTINOUS;
ioctl(dev_, METEORCAPTUR, (char*)&cmd);
@@ -319,19 +320,6 @@
int cmd = METEOR_CAP_STOP_CONT;
ioctl(dev_, METEORCAPTUR, (char*)&cmd);
-#ifdef FRAME_CNTS
- double endtime = gettimeofday() ;
- ioctl(dev_, METEORGCOUNT, &cnts_);
- int diff = (int)((endtime-start_time_) * 1e-6 + 0.5);
- printf("frames = %d, even fields = %d, odd fields = %d,\n\
-fifo errors = %d, dma errors = %d, seconds = %d",
- cnts_.frames_captured, cnts_.even_fields_captured,
- cnts_.odd_fields_captured, cnts_.fifo_errors, cnts_.dma_errors,
- diff);
- if(diff)
- printf(",fps = %d", cnts_.frames_captured/diff);
- printf("\n");
-#endif
Grabber::stop();
}
@@ -345,15 +333,15 @@
int MeteorGrabber::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_) {
+ if ((u_int)dec != decimate_) {
decimate_ = dec;
if(running_) {
stop();
@@ -362,7 +350,8 @@
}
}
return (TCL_OK);
- } else if (strcmp(argv[1], "port") == 0) {
+ }
+ if (strcmp(argv[1], "port") == 0) {
int p = port_;
if(!strcmp(argv[2], "RCA")) p = METEOR_INPUT_DEV0;
if(!strcmp(argv[2], "Port-1")) p = METEOR_INPUT_DEV1;
@@ -377,7 +366,8 @@
ioctl(dev_, METEORSINPUT, &port_);
}
return (TCL_OK);
- } else if (strcmp(argv[1], "format") == 0 ||
+ }
+ if (strcmp(argv[1], "format") == 0 ||
strcmp(argv[1], "type") == 0) {
if (strcmp(argv[2], "auto") == 0)
video_format_ = METEOR_FMT_AUTOMODE;
@@ -390,14 +380,35 @@
if (running_)
format();
return (TCL_OK);
- } else if (strcmp(argv[1], "contrast") == 0) {
- contrast(atof(argv[2]));
- return (TCL_OK);
+ }
+ if (strcmp(argv[1], "brightness") == 0) {
+ u_char val = atoi(argv[2]);
+ ioctl(dev_, METEORSBRIG, &val);
+ return (TCL_OK);
+ }
+ if (strcmp(argv[1], "contrast") == 0) {
+ u_char val = atoi(argv[2]);
+ ioctl(dev_, METEORSCONT, &val);
+ return (TCL_OK);
+ }
+ if (strcmp(argv[1], "hue") == 0) {
+ char val = atoi(argv[2]);
+ ioctl(dev_, METEORSHUE, &val);
+ return (TCL_OK);
+ }
+ if (strcmp(argv[1], "saturation") == 0) {
+ u_char val = atoi(argv[2]);
+ ioctl(dev_, METEORSCSAT, &val);
+ return (TCL_OK);
+ }
+ if (strcmp(argv[1], "uvgain") == 0) {
+ u_char val = atoi(argv[2]);
+ ioctl(dev_, METEORSCHCV, &val);
+ return (TCL_OK);
}
} else if (argc == 2) {
if (strcmp(argv[1], "format") == 0 ||
strcmp(argv[1], "type") == 0) {
- Tcl& tcl = Tcl::instance();
switch (video_format_) {
case METEOR_FMT_AUTOMODE:
@@ -423,54 +434,316 @@
return (TCL_OK);
}
+ if (strcmp(argv[1], "brightness") == 0) {
+ u_char val;
+ ioctl(dev_, METEORGBRIG, &val);
+ tcl.resultf("%d", (int)val);
+ return (TCL_OK);
+ }
+ if (strcmp(argv[1], "contrast") == 0) {
+ u_char val;
+ ioctl(dev_, METEORGCONT, &val);
+ tcl.resultf("%d", (int)val);
+ return (TCL_OK);
+ }
+ if (strcmp(argv[1], "hue") == 0) {
+ char val;
+ ioctl(dev_, METEORGHUE, &val);
+ tcl.resultf("%d", (int)val);
+ return (TCL_OK);
+ }
+ if (strcmp(argv[1], "saturation") == 0) {
+ u_char val;
+ ioctl(dev_, METEORGCSAT, &val);
+ tcl.resultf("%d", (int)val);
+ return (TCL_OK);
+ }
+ if (strcmp(argv[1], "uvgain") == 0) {
+ u_char val;
+ ioctl(dev_, METEORGCHCV, &val);
+ tcl.resultf("%d", (int)val);
+ return (TCL_OK);
+ }
}
return (Grabber::command(argc, argv));
}
-int MeteorGrabber::capture()
-{
- if(pyuv_ == 0) return 0;
-
- volatile u_int* py = pyuv_;
- volatile u_int* pu = (u_int *)((u_int)py + (u_int)framesize_);
- volatile u_int* pv = (u_int *)((u_int)pu + (framesize_ >> 1));
- u_int* lum = (u_int *)frame_;
- u_int* uoff = (u_int *)((u_int)lum + (u_int)framesize_);
- int f422 = coder_format_ == f_422;
- u_int* voff = (u_int *)((u_int)uoff +
- (u_int)(framesize_>>(f422?1:2)));
- int numc = ((basewidth_/decimate_) &~0xf) >> 3;
-
- for (int row = 0; row < (((baseheight_/decimate_)&~0xf) >> 1); row++) {
- for(int col = 0; col < numc; col++) {
- *lum++ = *py++;
- *lum++ = *py++;
- *uoff++ = *pu++;
- *voff++ = *pv++;
- }
- for(col = 0; col < numc; col++) {
- *lum++ = *py++;
- *lum++ = *py++;
- if(f422) { /* only copy odd in 4:2:2 format */
- *uoff++ = *pu++;
- *voff++ = *pv++;
-
- }
- }
- if(!f422) { /* skip odd if 4:1:1 or cif format */
- pu += numc;
- pv += numc;
- }
- }
- return 1;
+#define U 0
+#define Y0 1
+#define V 2
+#define Y1 3
+
+/*
+ * define these for REPLENISH macro used below
+ */
+#define DIFF4(in, frm, v) \
+ v += (in)[Y0] - (frm)[0]; \
+ v += (in)[Y1] - (frm)[1]; \
+ v += (in)[Y0+4] - (frm)[2]; \
+ v += (in)[Y1+4] - (frm)[3];
+
+#define DIFFLINE(in, frm, left, center, right) \
+ DIFF4(in + 0*8, frm + 0*4, 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 MeteorGrabber::suppress(const u_char* devbuf, int is)
+{
+ const u_char* start = frame_ + 16 * vstart_ * outw_ + 16 * hstart_;
+ REPLENISH(devbuf, start, is, 2,
+ hstart_, hstop_, vstart_, vstop_);
}
int MeteorGrabber::grab()
{
- if (capture() == 0)
- return (0);
- suppress(frame_);
- saveblks(frame_);
- YuvFrame f(media_ts(), frame_, crvec_, outw_, outh_);
+ if (pyuv_ == 0)
+ return 0;
+
+ int istride = inw_ * 2;
+ suppress((u_char*)pyuv_, istride);
+ saveblks((u_char*)pyuv_, istride);
+ u_int32_t ts = media_ts();
+ YuvFrame f(ts, frame_, crvec_, outw_, outh_);
return (target_->consume(&f));
+}
+
+Meteor422Grabber::Meteor422Grabber(const char* name)
+ : MeteorGrabber(name)
+{
+}
+
+MeteorCIFGrabber::MeteorCIFGrabber(const char* name)
+ : MeteorGrabber(name)
+{
+}
+
+void Meteor422Grabber::setsize()
+{
+ int w = basewidth_ / decimate_;
+ int h = baseheight_ / decimate_;
+ set_size_meteor(w, h);
+ set_size_422(w, h);
+}
+
+inline void
+Meteor422Grabber::saveblk(const u_char* in,
+ u_char* yp, u_char* up, u_char* vp, int stride, int istride)
+{
+ 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[U + 0*4] << SHIFT(24) |
+ in[U + 1*4] << SHIFT(16) |
+ in[U + 2*4] << SHIFT(8) |
+ in[U + 3*4] << SHIFT(0);
+ v = in[V + 0*4] << SHIFT(24) |
+ in[V + 1*4] << SHIFT(16) |
+ in[V + 2*4] << SHIFT(8) |
+ in[V + 3*4] << SHIFT(0);
+ y0 = in[Y0 + 0*4] << SHIFT(24) |
+ in[Y1 + 0*4] << SHIFT(16) |
+ in[Y0 + 1*4] << SHIFT(8) |
+ in[Y1 + 1*4] << SHIFT(0);
+ y1 = in[Y0 + 2*4] << SHIFT(24) |
+ in[Y1 + 2*4] << SHIFT(16) |
+ in[Y0 + 3*4] << SHIFT(8) |
+ in[Y1 + 3*4] << SHIFT(0);
+
+ ((u_int*)yp)[0] = y0;
+ ((u_int*)yp)[1] = y1;
+ ((u_int*)up)[0] = u;
+ ((u_int*)vp)[0] = v;
+
+ u = in[U + 4*4] << SHIFT(24) |
+ in[U + 5*4] << SHIFT(16) |
+ in[U + 6*4] << SHIFT(8) |
+ in[U + 7*4] << SHIFT(0);
+ v = in[V + 4*4] << SHIFT(24) |
+ in[V + 5*4] << SHIFT(16) |
+ in[V + 6*4] << SHIFT(8) |
+ in[V + 7*4] << SHIFT(0);
+ y0 = in[Y0 + 4*4] << SHIFT(24) |
+ in[Y1 + 4*4] << SHIFT(16) |
+ in[Y0 + 5*4] << SHIFT(8) |
+ in[Y1 + 5*4] << SHIFT(0);
+ y1 = in[Y0 + 6*4] << SHIFT(24) |
+ in[Y1 + 6*4] << SHIFT(16) |
+ in[Y0 + 7*4] << SHIFT(8) |
+ in[Y1 + 7*4] << SHIFT(0);
+
+ ((u_int*)yp)[2] = y0;
+ ((u_int*)yp)[3] = y1;
+ ((u_int*)up)[1] = u;
+ ((u_int*)vp)[1] = v;
+
+ in += istride;
+ yp += stride;
+ up += stride >> 1;
+ vp += stride >> 1;
+ }
+}
+
+void Meteor422Grabber::saveblks(const u_char* devbuf, int is)
+{
+ u_char* crv = crvec_;
+ int off = framesize_;
+ u_char* lum = frame_;
+ u_char* chm = lum + off;
+ off >>= 1;
+ int stride = 15 * outw_;
+ int istride = is * 15;
+ for (int y = 0; y < blkh_; ++y) {
+ for (int x = 0; x < blkw_; ++x) {
+ int s = *crv++;
+ if ((s & CR_SEND) != 0)
+ saveblk(devbuf, lum, chm, chm + off, outw_, is);
+
+ devbuf += 32;
+ lum += 16;
+ chm += 8;
+ }
+ lum += stride;
+ chm += stride >> 1;
+ devbuf += istride;
+ }
+}
+
+void MeteorCIFGrabber::setsize()
+{
+ int w = basewidth_ / decimate_;
+ int h = baseheight_ / decimate_;
+ set_size_meteor(w, h);
+ set_size_cif(w, h);
+}
+
+inline void
+MeteorCIFGrabber::saveblk(const u_char* in,
+ u_char* yp, u_char* up, u_char* vp, int stride, int istride)
+{
+ for (int i = 8; --i >= 0; ) {
+ /*
+ * Each iteration of this loop grabs 32 Ys & 16 U/Vs.
+ */
+ register u_int y0, y1, u, v;
+
+ u = in[U + 0*4] << SHIFT(24) |
+ in[U + 1*4] << SHIFT(16) |
+ in[U + 2*4] << SHIFT(8) |
+ in[U + 3*4] << SHIFT(0);
+ v = in[V + 0*4] << SHIFT(24) |
+ in[V + 1*4] << SHIFT(16) |
+ in[V + 2*4] << SHIFT(8) |
+ in[V + 3*4] << SHIFT(0);
+ y0 = in[Y0 + 0*4] << SHIFT(24) |
+ in[Y1 + 0*4] << SHIFT(16) |
+ in[Y0 + 1*4] << SHIFT(8) |
+ in[Y1 + 1*4] << SHIFT(0);
+ y1 = in[Y0 + 2*4] << SHIFT(24) |
+ in[Y1 + 2*4] << SHIFT(16) |
+ in[Y0 + 3*4] << SHIFT(8) |
+ in[Y1 + 3*4] << SHIFT(0);
+
+ ((u_int*)yp)[0] = y0;
+ ((u_int*)yp)[1] = y1;
+ ((u_int*)up)[0] = u;
+ ((u_int*)vp)[0] = v;
+
+ u = in[U + 4*4] << SHIFT(24) |
+ in[U + 5*4] << SHIFT(16) |
+ in[U + 6*4] << SHIFT(8) |
+ in[U + 7*4] << SHIFT(0);
+ v = in[V + 4*4] << SHIFT(24) |
+ in[V + 5*4] << SHIFT(16) |
+ in[V + 6*4] << SHIFT(8) |
+ in[V + 7*4] << SHIFT(0);
+ y0 = in[Y0 + 4*4] << SHIFT(24) |
+ in[Y1 + 4*4] << SHIFT(16) |
+ in[Y0 + 5*4] << SHIFT(8) |
+ in[Y1 + 5*4] << SHIFT(0);
+ y1 = in[Y0 + 6*4] << SHIFT(24) |
+ in[Y1 + 6*4] << SHIFT(16) |
+ in[Y0 + 7*4] << SHIFT(8) |
+ in[Y1 + 7*4] << SHIFT(0);
+
+ ((u_int*)yp)[2] = y0;
+ ((u_int*)yp)[3] = y1;
+ ((u_int*)up)[1] = u;
+ ((u_int*)vp)[1] = v;
+
+ in += istride;
+ yp += stride;
+ up += stride >> 1;
+ vp += stride >> 1;
+
+ /* do the 2nd (y only instead of yuv) line */
+
+ y0 = in[Y0 + 0*4] << SHIFT(24) |
+ in[Y1 + 0*4] << SHIFT(16) |
+ in[Y0 + 1*4] << SHIFT(8) |
+ in[Y1 + 1*4] << SHIFT(0);
+ y1 = in[Y0 + 2*4] << SHIFT(24) |
+ in[Y1 + 2*4] << SHIFT(16) |
+ in[Y0 + 3*4] << SHIFT(8) |
+ in[Y1 + 3*4] << SHIFT(0);
+
+ ((u_int*)yp)[0] = y0;
+ ((u_int*)yp)[1] = y1;
+
+ y0 = in[Y0 + 4*4] << SHIFT(24) |
+ in[Y1 + 4*4] << SHIFT(16) |
+ in[Y0 + 5*4] << SHIFT(8) |
+ in[Y1 + 5*4] << SHIFT(0);
+ y1 = in[Y0 + 6*4] << SHIFT(24) |
+ in[Y1 + 6*4] << SHIFT(16) |
+ in[Y0 + 7*4] << SHIFT(8) |
+ in[Y1 + 7*4] << SHIFT(0);
+
+ ((u_int*)yp)[2] = y0;
+ ((u_int*)yp)[3] = y1;
+
+ in += istride;
+ yp += stride;
+ }
+}
+
+void MeteorCIFGrabber::saveblks(const u_char* in, int is)
+{
+ u_char* crv = crvec_;
+ int off = framesize_;
+ u_char* lum = frame_;
+ u_char* chm = lum + off;
+ off >>= 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;
+ }
}