freddy - 2007-01-27

Logged In: YES
user_id=1703011
Originator: NO

This is caused by a change in the linux driver. The driver does not longer support the conversion to the RGB32 colorspace (it least not by default). The code for the conversion can be found in the cpia driver ...

In addition to this the code asks hardcoded for video2 ...

I changed the code to cope with this. Working at least with Fedora Core 5 x86_64

Here is a patch for the two issues mentioned above:
diff -u QtX3.orig/Qx3Model.cc QtX3/Qx3Model.cc
--- QtX3.orig/Qx3Model.cc 2002-10-31 03:33:51.000000000 +0100
+++ QtX3/Qx3Model.cc 2007-01-27 14:19:37.000000000 +0100
@@ -54,27 +54,151 @@
}

+
+#define LIMIT(x) ((((x)>0xffffff)?0xff0000:(((x)<=0xffff)?0:(x)&0xff0000))>>16)
+
+static int convert420(unsigned char *yuv, unsigned char *rgb, int out_fmt,
+ int linesize, int mmap_kludge)
+{
+ int y, u, v, r, g, b, y1;
+
+ /* Odd lines use the same u and v as the previous line.
+ * Because of compression, it is necessary to get this
+ * information from the decoded image. */
+ switch(out_fmt) {
+ case VIDEO_PALETTE_RGB555:
+ y = (*yuv++ - 16) * 76310;
+ y1 = (*yuv - 16) * 76310;
+ r = ((*(rgb+1-linesize)) & 0x7c) << 1;
+ g = ((*(rgb-linesize)) & 0xe0) >> 4 |
+ ((*(rgb+1-linesize)) & 0x03) << 6;
+ b = ((*(rgb-linesize)) & 0x1f) << 3;
+ u = (-53294 * r - 104635 * g + 157929 * b) / 5756495;
+ v = (157968 * r - 132278 * g - 25690 * b) / 5366159;
+ r = 104635 * v;
+ g = -25690 * u - 53294 * v;
+ b = 132278 * u;
+ *rgb++ = ((LIMIT(g+y) & 0xf8) << 2) | (LIMIT(b+y) >> 3);
+ *rgb++ = ((LIMIT(r+y) & 0xf8) >> 1) | (LIMIT(g+y) >> 6);
+ *rgb++ = ((LIMIT(g+y1) & 0xf8) << 2) | (LIMIT(b+y1) >> 3);
+ *rgb = ((LIMIT(r+y1) & 0xf8) >> 1) | (LIMIT(g+y1) >> 6);
+ return 4;
+ case VIDEO_PALETTE_RGB565:
+ y = (*yuv++ - 16) * 76310;
+ y1 = (*yuv - 16) * 76310;
+ r = (*(rgb+1-linesize)) & 0xf8;
+ g = ((*(rgb-linesize)) & 0xe0) >> 3 |
+ ((*(rgb+1-linesize)) & 0x07) << 5;
+ b = ((*(rgb-linesize)) & 0x1f) << 3;
+ u = (-53294 * r - 104635 * g + 157929 * b) / 5756495;
+ v = (157968 * r - 132278 * g - 25690 * b) / 5366159;
+ r = 104635 * v;
+ g = -25690 * u - 53294 * v;
+ b = 132278 * u;
+ *rgb++ = ((LIMIT(g+y) & 0xfc) << 3) | (LIMIT(b+y) >> 3);
+ *rgb++ = (LIMIT(r+y) & 0xf8) | (LIMIT(g+y) >> 5);
+ *rgb++ = ((LIMIT(g+y1) & 0xfc) << 3) | (LIMIT(b+y1) >> 3);
+ *rgb = (LIMIT(r+y1) & 0xf8) | (LIMIT(g+y1) >> 5);
+ return 4;
+ break;
+ case VIDEO_PALETTE_RGB24:
+ case VIDEO_PALETTE_RGB32:
+ y = (*yuv++ - 16) * 76310;
+ y1 = (*yuv - 16) * 76310;
+ if (mmap_kludge) {
+ r = *(rgb+2-linesize);
+ g = *(rgb+1-linesize);
+ b = *(rgb-linesize);
+ } else {
+ r = *(rgb-linesize);
+ g = *(rgb+1-linesize);
+ b = *(rgb+2-linesize);
+ }
+ u = (-53294 * r - 104635 * g + 157929 * b) / 5756495;
+ v = (157968 * r - 132278 * g - 25690 * b) / 5366159;
+ r = 104635 * v;
+ g = -25690 * u + -53294 * v;
+ b = 132278 * u;
+ if (mmap_kludge) {
+ *rgb++ = LIMIT(b+y);
+ *rgb++ = LIMIT(g+y);
+ *rgb++ = LIMIT(r+y);
+ if(out_fmt == VIDEO_PALETTE_RGB32)
+ rgb++;
+ *rgb++ = LIMIT(b+y1);
+ *rgb++ = LIMIT(g+y1);
+ *rgb = LIMIT(r+y1);
+ } else {
+ *rgb++ = LIMIT(r+y);
+ *rgb++ = LIMIT(g+y);
+ *rgb++ = LIMIT(b+y);
+ if(out_fmt == VIDEO_PALETTE_RGB32)
+ rgb++;
+ *rgb++ = LIMIT(r+y1);
+ *rgb++ = LIMIT(g+y1);
+ *rgb = LIMIT(b+y1);
+ }
+ if(out_fmt == VIDEO_PALETTE_RGB32)
+ return 8;
+ return 6;
+ case VIDEO_PALETTE_YUV422:
+ case VIDEO_PALETTE_YUYV:
+ y = *yuv++;
+ u = *(rgb+1-linesize);
+ y1 = *yuv;
+ v = *(rgb+3-linesize);
+ *rgb++ = y;
+ *rgb++ = u;
+ *rgb++ = y1;
+ *rgb = v;
+ return 4;
+ case VIDEO_PALETTE_UYVY:
+ u = *(rgb-linesize);
+ y = *yuv++;
+ v = *(rgb+2-linesize);
+ y1 = *yuv;
+ *rgb++ = u;
+ *rgb++ = y;
+ *rgb++ = v;
+ *rgb = y1;
+ return 4;
+ case VIDEO_PALETTE_GREY:
+ *rgb++ = *yuv++;
+ *rgb = *yuv;
+ return 2;
+ default:
+ return 0;
+ }
+}
+
+
const char* Qx3Model::getFrame(void) {
- static char buffer[352*288*4];
+ static unsigned char buffer_yuv[352*288*2];
+ static unsigned char buffer_rgb[352*288*4];

- int buflen = sizeof(buffer);
+ int buflen = sizeof(buffer_yuv);
int len = 0;

- while( (len = read (device, buffer, buflen)) <= 0 ) {
+ while( (len = read (device, buffer_yuv, buflen)) <= 0 ) {
if(errno!=0 && errno!=4) {
cerr << "Bad grab" << endl;
}
}

+ for(int i=0; i<buflen; i++) {
+ convert420(buffer_yuv + i, buffer_rgb + 2*i, VIDEO_PALETTE_RGB32, VIDEO_PALETTE_YUV422, 0);
+ }
+
char temp;
- for(int i = 0; i < buflen; i+=4) {
- temp = buffer[i+2];
- buffer[i+2] = buffer[i];
- buffer[i]=temp;
+ for(int i = 0; i < (int)sizeof(buffer_rgb); i+=4) {
+ temp = buffer_rgb[i+2];
+ buffer_rgb[i+2] = buffer_rgb[i];
+ buffer_rgb[i]=temp;
}
- return buffer;
+ return (const char *)buffer_rgb;
}

+
int Qx3Model::setupVideo(string devfile, string cpiafile) {
#ifdef DEBUG
cout << "Video device: " << devfile << endl;
@@ -97,9 +221,9 @@
ioctl (device, VIDIOCGWIN, &vid_win);
ioctl (device, VIDIOCGPICT, &vid_pic);

- vid_pic.palette = VIDEO_PALETTE_RGB32;
- vid_pic.depth = 32;
- if(ioctl (device, VIDIOCSPICT, &vid_pic)) {
+ vid_pic.palette = VIDEO_PALETTE_YUV422;
+ vid_pic.depth = 16;
+ if(ioctl(device, VIDIOCSPICT, &vid_pic)) {
cerr << "wrong palette/depth" << endl;
//close(device);
return -1;
@@ -118,7 +242,7 @@
}

bool Qx3Model::getLineBoolean( string token ) {
- std::ifstream from("/proc/cpia/video2");
+ std::ifstream from("/proc/cpia/video0");
char line[256];
bool found = false;
while( !from.eof()) {
@@ -143,7 +267,7 @@
}

void Qx3Model::setTopLight(bool state) {
- std::ofstream to("/proc/cpia/video2");
+ std::ofstream to("/proc/cpia/video0");
to << "toplight: " << (state ? "on":"off") << endl;
to.close();
}
@@ -153,7 +277,7 @@
}

void Qx3Model::setBottomLight(bool state) {
- std::ofstream to("/proc/cpia/video2");
+ std::ofstream to("/proc/cpia/video0");
to << "bottomlight: " << (state?"on":"off") << endl;
to.close();
}