📄 ibmcam.c
字号:
case 0x0268: /* 320x240, best frame rate compression */ case 0x02CA: /* 160x120, best quality compression */ case 0x02EA: /* 160x120, best frame rate compression */ /* Do nothing with this - not supported */ err("Unsupported mode $%04lx", frame->header); return scan_NextFrame; default: /* Catch unknown headers, may help in learning new headers */ err("Strange frame->header=$%08lx", frame->header); return scan_NextFrame; } /* * Make sure that our writing into output buffer * will not exceed the buffer. Note 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) >= data_h) { if (uvd->debug >= 3) info("Reached line %d. (frame is done)", frame->curline); return scan_NextFrame; } /* Make sure there's enough data for the entire line */ len = 3 * data_w; /* <y-data> <uv-data> */ assert(len <= sizeof(lineBuffer)); /* Make sure there's enough data for the entire line */ if (RingQueue_GetLength(&uvd->dp) < len) return scan_Out; /* Suck one line out of the ring queue */ RingQueue_Dequeue(&uvd->dp, lineBuffer, len); data = lineBuffer; color = data + data_w; /* Point to where color planes begin */ /* Bottom-to-top scanning */ rw = (int)VIDEOSIZE_Y(frame->request) - (int)(frame->curline) - 1; RESTRICT_TO_RANGE(rw, 0, VIDEOSIZE_Y(frame->request)-1); for (i = 0; i < VIDEOSIZE_X(frame->request); i++) { int y, rv, gv, bv; /* RGB components */ if (i < data_w) { y = data[i]; /* Luminosity is the first line */ /* Apply static color correction */ u = color[i*2] + hue_corr; v = color[i*2 + 1] + 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; } } else y = 0, u = v = 128; YUV_TO_RGB_BY_THE_BOOK(y, u, v, rv, gv, bv); RGB24_PUTPIXEL(frame, i, rw, rv, gv, bv); /* Done by deinterlacing now */ } frame->deinterlace = Deinterlace_FillEvenLines; /* * Account for number of bytes that we wrote into output V4L frame. * We do it here, after we are done with the scanline, because we * may fill more than one output scanline if we do vertical * enlargement. */ frame->curline += 2; *pcopylen += 2 * v4l_linesize; if (frame->curline >= VIDEOSIZE_Y(frame->request)) { if (uvd->debug >= 3) { info("All requested lines (%ld.) done.", VIDEOSIZE_Y(frame->request)); } return scan_NextFrame; } else return scan_Continue;}/* * ibmcam_model4_128x96_parse_lines() * * This decoder is for one strange data format that is produced by Model 4 * camera only in 128x96 mode. This is RGB format and here is its description. * First of all, this is non-interlaced stream, meaning that all scan lines * are present in the datastream. There are 96 consecutive blocks of data * that describe all 96 lines of the image. Each block is 5*128 bytes long * and carries R, G, B components. The format of the block is shown in the * code below. First 128*2 bytes are interleaved R and G components. Then * we have a gap (junk data) 64 bytes long. Then follow B and something * else, also interleaved (this makes another 128*2 bytes). After that * probably another 64 bytes of junk follow. * * History: * 10-Feb-2001 Created. */static ParseState_t ibmcam_model4_128x96_parse_lines( uvd_t *uvd, usbvideo_frame_t *frame, long *pcopylen){ const unsigned char *data_rv, *data_gv, *data_bv; unsigned int len; int i, v4l_linesize; /* V4L line offset */ const int data_w=128, data_h=96; static unsigned char lineBuffer[128*5]; v4l_linesize = VIDEOSIZE_X(frame->request) * V4L_BYTES_PER_PIXEL; /* * Make sure that our writing into output buffer * will not exceed the buffer. Note 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) >= data_h) { if (uvd->debug >= 3) info("Reached line %d. (frame is done)", frame->curline); return scan_NextFrame; } /* * RGRGRG .... RGRG_____________B?B?B? ... B?B?____________ * <---- 128*2 ---><---- 64 ---><--- 128*2 ---><--- 64 ---> */ /* Make sure there's enough data for the entire line */ len = 5 * data_w; assert(len <= sizeof(lineBuffer)); /* Make sure there's enough data for the entire line */ if (RingQueue_GetLength(&uvd->dp) < len) return scan_Out; /* Suck one line out of the ring queue */ RingQueue_Dequeue(&uvd->dp, lineBuffer, len); data_rv = lineBuffer; data_gv = lineBuffer + 1; data_bv = lineBuffer + data_w*2 + data_w/2; for (i = 0; i < VIDEOSIZE_X(frame->request); i++) { int rv, gv, bv; /* RGB components */ if (i < data_w) { const int j = i * 2; gv = data_rv[j]; rv = data_gv[j]; bv = data_bv[j]; if (flags & FLAGS_MONOCHROME) { unsigned long y; y = rv + gv + bv; y /= 3; if (y > 0xFF) y = 0xFF; rv = gv = bv = (unsigned char) y; } } else { rv = gv = bv = 0; } RGB24_PUTPIXEL(frame, i, frame->curline, rv, gv, bv); } frame->deinterlace = Deinterlace_None; frame->curline++; *pcopylen += v4l_linesize; if (frame->curline >= VIDEOSIZE_Y(frame->request)) { if (uvd->debug >= 3) { info("All requested lines (%ld.) done.", VIDEOSIZE_Y(frame->request)); } return scan_NextFrame; } else return scan_Continue;}/* * ibmcam_ProcessIsocData() * * Generic routine to parse the ring queue data. It employs either * ibmcam_find_header() or ibmcam_parse_lines() to do most * of work. * * History: * 1/21/00 Created. */void ibmcam_ProcessIsocData(uvd_t *uvd, usbvideo_frame_t *frame){ ParseState_t newstate; long copylen = 0; int mod = IBMCAM_T(uvd)->camera_model; while (1) { newstate = scan_Out; if (RingQueue_GetLength(&uvd->dp) > 0) { if (frame->scanstate == ScanState_Scanning) { newstate = ibmcam_find_header(uvd); } else if (frame->scanstate == ScanState_Lines) { if ((mod == IBMCAM_MODEL_2) && ((uvd->videosize == VIDEOSIZE_352x288) || (uvd->videosize == VIDEOSIZE_320x240) || (uvd->videosize == VIDEOSIZE_352x240))) { newstate = ibmcam_model2_320x240_parse_lines( uvd, frame, ©len); } else if (mod == IBMCAM_MODEL_4) { /* * Model 4 cameras (IBM NetCamera) use Model 2 decoder (RGB) * for 320x240 and above; 160x120 and 176x144 uses Model 1 * decoder (YUV), and 128x96 mode uses ??? */ if ((uvd->videosize == VIDEOSIZE_352x288) || (uvd->videosize == VIDEOSIZE_320x240) || (uvd->videosize == VIDEOSIZE_352x240)) { newstate = ibmcam_model2_320x240_parse_lines(uvd, frame, ©len); } else if (uvd->videosize == VIDEOSIZE_128x96) { newstate = ibmcam_model4_128x96_parse_lines(uvd, frame, ©len); } else { newstate = ibmcam_parse_lines(uvd, frame, ©len); } } else if (mod == IBMCAM_MODEL_3) { newstate = ibmcam_model3_parse_lines(uvd, frame, ©len); } else { newstate = ibmcam_parse_lines(uvd, frame, ©len); } } } if (newstate == scan_Continue) continue; else if ((newstate == scan_NextFrame) || (newstate == scan_Out)) break; else return; /* scan_EndParse */ } if (newstate == scan_NextFrame) { frame->frameState = FrameState_Done; uvd->curframe = -1; uvd->stats.frame_num++; if ((mod == IBMCAM_MODEL_2) || (mod == IBMCAM_MODEL_4)) { /* Need software contrast adjustment for those cameras */ frame->flags |= USBVIDEO_FRAME_FLAG_SOFTWARE_CONTRAST; } } /* Update the frame's uncompressed length. */ frame->seqRead_Length += copylen;#if 0 { static unsigned char j=0; memset(frame->data, j++, uvd->max_frame_size); frame->frameState = FrameState_Ready; }#endif}/* * ibmcam_veio() * * History: * 1/27/00 Added check for dev == NULL; this happens if camera is unplugged. */static int ibmcam_veio( uvd_t *uvd, unsigned char req, unsigned short value, unsigned short index){ static const char proc[] = "ibmcam_veio"; unsigned char cp[8] /* = { 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef } */; int i; if (!CAMERA_IS_OPERATIONAL(uvd)) return 0; if (req == 1) { i = usb_control_msg( uvd->dev, usb_rcvctrlpipe(uvd->dev, 0), req, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT, value, index, cp, sizeof(cp), HZ);#if 0 info("USB => %02x%02x%02x%02x%02x%02x%02x%02x " "(req=$%02x val=$%04x ind=$%04x)", cp[0],cp[1],cp[2],cp[3],cp[4],cp[5],cp[6],cp[7], req, value, index);#endif } else { i = usb_control_msg( uvd->dev, usb_sndctrlpipe(uvd->dev, 0), req, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT, value, index, NULL, 0, HZ); } if (i < 0) { err("%s: ERROR=%d. Camera stopped; Reconnect or reload driver.", proc, i); uvd->last_error = i; } return i;}/* * ibmcam_calculate_fps() * * This procedure roughly calculates the real frame rate based * on FPS code (framerate=NNN option). Actual FPS differs * slightly depending on lighting conditions, so that actual frame * rate is determined by the camera. Since I don't know how to ask * the camera what FPS is now I have to use the FPS code instead. * * The FPS code is in range [0..6], 0 is slowest, 6 is fastest. * Corresponding real FPS should be in range [3..30] frames per second. * The conversion formula is obvious: * * real_fps = 3 + (fps_code * 4.5) * * History: * 1/18/00 Created. */static int ibmcam_calculate_fps(uvd_t *uvd){ return 3 + framerate*4 + framerate/2;}/* * ibmcam_send_FF_04_02() * * This procedure sends magic 3-command prefix to the camera. * The purpose of this prefix is not known. * * History: * 1/2/00 Created. */static void ibmcam_send_FF_04_02(uvd_t *uvd){ ibmcam_veio(uvd, 0, 0x00FF, 0x0127); ibmcam_veio(uvd, 0, 0x0004, 0x0124); ibmcam_veio(uvd, 0, 0x0002, 0x0124);}static void ibmcam_send_00_04_06(uvd_t *uvd){ ibmcam_veio(uvd, 0, 0x0000, 0x0127); ibmcam_veio(uvd, 0, 0x0004, 0x0124); ibmcam_veio(uvd, 0, 0x0006, 0x0124);}static void ibmcam_send_x_00(uvd_t *uvd, unsigned short x){ ibmcam_veio(uvd, 0, x, 0x0127); ibmcam_veio(uvd, 0, 0x0000, 0x0124);}static void ibmcam_send_x_00_05(uvd_t *uvd, unsigned short x){ ibmcam_send_x_00(uvd, x); ibmcam_veio(uvd, 0, 0x0005, 0x0124);}static void ibmcam_send_x_00_05_02(uvd_t *uvd, unsigned short x){ ibmcam_veio(uvd, 0, x, 0x0127); ibmcam_veio(uvd, 0, 0x0000, 0x0124); ibmcam_veio(uvd, 0, 0x0005, 0x0124); ibmcam_veio(uvd, 0, 0x0002, 0x0124);}static void ibmcam_send_x_01_00_05(uvd_t *uvd, unsigned short x){ ibmcam_veio(uvd, 0, x, 0x0127); ibmcam_veio(uvd, 0, 0x0001, 0x0124); ibmcam_veio(uvd, 0, 0x0000, 0x0124); ibmcam_veio(uvd, 0, 0x0005, 0x0124);}static void ibmcam_send_x_00_05_02_01(uvd_t *uvd, unsigned short x){ ibmcam_veio(uvd, 0, x, 0x0127); ibmcam_veio(uvd, 0, 0x0000, 0x0124); ibmcam_veio(uvd, 0, 0x0005, 0x0124); ibmcam_veio(uvd, 0, 0x0002, 0x0124); ibmcam_veio(uvd, 0, 0x0001, 0x0124);}static void ibmcam_send_x_00_05_02_08_01(uvd_t *uvd, unsigned short x){ ibmcam_veio(uvd, 0, x, 0x0127); ibmcam_veio(uvd, 0, 0x0000, 0x0124); ibmcam_veio(uvd, 0, 0x0005, 0x0124); ibmcam_veio(uvd, 0, 0x0002, 0x0124); ibmcam_veio(uvd, 0, 0x0008, 0x0124); ibmcam_veio(uvd, 0, 0x0001, 0x0124);}static void ibmcam_Packet_Format1(uvd_t *uvd, unsigned char fkey, unsigned char val){ ibmcam_send_x_01_00_05(uvd, unknown_88); ibmcam_send_x_00_05(uvd, fkey); ibmcam_send_x_00_05_02_08_01(uvd, val); ibmcam_send_x_00_05(uvd, unknown_88); ibmcam_send_x_00_05_02_01(uvd, fkey); ibmcam_send_x_00_05(uvd, unknown_89); ibmcam_send_x_00(uvd, fkey); ibmcam_send_00_04_06(uvd); ibmcam_veio(uvd, 1, 0x0000, 0x0126); ibmcam_send_FF_04_02(uvd);}static void ibmcam_PacketFormat2(uvd_t *uvd, unsigned char fkey, unsigned char val){ ibmcam_send_x_01_00_05 (uvd, unknown_88); ibmcam_send_x_00_05 (uvd, fkey);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -