Skip to content

AFNI/NIfTI Server

Sections
Personal tools
You are here: Home » AFNI » Documentation

Doxygen Source Code Documentation


Main Page   Alphabetical List   Data Structures   File List   Data Fields   Globals   Search  

block.c

Go to the documentation of this file.
00001 /*===========================================================================*
00002  * block.c                                                                   *
00003  *                                                                           *
00004  *      Block routines                                                       *
00005  *                                                                           *
00006  * EXPORTED PROCEDURES:                                                      *
00007  *      ComputeDiffDCTBlock                                                  *
00008  *      ComputeDiffDCTs                                                      *
00009  *      ComputeMotionBlock                                                   *
00010  *      ComputeMotionLumBlock                                                *
00011  *      LumBlockMAD                                                          *
00012  *      LumMotionError                                                       *
00013  *      LumMotionErrorSubSampled                                             *
00014  *      LumAddMotionError                                                    *
00015  *      AddMotionBlock                                                       *
00016  *      BlockToData                                                          *
00017  *      BlockifyFrame                                                        *
00018  *                                                                           *
00019  * NOTES:   MAD =   Mean Absolute Difference                                 *
00020  *                                                                           *
00021  *===========================================================================*/
00022 
00023 /*
00024  * Copyright (c) 1995 The Regents of the University of California.
00025  * All rights reserved.
00026  *
00027  * Permission to use, copy, modify, and distribute this software and its
00028  * documentation for any purpose, without fee, and without written agreement is
00029  * hereby granted, provided that the above copyright notice and the following
00030  * two paragraphs appear in all copies of this software.
00031  *
00032  * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
00033  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
00034  * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
00035  * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00036  *
00037  * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
00038  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
00039  * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
00040  * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
00041  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
00042  */
00043 
00044 /*  
00045  *  $Header: /misc/elrond0/share/cvs/AFNI/src/mpeg_encodedir/block.c,v 1.4 2004/04/02 15:12:40 rwcox Exp $
00046  *  $Log: block.c,v $
00047  *  Revision 1.4  2004/04/02 15:12:40  rwcox
00048  *  Cput
00049  *
00050  *  Revision 1.3  2003/12/23 13:50:08  rwcox
00051  *  Cput
00052  *
00053  *  Revision 1.2  2003/12/03 14:46:14  rwcox
00054  *  Cput
00055  *
00056  *  Revision 1.1  2001/12/17 16:11:53  rwcox
00057  *  Cadd
00058  *
00059  *  Revision 1.16  1995/08/07 21:43:29  smoot
00060  *  restructured lumdiff so it read better and used a switch instead of ifs
00061  *
00062  *  Revision 1.15  1995/06/21 22:21:16  smoot
00063  *  added TUNEing options
00064  *
00065  * Revision 1.14  1995/05/08  22:47:45  smoot
00066  * typechecking better
00067  *
00068  * Revision 1.13  1995/05/08  22:44:14  smoot
00069  * added prototypes (postdct.h)
00070  *
00071  * Revision 1.12  1995/05/02  21:44:07  smoot
00072  * added tuneing parameters
00073  *
00074  * Revision 1.11  1995/03/31  23:50:45  smoot
00075  * removed block bound (moved to opts.c)
00076  *
00077  * Revision 1.10  1995/03/29  20:12:39  smoot
00078  * added block_bound for TUNEing
00079  *
00080  * Revision 1.9  1995/02/01  21:43:55  smoot
00081  * cleanup
00082  *
00083  * Revision 1.8  1995/01/19  23:52:43  smoot
00084  * Made computeDiffDCTs able to rule out changes to the pattern (diff too small)
00085  *
00086  * Revision 1.7  1995/01/19  23:07:17  eyhung
00087  * Changed copyrights
00088  *
00089  * Revision 1.6  1994/11/12  02:11:44  keving
00090  * nothing
00091  *
00092  * Revision 1.5  1993/12/22  19:19:01  keving
00093  * nothing
00094  *
00095  * Revision 1.5  1993/12/22  19:19:01  keving
00096  * nothing
00097  *
00098  * Revision 1.4  1993/07/22  22:23:43  keving
00099  * nothing
00100  *
00101  * Revision 1.3  1993/06/30  20:06:09  keving
00102  * nothing
00103  *
00104  * Revision 1.2  1993/06/03  21:08:08  keving
00105  * nothing
00106  *
00107  * Revision 1.1  1993/04/08  21:31:59  keving
00108  * nothing
00109  *
00110  */
00111 
00112 
00113 /*==============*
00114  * HEADER FILES *
00115  *==============*/
00116 
00117 #include "all.h"
00118 #include "mtypes.h"
00119 #include "frames.h"
00120 #include "bitio.h"
00121 #include "prototypes.h"
00122 #include "fsize.h"
00123 #include "opts.h"
00124 #include "postdct.h"
00125 
00126 #undef ABS
00127 #define ABS(x)  ((x < 0) ? (-x) : x)
00128 
00129 #define TRUNCATE_UINT8(x)       ((x < 0) ? 0 : ((x > 255) ? 255 : x))
00130 
00131 /*==================*
00132  * GLOBAL VARIABLES *
00133  *==================*/
00134 
00135 
00136 extern Block **dct, **dctb, **dctr;
00137 
00138 /*===========================*
00139  * COMPUTE DCT OF DIFFERENCE *
00140  *===========================*/
00141 
00142 /*===========================================================================*
00143  *
00144  * ComputeDiffDCTBlock
00145  *
00146  *      compute current-motionBlock, take the DCT, and put the difference
00147  *      back into current
00148  *
00149  * RETURNS:     current block modified
00150  *
00151  * SIDE EFFECTS:    none
00152  *
00153  *===========================================================================*/
00154 boolean
00155 ComputeDiffDCTBlock(current, dest, motionBlock)
00156     Block current, dest, motionBlock;
00157 {
00158     register int x, y, diff = 0;
00159 
00160     for ( y = 0; y < 8; y++ ) {
00161         for ( x = 0; x < 8; x++ ) {
00162           current[y][x] -= motionBlock[y][x];
00163           diff += ABS(current[y][x]);
00164         }
00165     }
00166     /* Kill the block if change is too small     */
00167     /* (block_bound defaults to 128, see opts.c) */
00168     if (diff < block_bound) return FALSE;
00169 
00170     mp_fwd_dct_block2(current, dest);
00171 
00172     return TRUE;
00173 }
00174 
00175 /*===========================================================================*
00176  *
00177  * ComputeDiffDCTs
00178  *
00179  *      appropriate (according to pattern, the coded block pattern) blocks
00180  *      of 'current' are diff'ed and DCT'd.
00181  *
00182  * RETURNS:     current blocks modified
00183  *
00184  * SIDE EFFECTS:    Can remove too-small difference blocks from pattern
00185  *
00186  * PRECONDITIONS:       appropriate blocks of 'current' have not yet been
00187  *                      modified
00188  *
00189  *===========================================================================*/
00190 void
00191 ComputeDiffDCTs(current, prev, by, bx, my, mx, pattern)
00192     MpegFrame *current;
00193     MpegFrame *prev;
00194     int by;
00195     int bx;
00196     int my;
00197     int mx;
00198     int *pattern;
00199 {
00200     Block   motionBlock;
00201 
00202     if (collect_quant && (collect_quant_detailed & 1)) fprintf(collect_quant_fp, "l\n");
00203     if ( *pattern & 0x20 ) {
00204         ComputeMotionBlock(prev->ref_y, by, bx, my, mx, motionBlock);
00205         if (!ComputeDiffDCTBlock(current->y_blocks[by][bx], dct[by][bx], motionBlock))
00206           *pattern^=0x20;
00207     }
00208 
00209     if ( *pattern & 0x10 ) {
00210         ComputeMotionBlock(prev->ref_y, by, bx+1, my, mx, motionBlock);
00211         if (!ComputeDiffDCTBlock(current->y_blocks[by][bx+1], dct[by][bx+1], motionBlock))
00212           *pattern^=0x10;
00213     }
00214 
00215     if ( *pattern & 0x8 ) {
00216         ComputeMotionBlock(prev->ref_y, by+1, bx, my, mx, motionBlock);
00217         if (!ComputeDiffDCTBlock(current->y_blocks[by+1][bx], dct[by+1][bx], motionBlock))
00218           *pattern^=0x8;
00219     }
00220 
00221     if ( *pattern & 0x4 ) {
00222         ComputeMotionBlock(prev->ref_y, by+1, bx+1, my, mx, motionBlock);
00223         if (!ComputeDiffDCTBlock(current->y_blocks[by+1][bx+1], dct[by+1][bx+1], motionBlock))
00224           *pattern^=0x4;
00225     }
00226 
00227     if (collect_quant && (collect_quant_detailed & 1)) fprintf(collect_quant_fp, "c\n");
00228     if ( *pattern & 0x2 ) {
00229         ComputeMotionBlock(prev->ref_cb, by >> 1, bx >> 1, my/2, mx/2, motionBlock);
00230         if (!ComputeDiffDCTBlock(current->cb_blocks[by >> 1][bx >> 1], dctb[by >> 1][bx >> 1], motionBlock))
00231           *pattern^=0x2;
00232     }
00233 
00234     if ( *pattern & 0x1 ) {
00235         ComputeMotionBlock(prev->ref_cr, by >> 1, bx >> 1, my/2, mx/2, motionBlock);
00236         if (!ComputeDiffDCTBlock(current->cr_blocks[by >> 1][bx >> 1], dctr[by >> 1][bx >> 1], motionBlock))
00237           *pattern^=0x1;
00238     }
00239 }
00240 
00241 
00242         /*======================*
00243          * COMPUTE MOTION BLOCK *
00244          *======================*/
00245 
00246 /*===========================================================================*
00247  *
00248  * ComputeMotionBlock
00249  *
00250  *      compute the motion-compensated block
00251  *
00252  * RETURNS:     motionBlock
00253  *
00254  * SIDE EFFECTS:    none
00255  *
00256  * PRECONDITIONS:       motion vector MUST be valid
00257  *
00258  * NOTE:  could try to speed this up using halfX, halfY, halfBoth,
00259  *        but then would have to compute for chrominance, and it's just
00260  *        not worth the trouble (this procedure is not called relatively
00261  *        often -- a constant number of times per macroblock)
00262  *
00263  *===========================================================================*/
00264 void
00265 ComputeMotionBlock(prev, by, bx, my, mx, motionBlock)
00266     uint8 **prev;
00267     int by;     
00268     int bx;
00269     int my;
00270     int mx;
00271     Block motionBlock;
00272 {
00273     register int   fy, fx;
00274     register int   y;
00275     register int16 *destPtr;
00276     register uint8 *srcPtr;
00277     register uint8 *srcPtr2;
00278     boolean xHalf, yHalf;
00279 
00280     xHalf = (ABS(mx) % 2 == 1);
00281     yHalf = (ABS(my) % 2 == 1);
00282 
00283     MOTION_TO_FRAME_COORD(by, bx, (my/2), (mx/2), fy, fx);
00284 
00285     if ( xHalf && yHalf ) {
00286         /* really should be fy+y-1 and fy+y so do (fy-1)+y = fy+y-1 and
00287            (fy-1)+y+1 = fy+y
00288          */
00289         if ( my < 0 ) {
00290             fy--;
00291         }
00292         if ( mx < 0 ) {
00293             fx--;
00294         }
00295 
00296         for ( y = 0; y < 8; y++ ) {
00297             destPtr = motionBlock[y];
00298             srcPtr = &(prev[fy+y][fx]);
00299             srcPtr2 = &(prev[fy+y+1][fx]);
00300 
00301             destPtr[0] = (srcPtr[0]+srcPtr[1]+srcPtr2[0]+srcPtr2[1]+2)>>2;
00302             destPtr[1] = (srcPtr[1]+srcPtr[2]+srcPtr2[1]+srcPtr2[2]+2)>>2;
00303             destPtr[2] = (srcPtr[2]+srcPtr[3]+srcPtr2[2]+srcPtr2[3]+2)>>2;
00304             destPtr[3] = (srcPtr[3]+srcPtr[4]+srcPtr2[3]+srcPtr2[4]+2)>>2;
00305             destPtr[4] = (srcPtr[4]+srcPtr[5]+srcPtr2[4]+srcPtr2[5]+2)>>2;
00306             destPtr[5] = (srcPtr[5]+srcPtr[6]+srcPtr2[5]+srcPtr2[6]+2)>>2;
00307             destPtr[6] = (srcPtr[6]+srcPtr[7]+srcPtr2[6]+srcPtr2[7]+2)>>2;
00308             destPtr[7] = (srcPtr[7]+srcPtr[8]+srcPtr2[7]+srcPtr2[8]+2)>>2;
00309         }
00310     } else if ( xHalf ) {
00311         if ( mx < 0 ) {
00312             fx--;
00313         }
00314 
00315         for ( y = 0; y < 8; y++ ) {
00316             destPtr = motionBlock[y];
00317             srcPtr = &(prev[fy+y][fx]);
00318 
00319             destPtr[0] = (srcPtr[0]+srcPtr[1]+1)>>1;
00320             destPtr[1] = (srcPtr[1]+srcPtr[2]+1)>>1;
00321             destPtr[2] = (srcPtr[2]+srcPtr[3]+1)>>1;
00322             destPtr[3] = (srcPtr[3]+srcPtr[4]+1)>>1;
00323             destPtr[4] = (srcPtr[4]+srcPtr[5]+1)>>1;
00324             destPtr[5] = (srcPtr[5]+srcPtr[6]+1)>>1;
00325             destPtr[6] = (srcPtr[6]+srcPtr[7]+1)>>1;
00326             destPtr[7] = (srcPtr[7]+srcPtr[8]+1)>>1;
00327         }
00328     } else if ( yHalf ) {
00329         if ( my < 0 ) {
00330             fy--;
00331         }
00332 
00333         for ( y = 0; y < 8; y++ ) {
00334             destPtr = motionBlock[y];
00335             srcPtr = &(prev[fy+y][fx]);
00336             srcPtr2 = &(prev[fy+y+1][fx]);
00337 
00338             destPtr[0] = (srcPtr[0]+srcPtr2[0]+1)>>1;
00339             destPtr[1] = (srcPtr[1]+srcPtr2[1]+1)>>1;
00340             destPtr[2] = (srcPtr[2]+srcPtr2[2]+1)>>1;
00341             destPtr[3] = (srcPtr[3]+srcPtr2[3]+1)>>1;
00342             destPtr[4] = (srcPtr[4]+srcPtr2[4]+1)>>1;
00343             destPtr[5] = (srcPtr[5]+srcPtr2[5]+1)>>1;
00344             destPtr[6] = (srcPtr[6]+srcPtr2[6]+1)>>1;
00345             destPtr[7] = (srcPtr[7]+srcPtr2[7]+1)>>1;
00346         }
00347     } else {
00348         for ( y = 0; y < 8; y++ ) {
00349             destPtr = motionBlock[y];
00350             srcPtr = &(prev[fy+y][fx]);
00351 
00352             destPtr[0] = (uint8) srcPtr[0];
00353             destPtr[1] = (uint8) srcPtr[1];
00354             destPtr[2] = (uint8) srcPtr[2];
00355             destPtr[3] = (uint8) srcPtr[3];
00356             destPtr[4] = (uint8) srcPtr[4];
00357             destPtr[5] = (uint8) srcPtr[5];
00358             destPtr[6] = (uint8) srcPtr[6];
00359             destPtr[7] = (uint8) srcPtr[7];
00360         }
00361     }
00362 }
00363 
00364 
00365 /*===========================================================================*
00366  *
00367  * ComputeMotionLumBlock
00368  *
00369  *      compute the motion-compensated luminance block
00370  *
00371  * RETURNS:     motionBlock
00372  *
00373  * SIDE EFFECTS:    none
00374  *
00375  * PRECONDITIONS:       motion vector MUST be valid
00376  *
00377  * NOTE:  see ComputeMotionBlock
00378  *
00379  *===========================================================================*/
00380 void
00381 ComputeMotionLumBlock(prevFrame, by, bx, my, mx, motionBlock)
00382     MpegFrame *prevFrame;
00383     int by;
00384     int bx;
00385     int my;
00386     int mx;
00387     LumBlock motionBlock;
00388 {
00389     register uint8 *across;
00390     register int32 *macross;
00391     register int y;
00392     uint8 **prev;
00393     int     fy, fx;
00394     boolean xHalf, yHalf;
00395 
00396     xHalf = (ABS(mx) % 2 == 1);
00397     yHalf = (ABS(my) % 2 == 1);
00398 
00399     MOTION_TO_FRAME_COORD(by, bx, my/2, mx/2, fy, fx);
00400 
00401     if ( xHalf ) {
00402         if ( mx < 0 ) {
00403             fx--;
00404         }
00405 
00406         if ( yHalf ) {
00407             if ( my < 0 ) {
00408                 fy--;
00409             }
00410             
00411             prev = prevFrame->halfBoth;
00412         } else {
00413             prev = prevFrame->halfX;
00414         }
00415     } else if ( yHalf ) {
00416         if ( my < 0 ) {
00417             fy--;
00418         }
00419 
00420         prev = prevFrame->halfY;
00421     } else {
00422         prev = prevFrame->ref_y;
00423     }
00424 
00425     for ( y = 0; y < 16; y++ ) {
00426         across = &(prev[fy+y][fx]);
00427         macross = motionBlock[y];
00428 
00429         macross[0] = across[0];
00430         macross[1] = across[1];
00431         macross[2] = across[2];
00432         macross[3] = across[3];
00433         macross[4] = across[4];
00434         macross[5] = across[5];
00435         macross[6] = across[6];
00436         macross[7] = across[7];
00437         macross[8] = across[8];
00438         macross[9] = across[9];
00439         macross[10] = across[10];
00440         macross[11] = across[11];
00441         macross[12] = across[12];
00442         macross[13]= across[13];
00443         macross[14] = across[14];
00444         macross[15] = across[15];
00445     }
00446 
00447     /* this is what's really happening, in slow motion:
00448      *
00449      *  for ( y = 0; y < 16; y++, py++ )
00450      *      for ( x = 0; x < 16; x++, px++ )
00451      *          motionBlock[y][x] = prev[fy+y][fx+x];
00452      *
00453      */
00454 }
00455 
00456 
00457 /*=======================*
00458  * BASIC ERROR FUNCTIONS *
00459  *=======================*/
00460 
00461 
00462 /*===========================================================================*
00463  *
00464  * LumBlockMAD
00465  *
00466  *      return the MAD of two luminance blocks
00467  *
00468  * RETURNS:     the MAD, if less than bestSoFar, or
00469  *              some number bigger if not
00470  *
00471  * SIDE EFFECTS:    none
00472  *
00473  *===========================================================================*/
00474 int32
00475 LumBlockMAD(currentBlock, motionBlock, bestSoFar)
00476     LumBlock currentBlock;
00477     LumBlock motionBlock;
00478     int32 bestSoFar;
00479 {
00480     register int32   diff = 0;    /* max value of diff is 255*256 = 65280 */
00481     register int32 localDiff;
00482     register int y, x;
00483 
00484     for ( y = 0; y < 16; y++ ) {
00485         for ( x = 0; x < 16; x++ ) {
00486             localDiff = currentBlock[y][x] - motionBlock[y][x];
00487             diff += ABS(localDiff);
00488         }
00489 
00490         if ( diff > bestSoFar ) {
00491             return diff;
00492         }
00493     }
00494 
00495     return (int32)diff;
00496 }
00497 
00498 
00499 /*===========================================================================*
00500  *
00501  * LumMotionError
00502  *
00503  *      return the MAD of the currentBlock and the motion-compensated block
00504  *      (without TUNEing)
00505  *
00506  * RETURNS:     the MAD, if less than bestSoFar, or
00507  *              some number bigger if not
00508  *
00509  * SIDE EFFECTS:    none
00510  *
00511  * PRECONDITIONS:  motion vector MUST be valid
00512  *
00513  * NOTES:  this is the procedure that is called the most, and should therefore
00514  *         be the most optimized!!!
00515  *
00516  *===========================================================================*/
00517 int32
00518 LumMotionError(currentBlock, prevFrame, by, bx, my, mx, bestSoFar)
00519     LumBlock currentBlock;
00520     MpegFrame *prevFrame;
00521     int by;
00522     int bx;
00523     int my;     
00524     int mx;         
00525     int32 bestSoFar;
00526 {
00527     register int32 adiff = 0,  diff = 0;    /* max value of diff is 255*256 = 65280 */
00528     register int32 localDiff;
00529     register uint8 *across;
00530     register int32 *cacross;
00531     register int y;
00532     uint8 **prev;
00533     int     fy, fx;
00534     boolean xHalf, yHalf;
00535 
00536     xHalf = (ABS(mx) % 2 == 1);
00537     yHalf = (ABS(my) % 2 == 1);
00538 
00539     MOTION_TO_FRAME_COORD(by, bx, my/2, mx/2, fy, fx);
00540 
00541     if ( xHalf ) {
00542         if ( mx < 0 ) {
00543             fx--;
00544         }
00545 
00546         if ( yHalf ) {
00547             if ( my < 0 ) {
00548                 fy--;
00549             }
00550             
00551             prev = prevFrame->halfBoth;
00552         } else {
00553             prev = prevFrame->halfX;
00554         }
00555     } else if ( yHalf ) {
00556         if ( my < 0 ) {
00557             fy--;
00558         }
00559 
00560         prev = prevFrame->halfY;
00561     } else {
00562         prev = prevFrame->ref_y;
00563     }
00564 
00565     switch (SearchCompareMode) {
00566     case DEFAULT_SEARCH: /* Default. */
00567       /* this is what's happening:
00568        *        ComputeMotionLumBlock(prevFrame, by, bx, my, mx, lumMotionBlock);
00569        *        for ( y = 0; y < 16; y++ )
00570        *            for ( x = 0; x < 16; x++ )
00571        *            {
00572        *                localDiff = currentBlock[y][x] - lumMotionBlock[y][x];
00573        *                diff += ABS(localDiff);
00574        *            }
00575        */
00576       for ( y = 0; y < 16; y++ ) {
00577         across = &(prev[fy+y][fx]);
00578         cacross = currentBlock[y];
00579         
00580         localDiff = across[0]-cacross[0];     diff += ABS(localDiff);
00581         localDiff = across[1]-cacross[1];     diff += ABS(localDiff);
00582         localDiff = across[2]-cacross[2];     diff += ABS(localDiff);
00583         localDiff = across[3]-cacross[3];     diff += ABS(localDiff);
00584         localDiff = across[4]-cacross[4];     diff += ABS(localDiff);
00585         localDiff = across[5]-cacross[5];     diff += ABS(localDiff);
00586         localDiff = across[6]-cacross[6];     diff += ABS(localDiff);
00587         localDiff = across[7]-cacross[7];     diff += ABS(localDiff);
00588         localDiff = across[8]-cacross[8];     diff += ABS(localDiff);
00589         localDiff = across[9]-cacross[9];     diff += ABS(localDiff);
00590         localDiff = across[10]-cacross[10];     diff += ABS(localDiff);
00591         localDiff = across[11]-cacross[11];     diff += ABS(localDiff);
00592         localDiff = across[12]-cacross[12];     diff += ABS(localDiff);
00593         localDiff = across[13]-cacross[13];     diff += ABS(localDiff);
00594         localDiff = across[14]-cacross[14];     diff += ABS(localDiff);
00595         localDiff = across[15]-cacross[15];     diff += ABS(localDiff);
00596         
00597         if ( diff > bestSoFar ) {
00598           return diff;
00599         }
00600       }
00601       break;
00602       
00603     case LOCAL_DCT: {
00604       Block     dctdiff[4], dctquant[4];
00605       FlatBlock quant;
00606       int x, i, tmp;
00607       int distortion=0, datarate=0;
00608       int pq = GetPQScale();
00609       
00610       for (y = 0;  y < 16;  y++) {
00611         across = &(prev[fy+y][fx]);
00612         cacross = currentBlock[y];
00613         for (x = 0;  x < 16;  x++) {
00614           dctdiff[(x>7)+2*(y>7)][y%8][x%8] = cacross[x]-across[x];
00615         }}
00616 
00617       /* Calculate rate */
00618       for (i = 0;  i < 4;  i++) {
00619         mp_fwd_dct_block2(dctdiff[i], dctdiff[i]);
00620         if (Mpost_QuantZigBlock(dctdiff[i], quant, pq, FALSE) == MPOST_ZERO) {
00621           /* no sense in continuing */
00622           memset((char *)dctquant[i], 0, sizeof(Block));
00623         } else {
00624           Mpost_UnQuantZigBlock(quant, dctquant[i], pq, FALSE);
00625           mpeg_jrevdct((int16 *)dctquant[i]);
00626           datarate += CalcRLEHuffLength(quant);
00627         }
00628       }
00629       
00630       /* Calculate distortion */
00631       for (y = 0;  y < 16;  y++) {
00632         across = &(prev[fy+y][fx]);
00633         cacross = currentBlock[y];
00634         for (x = 0;  x < 16;  x++) {
00635           tmp = across[x] - cacross[x] + dctquant[(x>7)+2*(y>7)][y%8][x%8];
00636           distortion += tmp*tmp;
00637         }}
00638       distortion /= 256;
00639       distortion *= LocalDCTDistortScale;
00640       datarate *= LocalDCTRateScale;
00641       diff = (int) sqrt(distortion*distortion + datarate*datarate);
00642       break;
00643     }
00644 
00645     case NO_DC_SEARCH: {
00646       extern int32 niqtable[];
00647       int pq = niqtable[0]*GetPQScale();
00648       
00649       for ( y = 0; y < 16; y++ ) {
00650         across = &(prev[fy+y][fx]);
00651         cacross = currentBlock[y];
00652 
00653         localDiff = across[0]-cacross[0];  diff += localDiff; adiff += ABS(localDiff);
00654         localDiff = across[1]-cacross[1];  diff += localDiff; adiff += ABS(localDiff);
00655         localDiff = across[2]-cacross[2];  diff += localDiff; adiff += ABS(localDiff);
00656         localDiff = across[3]-cacross[3];  diff += localDiff; adiff += ABS(localDiff);
00657         localDiff = across[4]-cacross[4];  diff += localDiff; adiff += ABS(localDiff);
00658         localDiff = across[5]-cacross[5];  diff += localDiff; adiff += ABS(localDiff);
00659         localDiff = across[6]-cacross[6];  diff += localDiff; adiff += ABS(localDiff);
00660         localDiff = across[7]-cacross[7];  diff += localDiff; adiff += ABS(localDiff);
00661         localDiff = across[8]-cacross[8];  diff += localDiff; adiff += ABS(localDiff);
00662         localDiff = across[9]-cacross[9];  diff += localDiff; adiff += ABS(localDiff);
00663         localDiff = across[10]-cacross[10];  diff += localDiff; adiff += ABS(localDiff);
00664         localDiff = across[11]-cacross[11];  diff += localDiff; adiff += ABS(localDiff);
00665         localDiff = across[12]-cacross[12];  diff += localDiff; adiff += ABS(localDiff);
00666         localDiff = across[13]-cacross[13];  diff += localDiff; adiff += ABS(localDiff);
00667         localDiff = across[14]-cacross[14];  diff += localDiff; adiff += ABS(localDiff);
00668         localDiff = across[15]-cacross[15];  diff += localDiff; adiff += ABS(localDiff);
00669 
00670       }
00671 
00672       diff /= 64*pq;  /* diff is now the DC difference (with QSCALE 1) */
00673       adiff -= 64*pq*ABS(diff);
00674       diff = adiff;
00675     }
00676       break;
00677 
00678     case DO_Mean_Squared_Distortion:
00679       for ( y = 0; y < 16; y++ ) {
00680         across = &(prev[fy+y][fx]);
00681         cacross = currentBlock[y];
00682 
00683         localDiff = across[0]-cacross[0];     diff += localDiff*localDiff;
00684         localDiff = across[1]-cacross[1];     diff += localDiff*localDiff;
00685         localDiff = across[2]-cacross[2];     diff += localDiff*localDiff;
00686         localDiff = across[3]-cacross[3];     diff += localDiff*localDiff;
00687         localDiff = across[4]-cacross[4];     diff += localDiff*localDiff;
00688         localDiff = across[5]-cacross[5];     diff += localDiff*localDiff;
00689         localDiff = across[6]-cacross[6];     diff += localDiff*localDiff;
00690         localDiff = across[7]-cacross[7];     diff += localDiff*localDiff;
00691         localDiff = across[8]-cacross[8];     diff += localDiff*localDiff;
00692         localDiff = across[9]-cacross[9];     diff += localDiff*localDiff;
00693         localDiff = across[10]-cacross[10];     diff += localDiff*localDiff;
00694         localDiff = across[11]-cacross[11];     diff += localDiff*localDiff;
00695         localDiff = across[12]-cacross[12];     diff += localDiff*localDiff;
00696         localDiff = across[13]-cacross[13];     diff += localDiff*localDiff;
00697         localDiff = across[14]-cacross[14];     diff += localDiff*localDiff;
00698         localDiff = across[15]-cacross[15];     diff += localDiff*localDiff;
00699 
00700         if ( diff > bestSoFar ) {
00701           return diff;
00702         }
00703       }
00704       break;
00705     } /* End of Switch */
00706 
00707     return diff;
00708 }
00709 
00710 
00711 /*===========================================================================*
00712  *
00713  * LumAddMotionError
00714  *
00715  *      return the MAD of the currentBlock and the average of the blockSoFar
00716  *      and the motion-compensated block (this is used for B-frame searches)
00717  *
00718  * RETURNS:     the MAD, if less than bestSoFar, or
00719  *              some number bigger if not
00720  *
00721  * SIDE EFFECTS:    none
00722  *
00723  * PRECONDITIONS:  motion vector MUST be valid
00724  *
00725  *===========================================================================*/
00726 int32
00727 LumAddMotionError(currentBlock, blockSoFar, prevFrame, by, bx, my, mx,
00728                   bestSoFar)
00729     LumBlock currentBlock;
00730     LumBlock blockSoFar;
00731     MpegFrame *prevFrame;
00732     int by;
00733     int bx;
00734     int my;
00735     int mx;
00736     int32 bestSoFar;
00737 {
00738     register int32   diff = 0;    /* max value of diff is 255*256 = 65280 */
00739     register int32 localDiff;
00740     register uint8 *across;
00741     register int32 *bacross;
00742     register int32 *cacross;
00743     register int y;
00744     uint8 **prev;
00745     int     fy, fx;
00746     boolean xHalf, yHalf;
00747 
00748     xHalf = (ABS(mx) % 2 == 1);
00749     yHalf = (ABS(my) % 2 == 1);
00750 
00751     MOTION_TO_FRAME_COORD(by, bx, my/2, mx/2, fy, fx);
00752 
00753     if ( xHalf ) {
00754         if ( mx < 0 ) {
00755             fx--;
00756         }
00757 
00758         if ( yHalf ) {
00759             if ( my < 0 ) {
00760                 fy--;
00761             }
00762             
00763             prev = prevFrame->halfBoth;
00764         } else {
00765             prev = prevFrame->halfX;
00766         }
00767     } else if ( yHalf ) {
00768         if ( my < 0 ) {
00769             fy--;
00770         }
00771 
00772         prev = prevFrame->halfY;
00773     } else {
00774         prev = prevFrame->ref_y;
00775     }
00776 
00777 /* do we add 1 before dividing by two?  Yes -- see MPEG-1 doc page 46 */
00778 
00779 #define ADD_ADD_DIFF(d,l,a,b,c,i)       \
00780     l = ((a[i]+b[i]+1)>>1)-c[i];        \
00781     d += ABS(l)
00782 
00783     for ( y = 0; y < 16; y++ ) {
00784         across = &(prev[fy+y][fx]);
00785         bacross = blockSoFar[y];
00786         cacross = currentBlock[y];
00787 
00788         ADD_ADD_DIFF(diff,localDiff,across,bacross,cacross,0);
00789         ADD_ADD_DIFF(diff,localDiff,across,bacross,cacross,1);
00790         ADD_ADD_DIFF(diff,localDiff,across,bacross,cacross,2);
00791         ADD_ADD_DIFF(diff,localDiff,across,bacross,cacross,3);
00792         ADD_ADD_DIFF(diff,localDiff,across,bacross,cacross,4);
00793         ADD_ADD_DIFF(diff,localDiff,across,bacross,cacross,5);
00794         ADD_ADD_DIFF(diff,localDiff,across,bacross,cacross,6);
00795         ADD_ADD_DIFF(diff,localDiff,across,bacross,cacross,7);
00796         ADD_ADD_DIFF(diff,localDiff,across,bacross,cacross,8);
00797         ADD_ADD_DIFF(diff,localDiff,across,bacross,cacross,9);
00798         ADD_ADD_DIFF(diff,localDiff,across,bacross,cacross,10);
00799         ADD_ADD_DIFF(diff,localDiff,across,bacross,cacross,11);
00800         ADD_ADD_DIFF(diff,localDiff,across,bacross,cacross,12);
00801         ADD_ADD_DIFF(diff,localDiff,across,bacross,cacross,13);
00802         ADD_ADD_DIFF(diff,localDiff,across,bacross,cacross,14);
00803         ADD_ADD_DIFF(diff,localDiff,across,bacross,cacross,15);
00804 
00805         if ( diff > bestSoFar ) {
00806             return diff;
00807         }
00808     }
00809 
00810     /* this is what's happening:
00811      *
00812      *  ComputeMotionLumBlock(prevFrame, by, bx, my, mx, lumMotionBlock);
00813      *
00814      *  for ( y = 0; y < 16; y++ )
00815      *      for ( x = 0; x < 16; x++ )
00816      *      {
00817      *          localDiff = currentBlock[y][x] - lumMotionBlock[y][x];
00818      *          diff += ABS(localDiff);
00819      *      }
00820      *
00821      */
00822 
00823     return diff;
00824 }
00825 
00826 
00827 /*===========================================================================*
00828  *
00829  * AddMotionBlock
00830  *
00831  *      adds the motion-compensated block to the given block
00832  *
00833  * RETURNS:     block modified
00834  *
00835  * SIDE EFFECTS:    none
00836  *
00837  * PRECONDITIONS:  motion vector MUST be valid
00838  *
00839  *===========================================================================*/
00840 void
00841 AddMotionBlock(block, prev, by, bx, my, mx)
00842     Block block;
00843     uint8 **prev;
00844     int by;
00845     int bx;
00846     int my;
00847     int mx;
00848 {
00849     int     fy, fx;
00850     int     x, y;
00851     boolean xHalf, yHalf;
00852 
00853     xHalf = (ABS(mx) % 2 == 1);
00854     yHalf = (ABS(my) % 2 == 1);
00855 
00856     MOTION_TO_FRAME_COORD(by, bx, (my/2), (mx/2), fy, fx);
00857 
00858     if ( xHalf && yHalf ) {
00859         /* really should be fy+y-1 and fy+y so do (fy-1)+y = fy+y-1 and
00860            (fy-1)+y+1 = fy+y
00861          */
00862         if ( my < 0 ) {
00863             fy--;
00864         }
00865         if ( mx < 0 ) {
00866             fx--;
00867         }
00868 
00869         for ( y = 0; y < 8; y++ ) {
00870             for ( x = 0; x < 8; x++ ) {
00871                 block[y][x] += (prev[fy+y][fx+x]+prev[fy+y][fx+x+1]+
00872                                     prev[fy+y+1][fx+x]+prev[fy+y+1][fx+x+1]+2)>>2;
00873             }
00874         }
00875     } else if ( xHalf ) {
00876         if ( mx < 0 ) {
00877             fx--;
00878         }
00879 
00880         for ( y = 0; y < 8; y++ ) {
00881             for ( x = 0; x < 8; x++ ) {
00882                 block[y][x] += (prev[fy+y][fx+x]+prev[fy+y][fx+x+1]+1)>>1;
00883             }
00884         }
00885     } else if ( yHalf ) {
00886         if ( my < 0 ) {
00887             fy--;
00888         }
00889 
00890         for ( y = 0; y < 8; y++ ) {
00891             for ( x = 0; x < 8; x++ ) {
00892                 block[y][x] += (prev[fy+y][fx+x]+prev[fy+y+1][fx+x]+1)>>1;
00893             }
00894         }
00895     } else {
00896         for ( y = 0; y < 8; y++ ) {
00897             for ( x = 0; x < 8; x++ ) {
00898                 block[y][x] += (int16)prev[fy+y][fx+x];
00899             }
00900         }
00901     }
00902 }
00903 
00904 
00905 /*===========================================================================*
00906  *
00907  * AddBMotionBlock
00908  *
00909  *      adds the motion-compensated B-frame block to the given block
00910  *
00911  * RETURNS:     block modified
00912  *
00913  * SIDE EFFECTS:    none
00914  *
00915  * PRECONDITIONS:  motion vectors MUST be valid
00916  *
00917  *===========================================================================*/
00918 void
00919 AddBMotionBlock(block, prev, next, by, bx, mode, fmy, fmx, bmy, bmx)
00920     Block block;
00921     uint8 **prev;
00922     uint8 **next;
00923     int by;
00924     int bx;
00925     int mode;
00926     int fmy;
00927     int fmx;
00928     int bmy;
00929     int bmx;
00930 {
00931     int     x, y;
00932     Block   prevBlock, nextBlock;
00933 
00934     if ( mode == MOTION_FORWARD ) {
00935         AddMotionBlock(block, prev, by, bx, fmy, fmx);
00936     } else if ( mode == MOTION_BACKWARD ) {
00937         AddMotionBlock(block, next, by, bx, bmy, bmx);
00938     } else {
00939         ComputeMotionBlock(prev, by, bx, fmy, fmx, prevBlock);
00940         ComputeMotionBlock(next, by, bx, bmy, bmx, nextBlock);
00941 
00942         for ( y = 0; y < 8; y++ ) {
00943             for ( x = 0; x < 8; x++ ) {
00944                 block[y][x] += (prevBlock[y][x]+nextBlock[y][x]+1)/2;
00945             }
00946         }
00947     }
00948 }
00949 
00950 
00951 /*===========================================================================*
00952  *
00953  * BlockToData
00954  *
00955  *      copies the given block into the appropriate data area
00956  *
00957  * RETURNS:     data modified
00958  *
00959  * SIDE EFFECTS:    none
00960  *
00961  *===========================================================================*/
00962 void
00963 BlockToData(data, block, by, bx)
00964     uint8 **data;
00965     Block block;
00966     int by;
00967     int bx;
00968 {
00969     register int x, y;
00970     register int fy, fx;
00971     register int16    blockItem;
00972 
00973     BLOCK_TO_FRAME_COORD(by, bx, fy, fx);
00974 
00975     for ( y = 0; y < 8; y++ ) {
00976         for ( x = 0; x < 8; x++ ) {
00977             blockItem = block[y][x];
00978             data[fy+y][fx+x] = TRUNCATE_UINT8(blockItem);
00979         }
00980     }
00981 }
00982 
00983 
00984 /*===========================================================================*
00985  *
00986  * BlockifyFrame
00987  *
00988  *      copies data into appropriate blocks
00989  *
00990  * RETURNS:     mf modified
00991  *
00992  * SIDE EFFECTS:    none
00993  *
00994  * NOTES:  probably shouldn't be in this file
00995  *
00996  *===========================================================================*/
00997 void
00998 BlockifyFrame(framePtr)
00999     MpegFrame *framePtr;
01000 {
01001     register int dctx, dcty;
01002     register int x, y;
01003     register int bx, by;
01004     register int fy, fx;
01005     register int16  *destPtr;
01006     register uint8  *srcPtr;
01007     register int16  *destPtr2;
01008     register uint8  *srcPtr2;
01009     Block   *blockPtr;
01010     Block   *blockPtr2;
01011 
01012     dctx = Fsize_x / DCTSIZE;
01013     dcty = Fsize_y / DCTSIZE;
01014 
01015     /*
01016      * copy y data into y_blocks
01017      */
01018     for (by = 0; by < dcty; by++) {
01019         fy = by*DCTSIZE;
01020         for (bx = 0; bx < dctx; bx++) {
01021             fx = bx*DCTSIZE;
01022             blockPtr = (Block *) &(framePtr->y_blocks[by][bx][0][0]);
01023             for (y = 0; y < DCTSIZE; y++) {
01024                 destPtr = &((*blockPtr)[y][0]);
01025                 srcPtr = &(framePtr->orig_y[fy+y][fx]);
01026                 for (x = 0; x < DCTSIZE; x++) {
01027                     destPtr[x] = srcPtr[x];
01028                 }
01029             }
01030         }
01031     }
01032 
01033     /*
01034      * copy cr/cb data into cr/cb_blocks
01035      */
01036     for (by = 0; by < (dcty >> 1); by++) {
01037         fy = by*DCTSIZE;
01038         for (bx = 0; bx < (dctx >> 1); bx++) {
01039             fx = bx*DCTSIZE;
01040             blockPtr = (Block *) &(framePtr->cr_blocks[by][bx][0][0]);
01041             blockPtr2 = (Block *) &(framePtr->cb_blocks[by][bx][0][0]);
01042             for (y = 0; y < DCTSIZE; y++) {
01043                 destPtr = &((*blockPtr)[y][0]);
01044                 srcPtr = &(framePtr->orig_cr[fy+y][fx]);
01045                 destPtr2 = &((*blockPtr2)[y][0]);
01046                 srcPtr2 = &(framePtr->orig_cb[fy+y][fx]);
01047                 for (x = 0; x < DCTSIZE; x++) {
01048                     destPtr[x] = srcPtr[x];
01049                     destPtr2[x] = srcPtr2[x];
01050                 }
01051             }
01052         }
01053     }
01054 }
01055 
01056 
01057 /*===========================================================================*
01058  *                                                                           *
01059  * UNUSED PROCEDURES                                                         *
01060  *                                                                           *
01061  *      The following procedures are all unused by the encoder               *
01062  *                                                                           *
01063  *      They are listed here for your convenience.  You might want to use    *
01064  *      them if you experiment with different search techniques              *
01065  *                                                                           *
01066  *===========================================================================*/
01067 
01068 #ifdef UNUSED_PROCEDURES
01069 
01070 /* this procedure calculates the subsampled motion block (obviously)
01071  *
01072  * for speed, this procedure is probably not called anywhere (it is
01073  * incorporated directly into LumDiffA, LumDiffB, etc.
01074  *
01075  * but leave it here anyway for clarity
01076  *
01077  * (startY, startX) = (0,0) for A....(0,1) for B...(1,0) for C...(1,1) for D
01078  *  
01079  */
01080 void
01081 ComputeSubSampledMotionLumBlock(prevFrame, by, bx, my, mx, motionBlock,
01082                                 startY, startX)
01083     MpegFrame *prevFrame;
01084     int by;
01085     int bx;
01086     int my;
01087     int mx;
01088     LumBlock motionBlock;
01089     int startY;
01090     int startX;
01091 {
01092     register uint8 *across;
01093     register int32 *macross;
01094     register int32 *lastx;
01095     register int y;
01096     uint8 **prev;
01097     int    fy, fx;
01098     boolean xHalf, yHalf;
01099 
01100     xHalf = (ABS(mx) % 2 == 1);
01101     yHalf = (ABS(my) % 2 == 1);
01102 
01103     MOTION_TO_FRAME_COORD(by, bx, my/2, mx/2, fy, fx);
01104 
01105     if ( xHalf ) {
01106         if ( mx < 0 ) {
01107             fx--;
01108         }
01109 
01110         if ( yHalf ) {
01111             if ( my < 0 ) {
01112                 fy--;
01113             }
01114             
01115             prev = prevFrame->halfBoth;
01116         } else {
01117             prev = prevFrame->halfX;
01118         }
01119     } else if ( yHalf ) {
01120         if ( my < 0 ) {
01121             fy--;
01122         }
01123 
01124         prev = prevFrame->halfY;
01125     } else {
01126         prev = prevFrame->ref_y;
01127     }
01128 
01129     for ( y = startY; y < 16; y += 2 ) {
01130         across = &(prev[fy+y][fx+startX]);
01131         macross = &(motionBlock[y][startX]);
01132         lastx = &(motionBlock[y][16]);
01133         while ( macross < lastx ) {
01134             (*macross) = (*across);
01135             across += 2;
01136             macross += 2;
01137         }
01138     }
01139 
01140     /* this is what's really going on in slow motion:
01141      *
01142      *  for ( y = startY; y < 16; y += 2 )
01143      *      for ( x = startX; x < 16; x += 2 )
01144      *          motionBlock[y][x] = prev[fy+y][fx+x];
01145      *
01146      */
01147 }
01148 
01149 
01150 /*===========================================================================*
01151  *
01152  * LumMotionErrorSubSampled
01153  *
01154  *      return the MAD of the currentBlock and the motion-compensated block,
01155  *      subsampled 4:1 with given starting coordinates (startY, startX)
01156  *
01157  * RETURNS:     the MAD
01158  *
01159  * SIDE EFFECTS:    none
01160  *
01161  * PRECONDITIONS:  motion vector MUST be valid
01162  *
01163  * NOTES:  this procedure is never called.  Instead, see subsample.c.  This
01164  *         procedure is provided only for possible use in extensions
01165  *
01166  *===========================================================================*/
01167 int32
01168 LumMotionErrorSubSampled(currentBlock, prevFrame, by, bx, my, mx, startY,
01169                          startX)
01170     LumBlock currentBlock;
01171     MpegFrame *prevFrame;
01172     int by;
01173     int bx;
01174     int my;
01175     int mx;
01176     int startY;
01177     int startX;
01178 {
01179     register int32    diff = 0;     /* max value of diff is 255*256 = 65280 */
01180     register int32 localDiff;
01181     register int32 *cacross;
01182     register uint8 *macross;
01183     register int32 *lastx;
01184     register int y;
01185     uint8 **prev;
01186     int    fy, fx;
01187     boolean xHalf, yHalf;
01188 
01189     xHalf = (ABS(mx) % 2 == 1);
01190     yHalf = (ABS(my) % 2 == 1);
01191 
01192     MOTION_TO_FRAME_COORD(by, bx, my/2, mx/2, fy, fx);
01193 
01194     if ( xHalf ) {
01195         if ( mx < 0 ) {
01196             fx--;
01197         }
01198 
01199         if ( yHalf ) {
01200             if ( my < 0 ) {
01201                 fy--;
01202             }
01203             
01204             prev = prevFrame->halfBoth;
01205         } else {
01206             prev = prevFrame->halfX;
01207         }
01208     } else if ( yHalf ) {
01209         if ( my < 0 ) {
01210             fy--;
01211         }
01212 
01213         prev = prevFrame->halfY;
01214     } else {
01215         prev = prevFrame->ref_y;
01216     }
01217 
01218     for ( y = startY; y < 16; y += 2 ) {
01219         macross = &(prev[fy+y][fx+startX]);
01220         cacross = &(currentBlock[y][startX]);
01221         lastx = &(currentBlock[y][16]);
01222         while ( cacross < lastx ) {
01223             localDiff = (*cacross)-(*macross);
01224             diff += ABS(localDiff);
01225             macross += 2;
01226             cacross += 2;
01227         }
01228     }
01229 
01230     /* this is what's really happening:
01231      *
01232      *  ComputeSubSampledMotionLumBlock(prevFrame, by, bx, my, mx,
01233      *                                  lumMotionBlock, startY, startX);
01234      *
01235      *  for ( y = startY; y < 16; y += 2 )
01236      *      for ( x = startX; x < 16; x += 2 )
01237      *      {
01238      *          localDiff = currentBlock[y][x] - lumMotionBlock[y][x];
01239      *          diff += ABS(localDiff);
01240      *      }
01241      *
01242      */
01243 
01244     return (int32)diff;
01245 }
01246 
01247 
01248 #endif /* UNUSED_PROCEDURES */
 

Powered by Plone

This site conforms to the following standards: