1998-06-26 18:39:21 +00:00
|
|
|
--- grabber-meteor.cc.orig Fri Jun 26 11:25:55 1998
|
|
|
|
+++ grabber-meteor.cc Fri Jun 26 11:18:53 1998
|
1997-12-19 02:50:52 +00:00
|
|
|
@@ -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>
|
1998-06-26 18:39:21 +00:00
|
|
|
@@ -51,16 +50,16 @@
|
1997-12-19 02:50:52 +00:00
|
|
|
#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>
|
1998-06-26 18:39:21 +00:00
|
|
|
+#include <machine/ioctl_bt848.h>
|
1997-12-19 02:50:52 +00:00
|
|
|
|
1998-06-26 18:39:21 +00:00
|
|
|
/*XXX*/
|
|
|
|
#define NTSC_WIDTH 320
|
|
|
|
@@ -72,62 +71,78 @@
|
1997-12-19 02:50:52 +00:00
|
|
|
|
|
|
|
|
|
|
|
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
|
1998-06-26 18:39:21 +00:00
|
|
|
+ int tuner_ ; /* tuner device... */
|
1997-12-19 02:50:52 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
-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)
|
|
|
|
{
|
1998-06-26 18:39:21 +00:00
|
|
|
- char* devname_template = "/dev/meteor%d";
|
|
|
|
- char* nickname_template = "Matrox Meteor %d";
|
|
|
|
+ static char *d[] = { "/dev/bktr%d", "/dev/meteor%d", NULL };
|
|
|
|
+ char *nickname_template = "meteor-%d";
|
1997-12-19 02:50:52 +00:00
|
|
|
|
|
|
|
for(int i = 0; i < n; i++) {
|
1998-06-26 18:39:21 +00:00
|
|
|
- char *devname = new char[strlen(devname_template) + 3];
|
|
|
|
+ for (int j = 0 ; d[j] != NULL ; j++) {
|
|
|
|
+ char *devname = new char[strlen(d[j]) + 3];
|
1997-12-19 02:50:52 +00:00
|
|
|
char *nickname = new char[strlen(nickname_template) + 3];
|
|
|
|
|
1998-06-26 18:39:21 +00:00
|
|
|
+ sprintf(devname, d[j], i);
|
1997-12-19 02:50:52 +00:00
|
|
|
sprintf(nickname, nickname_template, i + 1);
|
1998-06-26 18:39:21 +00:00
|
|
|
- sprintf(devname, devname_template, i);
|
1997-12-19 02:50:52 +00:00
|
|
|
if(access(devname, R_OK) == 0) {
|
|
|
|
int fd = open(devname, O_RDONLY);
|
|
|
|
if(fd < 0) {
|
1998-06-26 18:39:21 +00:00
|
|
|
@@ -140,8 +155,9 @@
|
1997-12-19 02:50:52 +00:00
|
|
|
delete nickname;
|
|
|
|
delete devname;
|
|
|
|
}
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
}
|
1998-06-26 18:39:21 +00:00
|
|
|
-}
|
1997-12-19 02:50:52 +00:00
|
|
|
|
|
|
|
MeteorDevice::MeteorDevice(const char* nickname, const char *devname, int free):
|
1998-06-26 18:39:21 +00:00
|
|
|
InputDevice(nickname), name_(devname)
|
|
|
|
@@ -149,6 +165,7 @@
|
|
|
|
if(free)
|
|
|
|
attributes_ = "\
|
|
|
|
format {422 411} \
|
|
|
|
+type {pal ntsc secam auto} \
|
|
|
|
size {large normal small cif} \
|
|
|
|
port {RCA Port-1 Port-2 Port-3 S-Video RGB}";
|
|
|
|
else
|
|
|
|
@@ -160,7 +177,10 @@
|
1997-12-19 02:50:52 +00:00
|
|
|
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);
|
1998-06-26 18:39:21 +00:00
|
|
|
@@ -168,19 +188,15 @@
|
1997-12-19 02:50:52 +00:00
|
|
|
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();
|
|
|
|
- }
|
|
|
|
-
|
1998-06-26 18:39:21 +00:00
|
|
|
+ int devnum;
|
|
|
|
+ if (sscanf(name, "/dev/bktr%d", &devnum) == 1) {
|
|
|
|
+ char *tunerdev = new char[strlen(name) + 3];
|
|
|
|
+ sprintf(tunerdev, "/dev/tuner%d", devnum);
|
|
|
|
+ tuner_ = open(tunerdev, O_RDONLY);
|
|
|
|
+ } else
|
|
|
|
+ tuner_ = -1;
|
1997-12-19 02:50:52 +00:00
|
|
|
dev_ = open(name, O_RDONLY);
|
|
|
|
if (dev_ == -1) {
|
|
|
|
status_ = -1;
|
1998-06-26 18:39:21 +00:00
|
|
|
@@ -203,52 +219,33 @@
|
|
|
|
if (dev_ != -1) {
|
|
|
|
close(dev_);
|
1997-12-19 02:50:52 +00:00
|
|
|
}
|
1998-06-26 18:39:21 +00:00
|
|
|
+ if (tuner_ != -1)
|
|
|
|
+ close(tuner_);
|
1997-12-19 02:50:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
-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;
|
1998-06-26 18:39:21 +00:00
|
|
|
- ioctl(dev_, METEORSTATUS, &status);
|
1997-12-19 02:50:52 +00:00
|
|
|
- if(status & METEOR_STATUS_HCLK) { /* do we have a source? */
|
|
|
|
- /* No source, assume ntsc*/
|
1998-06-26 18:39:21 +00:00
|
|
|
+ // ioctl(dev_, METEORSTATUS, &status);
|
|
|
|
+ if ( video_format_ == METEOR_FMT_NTSC ) {
|
1997-12-19 02:50:52 +00:00
|
|
|
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? */
|
1998-06-26 18:39:21 +00:00
|
|
|
- /* 60 hz */
|
|
|
|
- if(geom.rows<=NTSC_HEIGHT && geom.columns<=NTSC_WIDTH)
|
|
|
|
- geom.oformat |= METEOR_GEO_EVEN_ONLY;
|
|
|
|
- } else { /* 50 hz */
|
|
|
|
if(geom.rows<=PAL_HEIGHT && geom.columns<=PAL_WIDTH)
|
1997-12-19 02:50:52 +00:00
|
|
|
geom.oformat |= METEOR_GEO_EVEN_ONLY;
|
1998-06-26 18:39:21 +00:00
|
|
|
}
|
|
|
|
- }
|
|
|
|
-
|
1997-12-19 02:50:52 +00:00
|
|
|
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()
|
1998-06-26 18:39:21 +00:00
|
|
|
@@ -285,11 +282,6 @@
|
1997-12-19 02:50:52 +00:00
|
|
|
baseheight_ = PAL_HEIGHT * 2;
|
|
|
|
basewidth_ = PAL_WIDTH * 2;
|
|
|
|
}
|
|
|
|
-
|
|
|
|
- if(coder_format_ == f_cif) {
|
|
|
|
- baseheight_ = CIF_HEIGHT * 2;
|
|
|
|
- basewidth_ = CIF_WIDTH * 2;
|
|
|
|
- }
|
|
|
|
setsize();
|
|
|
|
}
|
|
|
|
|
1998-06-26 18:39:21 +00:00
|
|
|
@@ -299,15 +291,6 @@
|
1997-12-19 02:50:52 +00:00
|
|
|
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);
|
1998-06-26 18:39:21 +00:00
|
|
|
@@ -319,19 +302,6 @@
|
1997-12-19 02:50:52 +00:00
|
|
|
|
|
|
|
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();
|
|
|
|
}
|
|
|
|
|
1998-06-26 18:39:21 +00:00
|
|
|
@@ -345,15 +315,15 @@
|
1997-12-19 02:50:52 +00:00
|
|
|
|
|
|
|
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();
|
1998-06-26 18:39:21 +00:00
|
|
|
@@ -362,7 +332,8 @@
|
1997-12-19 02:50:52 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
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;
|
1998-06-26 18:39:21 +00:00
|
|
|
@@ -377,7 +348,30 @@
|
1997-12-19 02:50:52 +00:00
|
|
|
ioctl(dev_, METEORSINPUT, &port_);
|
|
|
|
}
|
|
|
|
return (TCL_OK);
|
|
|
|
- } else if (strcmp(argv[1], "format") == 0 ||
|
|
|
|
+ }
|
1998-06-26 18:39:21 +00:00
|
|
|
+ if (strcmp(argv[1], "freeze") == 0) {
|
|
|
|
+ int cmd = METEOR_CAP_CONTINOUS ;
|
|
|
|
+ if ( atoi(argv[2]) != 0 )
|
|
|
|
+ cmd = METEOR_CAP_STOP_CONT;
|
|
|
|
+ ioctl(dev_, METEORCAPTUR, (char*)&cmd);
|
|
|
|
+ return (TCL_OK);
|
|
|
|
+ }
|
|
|
|
+ if (strcmp(argv[1], "chan") == 0) {
|
|
|
|
+ int p = port_;
|
|
|
|
+ int c = atoi(argv[2]);
|
|
|
|
+ if (c > 0 && c < 199)
|
|
|
|
+ p = METEOR_INPUT_DEV1 ;
|
|
|
|
+ else
|
|
|
|
+ p = METEOR_INPUT_DEV0 ;
|
|
|
|
+ if (p != port_) {
|
|
|
|
+ port_ = p;
|
|
|
|
+ ioctl(dev_, METEORSINPUT, &port_);
|
|
|
|
+ }
|
|
|
|
+ if (p == METEOR_INPUT_DEV1)
|
|
|
|
+ ioctl(tuner_, TVTUNER_SETCHNL, &c);
|
|
|
|
+ return (TCL_OK);
|
|
|
|
+ }
|
1997-12-19 02:50:52 +00:00
|
|
|
+ if (strcmp(argv[1], "format") == 0 ||
|
|
|
|
strcmp(argv[1], "type") == 0) {
|
|
|
|
if (strcmp(argv[2], "auto") == 0)
|
|
|
|
video_format_ = METEOR_FMT_AUTOMODE;
|
1998-06-26 18:39:21 +00:00
|
|
|
@@ -390,14 +384,35 @@
|
1997-12-19 02:50:52 +00:00
|
|
|
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:
|
1998-06-26 18:39:21 +00:00
|
|
|
@@ -423,54 +438,316 @@
|
1997-12-19 02:50:52 +00:00
|
|
|
return (TCL_OK);
|
|
|
|
|
|
|
|
}
|
|
|
|
+ if (strcmp(argv[1], "brightness") == 0) {
|
|
|
|
+ u_char val;
|
|
|
|
+ ioctl(dev_, METEORGBRIG, &val);
|
1998-06-26 18:39:21 +00:00
|
|
|
+ tcl.resultf("%d", (unsigned int)val);
|
1997-12-19 02:50:52 +00:00
|
|
|
+ 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;
|
|
|
|
+ }
|
|
|
|
}
|