ChangeSet 1.842.46.16, 2002/11/27 09:54:32-08:00, jtyner@cs.ucr.edu

[PATCH] [patch] speed/clean up vicam_decode_color

This patch cleans up the vicam_decode_color function by removing
unused/useless variables and combining the two "x" loops inside the
y loop into one. It also reduces the number of times that the "x"
loop occurs from 512 to 320 which should provide a decent speed
increase. It also fixes a bug in the y loop that wrote beyond its bound.


diff -Nru a/drivers/usb/media/vicam.c b/drivers/usb/media/vicam.c
--- a/drivers/usb/media/vicam.c	Wed Nov 27 12:49:22 2002
+++ b/drivers/usb/media/vicam.c	Wed Nov 27 12:49:22 2002
@@ -51,19 +51,25 @@
 #define DBG(fmn,args...) do {} while(0)
 #endif
 
-/* Version Information */
-#define DRIVER_VERSION "v1.0"
-#define DRIVER_AUTHOR "Joe Burks, jburks@wavicle.org"
-#define DRIVER_DESC "ViCam WebCam Driver"
+#define DRIVER_AUTHOR           "Joe Burks, jburks@wavicle.org"
+#define DRIVER_DESC             "ViCam WebCam Driver"
 
 /* Define these values to match your device */
 #define USB_VICAM_VENDOR_ID	0x04c1
 #define USB_VICAM_PRODUCT_ID	0x009d
 
-#define VICAM_BYTES_PER_PIXEL 3
-#define VICAM_MAX_READ_SIZE (512*242+128)
-#define VICAM_MAX_FRAME_SIZE (VICAM_BYTES_PER_PIXEL*320*240)
-#define VICAM_FRAMES 2
+#define VICAM_BYTES_PER_PIXEL   3
+#define VICAM_MAX_READ_SIZE     (512*242+128)
+#define VICAM_MAX_FRAME_SIZE    (VICAM_BYTES_PER_PIXEL*320*240)
+#define VICAM_FRAMES            2
+
+#define VICAM_HEADER_SIZE       64
+
+#define clamp( x, l, h )        max_t( __typeof__( x ),         \
+                                       ( l ),                   \
+                                       min_t( __typeof__( x ),  \
+                                              ( h ),            \
+                                              ( x ) ) )
 
 /* Not sure what all the bytes in these char
  * arrays do, but they're necessary to make
@@ -425,7 +431,7 @@
 static int vicam_probe( struct usb_interface *intf, const struct usb_device_id *id);
 static void vicam_disconnect(struct usb_interface *intf);
 static void read_frame(struct vicam_camera *cam, int framenum);
-static void vicam_decode_color( char *data, char *rgb);
+static void vicam_decode_color(const u8 *, u8 *);
 
 static int __send_control_msg(struct vicam_camera *cam,
 			      u8 request,
@@ -840,106 +846,75 @@
 	return 0;
 }
 
-inline int pin(int x)
+static void vicam_decode_color(const u8 *data, u8 *rgb)
 {
-	return((x > 255) ? 255 : ((x < 0) ? 0 : x));
-}
+	/* vicam_decode_color - Convert from Vicam Y-Cr-Cb to RGB
+	 * Copyright (C) 2002 Monroe Williams (monroe@pobox.com)
+	 */
 
-inline void writepixel(char *rgb, int Y, int Cr, int Cb)
-{
-	Y = 1160 * (Y - 16);
-	
-	rgb[2] = pin( ( ( Y + ( 1594 * Cr ) ) + 500 ) / 1300 );
-	rgb[1] = pin( ( ( Y - (  392 * Cb ) - ( 813 * Cr ) ) + 500 ) / 1000 );
-	rgb[0] = pin( ( ( Y + ( 2017 * Cb ) ) + 500 ) / 900 );
-}
-
-#define DATA_HEADER_SIZE 64
-
-// --------------------------------------------------------------------------------
-//	vicam_decode_color - Convert from Vicam Y-Cr-Cb to RGB
-//
-//   Copyright (C) 2002 Monroe Williams (monroe@pobox.com)
-// --------------------------------------------------------------------------------
-
-static void vicam_decode_color( char *data, char *rgb)
-{
-	int x,y;
-	int Cr, Cb;
-	int sign;
-	int prevX, nextX, prevY, nextY;
-	int skip;
-	unsigned char *src;
-	unsigned char *dst;
+	int i, prevY, nextY;
 
 	prevY = 512;
 	nextY = 512;
 
-	src = data + DATA_HEADER_SIZE;
-	dst = rgb;
-
-	for(y = 1; y < 241; y += 2)
-	{
-		// even line
-		sign = 1;
-		prevX = 1;
-		nextX = 1;
-
-		skip = 0;
-
-		dst = rgb + (y-1)*320*3;
-		
-		for(x = 0; x < 512; x++)
-		{
-			if(x == 512-1)
-				nextX = -1;
+	data += VICAM_HEADER_SIZE;
 
-			Cr = sign * ((src[prevX] - src[0]) + (src[nextX] - src[0])) >> 1;
-			Cb = sign * ((src[prevY] - src[prevX + prevY]) + (src[prevY] - src[nextX + prevY]) + (src[nextY] - src[prevX + nextY]) + (src[nextY] - src[nextX + nextY])) >> 2;
+	for( i = 0; i < 240; i++, data += 512 ) {
+		const int y = ( i * 242 ) / 240;
 
-			writepixel(
-					dst + ((x*5)>>3)*3,
-					src[0] + (sign * (Cr >> 1)),
-					Cr,
-					Cb);
-
-			src++;
-			sign *= -1;
-			prevX = -1;
-		}
+		int j, prevX, nextX;
+		int Y, Cr, Cb;
 
-		prevY = -512;
-
-		if(y == (242 - 2))
+		if ( y == 242 - 1 ) {
 			nextY = -512;
+		}
 
-		// odd line
-		sign = 1;
 		prevX = 1;
 		nextX = 1;
 
-		skip = 0;
+		for ( j = 0; j < 320; j++, rgb += 3 ) {
+			const int x = ( j * 512 ) / 320;
+			const u8 * const src = &data[x];
 
-		dst = rgb + (y)*320*3;
-		
-		for(x = 0; x < 512; x++)
-		{
-			if(x == 512-1)
+			if ( x == 512 - 1 ) {
 				nextX = -1;
-			
-			Cr = sign * ((src[prevX + prevY] - src[prevY]) + (src[nextX + prevY] - src[prevY]) + (src[prevX + nextY] - src[nextY]) + (src[nextX + nextY] - src[nextY])) >> 2;
-			Cb = sign * ((src[0] - src[prevX]) + (src[0] - src[nextX])) >> 1;
+			}
 
-			writepixel(
-					dst + ((x * 5)>>3)*3,
-					src[0] - (sign * (Cb >> 1)),
-					Cr,
-					Cb);
+			Cr = ( src[prevX] - src[0] ) +
+				( src[nextX] - src[0] );
+			Cr /= 2;
+
+			Cb = ( src[prevY] - src[prevX + prevY] ) +
+				( src[prevY] - src[nextX + prevY] ) +
+				( src[nextY] - src[prevX + nextY] ) +
+				( src[nextY] - src[nextX + nextY] );
+			Cb /= 4;
+
+			Y = 1160 * ( src[0] + ( Cr / 2 ) - 16 );
+
+			if ( i & 1 ) {
+				int Ct = Cr;
+				Cr = Cb;
+				Cb = Ct;
+			}
+
+			if ( ( x ^ i ) & 1 ) {
+				Cr = -Cr;
+				Cb = -Cb;
+			}
+
+			rgb[0] = clamp( ( ( Y + ( 2017 * Cb ) ) +
+					500 ) / 900, 0, 255 );
+			rgb[1] = clamp( ( ( Y - ( 392 * Cb ) -
+					  ( 813 * Cr ) ) +
+					  500 ) / 1000, 0, 255 );
+			rgb[2] = clamp( ( ( Y + ( 1594 * Cr ) ) +
+					500 ) / 1300, 0, 255 );
 
-			src++;
-			sign *= -1;
 			prevX = -1;
 		}
+
+		prevY = -512;
 	}
 }
 
@@ -1030,7 +1005,6 @@
 		vicam_decode_color(cam->raw_image,
 				   cam->framebuf +
 				   0 * VICAM_MAX_FRAME_SIZE);
-
 	}
 
 	count = min_t(size_t, count, VICAM_MAX_FRAME_SIZE - *ppos);