/* transfrm.c, forward / inverse transformation */ /* Copyright (C) 1996, MPEG Software Simulation Group. All Rights Reserved. */ /* * Disclaimer of Warranty * * These software programs are available to the user without any license fee or * royalty on an "as is" basis. The MPEG Software Simulation Group disclaims * any and all warranties, whether express, implied, or statuary, including any * implied warranties or merchantability or of fitness for a particular * purpose. In no event shall the copyright-holder be liable for any * incidental, punitive, or consequential damages of any kind whatsoever * arising from the use of these programs. * * This disclaimer of warranty extends to the user of these programs and user's * customers, employees, agents, transferees, successors, and assigns. * * The MPEG Software Simulation Group does not represent or warrant that the * programs furnished hereunder are free of infringement of any third-party * patents. * * Commercial implementations of MPEG-1 and MPEG-2 video, including shareware, * are subject to royalty fees to patent holders. Many of these patents are * general enough such that they are unavoidable regardless of implementation * design. * */ #include #include #include "config.h" #include "global.h" /* private prototypes*/ static void add_pred _ANSI_ARGS_((unsigned char *pred, unsigned char *cur, int lx, short *blk)); static void sub_pred _ANSI_ARGS_((unsigned char *pred, unsigned char *cur, int lx, short *blk)); /* subtract prediction and transform prediction error */ void transform(pred,cur,mbi,blocks) unsigned char *pred[], *cur[]; struct mbinfo *mbi; short blocks[][64]; { int i, j, i1, j1, k, n, cc, offs, lx; k = 0; for (j=0; j>1)); lx = width<<1; } else { /* frame DCT */ offs = i + ((n&1)<<3) + width2*(j+((n&2)<<2)); lx = width2; } if (pict_struct==BOTTOM_FIELD) offs += width; } else { /* chrominance */ /* scale coordinates */ i1 = (chroma_format==CHROMA444) ? i : i>>1; j1 = (chroma_format!=CHROMA420) ? j : j>>1; if ((pict_struct==FRAME_PICTURE) && mbi[k].dct_type && (chroma_format!=CHROMA420)) { /* field DCT */ offs = i1 + (n&8) + chrom_width*(j1+((n&2)>>1)); lx = chrom_width<<1; } else { /* frame DCT */ offs = i1 + (n&8) + chrom_width2*(j1+((n&2)<<2)); lx = chrom_width2; } if (pict_struct==BOTTOM_FIELD) offs += chrom_width; } sub_pred(pred[cc]+offs,cur[cc]+offs,lx,blocks[k*block_count+n]); fdct(blocks[k*block_count+n]); } k++; } } /* inverse transform prediction error and add prediction */ void itransform(pred,cur,mbi,blocks) unsigned char *pred[],*cur[]; struct mbinfo *mbi; short blocks[][64]; { int i, j, i1, j1, k, n, cc, offs, lx; k = 0; for (j=0; j>1)); lx = width<<1; } else { /* frame DCT */ offs = i + ((n&1)<<3) + width2*(j+((n&2)<<2)); lx = width2; } if (pict_struct==BOTTOM_FIELD) offs += width; } else { /* chrominance */ /* scale coordinates */ i1 = (chroma_format==CHROMA444) ? i : i>>1; j1 = (chroma_format!=CHROMA420) ? j : j>>1; if ((pict_struct==FRAME_PICTURE) && mbi[k].dct_type && (chroma_format!=CHROMA420)) { /* field DCT */ offs = i1 + (n&8) + chrom_width*(j1+((n&2)>>1)); lx = chrom_width<<1; } else { /* frame DCT */ offs = i1 + (n&8) + chrom_width2*(j1+((n&2)<<2)); lx = chrom_width2; } if (pict_struct==BOTTOM_FIELD) offs += chrom_width; } idct(blocks[k*block_count+n]); add_pred(pred[cc]+offs,cur[cc]+offs,lx,blocks[k*block_count+n]); } k++; } } /* add prediction and prediction error, saturate to 0...255 */ static void add_pred(pred,cur,lx,blk) unsigned char *pred, *cur; int lx; short *blk; { int i, j; for (j=0; j<8; j++) { for (i=0; i<8; i++) cur[i] = clp[blk[i] + pred[i]]; blk+= 8; cur+= lx; pred+= lx; } } /* subtract prediction from block data */ static void sub_pred(pred,cur,lx,blk) unsigned char *pred, *cur; int lx; short *blk; { int i, j; for (j=0; j<8; j++) { for (i=0; i<8; i++) blk[i] = cur[i] - pred[i]; blk+= 8; cur+= lx; pred+= lx; } } /* * select between frame and field DCT * * preliminary version: based on inter-field correlation */ void dct_type_estimation(pred,cur,mbi) unsigned char *pred,*cur; struct mbinfo *mbi; { short blk0[128], blk1[128]; int i, j, i0, j0, k, offs, s0, s1, sq0, sq1, s01; double d, r; k = 0; for (j0=0; j00.0) { r = (s01-(s0*s1)/128.0)/sqrt(d); if (r>0.5) mbi[k].dct_type = 0; /* frame DCT */ else mbi[k].dct_type = 1; /* field DCT */ } else mbi[k].dct_type = 1; /* field DCT */ } k++; } }