home *** CD-ROM | disk | FTP | other *** search
/ DP Tool Club 9 / CD_ASCQ_09_1193.iso / news / 4441 / mpegcode / src / block.c < prev    next >
C/C++ Source or Header  |  1993-09-27  |  28KB  |  1,082 lines

  1. /*===========================================================================*
  2.  * block.c                                     *
  3.  *                                         *
  4.  *    Block routines                                 *
  5.  *                                         *
  6.  * EXPORTED PROCEDURES:                                 *
  7.  *    ComputeDiffDCTBlock                             *
  8.  *    ComputeDiffDCTs                                 *
  9.  *    ComputeMotionBlock                             *
  10.  *    ComputeMotionLumBlock                             *
  11.  *    LumBlockMAD                                 *
  12.  *    LumMotionError                                 *
  13.  *    LumMotionErrorSubSampled                         *
  14.  *    LumAddMotionError                             *
  15.  *    AddMotionBlock                                 *
  16.  *    BlockToData                                 *
  17.  *    BlockifyFrame                                 *
  18.  *                                         *
  19.  * NOTES:   MAD    =   Mean Absolute Difference                     *
  20.  *                                         *
  21.  *===========================================================================*/
  22.  
  23. /*
  24.  * Copyright (c) 1993 The Regents of the University of California.
  25.  * All rights reserved.
  26.  *
  27.  * Permission to use, copy, modify, and distribute this software and its
  28.  * documentation for any purpose, without fee, and without written agreement is
  29.  * hereby granted, provided that the above copyright notice and the following
  30.  * two paragraphs appear in all copies of this software.
  31.  *
  32.  * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
  33.  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
  34.  * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
  35.  * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  36.  *
  37.  * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
  38.  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
  39.  * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
  40.  * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
  41.  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
  42.  */
  43.  
  44. /*  
  45.  *  $Header: /n/picasso/users/keving/encode/src/RCS/block.c,v 1.4 1993/07/22 22:23:43 keving Exp keving $
  46.  *  $Log: block.c,v $
  47.  * Revision 1.4  1993/07/22  22:23:43  keving
  48.  * nothing
  49.  *
  50.  * Revision 1.3  1993/06/30  20:06:09  keving
  51.  * nothing
  52.  *
  53.  * Revision 1.2  1993/06/03  21:08:08  keving
  54.  * nothing
  55.  *
  56.  * Revision 1.1  1993/04/08  21:31:59  keving
  57.  * nothing
  58.  *
  59.  */
  60.  
  61.  
  62. /*==============*
  63.  * HEADER FILES *
  64.  *==============*/
  65.  
  66. #include "all.h"
  67. #include "mtypes.h"
  68. #include "frames.h"
  69. #include "bitio.h"
  70. #include "prototypes.h"
  71. #include "fsize.h"
  72.  
  73.  
  74. #undef ABS
  75. #define ABS(x)    ((x < 0) ? (-x) : x)
  76.  
  77. #define TRUNCATE_UINT8(x)    ((x < 0) ? 0 : ((x > 255) ? 255 : x))
  78.  
  79.  
  80. /*==========================*
  81.  * INITIALIZATION FUNCTIONS *
  82.  *==========================*/
  83.  
  84.  
  85. /*===========================*
  86.  * COMPUTE DCT OF DIFFERENCE *
  87.  *===========================*/
  88.  
  89. /*===========================================================================*
  90.  *
  91.  * ComputeDiffDCTBlock
  92.  *
  93.  *    compute current-motionBlock, take the DCT, and put the difference
  94.  *    back into current
  95.  *
  96.  * RETURNS:    current block modified
  97.  *
  98.  * SIDE EFFECTS:    none
  99.  *
  100.  *===========================================================================*/
  101. void
  102. ComputeDiffDCTBlock(current, motionBlock)
  103.     Block current;
  104.     Block motionBlock;
  105. {
  106.     register int x, y;
  107.  
  108.     for ( y = 0; y < 8; y++ ) {
  109.     for ( x = 0; x < 8; x++ ) {
  110.         current[y][x] -= motionBlock[y][x];
  111.     }
  112.     }
  113.  
  114.     mp_fwd_dct_block(current);
  115.  
  116.     return /* nothing */;
  117. }
  118.  
  119.  
  120. /*===========================================================================*
  121.  *
  122.  * ComputeDiffDCTs
  123.  *
  124.  *    appropriate (according to pattern, the coded block pattern) blocks
  125.  *    of 'current' are diff'ed and DCT'd.
  126.  *
  127.  * RETURNS:    current blocks modified
  128.  *
  129.  * SIDE EFFECTS:    none
  130.  *
  131.  * PRECONDITIONS:    appropriate blocks of 'current' have not yet been
  132.  *            modified
  133.  *
  134.  *===========================================================================*/
  135. void
  136. ComputeDiffDCTs(current, prev, by, bx, my, mx, pattern)
  137.     MpegFrame *current;
  138.     MpegFrame *prev;
  139.     int by;
  140.     int bx;
  141.     int my;
  142.     int mx;
  143.     int pattern;
  144. {
  145.     Block   motionBlock;
  146.  
  147.     if ( pattern & 0x20 ) {
  148.     ComputeMotionBlock(prev->ref_y, by, bx, my, mx, motionBlock);
  149.     ComputeDiffDCTBlock(current->y_blocks[by][bx], motionBlock);
  150.     }
  151.  
  152.     if ( pattern & 0x10 ) {
  153.     ComputeMotionBlock(prev->ref_y, by, bx+1, my, mx, motionBlock);
  154.     ComputeDiffDCTBlock(current->y_blocks[by][bx+1], motionBlock);
  155.     }
  156.  
  157.     if ( pattern & 0x8 ) {
  158.     ComputeMotionBlock(prev->ref_y, by+1, bx, my, mx, motionBlock);
  159.     ComputeDiffDCTBlock(current->y_blocks[by+1][bx], motionBlock);
  160.     }
  161.  
  162.     if ( pattern & 0x4 ) {
  163.     ComputeMotionBlock(prev->ref_y, by+1, bx+1, my, mx, motionBlock);
  164.     ComputeDiffDCTBlock(current->y_blocks[by+1][bx+1], motionBlock);
  165.     }
  166.  
  167.     if ( pattern & 0x2 ) {
  168.     ComputeMotionBlock(prev->ref_cb, by >> 1, bx >> 1, my/2, mx/2, motionBlock);
  169.     ComputeDiffDCTBlock(current->cb_blocks[by >> 1][bx >> 1], motionBlock);
  170.     }
  171.  
  172.     if ( pattern & 0x1 ) {
  173.     ComputeMotionBlock(prev->ref_cr, by >> 1, bx >> 1, my/2, mx/2, motionBlock);
  174.     ComputeDiffDCTBlock(current->cr_blocks[by >> 1][bx >> 1], motionBlock);
  175.     }
  176. }
  177.  
  178.  
  179.     /*======================*
  180.      * COMPUTE MOTION BLOCK *
  181.      *======================*/
  182.  
  183. /*===========================================================================*
  184.  *
  185.  * ComputeMotionBlock
  186.  *
  187.  *    compute the motion-compensated block
  188.  *
  189.  * RETURNS:    motionBlock
  190.  *
  191.  * SIDE EFFECTS:    none
  192.  *
  193.  * PRECONDITIONS:    motion vector MUST be valid
  194.  *
  195.  * NOTE:  could try to speed this up using halfX, halfY, halfBoth,
  196.  *      but then would have to compute for chrominance, and it's just
  197.  *      not worth the trouble (this procedure is not called relatively
  198.  *      often -- a constant number of times per macroblock)
  199.  *
  200.  *===========================================================================*/
  201. void
  202. ComputeMotionBlock(prev, by, bx, my, mx, motionBlock)
  203.     uint8 **prev;
  204.     int by;    
  205.     int bx;
  206.     int my;
  207.     int mx;
  208.     Block motionBlock;
  209. {
  210.     register int   fy, fx;
  211.     register int   y;
  212.     register int16 *destPtr;
  213.     register uint8 *srcPtr;
  214.     register uint8 *srcPtr2;
  215.     boolean xHalf, yHalf;
  216.  
  217.     xHalf = (ABS(mx) % 2 == 1);
  218.     yHalf = (ABS(my) % 2 == 1);
  219.  
  220.     MOTION_TO_FRAME_COORD(by, bx, (my/2), (mx/2), fy, fx);
  221.  
  222.     if ( xHalf && yHalf ) {
  223.     /* really should be fy+y-1 and fy+y so do (fy-1)+y = fy+y-1 and
  224.        (fy-1)+y+1 = fy+y
  225.      */
  226.     if ( my < 0 ) {
  227.         fy--;
  228.     }
  229.     if ( mx < 0 ) {
  230.         fx--;
  231.     }
  232.  
  233.     for ( y = 0; y < 8; y++ ) {
  234.         destPtr = motionBlock[y];
  235.         srcPtr = &(prev[fy+y][fx]);
  236.         srcPtr2 = &(prev[fy+y+1][fx]);
  237.  
  238.         destPtr[0] = (srcPtr[0]+srcPtr[1]+srcPtr2[0]+srcPtr2[1]+2)>>2;
  239.         destPtr[1] = (srcPtr[1]+srcPtr[2]+srcPtr2[1]+srcPtr2[2]+2)>>2;
  240.         destPtr[2] = (srcPtr[2]+srcPtr[3]+srcPtr2[2]+srcPtr2[3]+2)>>2;
  241.         destPtr[3] = (srcPtr[3]+srcPtr[4]+srcPtr2[3]+srcPtr2[4]+2)>>2;
  242.         destPtr[4] = (srcPtr[4]+srcPtr[5]+srcPtr2[4]+srcPtr2[5]+2)>>2;
  243.         destPtr[5] = (srcPtr[5]+srcPtr[6]+srcPtr2[5]+srcPtr2[6]+2)>>2;
  244.         destPtr[6] = (srcPtr[6]+srcPtr[7]+srcPtr2[6]+srcPtr2[7]+2)>>2;
  245.         destPtr[7] = (srcPtr[7]+srcPtr[8]+srcPtr2[7]+srcPtr2[8]+2)>>2;
  246.     }
  247.     } else if ( xHalf ) {
  248.     if ( mx < 0 ) {
  249.         fx--;
  250.     }
  251.  
  252.     for ( y = 0; y < 8; y++ ) {
  253.         destPtr = motionBlock[y];
  254.         srcPtr = &(prev[fy+y][fx]);
  255.  
  256.         destPtr[0] = (srcPtr[0]+srcPtr[1]+1)>>1;
  257.         destPtr[1] = (srcPtr[1]+srcPtr[2]+1)>>1;
  258.         destPtr[2] = (srcPtr[2]+srcPtr[3]+1)>>1;
  259.         destPtr[3] = (srcPtr[3]+srcPtr[4]+1)>>1;
  260.         destPtr[4] = (srcPtr[4]+srcPtr[5]+1)>>1;
  261.         destPtr[5] = (srcPtr[5]+srcPtr[6]+1)>>1;
  262.         destPtr[6] = (srcPtr[6]+srcPtr[7]+1)>>1;
  263.         destPtr[7] = (srcPtr[7]+srcPtr[8]+1)>>1;
  264.     }
  265.     } else if ( yHalf ) {
  266.     if ( my < 0 ) {
  267.         fy--;
  268.     }
  269.  
  270.     for ( y = 0; y < 8; y++ ) {
  271.         destPtr = motionBlock[y];
  272.         srcPtr = &(prev[fy+y][fx]);
  273.         srcPtr2 = &(prev[fy+y+1][fx]);
  274.  
  275.         destPtr[0] = (srcPtr[0]+srcPtr2[0]+1)>>1;
  276.         destPtr[1] = (srcPtr[1]+srcPtr2[1]+1)>>1;
  277.         destPtr[2] = (srcPtr[2]+srcPtr2[2]+1)>>1;
  278.         destPtr[3] = (srcPtr[3]+srcPtr2[3]+1)>>1;
  279.         destPtr[4] = (srcPtr[4]+srcPtr2[4]+1)>>1;
  280.         destPtr[5] = (srcPtr[5]+srcPtr2[5]+1)>>1;
  281.         destPtr[6] = (srcPtr[6]+srcPtr2[6]+1)>>1;
  282.         destPtr[7] = (srcPtr[7]+srcPtr2[7]+1)>>1;
  283.     }
  284.     } else {
  285.     for ( y = 0; y < 8; y++ ) {
  286.         destPtr = motionBlock[y];
  287.         srcPtr = &(prev[fy+y][fx]);
  288.  
  289.         destPtr[0] = srcPtr[0];
  290.         destPtr[1] = srcPtr[1];
  291.         destPtr[2] = srcPtr[2];
  292.         destPtr[3] = srcPtr[3];
  293.         destPtr[4] = srcPtr[4];
  294.         destPtr[5] = srcPtr[5];
  295.         destPtr[6] = srcPtr[6];
  296.         destPtr[7] = srcPtr[7];
  297.     }
  298.     }
  299. }
  300.  
  301.  
  302. /*===========================================================================*
  303.  *
  304.  * ComputeMotionLumBlock
  305.  *
  306.  *    compute the motion-compensated luminance block
  307.  *
  308.  * RETURNS:    motionBlock
  309.  *
  310.  * SIDE EFFECTS:    none
  311.  *
  312.  * PRECONDITIONS:    motion vector MUST be valid
  313.  *
  314.  * NOTE:  see ComputeMotionBlock
  315.  *
  316.  *===========================================================================*/
  317. void
  318. ComputeMotionLumBlock(prevFrame, by, bx, my, mx, motionBlock)
  319.     MpegFrame *prevFrame;
  320.     int by;
  321.     int bx;
  322.     int my;
  323.     int mx;
  324.     LumBlock motionBlock;
  325. {
  326.     register uint8 *across;
  327.     register int32 *macross;
  328.     register int y;
  329.     uint8 **prev;
  330.     int        fy, fx;
  331.     boolean xHalf, yHalf;
  332.  
  333.     xHalf = (ABS(mx) % 2 == 1);
  334.     yHalf = (ABS(my) % 2 == 1);
  335.  
  336.     MOTION_TO_FRAME_COORD(by, bx, my/2, mx/2, fy, fx);
  337.  
  338.     if ( xHalf ) {
  339.     if ( mx < 0 ) {
  340.         fx--;
  341.     }
  342.  
  343.     if ( yHalf ) {
  344.         if ( my < 0 ) {
  345.         fy--;
  346.         }
  347.         
  348.         prev = prevFrame->halfBoth;
  349.     } else {
  350.         prev = prevFrame->halfX;
  351.     }
  352.     } else if ( yHalf ) {
  353.     if ( my < 0 ) {
  354.         fy--;
  355.     }
  356.  
  357.     prev = prevFrame->halfY;
  358.     } else {
  359.     prev = prevFrame->ref_y;
  360.     }
  361.  
  362.     for ( y = 0; y < 16; y++ ) {
  363.     across = &(prev[fy+y][fx]);
  364.     macross = motionBlock[y];
  365.  
  366.     macross[0] = across[0];
  367.     macross[1] = across[1];
  368.     macross[2] = across[2];
  369.     macross[3] = across[3];
  370.     macross[4] = across[4];
  371.     macross[5] = across[5];
  372.     macross[6] = across[6];
  373.     macross[7] = across[7];
  374.     macross[8] = across[8];
  375.     macross[9] = across[9];
  376.     macross[10] = across[10];
  377.     macross[11] = across[11];
  378.     macross[12] = across[12];
  379.     macross[13]= across[13];
  380.     macross[14] = across[14];
  381.     macross[15] = across[15];
  382.     }
  383.  
  384.     /* this is what's really happening, in slow motion:
  385.      *
  386.      *    for ( y = 0; y < 16; y++, py++ )
  387.      *      for ( x = 0; x < 16; x++, px++ )
  388.      *        motionBlock[y][x] = prev[fy+y][fx+x];
  389.      *
  390.      */
  391. }
  392.  
  393.  
  394. /*=======================*
  395.  * BASIC ERROR FUNCTIONS *
  396.  *=======================*/
  397.  
  398.  
  399. /*===========================================================================*
  400.  *
  401.  * LumBlockMAD
  402.  *
  403.  *    return the MAD of two luminance blocks
  404.  *
  405.  * RETURNS:    the MAD, if less than bestSoFar, or
  406.  *        some number bigger if not
  407.  *
  408.  * SIDE EFFECTS:    none
  409.  *
  410.  *===========================================================================*/
  411. int32
  412. LumBlockMAD(currentBlock, motionBlock, bestSoFar)
  413.     LumBlock currentBlock;
  414.     LumBlock motionBlock;
  415.     int32 bestSoFar;
  416. {
  417.     register int32   diff = 0;    /* max value of diff is 255*256 = 65280 */
  418.     register int32 localDiff;
  419.     register int y, x;
  420.  
  421.     for ( y = 0; y < 16; y++ ) {
  422.     for ( x = 0; x < 16; x++ ) {
  423.         localDiff = currentBlock[y][x] - motionBlock[y][x];
  424.         diff += ABS(localDiff);
  425.     }
  426.  
  427.     if ( diff > bestSoFar ) {
  428.         return diff;
  429.     }
  430.     }
  431.  
  432.     return (int32)diff;
  433. }
  434.  
  435.  
  436. /*===========================================================================*
  437.  *
  438.  * LumMotionError
  439.  *
  440.  *    return the MAD of the currentBlock and the motion-compensated block
  441.  *
  442.  * RETURNS:    the MAD, if less than bestSoFar, or
  443.  *        some number bigger if not
  444.  *
  445.  * SIDE EFFECTS:    none
  446.  *
  447.  * PRECONDITIONS:  motion vector MUST be valid
  448.  *
  449.  * NOTES:  this is the procedure that is called the most, and should therefore
  450.  *         be the most optimized!!!
  451.  *
  452.  *===========================================================================*/
  453. int32
  454. LumMotionError(currentBlock, prevFrame, by, bx, my, mx, bestSoFar)
  455.     LumBlock currentBlock;
  456.     MpegFrame *prevFrame;
  457.     int by;
  458.     int bx;
  459.     int my;    
  460.     int mx;        
  461.     int32 bestSoFar;
  462. {
  463.     register int32   diff = 0;    /* max value of diff is 255*256 = 65280 */
  464.     register int32 localDiff;
  465.     register uint8 *across;
  466.     register int32 *cacross;
  467.     register int y;
  468.     uint8 **prev;
  469.     int        fy, fx;
  470.     boolean xHalf, yHalf;
  471.  
  472.     xHalf = (ABS(mx) % 2 == 1);
  473.     yHalf = (ABS(my) % 2 == 1);
  474.  
  475.     MOTION_TO_FRAME_COORD(by, bx, my/2, mx/2, fy, fx);
  476.  
  477.     if ( xHalf ) {
  478.     if ( mx < 0 ) {
  479.         fx--;
  480.     }
  481.  
  482.     if ( yHalf ) {
  483.         if ( my < 0 ) {
  484.         fy--;
  485.         }
  486.         
  487.         prev = prevFrame->halfBoth;
  488.     } else {
  489.         prev = prevFrame->halfX;
  490.     }
  491.     } else if ( yHalf ) {
  492.     if ( my < 0 ) {
  493.         fy--;
  494.     }
  495.  
  496.     prev = prevFrame->halfY;
  497.     } else {
  498.     prev = prevFrame->ref_y;
  499.     }
  500.  
  501.     for ( y = 0; y < 16; y++ ) {
  502.     across = &(prev[fy+y][fx]);
  503.     cacross = currentBlock[y];
  504.  
  505.     localDiff = across[0]-cacross[0];     diff += ABS(localDiff);
  506.     localDiff = across[1]-cacross[1];     diff += ABS(localDiff);
  507.     localDiff = across[2]-cacross[2];     diff += ABS(localDiff);
  508.     localDiff = across[3]-cacross[3];     diff += ABS(localDiff);
  509.     localDiff = across[4]-cacross[4];     diff += ABS(localDiff);
  510.     localDiff = across[5]-cacross[5];     diff += ABS(localDiff);
  511.     localDiff = across[6]-cacross[6];     diff += ABS(localDiff);
  512.     localDiff = across[7]-cacross[7];     diff += ABS(localDiff);
  513.     localDiff = across[8]-cacross[8];     diff += ABS(localDiff);
  514.     localDiff = across[9]-cacross[9];     diff += ABS(localDiff);
  515.     localDiff = across[10]-cacross[10];     diff += ABS(localDiff);
  516.     localDiff = across[11]-cacross[11];     diff += ABS(localDiff);
  517.     localDiff = across[12]-cacross[12];     diff += ABS(localDiff);
  518.     localDiff = across[13]-cacross[13];     diff += ABS(localDiff);
  519.     localDiff = across[14]-cacross[14];     diff += ABS(localDiff);
  520.     localDiff = across[15]-cacross[15];     diff += ABS(localDiff);
  521.  
  522.     if ( diff > bestSoFar ) {
  523.         return diff;
  524.     }
  525.     }
  526.  
  527.     /* this is what's happening:
  528.      *
  529.      *    ComputeMotionLumBlock(prevFrame, by, bx, my, mx, lumMotionBlock);
  530.      *
  531.      *    for ( y = 0; y < 16; y++ )
  532.      *        for ( x = 0; x < 16; x++ )
  533.      *        {
  534.      *        localDiff = currentBlock[y][x] - lumMotionBlock[y][x];
  535.      *        diff += ABS(localDiff);
  536.      *        }
  537.      *
  538.      */
  539.  
  540.     return diff;
  541. }
  542.  
  543.  
  544. /*===========================================================================*
  545.  *
  546.  * LumAddMotionError
  547.  *
  548.  *    return the MAD of the currentBlock and the average of the blockSoFar
  549.  *    and the motion-compensated block (this is used for B-frame searches)
  550.  *
  551.  * RETURNS:    the MAD, if less than bestSoFar, or
  552.  *        some number bigger if not
  553.  *
  554.  * SIDE EFFECTS:    none
  555.  *
  556.  * PRECONDITIONS:  motion vector MUST be valid
  557.  *
  558.  *===========================================================================*/
  559. int32
  560. LumAddMotionError(currentBlock, blockSoFar, prevFrame, by, bx, my, mx,
  561.           bestSoFar)
  562.     LumBlock currentBlock;
  563.     LumBlock blockSoFar;
  564.     MpegFrame *prevFrame;
  565.     int by;
  566.     int bx;
  567.     int my;
  568.     int mx;
  569.     int32 bestSoFar;
  570. {
  571.     register int32   diff = 0;    /* max value of diff is 255*256 = 65280 */
  572.     register int32 localDiff;
  573.     register uint8 *across;
  574.     register int32 *bacross;
  575.     register int32 *cacross;
  576.     register int y;
  577.     uint8 **prev;
  578.     int        fy, fx;
  579.     boolean xHalf, yHalf;
  580.  
  581.     xHalf = (ABS(mx) % 2 == 1);
  582.     yHalf = (ABS(my) % 2 == 1);
  583.  
  584.     MOTION_TO_FRAME_COORD(by, bx, my/2, mx/2, fy, fx);
  585.  
  586.     if ( xHalf ) {
  587.     if ( mx < 0 ) {
  588.         fx--;
  589.     }
  590.  
  591.     if ( yHalf ) {
  592.         if ( my < 0 ) {
  593.         fy--;
  594.         }
  595.         
  596.         prev = prevFrame->halfBoth;
  597.     } else {
  598.         prev = prevFrame->halfX;
  599.     }
  600.     } else if ( yHalf ) {
  601.     if ( my < 0 ) {
  602.         fy--;
  603.     }
  604.  
  605.     prev = prevFrame->halfY;
  606.     } else {
  607.     prev = prevFrame->ref_y;
  608.     }
  609.  
  610. /* do we add 1 before dividing by two?  Yes -- see MPEG-1 doc page 46 */
  611.  
  612. #define ADD_ADD_DIFF(d,l,a,b,c,i)       \
  613.     l = ((a[i]+b[i]+1)>>1)-c[i];        \
  614.     d += ABS(l)
  615.  
  616.     for ( y = 0; y < 16; y++ ) {
  617.     across = &(prev[fy+y][fx]);
  618.     bacross = blockSoFar[y];
  619.     cacross = currentBlock[y];
  620.  
  621.     ADD_ADD_DIFF(diff,localDiff,across,bacross,cacross,0);
  622.     ADD_ADD_DIFF(diff,localDiff,across,bacross,cacross,1);
  623.     ADD_ADD_DIFF(diff,localDiff,across,bacross,cacross,2);
  624.     ADD_ADD_DIFF(diff,localDiff,across,bacross,cacross,3);
  625.     ADD_ADD_DIFF(diff,localDiff,across,bacross,cacross,4);
  626.     ADD_ADD_DIFF(diff,localDiff,across,bacross,cacross,5);
  627.     ADD_ADD_DIFF(diff,localDiff,across,bacross,cacross,6);
  628.     ADD_ADD_DIFF(diff,localDiff,across,bacross,cacross,7);
  629.     ADD_ADD_DIFF(diff,localDiff,across,bacross,cacross,8);
  630.     ADD_ADD_DIFF(diff,localDiff,across,bacross,cacross,9);
  631.     ADD_ADD_DIFF(diff,localDiff,across,bacross,cacross,10);
  632.     ADD_ADD_DIFF(diff,localDiff,across,bacross,cacross,11);
  633.     ADD_ADD_DIFF(diff,localDiff,across,bacross,cacross,12);
  634.     ADD_ADD_DIFF(diff,localDiff,across,bacross,cacross,13);
  635.     ADD_ADD_DIFF(diff,localDiff,across,bacross,cacross,14);
  636.     ADD_ADD_DIFF(diff,localDiff,across,bacross,cacross,15);
  637.  
  638.     if ( diff > bestSoFar ) {
  639.         return diff;
  640.     }
  641.     }
  642.  
  643.     /* this is what's happening:
  644.      *
  645.      *    ComputeMotionLumBlock(prevFrame, by, bx, my, mx, lumMotionBlock);
  646.      *
  647.      *    for ( y = 0; y < 16; y++ )
  648.      *        for ( x = 0; x < 16; x++ )
  649.      *        {
  650.      *        localDiff = currentBlock[y][x] - lumMotionBlock[y][x];
  651.      *        diff += ABS(localDiff);
  652.      *        }
  653.      *
  654.      */
  655.  
  656.     return diff;
  657. }
  658.  
  659.  
  660. /*===========================================================================*
  661.  *
  662.  * AddMotionBlock
  663.  *
  664.  *    adds the motion-compensated block to the given block
  665.  *
  666.  * RETURNS:    block modified
  667.  *
  668.  * SIDE EFFECTS:    none
  669.  *
  670.  * PRECONDITIONS:  motion vector MUST be valid
  671.  *
  672.  *===========================================================================*/
  673. void
  674. AddMotionBlock(block, prev, by, bx, my, mx)
  675.     Block block;
  676.     uint8 **prev;
  677.     int by;
  678.     int bx;
  679.     int my;
  680.     int mx;
  681. {
  682.     int        fy, fx;
  683.     int        x, y;
  684.     boolean xHalf, yHalf;
  685.  
  686.     xHalf = (ABS(mx) % 2 == 1);
  687.     yHalf = (ABS(my) % 2 == 1);
  688.  
  689.     MOTION_TO_FRAME_COORD(by, bx, (my/2), (mx/2), fy, fx);
  690.  
  691.     if ( xHalf && yHalf ) {
  692.     /* really should be fy+y-1 and fy+y so do (fy-1)+y = fy+y-1 and
  693.        (fy-1)+y+1 = fy+y
  694.      */
  695.     if ( my < 0 ) {
  696.         fy--;
  697.     }
  698.     if ( mx < 0 ) {
  699.         fx--;
  700.     }
  701.  
  702.     for ( y = 0; y < 8; y++ ) {
  703.         for ( x = 0; x < 8; x++ ) {
  704.         block[y][x] += (prev[fy+y][fx+x]+prev[fy+y][fx+x+1]+
  705.                     prev[fy+y+1][fx+x]+prev[fy+y+1][fx+x+1]+2)>>2;
  706.         }
  707.     }
  708.     } else if ( xHalf ) {
  709.     if ( mx < 0 ) {
  710.         fx--;
  711.     }
  712.  
  713.     for ( y = 0; y < 8; y++ ) {
  714.         for ( x = 0; x < 8; x++ ) {
  715.         block[y][x] += (prev[fy+y][fx+x]+prev[fy+y][fx+x+1]+1)>>1;
  716.         }
  717.     }
  718.     } else if ( yHalf ) {
  719.     if ( my < 0 ) {
  720.         fy--;
  721.     }
  722.  
  723.     for ( y = 0; y < 8; y++ ) {
  724.         for ( x = 0; x < 8; x++ ) {
  725.         block[y][x] += (prev[fy+y][fx+x]+prev[fy+y+1][fx+x]+1)>>1;
  726.         }
  727.     }
  728.     } else {
  729.     for ( y = 0; y < 8; y++ ) {
  730.         for ( x = 0; x < 8; x++ ) {
  731.         block[y][x] += (int32)prev[fy+y][fx+x];
  732.         }
  733.     }
  734.     }
  735. }
  736.  
  737.  
  738. /*===========================================================================*
  739.  *
  740.  * AddBMotionBlock
  741.  *
  742.  *    adds the motion-compensated B-frame block to the given block
  743.  *
  744.  * RETURNS:    block modified
  745.  *
  746.  * SIDE EFFECTS:    none
  747.  *
  748.  * PRECONDITIONS:  motion vectors MUST be valid
  749.  *
  750.  *===========================================================================*/
  751. void
  752. AddBMotionBlock(block, prev, next, by, bx, mode, fmy, fmx, bmy, bmx)
  753.     Block block;
  754.     uint8 **prev;
  755.     uint8 **next;
  756.     int by;
  757.     int bx;
  758.     int    mode;
  759.     int fmy;
  760.     int fmx;
  761.     int bmy;
  762.     int bmx;
  763. {
  764.     int        x, y;
  765.     Block   prevBlock, nextBlock;
  766.  
  767.     if ( mode == MOTION_FORWARD ) {
  768.     AddMotionBlock(block, prev, by, bx, fmy, fmx);
  769.     } else if ( mode == MOTION_BACKWARD ) {
  770.     AddMotionBlock(block, next, by, bx, bmy, bmx);
  771.     } else {
  772.     ComputeMotionBlock(prev, by, bx, fmy, fmx, prevBlock);
  773.     ComputeMotionBlock(next, by, bx, bmy, bmx, nextBlock);
  774.  
  775.     for ( y = 0; y < 8; y++ ) {
  776.         for ( x = 0; x < 8; x++ ) {
  777.         block[y][x] += (prevBlock[y][x]+nextBlock[y][x]+1)/2;
  778.         }
  779.     }
  780.     }
  781. }
  782.  
  783.  
  784. /*===========================================================================*
  785.  *
  786.  * BlockToData
  787.  *
  788.  *    copies the given block into the appropriate data area
  789.  *
  790.  * RETURNS:    data modified
  791.  *
  792.  * SIDE EFFECTS:    none
  793.  *
  794.  *===========================================================================*/
  795. void
  796. BlockToData(data, block, by, bx)
  797.     uint8 **data;
  798.     Block block;
  799.     int by;
  800.     int bx;
  801. {
  802.     register int x, y;
  803.     register int fy, fx;
  804.     register int16    blockItem;
  805.  
  806.     BLOCK_TO_FRAME_COORD(by, bx, fy, fx);
  807.  
  808.     for ( y = 0; y < 8; y++ ) {
  809.     for ( x = 0; x < 8; x++ ) {
  810.         blockItem = block[y][x];
  811.         data[fy+y][fx+x] = TRUNCATE_UINT8(blockItem);
  812.     }
  813.     }
  814. }
  815.  
  816.  
  817. /*===========================================================================*
  818.  *
  819.  * BlockifyFrame
  820.  *
  821.  *    copies data into appropriate blocks
  822.  *
  823.  * RETURNS:    mf modified
  824.  *
  825.  * SIDE EFFECTS:    none
  826.  *
  827.  * NOTES:  probably shouldn't be in this file
  828.  *
  829.  *===========================================================================*/
  830. void
  831. BlockifyFrame(framePtr)
  832.     MpegFrame *framePtr;
  833. {
  834.     register int dctx, dcty;
  835.     register int x, y;
  836.     register int bx, by;
  837.     register int fy, fx;
  838.     register int16  *destPtr;
  839.     register uint8  *srcPtr;
  840.     register int16  *destPtr2;
  841.     register uint8  *srcPtr2;
  842.     Block   *blockPtr;
  843.     Block   *blockPtr2;
  844.  
  845.     dctx = Fsize_x / DCTSIZE;
  846.     dcty = Fsize_y / DCTSIZE;
  847.  
  848.     /*
  849.      * copy y data into y_blocks
  850.      */
  851.     for (by = 0; by < dcty; by++) {
  852.     fy = by*DCTSIZE;
  853.     for (bx = 0; bx < dctx; bx++) {
  854.         fx = bx*DCTSIZE;
  855.         blockPtr = &framePtr->y_blocks[by][bx];
  856.         for (y = 0; y < DCTSIZE; y++) {
  857.         destPtr = &((*blockPtr)[y][0]);
  858.         srcPtr = &(framePtr->orig_y[fy+y][fx]);
  859.         for (x = 0; x < DCTSIZE; x++) {
  860.             destPtr[x] = srcPtr[x];
  861.         }
  862.         }
  863.     }
  864.     }
  865.  
  866.     /*
  867.      * copy cr/cb data into cr/cb_blocks
  868.      */
  869.     for (by = 0; by < dcty / 2; by++) {
  870.     fy = by*DCTSIZE;
  871.     for (bx = 0; bx < dctx / 2; bx++) {
  872.         fx = bx*DCTSIZE;
  873.         blockPtr = &framePtr->cr_blocks[by][bx];
  874.         blockPtr2 = &framePtr->cb_blocks[by][bx];
  875.         for (y = 0; y < DCTSIZE; y++) {
  876.         destPtr = &((*blockPtr)[y][0]);
  877.         srcPtr = &(framePtr->orig_cr[fy+y][fx]);
  878.         destPtr2 = &((*blockPtr2)[y][0]);
  879.         srcPtr2 = &(framePtr->orig_cb[fy+y][fx]);
  880.         for (x = 0; x < DCTSIZE; x++) {
  881.             destPtr[x] = srcPtr[x];
  882.             destPtr2[x] = srcPtr2[x];
  883.         }
  884.         }
  885.     }
  886.     }
  887. }
  888.  
  889.  
  890. /*===========================================================================*
  891.  *                                         *
  892.  * UNUSED PROCEDURES                                 *
  893.  *                                         *
  894.  *    The following procedures are all unused by the encoder             *
  895.  *                                         *
  896.  *    They are listed here for your convenience.  You might want to use    *
  897.  *    them if you experiment with different search techniques             *
  898.  *                                         *
  899.  *===========================================================================*/
  900.  
  901. #ifdef UNUSED_PROCEDURES
  902.  
  903. /* this procedure calculates the subsampled motion block (obviously)
  904.  *
  905.  * for speed, this procedure is probably not called anywhere (it is
  906.  * incorporated directly into LumDiffA, LumDiffB, etc.
  907.  *
  908.  * but leave it here anyway for clarity
  909.  *
  910.  * (startY, startX) = (0,0) for A....(0,1) for B...(1,0) for C...(1,1) for D
  911.  *  
  912.  */
  913. void
  914. ComputeSubSampledMotionLumBlock(prevFrame, by, bx, my, mx, motionBlock,
  915.                 startY, startX)
  916.     MpegFrame *prevFrame;
  917.     int by;
  918.     int bx;
  919.     int my;
  920.     int mx;
  921.     LumBlock motionBlock;
  922.     int startY;
  923.     int startX;
  924. {
  925.     register uint8 *across;
  926.     register int32 *macross;
  927.     register int32 *lastx;
  928.     register int y;
  929.     uint8 **prev;
  930.     int    fy, fx;
  931.     boolean xHalf, yHalf;
  932.  
  933.     xHalf = (ABS(mx) % 2 == 1);
  934.     yHalf = (ABS(my) % 2 == 1);
  935.  
  936.     MOTION_TO_FRAME_COORD(by, bx, my/2, mx/2, fy, fx);
  937.  
  938.     if ( xHalf ) {
  939.     if ( mx < 0 ) {
  940.         fx--;
  941.     }
  942.  
  943.     if ( yHalf ) {
  944.         if ( my < 0 ) {
  945.         fy--;
  946.         }
  947.         
  948.         prev = prevFrame->halfBoth;
  949.     } else {
  950.         prev = prevFrame->halfX;
  951.     }
  952.     } else if ( yHalf ) {
  953.     if ( my < 0 ) {
  954.         fy--;
  955.     }
  956.  
  957.     prev = prevFrame->halfY;
  958.     } else {
  959.     prev = prevFrame->ref_y;
  960.     }
  961.  
  962.     for ( y = startY; y < 16; y += 2 ) {
  963.     across = &(prev[fy+y][fx+startX]);
  964.     macross = &(motionBlock[y][startX]);
  965.     lastx = &(motionBlock[y][16]);
  966.     while ( macross < lastx ) {
  967.         (*macross) = (*across);
  968.         across += 2;
  969.         macross += 2;
  970.     }
  971.     }
  972.  
  973.     /* this is what's really going on in slow motion:
  974.      *
  975.      *    for ( y = startY; y < 16; y += 2 )
  976.      *        for ( x = startX; x < 16; x += 2 )
  977.      *        motionBlock[y][x] = prev[fy+y][fx+x];
  978.      *
  979.      */
  980. }
  981.  
  982.  
  983. /*===========================================================================*
  984.  *
  985.  * LumMotionErrorSubSampled
  986.  *
  987.  *    return the MAD of the currentBlock and the motion-compensated block,
  988.  *    subsampled 4:1 with given starting coordinates (startY, startX)
  989.  *
  990.  * RETURNS:    the MAD
  991.  *
  992.  * SIDE EFFECTS:    none
  993.  *
  994.  * PRECONDITIONS:  motion vector MUST be valid
  995.  *
  996.  * NOTES:  this procedure is never called.  Instead, see subsample.c.  This
  997.  *         procedure is provided only for possible use in extensions
  998.  *
  999.  *===========================================================================*/
  1000. int32
  1001. LumMotionErrorSubSampled(currentBlock, prevFrame, by, bx, my, mx, startY,
  1002.              startX)
  1003.     LumBlock currentBlock;
  1004.     MpegFrame *prevFrame;
  1005.     int by;
  1006.     int bx;
  1007.     int my;
  1008.     int mx;
  1009.     int startY;
  1010.     int startX;
  1011. {
  1012.     register int32    diff = 0;        /* max value of diff is 255*256 = 65280 */
  1013.     register int32 localDiff;
  1014.     register int32 *cacross;
  1015.     register uint8 *macross;
  1016.     register int32 *lastx;
  1017.     register int y;
  1018.     uint8 **prev;
  1019.     int    fy, fx;
  1020.     boolean xHalf, yHalf;
  1021.  
  1022.     xHalf = (ABS(mx) % 2 == 1);
  1023.     yHalf = (ABS(my) % 2 == 1);
  1024.  
  1025.     MOTION_TO_FRAME_COORD(by, bx, my/2, mx/2, fy, fx);
  1026.  
  1027.     if ( xHalf ) {
  1028.     if ( mx < 0 ) {
  1029.         fx--;
  1030.     }
  1031.  
  1032.     if ( yHalf ) {
  1033.         if ( my < 0 ) {
  1034.         fy--;
  1035.         }
  1036.         
  1037.         prev = prevFrame->halfBoth;
  1038.     } else {
  1039.         prev = prevFrame->halfX;
  1040.     }
  1041.     } else if ( yHalf ) {
  1042.     if ( my < 0 ) {
  1043.         fy--;
  1044.     }
  1045.  
  1046.     prev = prevFrame->halfY;
  1047.     } else {
  1048.     prev = prevFrame->ref_y;
  1049.     }
  1050.  
  1051.     for ( y = startY; y < 16; y += 2 ) {
  1052.     macross = &(prev[fy+y][fx+startX]);
  1053.     cacross = &(currentBlock[y][startX]);
  1054.     lastx = &(currentBlock[y][16]);
  1055.     while ( cacross < lastx ) {
  1056.         localDiff = (*cacross)-(*macross);
  1057.         diff += ABS(localDiff);
  1058.         macross += 2;
  1059.         cacross += 2;
  1060.     }
  1061.     }
  1062.  
  1063.     /* this is what's really happening:
  1064.      *
  1065.      *    ComputeSubSampledMotionLumBlock(prevFrame, by, bx, my, mx,
  1066.      *                    lumMotionBlock, startY, startX);
  1067.      *
  1068.      *    for ( y = startY; y < 16; y += 2 )
  1069.      *        for ( x = startX; x < 16; x += 2 )
  1070.      *        {
  1071.      *             localDiff = currentBlock[y][x] - lumMotionBlock[y][x];
  1072.      *        diff += ABS(localDiff);
  1073.      *        }
  1074.      *
  1075.      */
  1076.  
  1077.     return (int32)diff;
  1078. }
  1079.  
  1080.  
  1081. #endif UNUSED_PROCEDURES
  1082.