diff -r 033b5968aa1a linux/drivers/media/video/uvc/uvc_driver.c --- a/linux/drivers/media/video/uvc/uvc_driver.c Fri Dec 11 01:19:31 2009 +0100 +++ b/linux/drivers/media/video/uvc/uvc_driver.c Fri Dec 11 23:03:03 2009 +0800 @@ -48,6 +48,7 @@ static unsigned int uvc_quirks_param = -1; unsigned int uvc_trace_param; unsigned int uvc_timeout_param = UVC_CTRL_STREAMING_TIMEOUT; +unsigned int to320; /* ------------------------------------------------------------------------ * Video formats @@ -1933,7 +1934,9 @@ MODULE_PARM_DESC(trace, "Trace level bitmask"); module_param_named(timeout, uvc_timeout_param, uint, S_IRUGO|S_IWUSR); MODULE_PARM_DESC(timeout, "Streaming control requests timeout"); - +module_param_named(to320, to320, uint, S_IRUGO|S_IWUSR); +MODULE_PARM_DESC(to320, "Convert 640x480 to 320x240, only used for special hardware"); + /* ------------------------------------------------------------------------ * Driver initialization and cleanup */ diff -r 033b5968aa1a linux/drivers/media/video/uvc/uvc_video.c --- a/linux/drivers/media/video/uvc/uvc_video.c Fri Dec 11 01:19:31 2009 +0100 +++ b/linux/drivers/media/video/uvc/uvc_video.c Fri Dec 11 23:03:03 2009 +0800 @@ -25,6 +25,9 @@ #include "uvcvideo.h" +static int kindex; +static __u8 t320buf[640*480*2]; +static int t320count; /* ------------------------------------------------------------------------ * UVC Controls */ @@ -431,6 +434,8 @@ /* TODO: Handle PTS and SCR. */ buf->state = UVC_BUF_STATE_ACTIVE; + kindex=0; + t320count = 0; } /* Mark the buffer as done if we're at the beginning of a new frame. @@ -466,6 +471,7 @@ struct uvc_video_queue *queue = &stream->queue; unsigned int maxlen, nbytes; void *mem; + int i, k, bpp; if (len <= 0) return; @@ -473,8 +479,30 @@ /* Copy the video data to the buffer. */ maxlen = buf->buf.length - buf->buf.bytesused; mem = queue->mem + buf->buf.m.offset + buf->buf.bytesused; - nbytes = min((unsigned int)len, maxlen); - memcpy(mem, data, nbytes); + if(to320 && stream->cur_frame->wWidth == 320){ + /*store original 640x480 data into t320buf*/ + if((i=(sizeof(t320buf) - t320count))>0) { + memcpy(t320buf+t320count, data, min(len, i)); + t320count+=min(len,i); + } + bpp = stream->format->bpp / 8; /*bytes per pixel*/ + i=0,k=0; + while(i*bppbuf.bytesused += nbytes; /* Complete the current frame if the buffer size was exceeded. */ @@ -483,6 +511,45 @@ buf->state = UVC_BUF_STATE_DONE; } } +/*Convert the frame in 640x480 stored in c320buf to frame in 320x240 +My Motororal E6 camera send its video stream in YUYV, which one macro +pixel is two pixel in frame, so this function convert 8 pixel(4 macro +pixel) into 2 pixel(1 macro pixel). In this 8 pixel, 4 are from the +even line, 4 are from odd line, these 8 pixel is represented by 4 ma- +cro pixel. + */ +static void to320_compress_frame(int bpp, __u8 * dst, int dstlen, __u8 *src, int srclen) +{ + int col, row; + __u32 tmp; + __u8 *even, *odd, *p; + + for(row=0;row<240;row++) + { + for(col=0;col<320 && (row*320+col)*bpp+4<=dstlen;col+=2) + { + even = &src[(row*640*2+col*2)*bpp]; + odd = &src[(row*640*2+640+col*2)*bpp]; + p = &dst[(row*320+col)*bpp]; + + //compute y1 + tmp = (*(even+0) + *(even+2) + *(odd+0) + *(odd+2))/4; + *p = (__u8)tmp; + p++; + //compute Cb + tmp = (*(even+1) + *(even+5) + *(odd+1) + *(odd+5))/4; + *p = (__u8)tmp; + p++; + //compute y2 + tmp = (*(even+4) + *(even+6) + *(odd+4) + *(odd+6))/4; + *p = (__u8)tmp; + p++; + //compute Cr + tmp = (*(even+3) + *(even+7) + *(odd+3) + *(odd+7))/4; + *p = (__u8)tmp; + } + } +} static void uvc_video_decode_end(struct uvc_streaming *stream, struct uvc_buffer *buf, const __u8 *data, int len) @@ -496,6 +563,12 @@ if (stream->dev->quirks & UVC_QUIRK_STREAM_NO_FID) stream->last_fid ^= UVC_STREAM_FID; } + /*It's a good time to convert whole buf*/ + if(to320 && stream->cur_frame->wWidth == 320 && buf->state == UVC_BUF_STATE_DONE){ + to320_compress_frame(stream->format->bpp / 8, + stream->queue.mem + buf->buf.m.offset, buf->buf.length, + t320buf, sizeof(t320buf)); + } } /* Video payload encoding is handled by uvc_video_encode_header() and diff -r 033b5968aa1a linux/drivers/media/video/uvc/uvcvideo.h --- a/linux/drivers/media/video/uvc/uvcvideo.h Fri Dec 11 01:19:31 2009 +0100 +++ b/linux/drivers/media/video/uvc/uvcvideo.h Fri Dec 11 23:03:03 2009 +0800 @@ -537,6 +537,7 @@ extern unsigned int uvc_no_drop_param; extern unsigned int uvc_trace_param; extern unsigned int uvc_timeout_param; +extern unsigned int to320; #define uvc_trace(flag, msg...) \ do { \