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