gspcadecoder.c

来自「linux下摄像头驱动 采用中星微301芯片」· C语言 代码 · 共 2,246 行 · 第 1/5 页

C
2,246
字号
    10, 19, 23, 32, 39, 45, 52, 54,    20, 22, 33, 38, 46, 51, 55, 60,    21, 34, 37, 47, 50, 56, 59, 61,    35, 36, 48, 49, 57, 58, 62, 63};static int aaidct[8] = {    IFIX(0.3535533906), IFIX(0.4903926402),    IFIX(0.4619397663), IFIX(0.4157348062),    IFIX(0.3535533906), IFIX(0.2777851165),    IFIX(0.1913417162), IFIX(0.0975451610)};inline static void idctqtab(unsigned char *qin, int *qout){    int i, j;    for (i = 0; i < 8; i++)	for (j = 0; j < 8; j++)	    qout[zig[i * 8 + j]] = qin[zig[i * 8 + j]] *		IMULT(aaidct[i], aaidct[j]);}inline static void scaleidctqtab(int *q, int sc){    int i;    for (i = 0; i < 64; i++)	q[i] = IMULT(q[i], sc);}/* Reduce to the necessary minimum. FIXME */void init_qTable(struct usb_spca50x *spca50x, unsigned int qIndex){    int i, j;    /* set up a quantization table */    for (i = 0; i < 2; i++) {	for (j = 0; j < 64; j++) {	    spca50x->maindecode.quant[i][j] =		GsmartQTable[qIndex * 2 + i][j];	}    }    idctqtab(spca50x->maindecode.	     quant[spca50x->maindecode.dscans[0].tq],	     spca50x->maindecode.dquant[0]);    idctqtab(spca50x->maindecode.	     quant[spca50x->maindecode.dscans[1].tq],	     spca50x->maindecode.dquant[1]);    idctqtab(spca50x->maindecode.	     quant[spca50x->maindecode.dscans[2].tq],	     spca50x->maindecode.dquant[2]);    /* rescale qtab */    //scaleidctqtab (spca50x->maindecode.dquant[0], IFIX (0.7));    //scaleidctqtab (spca50x->maindecode.dquant[1], IFIX (0.7));    //scaleidctqtab (spca50x->maindecode.dquant[2], IFIX (0.7));    }void init_jpeg_decoder(struct usb_spca50x *spca50x){    unsigned int i, j, k, l;    int tc, th, tt, tac, tdc;    const unsigned char *ptr;    unsigned int qIndex = spca50x->qindex;    memcpy(spca50x->maindecode.comps, comp_template,	   MAXCOMP * sizeof(struct comp));    /* set up the huffman table */    ptr = (const unsigned char *) GsmartJPEGHuffmanTable;    l = GSMART_JPG_HUFFMAN_TABLE_LENGTH;    while (l > 0) {	int hufflen[16];	unsigned char huffvals[256];	tc = *ptr++;	th = tc & 15;	tc >>= 4;	tt = tc * 2 + th;	if (tc > 1 || th > 1) {	    //printf("died whilst setting up huffman table.\n");	    //abort();	}	for (i = 0; i < 16; i++)	    hufflen[i] = *ptr++;	l -= 1 + 16;	k = 0;	for (i = 0; i < 16; i++) {	    for (j = 0; j < (unsigned int) hufflen[i]; j++)		huffvals[k++] = *ptr++;	    l -= hufflen[i];	}	dec_makehuff(dhuff + tt, hufflen, huffvals);    }    /* set up the scan table */    ptr = (const unsigned char *) GsmartJPEGScanTable;    for (i = 0; i < 3; i++) {	spca50x->maindecode.dscans[i].cid = *ptr++;	tdc = *ptr++;	tac = tdc & 15;	tdc >>= 4;	if (tdc > 1 || tac > 1) {	    //printf("died whilst setting up scan table.\n");	    //abort();	}	/* for each component */	for (j = 0; j < 3; j++)	    if (spca50x->maindecode.comps[j].cid ==		spca50x->maindecode.dscans[i].cid)		break;	spca50x->maindecode.dscans[i].hv = spca50x->maindecode.comps[j].hv;	spca50x->maindecode.dscans[i].tq = spca50x->maindecode.comps[j].tq;	spca50x->maindecode.dscans[i].hudc.dhuff = dec_huffdc + tdc;	spca50x->maindecode.dscans[i].huac.dhuff = dec_huffac + tac;    }    if (spca50x->maindecode.dscans[0].cid != 1 ||	spca50x->maindecode.dscans[1].cid != 2 ||	spca50x->maindecode.dscans[2].cid != 3) {	//printf("invalid cid found.\n");	//abort();    }    if (spca50x->maindecode.dscans[0].hv != 0x22 ||	spca50x->maindecode.dscans[1].hv != 0x11 ||	spca50x->maindecode.dscans[2].hv != 0x11) {	//printf("invalid hv found.\n");	//abort();    }    spca50x->maindecode.dscans[0].next = 6 - 4;    spca50x->maindecode.dscans[1].next = 6 - 4 - 1;    spca50x->maindecode.dscans[2].next = 6 - 4 - 1 - 1;	/* 411 encoding */    /* set up a quantization table */    init_qTable(spca50x, qIndex);}static int bgr = 0;/* Gamma correction setting *//*	Gtable[0][n] -> 2.2*	Gtable[1][n] -> 1.7*	Gtable[2][n] -> 1.45*	Gtable[3][n] -> 1*	Gtable[4][n] -> 0.6896*	Gtable[5][n] -> 0.5882*	Gtable[6][n] -> 0.4545*	gCor coeff 0..6*/int spca50x_outpicture(struct spca50x_frame *myframe){				/* general idea keep a frame in the temporary buffer from the tasklet */    /* decode with native format at input and asked format at output */    /* myframe->cameratype is the native input format */    /* myframe->format is the asked format */    struct pictparam *gCorrect = &myframe->pictsetting;    unsigned char *red = myframe->decoder->Red;    unsigned char *green = myframe->decoder->Green;    unsigned char *blue = myframe->decoder->Blue;    int width = 0;    int height = 0;    int done = 0;    int i;    if (gCorrect->change) {	if (gCorrect->change == 0x01) {	    /* Gamma setting change compute all case */	    memcpy(red, &GTable[gCorrect->gamma], 256);	    memcpy(green, &GTable[gCorrect->gamma], 256);	    memcpy(blue, &GTable[gCorrect->gamma], 256);	    for (i = 0; i < 256; i++) {		red[i] =		    CLIP(((red[i] +			   gCorrect->OffRed) * gCorrect->GRed) >> 8);		green[i] =		    CLIP(((green[i] +			   gCorrect->OffGreen) * gCorrect->GGreen) >> 8);		blue[i] =		    CLIP(((blue[i] +			   gCorrect->OffBlue) * gCorrect->GBlue) >> 8);	    }	    bgr = gCorrect->force_rgb;	    gCorrect->change = 0x00;	}	if (gCorrect->change == 0x02) {	    /* Red setting change compute Red Value */	    memcpy(red, &GTable[gCorrect->gamma], 256);	    for (i = 0; i < 256; i++) {		red[i] =		    CLIP(((red[i] +			   gCorrect->OffRed) * gCorrect->GRed) >> 8);	    }	    gCorrect->change &= ~0x02;	}	if (gCorrect->change == 0x04) {	    /* Green setting change compute Green Value */	    memcpy(green, &GTable[gCorrect->gamma], 256);	    for (i = 0; i < 256; i++) {		green[i] =		    CLIP(((green[i] +			   gCorrect->OffGreen) * gCorrect->GGreen) >> 8);	    }	    gCorrect->change &= ~0x04;	}	if (gCorrect->change == 0x08) {	    /* Blue setting change compute Blue Value */	    memcpy(blue, &GTable[gCorrect->gamma], 256);	    for (i = 0; i < 256; i++) {		blue[i] =		    CLIP(((blue[i] +			   gCorrect->OffBlue) * gCorrect->GBlue) >> 8);	    }	    gCorrect->change &= ~0x08;	}	if (gCorrect->change == 0x10) {	    /* force_rgb setting change   */	    bgr = gCorrect->force_rgb;	    gCorrect->change &= ~0x10;	}    }    switch (myframe->cameratype) {    case JPGC:	height = (myframe->data[11] << 8) | myframe->data[12];	width = (myframe->data[13] << 8) | myframe->data[14];	if (myframe->hdrheight != height || myframe->hdrwidth != width)	    done = ERR_CORRUPTFRAME;	else {	    //set info.dri struct should be kmalloc with the	    // instance camera	    myframe->decoder->info.dri = myframe->data[5];	    if (myframe->format == VIDEO_PALETTE_JPEG) {		memcpy(myframe->tmpbuffer, myframe->data,		       myframe->scanlength);		done = make_jpeg_conexant(myframe);	    } else {		memcpy(myframe->tmpbuffer,		       myframe->data + 39, myframe->scanlength - 39);		done = jpeg_decode422(myframe, bgr);	    }	}	break;    case JPGH:	width = (myframe->data[10] << 8) | myframe->data[11];	height = (myframe->data[12] << 8) | myframe->data[13];	/* some camera did not respond with the good height ie:Labtec Pro 240 -> 232 */	if (myframe->hdrwidth != width)	    done = ERR_CORRUPTFRAME;	else {	    // reset info.dri	    myframe->decoder->info.dri = 0;	    memcpy(myframe->tmpbuffer, myframe->data + 16,		   myframe->scanlength - 16);	    if (myframe->format == VIDEO_PALETTE_JPEG)		done = make_jpeg(myframe);	    else		done = jpeg_decode422(myframe, bgr);	}	break;    case JPGM:    case JPGS:	// reset info.dri	myframe->decoder->info.dri = 0;	memcpy(myframe->tmpbuffer, myframe->data, myframe->scanlength);	if (myframe->format == VIDEO_PALETTE_JPEG)	    done = make_jpeg(myframe);	else	    done = jpeg_decode422(myframe, bgr);	break;    case JPEG:	memcpy(myframe->tmpbuffer, myframe->data, myframe->scanlength);	if (myframe->format == VIDEO_PALETTE_JPEG)	    done = make_jpeg(myframe);	else	    done = jpeg_decode411(myframe, bgr);	break;    case YUVY:    case YUYV:    case YYUV:	memcpy(myframe->tmpbuffer, myframe->data, myframe->scanlength);	done = yuv_decode(myframe, bgr);	break;    case YUY2:    	memcpy(myframe->tmpbuffer, myframe->data, myframe->scanlength);    	done= yvyu_translate(myframe,bgr);    	break;    case PGBRG:	done = pixart_decompress(myframe);	if (done < 0)	    break;	done = bayer_decode(myframe, bgr);	break;    case GBGR:	/* translate the tv8532 stream into GBRG stream */	tv8532_preprocess(myframe);	done = bayer_decode(myframe, bgr);	break;    case GBRG:	memcpy(myframe->tmpbuffer, myframe->data, myframe->scanlength);	done = bayer_decode(myframe, bgr);	break;    case S561:	if (myframe->data[1] & 0x10)	    decode_spca561(myframe->data, myframe->tmpbuffer,			   myframe->width, myframe->height);	else	    memcpy(myframe->tmpbuffer, myframe->data + 20,		   myframe->scanlength);	done = bayer_decode(myframe, bgr);	break;    case SN9C:	sonix_decompress(myframe);	done = bayer_decode(myframe, bgr);	break;    default:	done = -1;	break;    }    return done;}static int yuv_decode(struct spca50x_frame *myframe, int force_rgb){    int r_offset, g_offset, b_offset;    int my, mx;			/* scan input surface */    unsigned char *pic1;	/* output surface */    __u16 *pix1, *pix2;		/* same for 16 bits output */    unsigned char *U, *V;	/* chroma output pointer */    int inuv, inv, pocx;	/* offset chroma input */    int iny, iny1;		/* offset luma input */    int nextinline, nextoutline;    int u1, v1, rg;    unsigned char y, y1;    char u, v;    unsigned char *pic = myframe->data;	/* output surface */    unsigned char *buf = myframe->tmpbuffer;	/* input surface */    int width = myframe->hdrwidth;    int height = myframe->hdrheight;    int softwidth = myframe->width;    int softheight = myframe->height;    //int method = myframe->method;    int format = myframe->format;    int cropx1 = myframe->cropx1;    int cropx2 = myframe->cropx2;    int cropy1 = myframe->cropy1;    int cropy2 = myframe->cropy2;    unsigned char *red = myframe->decoder->Red;    unsigned char *green = myframe->decoder->Green;    unsigned char *blue = myframe->decoder->Blue;    int bpp;    int framesize, frameUsize;    framesize = softwidth * softheight;    frameUsize = framesize >> 2;    /* rgb or bgr like U or V that's the question */    if (force_rgb) {	U = pic + framesize;	V = U + frameUsize;	r_offset = 2;	g_offset = 1;	b_offset = 0;    } else {	V = pic + framesize;	U = V + frameUsize;	r_offset = 0;	g_offset = 1;	b_offset = 2;    }    switch (myframe->cameratype) {    case YUVY:{	    iny = 0;			   /********* iny **********/	    inuv = width;		   /*** inuv **** inv ******/	    nextinline = 3 * width;	    inv = (nextinline >> 1);	    iny1 = width << 1;		   /********* iny1 *********/	}	break;    case YUYV:{	    iny = 0;			   /********* iny **********/	    inuv = width;		   /*** inuv **** iny1 *****/	    nextinline = 3 * width;	    iny1 = (nextinline >> 1);	    inv = iny1 + width;		    /*** iny1 **** inv ******/	}	break;    case YYUV:{	    iny = 0;			   /********* iny **********/	    iny1 = width;		   /********* iny1 *********/	    inuv = width << 1;		   /*** inuv **** inv ******/	    inv = inuv + (width >> 1);	    nextinline = 3 * width;	}	break;    default:{	    iny = 0;		/* make compiler happy */	    iny1 = 0;	    inuv = 0;	    inv = 0;	    nextinline = 0;	}	break;    }    /* Decode to the correct format. */    switch (format) {    case VIDEO_PALETTE_RGB565:	{	    bpp = 2;	    /* initialize */	    pix1 = (__u16 *) pic;	    pix2 = pix1 + softwidth;	    for (my = 0; my < height; my += 2) {		for (mx = 0, pocx = 0; mx < width; mx += 2, pocx++) {		    /* test if we need to decode */		    if ((my >= cropy1)			&& (my < height - cropy2)			&& (mx >= cropx1)			&& (mx < width - cropx2)) {			/* yes decode */			if (force_rgb) {			    u = buf[inuv + pocx];			    v = buf[inv + pocx];			} else {			    v = buf[inuv + pocx];			    u = buf[inv + pocx];			}			v1 = ((v << 10) + (v << 9)) >> 10;			rg = ((u << 8) + (u << 7) +			      (v << 9) + (v << 4)) >> 10;			u1 = ((u << 11) + (u << 4)) >

⌨️ 快捷键说明

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