[PATCH] VC0323 YVYU and rotation quirks
"Claudio Matsuoka" <[email protected]>
| Newsgroups | gmane.linux.drivers.spca50x.devel |
|---|---|
| Message-ID | <[email protected]> |
Hi, Please ignore my previous patch for this extra-quirky camera. The attached patches make it work without breaking regular VC0323 cameras with JPGV output by adding two module parameters, one to force YVYU decoding for VC0323 (much like the VC0321, but it identifies itself as 0ac8:0323 and uses a different image offset) and other to decode to YUV, RGB15, RGB24 and RGB32 while rotating the image 180 degrees (since the sensor seems to be mounted upside-down in the camera). For the record, this is a no-brand, very cheap-looking black/silver plastic camera with four white leds and a foldable claw-like tripod. One quirk still remains: it produces RGB when it's supposed to produce BGR and vice versa, so force_rgb=1 is needed by spcaview but not gqcam. I'm not sure if this is a problem with my camera or all other cameras using yvyu_translate() are affected, so I didn't try to fix it. Best regards, Claudio ------------------------------------------------------------------------- This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2008. http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/ _______________________________________________ Spca50x-devs mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/spca50x-devs
gspcav1-20071224_vc0323-yuv.patch
(text/x-diff, 2.8 KB)
diff -rud gspcav1-20071224-orig/decoder/gspcadecoder.c gspcav1-20071224/decoder/gspcadecoder.c
--- gspcav1-20071224-orig/decoder/gspcadecoder.c 2007-12-24 11:35:27.000000000 -0200
+++ gspcav1-20071224/decoder/gspcadecoder.c 2008-02-03 21:03:15.000000000 -0200
@@ -2692,6 +2692,10 @@
memcpy(myframe->tmpbuffer, myframe->data, myframe->scanlength);
done= yvyu_translate(myframe,bgr);
break;
+ case YUY3:
+ memcpy(myframe->tmpbuffer, myframe->data + 0x20, myframe->scanlength);
+ done= yvyu_translate(myframe, bgr);
+ break;
case PGBRG:
done = pixart_decompress(myframe);
if (done < 0)
diff -rud gspcav1-20071224-orig/gspca.h gspcav1-20071224/gspca.h
--- gspcav1-20071224-orig/gspca.h 2007-12-24 14:56:47.000000000 -0200
+++ gspcav1-20071224/gspca.h 2008-02-03 21:33:45.000000000 -0200
@@ -177,6 +177,7 @@
S561, // Sunplus Compressed stream
PGBRG, // Pixart RGGB bayer
YUY2, // YUYV packed
+ YUY3, // Vimicro VC0323 YUYV packed
PJPG, // Pixart jpeg used with PAC7311
JPGV, // Vimicro VC0323
};
@@ -258,6 +259,7 @@
int GRed;
int GBlue;
int GGreen;
+ int rotate;
};
#define MAXCOMP 4
struct dec_hufftbl;
diff -rud gspcav1-20071224-orig/gspca_core.c gspcav1-20071224/gspca_core.c
--- gspcav1-20071224-orig/gspca_core.c 2007-12-24 14:56:47.000000000 -0200
+++ gspcav1-20071224/gspca_core.c 2008-02-03 21:05:06.000000000 -0200
@@ -82,6 +82,7 @@
/* Force image to be read in RGB instead of BGR. This option allow
* programs that expect RGB data (e.g. gqcam) to work with this driver. */
static int force_rgb = 0;
+static int force_yuv = 0;
static int gamma = 3;
static int OffRed = 0;
static int OffBlue = 0;
@@ -108,6 +109,7 @@
module_param(autoexpo, int, 0644);
module_param(debug, int, 0644);
module_param(force_rgb, int, 0644);
+module_param(force_yuv, int, 0644);
module_param(gamma, int, 0644);
module_param(OffRed, int, 0644);
module_param(OffBlue, int, 0644);
@@ -133,6 +135,7 @@
MODULE_PARM_DESC(debug,
"Debug level: 0=none, 1=init/detection, 2=warning, 3=config/control, 4=function call, 5=max");
MODULE_PARM_DESC(force_rgb, "Read RGB instead of BGR");
+MODULE_PARM_DESC(force_yuv, "Force YUV decoding in VC0323");
MODULE_PARM_DESC(gamma, "gamma setting range 0 to 7 3-> gamma=1");
MODULE_PARM_DESC(OffRed, "OffRed setting range -128 to 128");
MODULE_PARM_DESC(OffBlue, "OffBlue setting range -128 to 128");
@@ -190,6 +193,7 @@
{S561, "S561"},
{PGBRG,"GBRG"},
{YUY2, "YUYV"},
+ {YUY3, "YUYV"},
{PJPG, "JPEG"},
{-1, NULL}
};
@@ -2917,7 +2921,7 @@
break;
case BRIDGE_VC0323:
spca50x->epadr = 2;
- spca50x->cameratype = JPGV;
+ spca50x->cameratype = force_yuv ? YUY3 : JPGV;
info("USB GSPCA camera found.(VC0323) ");
memcpy(&spca50x->funct, &fvc0321,
sizeof (struct cam_operation));
gspcav1-20071224_yvyu-rotate.patch
(text/x-diff, 5.6 KB)
diff -rud gspcav1-20071224-orig/decoder/gspcadecoder.c gspcav1-20071224/decoder/gspcadecoder.c
--- gspcav1-20071224-orig/decoder/gspcadecoder.c 2008-02-03 23:19:23.000000000 -0200
+++ gspcav1-20071224/decoder/gspcadecoder.c 2008-02-03 23:04:13.000000000 -0200
@@ -2508,6 +2508,7 @@
static int bgr = 0;
+static int rot = 0;
@@ -2557,6 +2558,7 @@
}
bgr = gCorrect->force_rgb;
+ rot = gCorrect->rotate;
gCorrect->change = 0x00;
}
if (gCorrect->change == 0x02) {
@@ -4239,6 +4241,7 @@
char u, v;
char r, g, b;
int framesize, frameUsize;
+ int step = 1;
framesize = softwidth * softheight;
frameUsize = framesize >> 2;
@@ -4259,12 +4262,14 @@
g_offset = 1;
b_offset = 0;
}
+
/* initialize input pointer */
inl = 0;
inl1= width << 1;
pic1= pic+softwidth;
nextinline = width << 1;
nextoutline = softwidth;
+
/* Decode to the correct format. */
switch (format) {
case VIDEO_PALETTE_RGB565:
@@ -4273,6 +4278,11 @@
/* initialize */
pix = (__u16 *) pic;
+ if (rot) {
+ step = -1;
+ pix += softwidth * softheight - 1;
+ }
+
for (my = 0; my < height; my ++) {
for (mx = 0; mx < width; mx += 2) {
/* test if we need to decode */
@@ -4292,17 +4302,19 @@
g = green[CLIP((y - rg))];
b = blue[CLIP((y + u1))];
if (force_rgb)
- *pix++ = PACKRGB16(r, g, b);
+ *pix = PACKRGB16(r, g, b);
else
- *pix++ = PACKRGB16(b, g, r);
+ *pix = PACKRGB16(b, g, r);
+ pix += step;
y = buf[inl+mx*2+2];
r = red[CLIP((y + v1))];
g = green[CLIP((y - rg))];
b = blue[CLIP((y + u1))];
if (force_rgb)
- *pix++ = PACKRGB16(r, g, b);
+ *pix = PACKRGB16(r, g, b);
else
- *pix++ = PACKRGB16(b, g, r);
+ *pix = PACKRGB16(b, g, r);
+ pix += step;
}
} // end mx loop
@@ -4316,6 +4328,12 @@
case VIDEO_PALETTE_RGB24:
{
bpp = (format == VIDEO_PALETTE_RGB32) ? 4 : 3;
+
+ if (rot) {
+ step = -1;
+ pic += (softwidth * softheight - 1) * bpp;
+ }
+
/* initialize */
nextoutline = bpp * softwidth;
for (my = 0; my < height; my ++ ) {
@@ -4337,12 +4355,12 @@
pic[r_offset] = red[CLIP((y + v1))];
pic[g_offset] = green[CLIP((y - rg))];
pic[b_offset] = blue[CLIP((y + u1))];
- pic+=bpp;
+ pic+=bpp * step;
y = buf[inl+mx*2+2];
pic[r_offset] = red[CLIP((y + v1))];
pic[g_offset] = green[CLIP((y - rg))];
pic[b_offset] = blue[CLIP((y + u1))];
- pic+=bpp;
+ pic+=bpp * step;
} // end test decode
} // end mx loop
inl += nextinline;
@@ -4358,6 +4376,14 @@
break;
case VIDEO_PALETTE_YUV420P:
{ /* Not yet implemented */
+ if (rot) {
+ step = -1;
+ pic += framesize - 1;
+ pic1 = pic - softwidth;
+ U += frameUsize - 1;
+ V += frameUsize - 1;
+ }
+
for (my = 0; my < height; my +=2) {
for (mx = 0; mx < width; mx += 2) {
/* test if we need to decode */
@@ -4365,21 +4391,29 @@
&& (my < height - cropy2)
&& (mx >= cropx1)
&& (mx < width - cropx2)) {
- *pic++ = buf[inl+mx*2+0];
- *U++=buf[inl+mx*2+1];
- *pic++ = buf[inl+mx*2+2];
- *V++=buf[inl+mx*2+3];
- *pic1++ = buf[inl1+mx*2+0];
- *pic1++ = buf[inl1+mx*2+2];
-
+ if (rot) {
+ *pic-- = buf[inl+mx*2+0];
+ *U--=buf[inl+mx*2+1];
+ *pic-- = buf[inl+mx*2+2];
+ *V--=buf[inl+mx*2+3];
+ *pic1-- = buf[inl1+mx*2+0];
+ *pic1-- = buf[inl1+mx*2+2];
+ } else {
+ *pic++ = buf[inl+mx*2+0];
+ *U++=buf[inl+mx*2+1];
+ *pic++ = buf[inl+mx*2+2];
+ *V++=buf[inl+mx*2+3];
+ *pic1++ = buf[inl1+mx*2+0];
+ *pic1++ = buf[inl1+mx*2+2];
+ }
} // end test decode
} // end mx loop
inl += (nextinline << 1);
inl1 += (nextinline << 1);
if (my >= cropy1) {
/* are we in a decode surface move the output pointer */
- pic += (nextoutline);
- pic1 += (nextoutline);
+ pic += (nextoutline) * step;
+ pic1 += (nextoutline) * step;
}
} // end my loop
diff -rud gspcav1-20071224-orig/gspca_core.c gspcav1-20071224/gspca_core.c
--- gspcav1-20071224-orig/gspca_core.c 2008-02-03 23:19:23.000000000 -0200
+++ gspcav1-20071224/gspca_core.c 2008-02-03 23:22:37.000000000 -0200
@@ -83,6 +83,7 @@
* programs that expect RGB data (e.g. gqcam) to work with this driver. */
static int force_rgb = 0;
static int force_yuv = 0;
+static int rotate = 0;
static int gamma = 3;
static int OffRed = 0;
static int OffBlue = 0;
@@ -110,6 +111,7 @@
module_param(debug, int, 0644);
module_param(force_rgb, int, 0644);
module_param(force_yuv, int, 0644);
+module_param(rotate, int, 0644);
module_param(gamma, int, 0644);
module_param(OffRed, int, 0644);
module_param(OffBlue, int, 0644);
@@ -136,6 +138,7 @@
"Debug level: 0=none, 1=init/detection, 2=warning, 3=config/control, 4=function call, 5=max");
MODULE_PARM_DESC(force_rgb, "Read RGB instead of BGR");
MODULE_PARM_DESC(force_yuv, "Force YUV decoding in VC0323");
+MODULE_PARM_DESC(rotate, "Rotate output 180 degrees in YVYU decoding");
MODULE_PARM_DESC(gamma, "gamma setting range 0 to 7 3-> gamma=1");
MODULE_PARM_DESC(OffRed, "OffRed setting range -128 to 128");
MODULE_PARM_DESC(OffBlue, "OffBlue setting range -128 to 128");
@@ -1822,6 +1825,7 @@
memset(&spca50x->pictsetting, 0, sizeof (struct pictparam));
spca50x->pictsetting.change = 0x01;
spca50x->pictsetting.force_rgb = force_rgb;
+ spca50x->pictsetting.rotate = rotate;
spca50x->pictsetting.gamma = gamma;
spca50x->pictsetting.OffRed = OffRed;
spca50x->pictsetting.OffBlue = OffBlue;