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

  1. /*===========================================================================*
  2.  * iframe.c                                     *
  3.  *                                         *
  4.  *    Procedures concerned with the I-frame encoding                 *
  5.  *                                         *
  6.  * EXPORTED PROCEDURES:                                 *
  7.  *    GenIFrame                                 *
  8.  *    SetSlicesPerFrame                             *
  9.  *    SetBlocksPerSlice                             *
  10.  *    SetIQScale                                 *
  11.  *    ResetIFrameStats                             *
  12.  *    ShowIFrameSummary                             *
  13.  *    EstimateSecondsPerIFrame                         *
  14.  *    EncodeYDC                                 *
  15.  *    EncodeCDC                                 *
  16.  *                                         *
  17.  *===========================================================================*/
  18.  
  19. /*
  20.  * Copyright (c) 1993 The Regents of the University of California.
  21.  * All rights reserved.
  22.  *
  23.  * Permission to use, copy, modify, and distribute this software and its
  24.  * documentation for any purpose, without fee, and without written agreement is
  25.  * hereby granted, provided that the above copyright notice and the following
  26.  * two paragraphs appear in all copies of this software.
  27.  *
  28.  * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
  29.  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
  30.  * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
  31.  * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  32.  *
  33.  * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
  34.  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
  35.  * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
  36.  * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
  37.  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
  38.  */
  39.  
  40. /*
  41.  *  $Header: /n/picasso/users/keving/encode/src/RCS/iframe.c,v 1.6 1993/07/22 22:23:43 keving Exp keving $
  42.  *  $Log: iframe.c,v $
  43.  * Revision 1.6  1993/07/22  22:23:43  keving
  44.  * nothing
  45.  *
  46.  * Revision 1.5  1993/06/30  20:06:09  keving
  47.  * nothing
  48.  *
  49.  * Revision 1.4  1993/06/03  21:08:08  keving
  50.  * nothing
  51.  *
  52.  * Revision 1.3  1993/03/04  22:24:06  keving
  53.  * nothing
  54.  *
  55.  * Revision 1.2  1993/02/19  18:10:02  keving
  56.  * nothing
  57.  *
  58.  * Revision 1.1  1993/02/18  22:56:39  keving
  59.  * nothing
  60.  *
  61.  *
  62.  */
  63.  
  64.  
  65. /*==============*
  66.  * HEADER FILES *
  67.  *==============*/
  68.  
  69. #include <sys/times.h>
  70. #include "all.h"
  71. #include "mtypes.h"
  72. #include "frames.h"
  73. #include "prototypes.h"
  74. #include "mpeg.h"
  75. #include "param.h"
  76. #include "mheaders.h"
  77. #include "fsize.h"
  78. #include "postdct.h"
  79.  
  80.  
  81. /*==================*
  82.  * STATIC VARIABLES *
  83.  *==================*/
  84.  
  85. static int numBlocks = 0;
  86. static int numBits;
  87. static int numFrames = 0;
  88. static int numFrameBits = 0;
  89. static time_t totalTime = 0;
  90. static float    totalSNR = 0.0;
  91. static float    totalPSNR = 0.0;
  92.  
  93.  
  94. /*==================*
  95.  * GLOBAL VARIABLES *
  96.  *==================*/
  97.  
  98. int    qscaleI;
  99. int    slicesPerFrame;
  100. int    blocksPerSlice;
  101. int    fCode;
  102. boolean    printSNR = FALSE;
  103. boolean    decodeRefFrames = FALSE;
  104.  
  105.  
  106. /*=====================*
  107.  * EXPORTED PROCEDURES *
  108.  *=====================*/
  109.  
  110.  
  111. /*===========================================================================*
  112.  *
  113.  * SetFCode
  114.  *
  115.  *    set the forward_f_code and backward_f_code according to the search
  116.  *    range.  Must be called AFTER pixelFullSearch and searchRange have
  117.  *    been initialized.  Irrelevant for I-frames, but computation is
  118.  *    negligible (done only once, as well)
  119.  *
  120.  * RETURNS:    nothing
  121.  *
  122.  * SIDE EFFECTS:    fCode
  123.  *
  124.  *===========================================================================*/
  125. void
  126. SetFCode()
  127. {
  128.     int        range;
  129.  
  130.     if ( pixelFullSearch ) {
  131.     range = searchRange;
  132.     } else {
  133.     range = searchRange*2;
  134.     }
  135.  
  136.     if ( range < 256 ) {
  137.     if ( range < 64 ) {
  138.         if ( range < 32 ) {
  139.         fCode = 1;
  140.         } else {
  141.         fCode = 2;
  142.         }
  143.     } else {
  144.         if ( range < 128 ) {
  145.         fCode = 3;
  146.         } else {
  147.         fCode = 4;
  148.         }
  149.     }
  150.     } else {
  151.     if ( range < 1024 ) {
  152.         if ( range < 512 ) {
  153.         fCode = 5;
  154.         } else {
  155.         fCode = 6;
  156.         }
  157.     } else {
  158.         if ( range < 2048 ) {
  159.         fCode = 7;
  160.         } else {
  161.         fprintf(stdout, "ERROR:  INVALID SEARCH RANGE!!!\n");
  162.         exit(1);
  163.         }
  164.     }
  165.     }
  166. }
  167.  
  168.  
  169. /*===========================================================================*
  170.  *
  171.  * SetSlicesPerFrame
  172.  *
  173.  *    set the number of slices per frame
  174.  *
  175.  * RETURNS:    nothing
  176.  *
  177.  * SIDE EFFECTS:    slicesPerFrame
  178.  *
  179.  *===========================================================================*/
  180. void
  181. SetSlicesPerFrame(number)
  182.     int number;
  183. {
  184.     slicesPerFrame = number;
  185. }
  186.  
  187.  
  188. /*===========================================================================*
  189.  *
  190.  * SetBlocksPerSlice
  191.  *
  192.  *    set the number of blocks per slice, based on slicesPerFrame
  193.  *
  194.  * RETURNS:    nothing
  195.  *
  196.  * SIDE EFFECTS:    blocksPerSlice
  197.  *
  198.  *===========================================================================*/
  199. void
  200. SetBlocksPerSlice()
  201. {
  202.     int        totalBlocks;
  203.  
  204.     totalBlocks = (Fsize_y/16)*(Fsize_x/16);
  205.  
  206.     if ( slicesPerFrame > totalBlocks ) {
  207.     blocksPerSlice = 1;
  208.     } else {
  209.     blocksPerSlice = totalBlocks/slicesPerFrame;
  210.     }
  211. }
  212.  
  213.  
  214. /*===========================================================================*
  215.  *
  216.  * SetIQScale
  217.  *
  218.  *    set the I-frame Q-scale
  219.  *
  220.  * RETURNS:    nothing
  221.  *
  222.  * SIDE EFFECTS:    qscaleI
  223.  *
  224.  *===========================================================================*/
  225. void
  226. SetIQScale(qI)
  227. int qI;
  228. {
  229.     qscaleI = qI;
  230. }
  231.  
  232. /*===========================================================================*
  233.  *
  234.  * GenIFrame
  235.  *
  236.  *    generate an I-frame; appends result to bb
  237.  *
  238.  * RETURNS:    I-frame appended to bb
  239.  *
  240.  * SIDE EFFECTS:    none
  241.  *
  242.  *===========================================================================*/
  243. void
  244. GenIFrame(bb, current)
  245.     BitBucket *bb;
  246.     MpegFrame *current;
  247. {
  248.     register int x, y;
  249.     register int index;
  250.     FlatBlock    fb[6];
  251.     Block    dec[6];
  252.     int32 y_dc_pred, cr_dc_pred, cb_dc_pred;
  253.     int totalBits;
  254.     int    totalFrameBits;
  255.     time_t    startTime, endTime;
  256.     int        frameBlocks;
  257.     float   snr[3], psnr[3];
  258.  
  259.     /* set-up for statistics */
  260.     numFrames++;
  261.     totalFrameBits = bb->cumulativeBits;
  262.     time(&startTime);
  263.  
  264.     Frame_AllocBlocks(current);
  265.     BlockifyFrame(current);
  266.  
  267.     DBG_PRINT(("Generating iframe\n"));
  268.  
  269.     Mhead_GenPictureHeader(bb, I_FRAME, current->id, fCode);
  270.     Mhead_GenSliceHeader(bb, 1, qscaleI, NULL, 0);
  271.  
  272.     if ( referenceFrame == DECODED_FRAME ) {
  273.     Frame_AllocDecoded(current, TRUE);
  274.     } else if ( printSNR ) {
  275.     Frame_AllocDecoded(current, FALSE);
  276.     }
  277.  
  278.     y_dc_pred = cr_dc_pred = cb_dc_pred = 128;
  279.     totalBits = bb->cumulativeBits;
  280.     frameBlocks = 0;
  281.     for (y = 0; y < Fsize_y / 8; y += 2) {
  282.     for (x = 0; x < Fsize_x / 8; x += 2) {
  283.         /* DCT this macroblock */
  284.         mp_fwd_dct_block(current->y_blocks[y][x]);
  285.         mp_fwd_dct_block(current->y_blocks[y][x+1]);
  286.         mp_fwd_dct_block(current->y_blocks[y+1][x]);
  287.         mp_fwd_dct_block(current->y_blocks[y+1][x+1]);
  288.         mp_fwd_dct_block(current->cr_blocks[y>>1][x>>1]);
  289.         mp_fwd_dct_block(current->cb_blocks[y>>1][x>>1]);
  290.  
  291.         if ( (frameBlocks % blocksPerSlice == 0) && (frameBlocks != 0) ) {
  292.         /* create a new slice */
  293.         Mhead_GenSliceEnder(bb);
  294.         Mhead_GenSliceHeader(bb, 1+(y/2), qscaleI, NULL, 0);
  295.         y_dc_pred = cr_dc_pred = cb_dc_pred = 128;
  296.  
  297.         GEN_I_BLOCK(I_FRAME, current, bb, 1+(x/2), qscaleI);
  298.         } else {
  299.         GEN_I_BLOCK(I_FRAME, current, bb, 1, qscaleI);
  300.         }
  301.  
  302.         if ( decodeRefFrames ) {
  303.         /* need to decode block we just encoded */
  304.         Mpost_UnQuantZigBlock(fb[0], dec[0], qscaleI, TRUE);
  305.         Mpost_UnQuantZigBlock(fb[1], dec[1], qscaleI, TRUE);
  306.         Mpost_UnQuantZigBlock(fb[2], dec[2], qscaleI, TRUE);
  307.         Mpost_UnQuantZigBlock(fb[3], dec[3], qscaleI, TRUE);
  308.         Mpost_UnQuantZigBlock(fb[4], dec[4], qscaleI, TRUE);
  309.         Mpost_UnQuantZigBlock(fb[5], dec[5], qscaleI, TRUE);
  310.  
  311.         /* now, reverse the DCT transform */
  312.         for ( index = 0; index < 6; index++ ) {
  313.             j_rev_dct((int16 *)dec[index]);        
  314.         }
  315.  
  316.         /* now, unblockify */
  317.         BlockToData(current->decoded_y, dec[0], y, x);
  318.         BlockToData(current->decoded_y, dec[1], y, x+1);
  319.         BlockToData(current->decoded_y, dec[2], y+1, x);
  320.         BlockToData(current->decoded_y, dec[3], y+1, x+1);
  321.         BlockToData(current->decoded_cb, dec[4], y>>1, x>>1);
  322.         BlockToData(current->decoded_cr, dec[5], y>>1, x>>1);
  323.         }
  324.  
  325.         numBlocks++;
  326.         frameBlocks++;
  327.     }
  328.     }
  329.  
  330.     if ( printSNR ) {
  331.         ComputeSNR(current->orig_y, current->decoded_y, Fsize_y, Fsize_x,
  332.            &snr[0], &psnr[0]);
  333.         ComputeSNR(current->orig_cb, current->decoded_cb, Fsize_y/2, Fsize_x/2,
  334.            &snr[1], &psnr[1]);
  335.         ComputeSNR(current->orig_cr, current->decoded_cr, Fsize_y/2, Fsize_x/2,
  336.            &snr[2], &psnr[2]);
  337.  
  338.     totalSNR += snr[0];
  339.     totalPSNR += psnr[0];
  340.     }
  341. #ifdef BLEAH
  342.  
  343. if ( decodeRefFrames ) {
  344.     FILE    *fpointer;
  345.     char    fileName[256];
  346.     int    width, height;
  347.  
  348.     /* output the decoded frame */
  349.  
  350.     width = Fsize_x;
  351.     height = Fsize_y;
  352.  
  353.     sprintf(fileName, "/tmp/decoded%d.yuv", current->id);
  354.     fprintf(stdout, "outputting to %s\n", fileName);
  355.  
  356.     fpointer = fopen(fileName, "wb");
  357.  
  358.     for ( y = 0; y < height; y++ ) {
  359.         fwrite(current->decoded_y[y], 1, width, fpointer);
  360.     }
  361.  
  362.     for (y = 0; y < height / 2; y++) {            /* U */
  363.         fwrite(current->decoded_cb[y], 1, width / 2, fpointer);
  364.     }
  365.  
  366.     for (y = 0; y < height / 2; y++) {            /* V */
  367.         fwrite(current->decoded_cr[y], 1, width / 2, fpointer);
  368.     }
  369.  
  370.     fclose(fpointer);
  371. }
  372. #endif
  373.  
  374.     numBits += (bb->cumulativeBits-totalBits);
  375.  
  376.     DBG_PRINT(("End of frame\n"));
  377.  
  378.     Mhead_GenSliceEnder(bb);
  379.  
  380.     time(&endTime);
  381.     totalTime = (int32)(endTime-startTime);
  382.  
  383.     numFrameBits += (bb->cumulativeBits-totalFrameBits);
  384.  
  385.     if ( (! childProcess) && frameSummary ) {
  386.     fprintf(stdout, "FRAME %d (I):  %ld seconds\n", 
  387.         current->id, (long)(totalTime));
  388.     if ( printSNR ) {
  389.         fprintf(stdout, "FRAME %d:  SNR:  %.1f\t%.1f\t%.1f\tPSNR:  %.1f\t%.1f\t%.1f\n",
  390.             current->id, snr[0], snr[1], snr[2],
  391.             psnr[0], psnr[1], psnr[2]);
  392.     }
  393.     }
  394. }
  395.  
  396.  
  397. /*===========================================================================*
  398.  *
  399.  * ResetIFrameStats
  400.  *
  401.  *    reset the I-frame statistics
  402.  *
  403.  * RETURNS:    nothing
  404.  *
  405.  * SIDE EFFECTS:    none
  406.  *
  407.  *===========================================================================*/
  408. void
  409. ResetIFrameStats()
  410. {
  411.     numBlocks = 0;
  412.     numBits = 0;
  413.     numFrames = 0;
  414.     numFrameBits = 0;
  415.     totalTime = 0;
  416. }
  417.  
  418.  
  419. /*===========================================================================*
  420.  *
  421.  * ShowIFrameSummary
  422.  *
  423.  *    prints out statistics on all I-frames
  424.  *
  425.  * RETURNS:    nothing
  426.  *
  427.  * SIDE EFFECTS:    none
  428.  *
  429.  *===========================================================================*/
  430. void
  431. ShowIFrameSummary(inputFrameBits, totalBits, fpointer)
  432.     int inputFrameBits;
  433.     int32 totalBits;
  434.     FILE *fpointer;
  435. {
  436.     if ( numFrames == 0 ) {
  437.     return;
  438.     }
  439.  
  440.     fprintf(fpointer, "-------------------------\n");
  441.     fprintf(fpointer, "*****I FRAME SUMMARY*****\n");
  442.     fprintf(fpointer, "-------------------------\n");
  443.  
  444.     fprintf(fpointer, "  Blocks:    %5d     (%6d bits)     (%5d bpb)\n",
  445.         numBlocks, numBits, numBits/numBlocks);
  446.     fprintf(fpointer, "  Frames:    %5d     (%6d bits)     (%5d bpf)     (%2.1f%% of total)\n",
  447.         numFrames, numFrameBits, numFrameBits/numFrames,
  448.         100.0*(float)numFrameBits/(float)totalBits);
  449.     fprintf(fpointer, "  Compression:  %3d:1\n",
  450.         numFrames*inputFrameBits/numFrameBits);
  451.     if ( printSNR )
  452.     fprintf(fpointer, "  Avg Y SNR/PSNR:  %.1f     %.1f\n",
  453.         totalSNR/(float)numFrames, totalPSNR/(float)numFrames);
  454.     fprintf(fpointer, "  Seconds:  %9ld     (%9ld spf)     (%9ld bps)\n",
  455.         (long)(totalTime), (long)(totalTime/numFrames),
  456.         (long)((float)numFrames*(float)inputFrameBits/(float)totalTime));
  457. }
  458.  
  459.  
  460. /*===========================================================================*
  461.  *
  462.  * EstimateSecondsPerIFrame
  463.  *
  464.  *    estimates the number of seconds required per I-frame
  465.  *
  466.  * RETURNS:    seconds (floating point value)
  467.  *
  468.  * SIDE EFFECTS:    none
  469.  *
  470.  *===========================================================================*/
  471. float
  472. EstimateSecondsPerIFrame()
  473. {
  474.     return (float)totalTime/((float)numFrames);
  475. }
  476.  
  477.  
  478. /*===========================================================================*
  479.  *
  480.  * EncodeYDC
  481.  *
  482.  *    Encode the DC portion of a DCT of a luminance block
  483.  *
  484.  * RETURNS:    result appended to bb
  485.  *
  486.  * SIDE EFFECTS:    updates pred_term
  487.  *
  488.  *===========================================================================*/
  489. void
  490. EncodeYDC(dc_term, pred_term, bb)
  491.     int16 dc_term;
  492.     int32 *pred_term;
  493.     BitBucket *bb;
  494. {
  495.     int ydiff, ydiff_abs;
  496.  
  497.     ydiff = (dc_term - (*pred_term));
  498.     if (ydiff > 255) {
  499.     ydiff = 255;
  500.     } else if (ydiff < -255) {
  501.     ydiff = -255;
  502.     }
  503.  
  504.     ydiff_abs = ABS(ydiff);
  505.  
  506.     if (ydiff_abs == 0) {
  507.     Bitio_Write(bb, 0x4, 3);
  508.     } else if (ydiff_abs & 0x80) {
  509.     Bitio_Write(bb, 0x7e, 7);
  510.     if (ydiff > 0) {
  511.         Bitio_Write(bb, ydiff_abs, 8);
  512.     } else
  513.         Bitio_Write(bb, ~ydiff_abs, 8);
  514.     } else if (ydiff_abs & 0x40) {
  515.     Bitio_Write(bb, 0x3e, 6);
  516.     if (ydiff > 0) {
  517.         Bitio_Write(bb, ydiff_abs, 7);
  518.     } else {
  519.         Bitio_Write(bb, ~ydiff_abs, 7);
  520.     }
  521.     } else if (ydiff_abs & 0x20) {
  522.     Bitio_Write(bb, 0x1e, 5);
  523.     if (ydiff > 0) {
  524.         Bitio_Write(bb, ydiff_abs, 6);
  525.     } else {
  526.         Bitio_Write(bb, ~ydiff_abs, 6);
  527.     }
  528.     } else if (ydiff_abs & 0x10) {
  529.     Bitio_Write(bb, 0xe, 4);
  530.     if (ydiff > 0) {
  531.         Bitio_Write(bb, ydiff_abs, 5);
  532.     } else {
  533.         Bitio_Write(bb, ~ydiff_abs, 5);
  534.     }
  535.     } else if (ydiff_abs & 0x08) {
  536.     Bitio_Write(bb, 0x6, 3);
  537.     if (ydiff > 0) {
  538.         Bitio_Write(bb, ydiff_abs, 4);
  539.     } else {
  540.         Bitio_Write(bb, ~ydiff_abs, 4);
  541.     }
  542.     } else if (ydiff_abs & 0x04) {
  543.     Bitio_Write(bb, 0x5, 3);
  544.     if (ydiff > 0) {
  545.         Bitio_Write(bb, ydiff_abs, 3);
  546.     } else {
  547.         Bitio_Write(bb, ~ydiff_abs, 3);
  548.     }
  549.     } else if (ydiff_abs & 0x02) {
  550.     Bitio_Write(bb, 0x1, 2);
  551.     if (ydiff > 0) {
  552.         Bitio_Write(bb, ydiff_abs, 2);
  553.     } else {
  554.         Bitio_Write(bb, ~ydiff_abs, 2);
  555.     }
  556.     } else if (ydiff_abs & 0x01) {
  557.     Bitio_Write(bb, 0x0, 2);
  558.     if (ydiff > 0) {
  559.         Bitio_Write(bb, ydiff_abs, 1);
  560.     } else {
  561.         Bitio_Write(bb, ~ydiff_abs, 1);
  562.     }
  563.     } else {
  564.     fprintf(stderr, "ERROR in EncodeYDC\n");
  565.     exit(1);
  566.     }
  567.  
  568.     (*pred_term) += ydiff;
  569. }
  570.  
  571.  
  572. /*===========================================================================*
  573.  *
  574.  * EncodeCDC
  575.  *
  576.  *    Encode the DC portion of a DCT of a chrominance block
  577.  *
  578.  * RETURNS:    result appended to bb
  579.  *
  580.  * SIDE EFFECTS:    updates pred_term
  581.  *
  582.  *===========================================================================*/
  583. void
  584. EncodeCDC(dc_term, pred_term, bb)
  585.     int16 dc_term;
  586.     int32 *pred_term;
  587.     BitBucket *bb;
  588. {
  589.     int cdiff, cdiff_abs;
  590.  
  591.     cdiff = (dc_term - (*pred_term));
  592.     if (cdiff > 255) {
  593.     cdiff = 255;
  594.     } else if (cdiff < -255) {
  595.     cdiff = -255;
  596.     }
  597.  
  598.     cdiff_abs = ABS(cdiff);
  599.  
  600.     if (cdiff_abs == 0) {
  601.     Bitio_Write(bb, 0x0, 2);
  602.     } else if (cdiff_abs & 0x80) {
  603.     Bitio_Write(bb, 0xfe, 8);
  604.     if (cdiff > 0) {
  605.         Bitio_Write(bb, cdiff_abs, 8);
  606.     } else {
  607.         Bitio_Write(bb, ~cdiff_abs, 8);
  608.     }
  609.     } else if (cdiff_abs & 0x40) {
  610.     Bitio_Write(bb, 0x7e, 7);
  611.     if (cdiff > 0) {
  612.         Bitio_Write(bb, cdiff_abs, 7);
  613.     } else {
  614.         Bitio_Write(bb, ~cdiff_abs, 7);
  615.     }
  616.     } else if (cdiff_abs & 0x20) {
  617.     Bitio_Write(bb, 0x3e, 6);
  618.     if (cdiff > 0) {
  619.         Bitio_Write(bb, cdiff_abs, 6);
  620.     } else {
  621.         Bitio_Write(bb, ~cdiff_abs, 6);
  622.     }
  623.     } else if (cdiff_abs & 0x10) {
  624.     Bitio_Write(bb, 0x1e, 5);
  625.     if (cdiff > 0) {
  626.         Bitio_Write(bb, cdiff_abs, 5);
  627.     } else {
  628.         Bitio_Write(bb, ~cdiff_abs, 5);
  629.     }
  630.     } else if (cdiff_abs & 0x08) {
  631.     Bitio_Write(bb, 0xe, 4);
  632.     if (cdiff > 0) {
  633.         Bitio_Write(bb, cdiff_abs, 4);
  634.     } else {
  635.         Bitio_Write(bb, ~cdiff_abs, 4);
  636.     }
  637.     } else if (cdiff_abs & 0x04) {
  638.     Bitio_Write(bb, 0x6, 3);
  639.     if (cdiff > 0) {
  640.         Bitio_Write(bb, cdiff_abs, 3);
  641.     } else {
  642.         Bitio_Write(bb, ~cdiff_abs, 3);
  643.     }
  644.     } else if (cdiff_abs & 0x02) {
  645.     Bitio_Write(bb, 0x2, 2);
  646.     if (cdiff > 0) {
  647.         Bitio_Write(bb, cdiff_abs, 2);
  648.     } else {
  649.         Bitio_Write(bb, ~cdiff_abs, 2);
  650.     }
  651.     } else if (cdiff_abs & 0x01) {
  652.     Bitio_Write(bb, 0x1, 2);
  653.     if (cdiff > 0) {
  654.         Bitio_Write(bb, cdiff_abs, 1);
  655.     } else {
  656.         Bitio_Write(bb, ~cdiff_abs, 1);
  657.     }
  658.     } else {
  659.     fprintf(stderr, "ERROR in EncodeCDC\n");
  660.     exit(1);
  661.     }
  662.  
  663.     (*pred_term) += cdiff;
  664. }
  665.  
  666.  
  667. void
  668. ComputeSNR(origData, newData, ySize, xSize, snr, psnr)
  669.      register uint8 **origData;
  670.      register uint8 **newData;
  671.      int ySize;
  672.      int xSize;
  673.      float *snr;
  674.      float *psnr;
  675. {
  676.     register int32    tempInt;
  677.     register int y, x;
  678.     int32    varOrig = 0;
  679.     int32    varDiff = 0;
  680.  
  681.     /* compute Y-plane SNR */
  682.     for ( y = 0; y < ySize; y++ ) {
  683.     for ( x = 0; x < xSize; x++ ) {
  684.         tempInt = origData[y][x];
  685.         varOrig += (tempInt*tempInt);
  686.     }
  687.     }
  688.  
  689.     for ( y = 0; y < ySize; y++ ) {
  690.     for ( x = 0; x < xSize; x++ ) {
  691.         tempInt = (origData[y][x]-newData[y][x]);
  692.         varDiff += (tempInt*tempInt);
  693.     }
  694.     }
  695.  
  696.     *snr = 10.0*log10((double)varOrig/(double)varDiff);
  697.     *psnr = 20.0*log10(255.0/sqrt((double)varDiff/(double)(ySize*xSize)));
  698. }
  699.