📄 spcadecoder.c
字号:
/****************************************************************************# spcadecoder: Generic decoder for various input stream yyuv ## yuyv yuvy jpeg bayer rggb with gamma correct ## and various output palette rgb16 rgb24 rgb32 yuv420p ## various output size with crop feature ## Copyright (C) 2003 Michel Xhaard mxhaard@magic.fr ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 2 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, write to the Free Software ## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ## #****************************************************************************/#ifndef __KERNEL__#include <stdio.h>#include <stdlib.h>#include <string.h>#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <stdint.h>#include <sys/types.h>#else /* __KERNEL__ */#include <linux/string.h>#endif /* __KERNEL__ *//* FIXME */#define __u8 uint8_t#define __u16 uint16_t#define __u32 uint32_t#include "spcadecoder.h"#include "jpeg_header.h"#include "spcagamma.h"#include "spca50x.h"//int spca50x_outpicture (struct spca50x_frame *myframe, int force_rgb, int gCorrect);int spca50x_outpicture (struct spca50x_frame *myframe,int force_rgb,struct pictparam *gCorrect);static int jpeg_decode(struct spca50x_frame *myframe, int force_rgb);static int yuv_decode(struct spca50x_frame *myframe, int force_rgb);static int bayer_decode(struct spca50x_frame *myframe, int force_rgb);inline static void idct (int *, int *, int *, long, int);inline static void decode_mcus (struct in *, int *, int, struct scan *, int *);static void dec_makehuff (struct dec_hufftbl *, int *, unsigned char *);static void idctqtab (unsigned char *, int *);static void scaleidctqtab (int *, int);/* 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 Gtable[7][n] -> Red conponent after Correction Gtable[8][n] -> Green conponent after Correction Gtable[9][n] -> Blue conponent after Correction*///static int gCor = 2; static struct comp comps[MAXCOMP] = { {0x01, 0x22, 0x00}, {0x02, 0x11, 0x01}, {0x03, 0x11, 0x01}, {0x00, 0x00, 0x00}};static struct scan dscans[MAXCOMP];static unsigned char quant[4][64];static struct dec_hufftbl dhuff[4];#define dec_huffdc (dhuff + 0)#define dec_huffac (dhuff + 2)static struct in in;int dquant[3][64];voidjpeg_reset_input_context (unsigned char *buf){ /* set input context */ in.p = buf; in.left = 0; in.bits = 0; in.marker = 0;}#define CLIP(color) (unsigned char)((color>0xFF)?0xff:((color<0)?0:color))int spca50x_outpicture (struct spca50x_frame *myframe, int force_rgb,struct pictparam *gCorrect){ /* 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 */ int done = 0; int i; // gCor = gCorrect; if ( gCorrect->change == 0x01) { /* Gamma setting change compute all case */ memcpy (>able[7],>able[gCorrect->gamma],256); memcpy (>able[8],>able[gCorrect->gamma],256); memcpy (>able[9],>able[gCorrect->gamma],256); for (i =0; i < 256 ; i++){ GTable[7][i] = CLIP(((GTable[7][i] + gCorrect->OffRed) * gCorrect->GRed) >> 8); GTable[8][i] = CLIP(((GTable[8][i] + gCorrect->OffGreen) * gCorrect->GGreen) >> 8); GTable[9][i] = CLIP(((GTable[9][i] + gCorrect->OffBlue) * gCorrect->GBlue) >> 8); } } else if ( gCorrect->change == 0x02) { /* Red setting change compute Red Value */ memcpy (>able[7],>able[gCorrect->gamma],256); for (i =0; i < 256 ; i++){ GTable[7][i] = CLIP(((GTable[7][i] + gCorrect->OffRed) * gCorrect->GRed) >> 8); } } else if ( gCorrect->change == 0x04) { /* Green setting change compute Green Value */ memcpy (>able[8],>able[gCorrect->gamma],256); for (i =0; i < 256 ; i++){ GTable[8][i] = CLIP(((GTable[8][i] + gCorrect->OffGreen) * gCorrect->GGreen) >> 8); } } else if ( gCorrect->change == 0x08) { /* Blue setting change compute Blue Value */ memcpy (>able[9],>able[gCorrect->gamma],256); for (i =0; i < 256 ; i++){ GTable[9][i] = CLIP(((GTable[9][i] + gCorrect->OffBlue) * gCorrect->GBlue) >> 8); } } gCorrect->change = 0 ; switch(myframe->cameratype){ case JPEG: done = jpeg_decode( myframe, force_rgb); break; case YUVY: case YUYV: case YYUV: done = yuv_decode( myframe, force_rgb); break; case GBRG: done = bayer_decode( myframe, force_rgb); break; default : done = -1; break; }return done; }static int yuv_decode(struct spca50x_frame *myframe, int force_rgb ){ int cropx1,cropx2,cropy1,cropy2; int r_offset, g_offset, b_offset; int my , mx; /* scan input surface */ unsigned char *pic, *pic1; /* output surface */ __u16 *pix1,*pix2; /* same for 16 bits output */ unsigned char *buf; /* input surface */ 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; int width; int height; int softwidth; int softheight; int method; int format; int bpp; int framesize, frameUsize; /* init usefull data */ pic = myframe->data; buf = myframe->tmpbuffer; width = myframe->hdrwidth; height = myframe->hdrheight; softwidth = myframe->width; softheight = myframe->height; method = myframe->method; format = myframe->format; cropx1 = myframe->cropx1; cropx2 = myframe->cropx2; cropy1 = myframe->cropy1; cropy2 = myframe->cropy2; 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)) >> 10; /* top pixel Right */ y1 = 128 +buf [iny + mx]; *pix1++ = ((GTable[7][CLIP((y1 + v1))] & 0xF8) >> 3 | ((GTable[8][CLIP((y1 - rg))] & 0xFC) << 3) | ((GTable[9][CLIP((y1 + u1))] & 0xF8) << 8)) ; /* top pixel Left */ y1 = 128 +buf [iny + mx +1]; *pix1++ = ((GTable[7][CLIP((y1 + v1))] & 0xF8) >> 3 | ((GTable[8][CLIP((y1 - rg))] & 0xFC) << 3) | ((GTable[9][CLIP((y1 + u1))] & 0xF8) << 8)) ; /* bottom pixel Right */ y1 = 128 + buf [iny1 + mx]; *pix2++ = ((GTable[7][CLIP((y1 + v1))] & 0xF8) >> 3 | ((GTable[8][CLIP((y1 - rg))] & 0xFC) << 3) | ((GTable[9][CLIP((y1 + u1))] & 0xF8) << 8)) ; /* bottom pixel Left */ y1 = 128 + buf [iny1 + mx + 1]; *pix2++ = ((GTable[7][CLIP((y1 + v1))] & 0xF8) >> 3 | ((GTable[8][CLIP((y1 - rg))] & 0xFC) << 3) | ((GTable[9][CLIP((y1 + u1))] & 0xF8) << 8)) ; } // end test decode } // end mx loop iny += nextinline; inuv += nextinline ; inv += nextinline ; iny1 += nextinline; if (my >= cropy1){ /* are we in a decode surface move the output pointer */ pix1 += softwidth ; pix2 += softwidth ; } } // end my loop } break; case VIDEO_PALETTE_RGB32: case VIDEO_PALETTE_RGB24: { bpp = (format == VIDEO_PALETTE_RGB32) ? 4 : 3; /* initialize */ nextoutline = bpp * softwidth; pic1 = pic + nextoutline; 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 */ 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)) >> 10; y = 128 +buf [iny + mx]; /* top pixel Right */ pic[r_offset] = GTable[7][CLIP ((y + v1))]; pic[g_offset] = GTable[8][CLIP ((y - rg))]; pic[b_offset] = GTable[9][CLIP ((y + u1))]; pic += bpp; /* top pixel Left */ y = 128 +buf [iny + mx +1]; pic[r_offset] = GTable[7][CLIP ((y + v1))]; pic[g_offset] = GTable[8][CLIP ((y - rg))]; pic[b_offset] = GTable[9][CLIP ((y + u1))]; pic += bpp; /* bottom pixel Right */ y1 = 128 + buf [iny1 + mx]; pic1[r_offset] = GTable[7][CLIP ((y1 + v1))]; pic1[g_offset] = GTable[8][CLIP ((y1 - rg))]; pic1[b_offset] = GTable[9][CLIP ((y1 + u1))]; pic1 += bpp; /* bottom pixel Left */ y1 = 128 + buf [iny1 + mx + 1]; pic1[r_offset] = GTable[7][CLIP ((y1 + v1))]; pic1[g_offset] = GTable[8][CLIP ((y1 - rg))]; pic1[b_offset] = GTable[9][CLIP ((y1 + u1))]; pic1 += bpp; } // end test decode } // end mx loop iny += nextinline; inuv += nextinline ; inv += nextinline ; iny1 += nextinline; if (my >= cropy1){ /* are we in a decode surface move the output pointer */ pic += nextoutline; pic1 += nextoutline; } } // end my loop } break; case VIDEO_PALETTE_YUV420P: { /* initialize */ pic1 = pic + 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 */ *V++ = 128 + buf [inuv + pocx]; *U++ = 128 + buf [inv + pocx] ; *pic++ = 128 +buf [iny + mx]; *pic++ = 128 +buf [iny + mx+1]; *pic1++ = 128 + buf [iny1 + mx]; *pic1++ = 128 + buf [iny1 + mx +1]; } // end test decode } // end mx loop iny += nextinline; inuv += nextinline; inv += nextinline; iny1 += nextinline; if (my >= cropy1){ /* are we in a decode surface move the output pointer */ pic += softwidth; pic1 += softwidth; } } // end my loop } break; default: break; }// end case return 0;}/* * linux/drivers/video/fbcon-jpegdec.c - a tiny jpeg decoder. * * (w) August 2001 by Michael Schroeder, <mls@suse.de> * * I severly gutted this beast and hardcoded it to the palette and subset * of jpeg needed for the spca50x driver. Also converted it from K&R style * C to a more modern form ;). Michael can't be blamed for what is left. * All nice features are his, all bugs are mine. - till * * Change color space converter for YUVP and RGB - * Rework the IDCT implementation for best speed * For more details about idct look at : * http://rnvs.informatik.tu-chemnitz.de/~jan/MPEG/HTML/IDCT.html * 12/12/2003 mxhaard@magic.fr */static intjpeg_decode (struct spca50x_frame *myframe, int force_rgb){ int mcusx, mcusy, mx, my; int dcts[6 * 64 + 16]; int out[64 * 6]; int max[6]; int i; int bpp; int framesize, frameUsize; int k, j; int nextline, nextuv, nextblk, nextnewline; unsigned char *pic0, *pic1, *outv, *outu; __u16 *pix1,*pix2; int picy, picx, pocx, pocy; unsigned char *U, *V; int *outy, *inv, *inu; int outy1, outy2; int v, u, y1, v1, u1, u2; int r_offset, g_offset, b_offset; int cropx1,cropx2,cropy1,cropy2; unsigned char *pic; unsigned char *buf; int width; int height; int softwidth; int softheight; int method; int format; /* init usefull data */ pic = myframe->data; buf = myframe->tmpbuffer; width = myframe->hdrwidth; height = myframe->hdrheight; softwidth = myframe->width; softheight = myframe->height; method = myframe->method; format = myframe->format; cropx1 = myframe->cropx1; cropx2 = myframe->cropx2; cropy1 = myframe->cropy1; cropy2 = myframe->cropy2; if ((height & 15) || (width & 15)) return 1; if (width < softwidth || height < softheight) return 1; mcusx = width >> 4; mcusy = height >> 4; framesize = softwidth * softheight; frameUsize = framesize >> 2; jpeg_reset_input_context (buf); /* for each component. Reset dc values. */ for (i = 0; i < 3; i++) dscans[i].dc = 0; /* 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; } /* Decode to the correct format. */ switch (format) { case VIDEO_PALETTE_RGB565: { bpp = 2; nextline = ((softwidth << 1) - 16);// *bpp; nextblk = bpp * (softwidth << 4); nextnewline = softwidth ; // *bpp; for (my = 0, picy = 0; my < mcusy; my++) { for (mx = 0, picx = 0; mx < mcusx; mx++) { decode_mcus (&in, dcts, 6, dscans, max); if ((my >= cropy1) && (my < mcusy - cropy2) && (mx >= cropx1) && (mx < mcusx - cropx2)) { idct (dcts, out, dquant[0], IFIX (128.5),
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -