⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ov511 v1.28.c

📁 linux下ov511驱动程序
💻 C
📖 第 1 页 / 共 5 页
字号:
                /* Calculate and set the clock divisor */                clock = ((sub_flag ? ov511->subw * ov511->subh : width * height)                        * (mlist[i].color ? 3 : 2) / 2) / 66000;#if 0                clock *= cams;#endif                ov511_i2c_write(dev, 0x11, clock);                /* We only have code to convert GBR -> RGB24 */                if ((mode == VIDEO_PALETTE_RGB24) && sensor_gbr)                        ov511_i2c_write(dev, 0x12, mlist[i].common_A | (testpat?0x0a:0x08));                else                        ov511_i2c_write(dev, 0x12, mlist[i].common_A | (testpat?0x02:0x00));                /* 7620/6620 don't have register 0x35, so play it safe */                if (ov511->sensor == SEN_OV7610 ||                    ov511->sensor == SEN_OV7620AE)                        ov511_i2c_write(dev, 0x35, mlist[i].common_L);                break;        }        if (compress) {                ov511_reg_write(dev, 0x78, 0x03); // Turn on Y compression                ov511_reg_write(dev, 0x79, 0x00); // Disable LUTs        }        if (ov511_restart(ov511->dev) < 0)                return -EIO;        if (mlist[i].width == 0) {                err("Unknown mode (%d, %d): %d", width, height, mode);                return -EINVAL;        }#ifdef OV511_DEBUG        if (debug >= 5)                ov511_dump_i2c_regs(dev);#endif        return 0;}/********************************************************************** * * Color correction functions * **********************************************************************//* * Turn a YUV4:2:0 block into an RGB block * * Video4Linux seems to use the blue, green, red channel * order convention-- rgb[0] is blue, rgb[1] is green, rgb[2] is red. * * Color space conversion coefficients taken from the excellent * http://www.inforamp.net/~poynton/ColorFAQ.html * In his terminology, this is a CCIR 601.1 YCbCr -> RGB. * Y values are given for all 4 pixels, but the U (Pb) * and V (Pr) are assumed constant over the 2x2 block. * * To avoid floating point arithmetic, the color conversion * coefficients are scaled into 16.16 fixed-point integers. * They were determined as follows: * *      double brightness = 1.0;  (0->black; 1->full scale)  *      double saturation = 1.0;  (0->greyscale; 1->full color) *      double fixScale = brightness * 256 * 256; *      int rvScale = (int)(1.402 * saturation * fixScale); *      int guScale = (int)(-0.344136 * saturation * fixScale); *      int gvScale = (int)(-0.714136 * saturation * fixScale); *      int buScale = (int)(1.772 * saturation * fixScale); *      int yScale = (int)(fixScale);    *//* LIMIT: convert a 16.16 fixed-point value to a byte, with clipping. */#define LIMIT(x) ((x)>0xffffff?0xff: ((x)<=0xffff?0:((x)>>16)))static inline voidov511_move_420_block(int yTL, int yTR, int yBL, int yBR, int u, int v,         int rowPixels, unsigned char * rgb, int bits){        const int rvScale = 91881;        const int guScale = -22553;        const int gvScale = -46801;        const int buScale = 116129;        const int yScale  = 65536;        int r, g, b;        g = guScale * u + gvScale * v;        if (force_rgb) {                r = buScale * u;                b = rvScale * v;        } else {                r = rvScale * v;                b = buScale * u;        }        yTL *= yScale; yTR *= yScale;        yBL *= yScale; yBR *= yScale;        if (bits == 24) {                /* Write out top two pixels */                rgb[0] = LIMIT(b+yTL); rgb[1] = LIMIT(g+yTL); rgb[2] = LIMIT(r+yTL);                rgb[3] = LIMIT(b+yTR); rgb[4] = LIMIT(g+yTR); rgb[5] = LIMIT(r+yTR);                /* Skip down to next line to write out bottom two pixels */                rgb += 3 * rowPixels;                rgb[0] = LIMIT(b+yBL); rgb[1] = LIMIT(g+yBL); rgb[2] = LIMIT(r+yBL);                rgb[3] = LIMIT(b+yBR); rgb[4] = LIMIT(g+yBR); rgb[5] = LIMIT(r+yBR);        } else if (bits == 16) {                /* Write out top two pixels */                rgb[0] = ((LIMIT(b+yTL) >> 3) & 0x1F) | ((LIMIT(g+yTL) << 3) & 0xE0);                rgb[1] = ((LIMIT(g+yTL) >> 5) & 0x07) | (LIMIT(r+yTL) & 0xF8);                rgb[2] = ((LIMIT(b+yTR) >> 3) & 0x1F) | ((LIMIT(g+yTR) << 3) & 0xE0);                rgb[3] = ((LIMIT(g+yTR) >> 5) & 0x07) | (LIMIT(r+yTR) & 0xF8);                /* Skip down to next line to write out bottom two pixels */                rgb += 2 * rowPixels;                rgb[0] = ((LIMIT(b+yBL) >> 3) & 0x1F) | ((LIMIT(g+yBL) << 3) & 0xE0);                rgb[1] = ((LIMIT(g+yBL) >> 5) & 0x07) | (LIMIT(r+yBL) & 0xF8);                rgb[2] = ((LIMIT(b+yBR) >> 3) & 0x1F) | ((LIMIT(g+yBR) << 3) & 0xE0);                rgb[3] = ((LIMIT(g+yBR) >> 5) & 0x07) | (LIMIT(r+yBR) & 0xF8);        }}/* * For a 640x480 YUV4:2:0 images, data shows up in 1200 384 byte segments. * The first 64 bytes of each segment are U, the next 64 are V.  The U and * V are arranged as follows: * *      0  1 ...  7 *      8  9 ... 15 *           ...    *     56 57 ... 63 * * U and V are shipped at half resolution (1 U,V sample -> one 2x2 block). * * The next 256 bytes are full resolution Y data and 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 * * Note that the U and V data in one segment represents a 16 x 16 pixel * area, but the Y data represents a 32 x 8 pixel area. * * If dumppix module param is set, _parse_data just dumps the incoming segments, * verbatim, in order, into the frame. When used with vidcat -f ppm -s 640x480 * this puts the data on the standard output and can be analyzed with the * parseppm.c utility I wrote.  That's a much faster way for figuring out how * this data is scrambled. */#define HDIV 8#define WDIV (256/HDIV)static voidov511_parse_gbr422_to_rgb24(unsigned char *pIn0, unsigned char *pOut0,                       int iOutY, int iOutUV, int iHalf, int iWidth){        int k, l, m;        unsigned char *pIn;        unsigned char *pOut, *pOut1;        pIn = pIn0;        pOut = pOut0 + iOutUV + (force_rgb ? 2 : 0);                        for (k = 0; k < 8; k++) {                pOut1 = pOut;                for (l = 0; l < 8; l++) {                        *pOut1 = *(pOut1 + 3) = *(pOut1 + iWidth*3) =                                *(pOut1 + iWidth*3 + 3) = *pIn++;                        pOut1 += 6;                }                pOut += iWidth*3*2;        }        pIn = pIn0 + 64;        pOut = pOut0 + iOutUV + (force_rgb ? 0 : 2);        for (k = 0; k < 8; k++) {                pOut1 = pOut;                for (l = 0; l < 8; l++) {                        *pOut1 = *(pOut1 + 3) = *(pOut1 + iWidth*3) =                                *(pOut1 + iWidth*3 + 3) = *pIn++;                        pOut1 += 6;                }                pOut += iWidth*3*2;        }        pIn = pIn0 + 128;        pOut = pOut0 + iOutY + 1;        for (k = 0; k < 4; k++) {                pOut1 = pOut;                for (l = 0; l < 8; l++) {                        for (m = 0; m < 8; m++) {                                *pOut1 = *pIn++;                                pOut1 += 3;                        }                        pOut1 += (iWidth - 8) * 3;                }                pOut += 8 * 3;        }}static voidov511_parse_yuv420_to_rgb(unsigned char *pIn0, unsigned char *pOut0,                       int iOutY, int iOutUV, int iHalf, int iWidth, int bits){        int k, l, m;        int bytes = bits >> 3;        unsigned char *pIn;        unsigned char *pOut, *pOut1;        /* Just copy the Y's if in the first stripe */        if (!iHalf) {                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 += bytes;                                }                                pOut1 += (iWidth - 8) * bytes;                        }                        pOut += 8 * bytes;                }        }        /* Use the first half of VUs to calculate value */        pIn = pIn0;        pOut = pOut0 + iOutUV;        for (l = 0; l < 4; l++) {                for (m=0; m<8; m++) {                        int y00 = *(pOut);                        int y01 = *(pOut+bytes);                        int y10 = *(pOut+iWidth*bytes);                        int y11 = *(pOut+iWidth*bytes+bytes);                        int v   = *(pIn+64) - 128;                        int u   = *pIn++ - 128;                        ov511_move_420_block(y00, y01, y10, y11, u, v, iWidth,                                pOut, bits);                        pOut += 2 * bytes;                }                pOut += (iWidth*2 - 16) * bytes;        }        /* Just copy the other UV rows */        for (l = 0; l < 4; l++) {                for (m = 0; m < 8; m++) {                        *pOut++ = *(pIn + 64);                        *pOut = *pIn++;                        pOut += 2 * bytes - 1;                }                pOut += (iWidth*2 - 16) * bytes;        }        /* Calculate values if it's the second half */        if (iHalf) {                pIn = pIn0 + 128;                pOut = pOut0 + iOutY;                for (k = 0; k < 4; k++) {                        pOut1 = pOut;                        for (l=0; l<4; l++) {                                for (m=0; m<4; m++) {                                        int y10 = *(pIn+8);                                        int y00 = *pIn++;                                        int y11 = *(pIn+8);                                        int y01 = *pIn++;                                        int v   = *pOut1 - 128;                                        int u   = *(pOut1+1) - 128;                                        ov511_move_420_block(y00, y01, y10,                                                y11, u, v, iWidth, pOut1, bits);                                        pOut1 += 2 * bytes;                                }                                pOut1 += (iWidth*2 - 8) * bytes;                                pIn += 8;                        }                        pOut += 8 * bytes;                }        }}static voidov511_dumppix(unsigned char *pIn0, unsigned char *pOut0,              int iOutY, int iOutUV, int iHalf, int iWidth){        int i, j, k;        unsigned char *pIn, *pOut, *pOut1;        switch (dumppix) {        case 1: /* Just dump YUV data straight out for debug */                pOut0 += iOutY;                for (i = 0; i < HDIV; i++) {                        for (j = 0; j < WDIV; j++) {                                *pOut0++ = *pIn0++;                                *pOut0++ = *pIn0++;                                *pOut0++ = *pIn0++;                        }                        pOut0 += (iWidth - WDIV) * 3;                }                break;        case 2: /* This converts the Y data to "black-and-white" RGB data */                /* Useful for experimenting with compression */                pIn = pIn0 + 128;                pOut = pOut0 + iOutY;                for (i = 0; i < 4; i++) {                        pOut1 = pOut;                        for (j = 0; j < 8; j++) {                                for (k = 0; k < 8; k++) {                                        *pOut1++ = *pIn;                                        *pOut1++ = *pIn;                                        *pOut1++ = *pIn++;                                }                                pOut1 += (iWidth - 8) * 3;                        }                        pOut += 8 * 3;                }                break;        case 3: /* This will dump only the Y channel data stream as-is */                pIn = pIn0 + 128;                pOut = pOut0 + output_offset;                for (i = 0; i < 256; i++) {                        *pOut++ = *pIn;                        *pOut++ = *pIn;                        *pOut++ = *pIn++;                        output_offset += 3;                }                break;        } /* End switch (dumppix) */}/* This converts YUV420 segments to YUYV */static voidov511_parse_data_yuv422(unsigned char *pIn0, unsigned char *pOut0,                        int iOutY, int iOutUV, int iWidth){        int k, l, m;        unsigned char *pIn, *pOut, *pOut1;        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 += 2;                        }                        pOut1 += (iWidth - 8) * 2;                }                pOut += 8 * 2;        }        pIn = pIn0;        pOut = pOut0 + iOutUV + 1;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -