📄 ibmcam.c
字号:
sprintf(tmp, "%8lx", ibmcam->scratch_ovf_count); usb_ibmcam_overlaystring(ibmcam, frame, x, y, tmp); y += y_diff; sprintf(tmp, "%8lx", ibmcam->iso_skip_count); usb_ibmcam_overlaystring(ibmcam, frame, x, y, tmp); y += y_diff; sprintf(tmp, "%8lx", ibmcam->iso_err_count); usb_ibmcam_overlaystring(ibmcam, frame, x, y, tmp); y += y_diff; sprintf(tmp, "%8x", ibmcam->vpic.colour); usb_ibmcam_overlaystring(ibmcam, frame, x, y, tmp); y += y_diff; sprintf(tmp, "%8x", ibmcam->vpic.hue); usb_ibmcam_overlaystring(ibmcam, frame, x, y, tmp); y += y_diff; sprintf(tmp, "%8x", ibmcam->vpic.brightness >> 8); usb_ibmcam_overlaystring(ibmcam, frame, x, y, tmp); y += y_diff; sprintf(tmp, "%8x", ibmcam->vpic.contrast >> 12); usb_ibmcam_overlaystring(ibmcam, frame, x, y, tmp); y += y_diff; sprintf(tmp, "%8d", ibmcam->vpic.whiteness >> 8); usb_ibmcam_overlaystring(ibmcam, frame, x, y, tmp); y += y_diff;}/* * usb_ibmcam_testpattern() * * Procedure forms a test pattern (yellow grid on blue background). * * Parameters: * fullframe: if TRUE then entire frame is filled, otherwise the procedure * continues from the current scanline. * pmode 0: fill the frame with solid blue color (like on VCR or TV) * 1: Draw a colored grid * * History: * 1/2/00 Created. */void usb_ibmcam_testpattern(struct usb_ibmcam *ibmcam, int fullframe, int pmode){ static const char proc[] = "usb_ibmcam_testpattern"; struct ibmcam_frame *frame; unsigned char *f; int num_cell = 0; int scan_length = 0; static int num_pass = 0; if (ibmcam == NULL) { printk(KERN_ERR "%s: ibmcam == NULL\n", proc); return; } if ((ibmcam->curframe < 0) || (ibmcam->curframe >= IBMCAM_NUMFRAMES)) { printk(KERN_ERR "%s: ibmcam->curframe=%d.\n", proc, ibmcam->curframe); return; } /* Grab the current frame */ frame = &ibmcam->frame[ibmcam->curframe]; /* Optionally start at the beginning */ if (fullframe) { frame->curline = 0; frame->scanlength = 0; } /* Form every scan line */ for (; frame->curline < imgheight; frame->curline++) { int i; f = frame->data + (imgwidth * 3 * frame->curline); for (i=0; i < imgwidth; i++) { unsigned char cb=0x80; unsigned char cg = 0; unsigned char cr = 0; if (pmode == 1) { if (frame->curline % 32 == 0) cb = 0, cg = cr = 0xFF; else if (i % 32 == 0) { if (frame->curline % 32 == 1) num_cell++; cb = 0, cg = cr = 0xFF; } else { cb = ((num_cell*7) + num_pass) & 0xFF; cg = ((num_cell*5) + num_pass*2) & 0xFF; cr = ((num_cell*3) + num_pass*3) & 0xFF; } } else { /* Just the blue screen */ } *f++ = cb; *f++ = cg; *f++ = cr; scan_length += 3; } } frame->grabstate = FRAME_DONE; frame->scanlength += scan_length; ++num_pass; /* We do this unconditionally, regardless of FLAGS_OVERLAY_STATS */ usb_ibmcam_overlaystats(ibmcam, frame);}static unsigned char *ibmcam_model1_find_header(unsigned char hdr_sig, unsigned char *data, int len){ while (len >= 4) { if ((data[0] == 0x00) && (data[1] == 0xFF) && (data[2] == 0x00)) {#if 0 /* This code helps to detect new frame markers */ printk(KERN_DEBUG "Header sig: 00 FF 00 %02X\n", data[3]);#endif if (data[3] == hdr_sig) { if (debug > 2) printk(KERN_DEBUG "Header found.\n"); return data+4; } } ++data; --len; } return NULL;}static unsigned char *ibmcam_model2_find_header(unsigned char hdr_sig, unsigned char *data, int len){ int marker_len = 0; switch (videosize) { case VIDEOSIZE_176x144: marker_len = 10; break; default: marker_len = 2; break; } while (len >= marker_len) { if ((data[0] == 0x00) && (data[1] == 0xFF)) {#if 0 /* This code helps to detect new frame markers */ static int pass = 0; if (pass++ == 0) ibmcam_hexdump(data, (len > 16) ? 16 : len);#endif if (debug > 2) printk(KERN_DEBUG "Header found.\n"); return data+marker_len; } ++data; --len; } return NULL;}/* How much data is left in the scratch buf? */#define scratch_left(x) (ibmcam->scratchlen - (int)((char *)x - (char *)ibmcam->scratch))/* Grab the remaining */static void usb_ibmcam_align_scratch(struct usb_ibmcam *ibmcam, unsigned char *data){ unsigned long left; left = scratch_left(data); memmove(ibmcam->scratch, data, left); ibmcam->scratchlen = left;}/* * usb_ibmcam_find_header() * * Locate one of supported header markers in the scratch buffer. * Once found, remove all preceding bytes AND the marker (4 bytes) * from the scratch buffer. Whatever follows must be video lines. * * History: * 1/21/00 Created. */static scan_state_t usb_ibmcam_find_header(struct usb_ibmcam *ibmcam){ struct ibmcam_frame *frame; unsigned char *data, *tmp; data = ibmcam->scratch; frame = &ibmcam->frame[ibmcam->curframe]; if (ibmcam->camera_model == IBMCAM_MODEL_1) tmp = ibmcam_model1_find_header(frame->hdr_sig, data, scratch_left(data)); else if (ibmcam->camera_model == IBMCAM_MODEL_2) tmp = ibmcam_model2_find_header(frame->hdr_sig, data, scratch_left(data)); else tmp = NULL; if (tmp == NULL) { /* No header - entire scratch buffer is useless! */ if (debug > 2) printk(KERN_DEBUG "Skipping frame, no header\n"); ibmcam->scratchlen = 0; return scan_EndParse; } /* Header found */ data = tmp; ibmcam->has_hdr = 1; ibmcam->header_count++; frame->scanstate = STATE_LINES; frame->curline = 0; if (flags & FLAGS_FORCE_TESTPATTERN) { usb_ibmcam_testpattern(ibmcam, 1, 1); return scan_NextFrame; } usb_ibmcam_align_scratch(ibmcam, data); return scan_Continue;}/* * usb_ibmcam_parse_lines() * * Parse one line (TODO: more than one!) from the scratch buffer, put * decoded RGB value into the current frame buffer and add the written * number of bytes (RGB) to the *pcopylen. * * History: * 1/21/00 Created. */static scan_state_t usb_ibmcam_parse_lines(struct usb_ibmcam *ibmcam, long *pcopylen){ struct ibmcam_frame *frame; unsigned char *data, *f, *chromaLine; unsigned int len; const int v4l_linesize = imgwidth * V4L_BYTES_PER_PIXEL; /* V4L line offset */ const int hue_corr = (ibmcam->vpic.hue - 0x8000) >> 10; /* -32..+31 */ const int hue2_corr = (hue_correction - 128) / 4; /* -32..+31 */ const int ccm = 128; /* Color correction median - see below */ int y, u, v, i, frame_done=0, mono_plane, color_corr; color_corr = (ibmcam->vpic.colour - 0x8000) >> 8; /* -128..+127 = -ccm..+(ccm-1)*/ RESTRICT_TO_RANGE(color_corr, -ccm, ccm+1); data = ibmcam->scratch; frame = &ibmcam->frame[ibmcam->curframe]; len = frame->frmwidth * 3; /* 1 line of mono + 1 line of color */ /*printk(KERN_DEBUG "len=%d. left=%d.\n",len,scratch_left(data));*/ mono_plane = ((frame->curline & 1) == 0); /* * Lines are organized this way (or are they?) * * I420: * ~~~~ * ___________________________________ * |-----Y-----|---UVUVUV...UVUV-----| \ * |-----------+---------------------| \ * |<-- 176 -->|<------ 176*2 ------>| Total 72. pairs of lines * |... ... ...| / * |___________|_____________________| / * - odd line- ------- even line --- * * another format: * ~~~~~~~~~~~~~~ * ___________________________________ * |-----Y-----|---UVUVUV...UVUV-----| \ * |-----------+---------------------| \ * |<-- 352 -->|<------ 352*2 ------>| Total 144. pairs of lines * |... ... ...| / * |___________|_____________________| / * - odd line- ------- even line --- */ /* Make sure there's enough data for the entire line */ if (scratch_left(data) < (len+1024)) { /*printk(KERN_DEBUG "out of data, need %u.\n", len);*/ return scan_Out; }#if 0 { /* This code prints beginning of the source frame */ static int pass = 0; if ((pass++ % 3000) == 0) ibmcam_hexdump(data, 16); }#endif#if 0 if (frame->curline == 10 || frame->curline == 11) { /* This code prints beginning of 10th (mono), 11th (chroma) line */ static int pass = 0; if ((pass % 100) == 0) ibmcam_hexdump(data, 16); if (frame->curline == 11) pass++; }#endif /* * Make sure that our writing into output buffer * will not exceed the buffer. Mind that we may write * not into current output scanline but in several after * it as well (if we enlarge image vertically.) */ if ((frame->curline + 1) >= V4L_FRAME_HEIGHT) return scan_NextFrame; /* * Now we are sure that entire line (representing all 'frame->frmwidth' * pixels from the camera) is available in the scratch buffer. We * start copying the line left-aligned to the V4L buffer (which * might be larger - not smaller, hopefully). If the camera * line is shorter then we should pad the V4L buffer with something * (black in this case) to complete the line. */ f = frame->data + (v4l_linesize * frame->curline); /* * chromaLine points to 1st pixel of the line with chrominance. * If current line is monochrome then chromaLine points to next * line after monochrome one. If current line has chrominance * then chromaLine points to this very line. Such method allows * to access chrominance data uniformly. * * To obtain chrominance data from the 'chromaLine' use this: * v = chromaLine[0]; // 0-1:[0], 2-3:[4], 4-5:[8]... * u = chromaLine[2]; // 0-1:[2], 2-3:[6], 4-5:[10]... * * Indices must be calculated this way: * v_index = (i >> 1) << 2; * u_index = (i >> 1) << 2 + 2; * * where 'i' is the column number [0..frame->frmwidth-1] */ chromaLine = data; if (mono_plane) chromaLine += frame->frmwidth; for (i = 0; i < frame->frmwidth; i++, data += (mono_plane ? 1 : 2)) { unsigned char rv, gv, bv; /* RGB components */ /* * Search for potential Start-Of-Frame marker. It should * not be here, of course, but if your formats don't match * you might exceed the frame. We must match the marker to * each byte of multi-byte data element if it is multi-byte. */#if 1 if ((ibmcam->camera_model == IBMCAM_MODEL_1) && (scratch_left(data) >= (4+2))) { unsigned char *dp; int j; for (j=0, dp=data; j < 2; j++, dp++) { if ((dp[0] == 0x00) && (dp[1] == 0xFF) && (dp[2] == 0x00) && (dp[3] == frame->hdr_sig)) { ibmcam->has_hdr = 2; frame_done++; break; } } }#endif /* Check for various visual debugging hints (colorized pixels) */ if ((flags & FLAGS_DISPLAY_HINTS) && (ibmcam->has_hdr)) { /* * This is bad and should not happen. This means that * we somehow overshoot the line and encountered new * frame! Obviously our camera/V4L frame size is out * of whack. This cyan dot will help you to figure * out where exactly the new frame arrived. */ if (ibmcam->has_hdr == 1) { bv = 0; /* Yellow marker */ gv = 0xFF; rv = 0xFF; } else { bv = 0xFF; /* Cyan marker */ gv = 0xFF; rv = 0; } ibmcam->has_hdr = 0; goto make_pixel; } if (mono_plane || frame->order_yc) y = data[0]; else y = data[1]; if (flags & FLAGS_MONOCHROME) /* Use monochrome for debugging */ rv = gv = bv = y; else { int off_0, off_2; off_0 = (i >> 1) << 2; off_2 = off_0 + 2; if (frame->order_yc) { off_0++; off_2++; } if (!frame->order_uv) { off_0 += 2; off_2 -= 2; } u = chromaLine[off_0] + hue_corr; v = chromaLine[off_2] + hue2_corr; /* Apply color correction */ if (color_corr != 0) { /* Magnify up to 2 times, reduce down to zero saturation */ u = 128 + ((ccm + color_corr) * (u - 128)) / ccm; v = 128 + ((ccm + color_corr) * (v - 128)) / ccm; } YUV_TO_RGB_BY_THE_BOOK(y, u, v, rv, gv, bv); } make_pixel:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -