📄 ov511 v1.28.c
字号:
for (l = 0; l < 8; l++) { for (m=0; m<8; m++) { int v = *(pIn+64); int u = *pIn++; *pOut = u; *(pOut+2) = v; *(pOut+iWidth) = u; *(pOut+iWidth+2) = v; pOut += 4; } pOut += (iWidth*4 - 32); }}static voidov511_parse_data_yuv420(unsigned char *pIn0, unsigned char *pOut0, int iOutY, int iOutUV, int iWidth, int iHeight){ int k, l, m; unsigned char *pIn; unsigned char *pOut, *pOut1; unsigned a = iWidth * iHeight; unsigned w = iWidth / 2; pIn = pIn0; pOut = pOut0 + iOutUV + a; for (k = 0; k < 8; k++) { pOut1 = pOut; for (l = 0; l < 8; l++) *pOut1++ = *pIn++; pOut += w; } pIn = pIn0 + 64; pOut = pOut0 + iOutUV + a + a/4; for (k = 0; k < 8; k++) { pOut1 = pOut; for (l = 0; l < 8; l++) *pOut1++ = *pIn++; pOut += w; } pIn = pIn0 + 128; pOut = pOut0 + iOutY; for (k = 0; k < 4; k++) { pOut1 = pOut; for (l = 0; l < 8; l++) { for (m = 0; m < 8; m++) *pOut1++ =*pIn++; pOut1 += iWidth - 8; } pOut += 8; }}static voidov511_parse_data_yuv422p(unsigned char *pIn0, unsigned char *pOut0, int iOutY, int iOutUV, int iWidth, int iHeight){ int k, l, m; unsigned char *pIn; unsigned char *pOut, *pOut1; unsigned a = iWidth * iHeight; unsigned w = iWidth / 2; pIn = pIn0; pOut = pOut0 + iOutUV + a; for (k = 0; k < 8; k++) { pOut1 = pOut; for (l = 0; l < 8; l++) { *pOut1 = *(pOut1 + w) = *pIn++; pOut1++; } pOut += iWidth; } pIn = pIn0 + 64; pOut = pOut0 + iOutUV + a + a/2; for (k = 0; k < 8; k++) { pOut1 = pOut; for (l = 0; l < 8; l++) { *pOut1 = *(pOut1 + w) = *pIn++; pOut1++; } pOut += iWidth; } pIn = pIn0 + 128; pOut = pOut0 + iOutY; for (k = 0; k < 4; k++) { pOut1 = pOut; for (l = 0; l < 8; l++) { for (m = 0; m < 8; m++) *pOut1++ =*pIn++; pOut1 += iWidth - 8; } pOut += 8; }}/* * For 640x480 RAW BW images, data shows up in 1200 256 byte segments. * The segments represent 4 squares of 8x8 pixels as follows: * * 0 1 ... 7 64 65 ... 71 ... 192 193 ... 199 * 8 9 ... 15 72 73 ... 79 200 201 ... 207 * ... ... ... * 56 57 ... 63 120 121 ... 127 248 249 ... 255 * */ static voidov511_parse_data_grey(unsigned char *pIn0, unsigned char *pOut0, int iOutY, int iWidth) { int k, l, m; unsigned char *pIn; unsigned char *pOut, *pOut1; pIn = pIn0; pOut = pOut0 + iOutY; for (k = 0; k < 4; k++) { pOut1 = pOut; for (l = 0; l < 8; l++) { for (m = 0; m < 8; m++) { *pOut1++ = *pIn++; } pOut1 += iWidth - 8; } pOut += 8; }}/* * fixFrameRGBoffset-- * My camera seems to return the red channel about 1 pixel * low, and the blue channel about 1 pixel high. After YUV->RGB * conversion, we can correct this easily. OSL 2/24/2000. */static void fixFrameRGBoffset(struct ov511_frame *frame){ int x, y; int rowBytes = frame->width*3, w = frame->width; unsigned char *rgb = frame->data; const int shift = 1; /* Distance to shift pixels by, vertically */ /* Don't bother with little images */ if (frame->width < 400) return; /* Shift red channel up */ for (y = shift; y < frame->height; y++) { int lp = (y-shift)*rowBytes; /* Previous line offset */ int lc = y*rowBytes; /* Current line offset */ for (x = 0; x < w; x++) rgb[lp+x*3+2] = rgb[lc+x*3+2]; /* Shift red up */ } /* Shift blue channel down */ for (y = frame->height-shift-1; y >= 0; y--) { int ln = (y + shift) * rowBytes; /* Next line offset */ int lc = y * rowBytes; /* Current line offset */ for (x = 0; x < w; x++) rgb[ln+x*3+0] = rgb[lc+x*3+0]; /* Shift blue down */ }}/********************************************************************** * * OV511 data transfer, IRQ handler * **********************************************************************/static int ov511_move_data(struct usb_ov511 *ov511, urb_t *urb){ unsigned char *cdata; int i, totlen = 0; int aPackNum[10]; struct ov511_frame *frame; unsigned char *pData; int iPix; PDEBUG (4, "Moving %d packets", urb->number_of_packets); for (i = 0; i < urb->number_of_packets; i++) { int n = urb->iso_frame_desc[i].actual_length; int st = urb->iso_frame_desc[i].status; urb->iso_frame_desc[i].actual_length = 0; urb->iso_frame_desc[i].status = 0; cdata = urb->transfer_buffer + urb->iso_frame_desc[i].offset; aPackNum[i] = n ? cdata[ov511->packet_size - 1] : -1; if (!n || ov511->curframe == -1) continue; if (st) PDEBUG(2, "data error: [%d] len=%d, status=%d", i, n, st); frame = &ov511->frame[ov511->curframe]; /* SOF/EOF packets have 1st to 8th bytes zeroed and the 9th * byte non-zero. The EOF packet has image width/height in the * 10th and 11th packets. The 9th bit is given as follows: * * bit 7: EOF * 6: compression enabled * 5: 422/420/400 modes * 4: 422/420/400 modes * 3: 1 * 2: snapshot bottom on * 1: snapshot frame * 0: even/odd field */ /* Check for SOF/EOF packet */ if ((cdata[0] | cdata[1] | cdata[2] | cdata[3] | cdata[4] | cdata[5] | cdata[6] | cdata[7]) || (~cdata[8] & 0x08)) goto check_middle; /* Frame end */ if (cdata[8] & 0x80) { struct timeval *ts; ts = (struct timeval *)(frame->data + MAX_FRAME_SIZE); do_gettimeofday (ts); PDEBUG(4, "Frame end, curframe = %d, packnum=%d, hw=%d, vw=%d", ov511->curframe, (int)(cdata[ov511->packet_size - 1]), (int)(cdata[9]), (int)(cdata[10])); if (frame->scanstate == STATE_LINES) { int iFrameNext; if (fix_rgb_offset) fixFrameRGBoffset(frame); frame->grabstate = FRAME_DONE; if (waitqueue_active(&frame->wq)) { frame->grabstate = FRAME_DONE; wake_up_interruptible(&frame->wq); } /* If next frame is ready or grabbing, * point to it */ iFrameNext = (ov511->curframe + 1) % OV511_NUMFRAMES; if (ov511->frame[iFrameNext].grabstate == FRAME_READY || ov511->frame[iFrameNext].grabstate == FRAME_GRABBING) { ov511->curframe = iFrameNext; ov511->frame[iFrameNext].scanstate = STATE_SCANNING; } else { if (frame->grabstate == FRAME_DONE) { PDEBUG(4, "Frame done! congratulations"); } else { PDEBUG(4, "Frame not ready? state = %d", ov511->frame[iFrameNext].grabstate); } ov511->curframe = -1; } } /* Image corruption caused by misplaced frame->segment = 0 * fixed by carlosf@conectiva.com.br */ } else { /* Frame start */ PDEBUG(4, "Frame start, framenum = %d", ov511->curframe);#if 0 /* Make sure no previous data carries over; necessary * for compression experimentation */ memset(frame->data, 0, MAX_DATA_SIZE);#endif output_offset = 0; /* Check to see if it's a snapshot frame */ /* FIXME?? Should the snapshot reset go here? Performance? */ if (cdata[8] & 0x02) { frame->snapshot = 1; PDEBUG(3, "snapshot detected"); } frame->scanstate = STATE_LINES; frame->segment = 0; }check_middle: /* Are we in a frame? */ if (frame->scanstate != STATE_LINES) continue; /* Deal with leftover from last segment, if any */ if (frame->segment) { pData = ov511->scratch; iPix = -ov511->scratchlen; memmove(pData + ov511->scratchlen, cdata, iPix+frame->segsize); } else { pData = &cdata[iPix = 9]; } /* Parse the segments */ while (iPix <= (ov511->packet_size - 1) - frame->segsize && frame->segment < frame->width * frame->height / 256) { int iSegY, iSegUV; int iY, jY, iUV, jUV; int iOutY, iOutYP, iOutUV, iOutUVP; unsigned char *pOut; iSegY = iSegUV = frame->segment; pOut = frame->data; frame->segment++; iPix += frame->segsize; /* Handle subwindow */ if (frame->sub_flag) { int iSeg1; iSeg1 = iSegY / (ov511->subw / 32); iSeg1 *= frame->width / 32; iSegY = iSeg1 + (iSegY % (ov511->subw / 32)); if (iSegY >= frame->width * ov511->subh / 256) break; iSeg1 = iSegUV / (ov511->subw / 16); iSeg1 *= frame->width / 16; iSegUV = iSeg1 + (iSegUV % (ov511->subw / 16)); pOut += (ov511->subx + ov511->suby * frame->width) * (frame->depth >> 3); } /* * i counts segment lines * j counts segment columns * iOut is the offset (in bytes) of the upper left corner */ iY = iSegY / (frame->width / WDIV); jY = iSegY - iY * (frame->width / WDIV); iOutYP = iY*HDIV*frame->width + jY*WDIV; iOutY = iOutYP * (frame->depth >> 3); iUV = iSegUV / (frame->width / WDIV * 2); jUV = iSegUV - iUV * (frame->width / WDIV * 2); iOutUVP = iUV*HDIV*2*frame->width + jUV*WDIV/2; iOutUV = iOutUVP * (frame->depth >> 3); switch (frame->format) { case VIDEO_PALETTE_GREY: ov511_parse_data_grey (pData, pOut, iOutY, frame->width); break; case VIDEO_PALETTE_RGB24: if (dumppix) ov511_dumppix(pData, pOut, iOutY, iOutUV, iY & 1, frame->width); else if (sensor_gbr) ov511_parse_gbr422_to_rgb24(pData, pOut, iOutY, iOutUV, iY & 1, frame->width); else ov511_parse_yuv420_to_rgb(pData, pOut, iOutY, iOutUV, iY & 1, frame->width, 24); break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -