📄 qc-formats.c
字号:
{ v4l2_fourcc('Y','8',' ',' '), &qc_fmt_formats_Y800 }, { v4l2_fourcc('Y','U','N','V'), &qc_fmt_formats_YUY2 }, { v4l2_fourcc('V','4','2','2'), &qc_fmt_formats_YUY2 }, { v4l2_fourcc('Y','4','2','2'), &qc_fmt_formats_UYVY }, { v4l2_fourcc('U','Y','N','V'), &qc_fmt_formats_UYVY }, { v4l2_fourcc('I','4','2','0'), &qc_fmt_formats_IYUV },};/* }}} *//* {{{ [fold] struct qc_fmt_palette: table to convert V4L code into fourcc, supported formats */static struct qc_fmt_palette { int palette; /* V4L1 standard palette type */ struct qc_fmt_format const *format;} const qc_fmt_palettes[] = { { VIDEO_PALETTE_GREY, &qc_fmt_formats_Y800 }, { VIDEO_PALETTE_HI240, &qc_fmt_formats_RGB_HI }, /* RGB formats */ { VIDEO_PALETTE_RGB565, &qc_fmt_formats_RGB_565L }, { VIDEO_PALETTE_RGB24, &qc_fmt_formats_BGR_24L }, { VIDEO_PALETTE_RGB32, &qc_fmt_formats_BGR_32L }, { VIDEO_PALETTE_RGB555, &qc_fmt_formats_RGB_555L }, /* Component YUV formats */ { VIDEO_PALETTE_YUV422, &qc_fmt_formats_YUY2 }, /* Assume this is YUY2, even though V4L1 docs say this is 8 bpp format */ { VIDEO_PALETTE_YUYV, &qc_fmt_formats_YUY2 }, /* Benedict Bridgwater <bennyb@ntplx.net>: Bt848 maps this to Y41P, but it is simply wrong--we follow V4L2 v4l_compat.c */ { VIDEO_PALETTE_UYVY, &qc_fmt_formats_UYVY }, { VIDEO_PALETTE_YUV420, &qc_fmt_formats_IYUV }, /* Assume this is planar, even though V4L1 header file indicates otherwise */ { VIDEO_PALETTE_YUV411, &qc_fmt_formats_qcY1 }, /* Assume this is planar, even though V4L1 header file indicates otherwise (could be also fourcc 'Y41P') -from benedict */ { VIDEO_PALETTE_RAW, &qc_fmt_formats_qcBT }, /* Planar YUV formats */ { VIDEO_PALETTE_YUV422P, &qc_fmt_formats_qcY2 }, { VIDEO_PALETTE_YUV411P, &qc_fmt_formats_qcY1 }, { VIDEO_PALETTE_YUV420P, &qc_fmt_formats_IYUV }, { VIDEO_PALETTE_YUV410P, &qc_fmt_formats_qcU9 }, /* Special formats */ { VIDEO_PALETTE_BAYER, &qc_fmt_formats_qcBR }, { VIDEO_PALETTE_MJPEG, &qc_fmt_formats_qcMJ },};/* }}} *//* {{{ [fold] struct qc_fmt_v4l2: V4L2 defines its own conflicting format codes */static struct qc_fmt_v4l2 { u32 v4l2code; struct qc_fmt_format const *format;} const qc_fmt_v4l2s[] = { { v4l2_fourcc('R','G','B','1'), &qc_fmt_formats_RGB_332 }, /* V4L2_PIX_FMT_RGB332 8 RGB-3-3-2 */ { v4l2_fourcc('R','G','B','O'), &qc_fmt_formats_RGB_555L }, /* V4L2_PIX_FMT_RGB555 16 RGB-5-5-5 */ { v4l2_fourcc('R','G','B','P'), &qc_fmt_formats_RGB_565L }, /* V4L2_PIX_FMT_RGB565 16 RGB-5-6-5 */ { v4l2_fourcc('R','G','B','Q'), &qc_fmt_formats_RGB_555B }, /* V4L2_PIX_FMT_RGB555X 16 RGB-5-5-5 BE */ { v4l2_fourcc('R','G','B','R'), &qc_fmt_formats_RGB_565B }, /* V4L2_PIX_FMT_RGB565X 16 RGB-5-6-5 BE */ { v4l2_fourcc('B','G','R','3'), &qc_fmt_formats_BGR_24L }, /* V4L2_PIX_FMT_BGR24 24 BGR-8-8-8 */ { v4l2_fourcc('R','G','B','3'), &qc_fmt_formats_RGB_24L }, /* V4L2_PIX_FMT_RGB24 24 RGB-8-8-8 */ { v4l2_fourcc('B','G','R','4'), &qc_fmt_formats_BGR_32L }, /* V4L2_PIX_FMT_BGR32 32 BGR-8-8-8-8 */ { v4l2_fourcc('R','G','B','4'), &qc_fmt_formats_RGB_32L }, /* V4L2_PIX_FMT_RGB32 32 RGB-8-8-8-8 */ { v4l2_fourcc('G','R','E','Y'), &qc_fmt_formats_Y800 }, /* V4L2_PIX_FMT_GREY 8 Greyscale */ { v4l2_fourcc('Y','V','U','9'), &qc_fmt_formats_YVU9 }, /* V4L2_PIX_FMT_YVU410 9 YVU 4:1:0 */ { v4l2_fourcc('Y','V','1','2'), &qc_fmt_formats_YV12 }, /* V4L2_PIX_FMT_YVU420 12 YVU 4:2:0 */ { v4l2_fourcc('Y','U','Y','V'), &qc_fmt_formats_YUY2 }, /* V4L2_PIX_FMT_YUYV 16 YUV 4:2:2 */ { v4l2_fourcc('Y','U','Y','2'), &qc_fmt_formats_YUY2 }, /* V4L2_PIX_FMT_YUY2 16 YUV 4:2:2: undocumented, guess same as YUY2 */ { v4l2_fourcc('U','Y','V','Y'), &qc_fmt_formats_UYVY }, /* V4L2_PIX_FMT_UYVY 16 YUV 4:2:2 */ { v4l2_fourcc('Y','4','1','P'), &qc_fmt_formats_Y41P }, /* V4L2_PIX_FMT_Y41P 12 YUV 4:1:1 */ { v4l2_fourcc('Y','U','V','9'), &qc_fmt_formats_qcU9 }, /* V4L2_PIX_FMT_YUV410 9 YUV 4:1:0 */ { v4l2_fourcc('Y','U','1','2'), &qc_fmt_formats_IYUV }, /* V4L2_PIX_FMT_YUV420 12 YUV 4:2:0 */ { v4l2_fourcc('P','4','2','2'), &qc_fmt_formats_qcY2 }, /* V4L2_PIX_FMT_YUV422P 16 YUV422 planar */ { v4l2_fourcc('P','4','1','1'), &qc_fmt_formats_qcY1 }, /* V4L2_PIX_FMT_YUV411P 16 YUV411 planar: assume bpp should be 12 */ { v4l2_fourcc('N','V','1','2'), &qc_fmt_formats_NV12 }, /* V4L2_PIX_FMT_NV12 12 Y/UV 4:2:0 */ { v4l2_fourcc('4','2','2','P'), &qc_fmt_formats_qcV2 }, /* V4L2_PIX_FMT_YVU422P 16 YVU422 planar */ { v4l2_fourcc('4','1','1','P'), &qc_fmt_formats_qcV1 }, /* V4L2_PIX_FMT_YVU411P 16 YVU411 planar: assume bpp should be 12 */ { v4l2_fourcc('Y','Y','U','V'), &qc_fmt_formats_qcYY }, /* V4L2_PIX_FMT_YYUV 16 YUV 4:2:2: undocumented, guess this is qc YY */ { v4l2_fourcc('H','I','2','4'), &qc_fmt_formats_RGB_HI }, /* V4L2_PIX_FMT_HI240 8 8-bit color */ { v4l2_fourcc('N','V','2','1'), &qc_fmt_formats_NV21 }, /* V4L2_PIX_FMT_NV21 12 Y/UV 4:2:0 */ { v4l2_fourcc('W','N','V','A'), &qc_fmt_formats_qcWN }, /* V4L2_PIX_FMT_WNVA Winnov hw compres */};/* }}} *//* {{{ [fold] qc_fmt_issupported(int palette) *//* Check the format (can be called even before qc_fmt_init) */int qc_fmt_issupported(int palette){ int i; for (i=0; i<SIZE(qc_fmt_palettes); i++) { if (qc_fmt_palettes[i].palette==palette && qc_fmt_palettes[i].format->supported) return 0; } return -EINVAL;}/* }}} *//* {{{ [fold] qc_fmt_getname(int palette) *//* Return the format name (can be called even before qc_fmt_init) */const char *qc_fmt_getname(int palette){ int i; for (i=0; i<SIZE(qc_fmt_palettes); i++) { if (qc_fmt_palettes[i].palette==palette) return qc_fmt_palettes[i].format->name; } return "Unknown";}/* }}} *//* {{{ [fold] qc_fmt_getdepth(int palette) *//* Return bits per pixel for the format, or * 0=variable number (compressed formats), -1=unknown * (can be called even before qc_fmt_init) */int qc_fmt_getdepth(int palette){ int i; for (i=0; i<SIZE(qc_fmt_palettes); i++) { if (qc_fmt_palettes[i].palette==palette) return qc_fmt_palettes[i].format->bpp; } return -1; /* Unknown bit depth */}/* }}} *//* {{{ [fold] qc_fmt_init(struct quickcam *qc) */int qc_fmt_init(struct quickcam *qc){ int r = 0; if (qcdebug&QC_DEBUGLOGIC) PDEBUG("qc_fmt_init(qc=%p/compr=%i)",qc,qc->settings.compress);#if COMPRESS if (qc->settings.compress) { qc->fmt_data.compress = TRUE; r = qc_mjpeg_init(&qc->fmt_data.mjpeg_data, 24, DEFAULT_BGR); } else { qc->fmt_data.compress = FALSE; }#endif if (r>=0) IDEBUG_INIT(qc->fmt_data); return r;}/* }}} *//* {{{ [fold] qc_fmt_exit(struct quickcam *qc) */void qc_fmt_exit(struct quickcam *qc){ if (qcdebug&QC_DEBUGLOGIC) PDEBUG("qc_fmt_exit(qc=%p)",qc);#if COMPRESS if (qcdebug&QC_DEBUGLOGIC) PDEBUG("qc_fmt_exit/compress=%i",qc->fmt_data.compress); if (qc->fmt_data.compress) qc_mjpeg_exit(&qc->fmt_data.mjpeg_data); POISON(qc->fmt_data.compress); POISON(qc->fmt_data.mjpeg_data);#endif POISON(qc->fmt_data.lut); IDEBUG_EXIT_NOPOISON(qc->fmt_data);}/* }}} *//* {{{ [fold] qc_fmt_convert(struct quickcam *qc, unsigned char *src, unsigned int src_len, unsigned char *dst, unsigned int dst_len, int *midvalue) *//* Called after each full frame of bayer or compressed image obtained *//* Convert camera data in src to the application requested palette in dst *//* Return negative error code if failure, otherwise data length stored in dst *//* src_len is the length of actual data in src, dst_len is the maximum data size storable in dst *//* Also src buffer may be modified *//* Return image average brightness in midvalue (or -1 if not computed) */int qc_fmt_convert(struct quickcam *qc, unsigned char *src, unsigned int src_len, unsigned char *dst, unsigned int dst_len, int *midvalue){ signed int originx, originy; /* Upper-left corner coordinates of the capture window in the bayer image */ unsigned char *bayerwin; int length; /* Converted image data length in bytes */ int r = 0; if (qcdebug&QC_DEBUGLOGIC) PDEBUG("qc_imag_convert(qc=%p,src=%p,src_len=%i,dst=%p,dst_len=%i)",qc,src,src_len,dst,dst_len); if (PARANOID && (qc==NULL || src==NULL || dst==NULL)) { PRINTK(KERN_CRIT,"NULL"); return -EINVAL; } if (PARANOID && midvalue==NULL) { PRINTK(KERN_CRIT,"NULL"); return -EINVAL; } IDEBUG_TEST(qc->fmt_data); *midvalue = -1; if (qcdebug&QC_DEBUGLOGIC) PDEBUG("sensor_width=%i sensor_height=%i vwin.width=%i vwin.height=%i", qc->sensor_data.width,qc->sensor_data.height,qc->vwin.width,qc->vwin.height); if (qc->sensor_data.width < qc->vwin.width || qc->sensor_data.height < qc->vwin.height) { if (qcdebug&QC_DEBUGERRORS) PDEBUG("sensor window is smaller than requested"); r = -ENOMSG; goto fail; }#if DUMPDATA if (midvalue) *midvalue = -1; memset(dst, 0, dst_len); memcpy(dst, src, src_len>dst_len ? dst_len : src_len); length = (int)qc->vwin.width * (int)qc->vwin.height * 3; return length;#endif#if COMPRESS if (!qc->sensor_data.compress) {#endif /* src buffer contains fixed length data in bayer format */ /* sensor_data.height/width = frame size that is captured from the camera */ /* vwin.height/width = frame size that the application is expecting */ /* Check if src buffer contains enough data */ if (src_len < qc->sensor_data.width * qc->sensor_data.height) { if (qcdebug&QC_DEBUGERRORS) PDEBUG("too little data by %i (expected %i)", qc->sensor_data.width*qc->sensor_data.height - src_len, qc->sensor_data.width * qc->sensor_data.height); r = -EBADE; goto fail; } /* calculate view window origin inside the whole frame */ originy = ((signed int)qc->sensor_data.height - (signed int)qc->vwin.height) / 2; originx = ((signed int)qc->sensor_data.width - (signed int)qc->vwin.width) / 2; originx &= ~1; /* Set upper-left corner to a even coordinate */ originy &= ~1; /* so that the first bayer pixel is green */ bayerwin = src + originy * qc->sensor_data.width + originx; if (qcdebug&QC_DEBUGLOGIC) PDEBUG("originy=%i originx=%i", originy,originx); if (qc->settings.adaptive && midvalue!=NULL) *midvalue = qc_imag_bayer_midvalue(bayerwin, qc->sensor_data.width, qc->vwin.width, qc->vwin.height); if (qc->settings.equalize || qc->settings.userlut) { if (qc->settings.equalize) { qc_imag_bayer_equalize(bayerwin, qc->sensor_data.width, qc->vwin.width, qc->vwin.height, &qc->fmt_data.lut); } else { /* Initialize LUT */ int i; for (i=0; i<256; i++) qc->fmt_data.lut[QC_LUT_RED+i] = i; for (i=0; i<256; i++) qc->fmt_data.lut[QC_LUT_GREEN+i] = i; for (i=0; i<256; i++) qc->fmt_data.lut[QC_LUT_BLUE+i] = i; } if (qc->settings.userlut) { qc_imag_userlut(&qc->fmt_data.userlut, &qc->fmt_data.lut); } /* Could do here other effects to the lookup table */ qc_imag_bayer_lut(bayerwin, qc->sensor_data.width, qc->vwin.width, qc->vwin.height, &qc->fmt_data.lut); } if (qc->vpic.palette==VIDEO_PALETTE_BAYER) { int i; length = (int)qc->vwin.width * (int)qc->vwin.height; if (length > dst_len) { r = -ENOSPC; goto fail; } /* It would be more efficient to capture data directly to the mmapped buffer, * but more complex and hardly any application will use bayer palette anyway */ for (i=0; i<qc->vwin.height; i++) { memcpy(dst, bayerwin, qc->vwin.width); bayerwin += qc->sensor_data.width; dst += qc->vwin.width; } } else { /* Convert the current frame to RGB */ length = (int)qc->vwin.width * (int)qc->vwin.height * 3; if (length > dst_len) { r = -ENOSPC; goto fail; } switch (qc->settings.quality) { case 0: qc_imag_bay2rgb_cottnoip(bayerwin, qc->sensor_data.width, dst, 3*qc->vwin.width, qc->vwin.width, qc->vwin.height, 3); break; case 1: qc_imag_bay2rgb_cott(bayerwin, qc->sensor_data.width, dst, 3*qc->vwin.width, qc->vwin.width, qc->vwin.height, 3); break; case 2: qc_imag_bay2rgb_horip(bayerwin, qc->sensor_data.width, dst, 3*qc->vwin.width, qc->vwin.width, qc->vwin.height, 3); break; case 3: qc_imag_bay2rgb_ip(bayerwin, qc->sensor_data.width, dst, 3*qc->vwin.width, qc->vwin.width, qc->vwin.height, 3); break; default: case 4: qc_imag_bay2rgb_gptm_fast(bayerwin, qc->sensor_data.width, dst, 3*qc->vwin.width, qc->vwin.width, qc->vwin.height, 3); break; case 5: qc_imag_bay2rgb_gptm(bayerwin, qc->sensor_data.width, dst, 3*qc->vwin.width, qc->vwin.width, qc->vwin.height, 3, qc->vpic.whiteness); break; } goto rgb24; }#if COMPRESS } else { /* src buffer contains variable length data in mjpeg format */ if (qc->vpic.palette==VIDEO_PALETTE_MJPEG) { /* Directly copy data from src to dst, can not resize */ length = src_len; if (length > dst_len) { r = -ENOSPC; goto fail; } memcpy(dst, src, src_len); } else { /* Decode compressed images */ if (!qc->fmt_data.compress) { r = -EINVAL
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -