home *** CD-ROM | disk | FTP | other *** search
/ DP Tool Club 9 / CD_ASCQ_09_1193.iso / news / 4441 / mpegcode / src / iframe.ori < prev    next >
Text File  |  1993-09-27  |  18KB  |  702 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 int32 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.     struct tms timeBuffer;
  256.     int32    startTime, endTime;
  257.     int        frameBlocks;
  258.     float   snr[3], psnr[3];
  259.  
  260.     /* set-up for statistics */
  261.     numFrames++;
  262.     totalFrameBits = bb->cumulativeBits;
  263.     times(&timeBuffer);
  264.     startTime = timeBuffer.tms_utime + timeBuffer.tms_stime;
  265.  
  266.     Frame_AllocBlocks(current);
  267.     BlockifyFrame(current);
  268.  
  269.     DBG_PRINT(("Generating iframe\n"));
  270.  
  271.     Mhead_GenPictureHeader(bb, I_FRAME, current->id, fCode);
  272.     Mhead_GenSliceHeader(bb, 1, qscaleI, NULL, 0);
  273.  
  274.     if ( referenceFrame == DECODED_FRAME ) {
  275.     Frame_AllocDecoded(current, TRUE);
  276.     } else if ( printSNR ) {
  277.     Frame_AllocDecoded(current, FALSE);
  278.     }
  279.  
  280.     y_dc_pred = cr_dc_pred = cb_dc_pred = 128;
  281.     totalBits = bb->cumulativeBits;
  282.     frameBlocks = 0;
  283.     for (y = 0; y < Fsize_y / 8; y += 2) {
  284.     for (x = 0; x < Fsize_x / 8; x += 2) {
  285.         /* DCT this macroblock */
  286.         mp_fwd_dct_block(current->y_blocks[y][x]);
  287.         mp_fwd_dct_block(current->y_blocks[y][x+1]);
  288.         mp_fwd_dct_block(current->y_blocks[y+1][x]);
  289.         mp_fwd_dct_block(current->y_blocks[y+1][x+1]);
  290.         mp_fwd_dct_block(current->cr_blocks[y>>1][x>>1]);
  291.         mp_fwd_dct_block(current->cb_blocks[y>>1][x>>1]);
  292.  
  293.         if ( (frameBlocks % blocksPerSlice == 0) && (frameBlocks != 0) ) {
  294.         /* create a new slice */
  295.         Mhead_GenSliceEnder(bb);
  296.         Mhead_GenSliceHeader(bb, 1+(y/2), qscaleI, NULL, 0);
  297.         y_dc_pred = cr_dc_pred = cb_dc_pred = 128;
  298.  
  299.         GEN_I_BLOCK(I_FRAME, current, bb, 1+(x/2), qscaleI);
  300.         } else {
  301.         GEN_I_BLOCK(I_FRAME, current, bb, 1, qscaleI);
  302.         }
  303.  
  304.         if ( decodeRefFrames ) {
  305.         /* need to decode block we just encoded */
  306.         Mpost_UnQuantZigBlock(fb[0], dec[0], qscaleI, TRUE);
  307.         Mpost_UnQuantZigBlock(fb[1], dec[1], qscaleI, TRUE);
  308.         Mpost_UnQuantZigBlock(fb[2], dec[2], qscaleI, TRUE);
  309.         Mpost_UnQuantZigBlock(fb[3], dec[3], qscaleI, TRUE);
  310.         Mpost_UnQuantZigBlock(fb[4], dec[4], qscaleI, TRUE);
  311.         Mpost_UnQuantZigBlock(fb[5], dec[5], qscaleI, TRUE);
  312.  
  313.         /* now, reverse the DCT transform */
  314.         for ( index = 0; index < 6; index++ ) {
  315.             j_rev_dct((int16 *)dec[index]);        
  316.         }
  317.  
  318.         /* now, unblockify */
  319.         BlockToData(current->decoded_y, dec[0], y, x);
  320.         BlockToData(current->decoded_y, dec[1], y, x+1);
  321.         BlockToData(current->decoded_y, dec[2], y+1, x);
  322.         BlockToData(current->decoded_y, dec[3], y+1, x+1);
  323.         BlockToData(current->decoded_cb, dec[4], y>>1, x>>1);
  324.         BlockToData(current->decoded_cr, dec[5], y>>1, x>>1);
  325.         }
  326.  
  327.         numBlocks++;
  328.         frameBlocks++;
  329.     }
  330.     }
  331.  
  332.     if ( printSNR ) {
  333.         ComputeSNR(current->orig_y, current->decoded_y, Fsize_y, Fsize_x,
  334.            &snr[0], &psnr[0]);
  335.         ComputeSNR(current->orig_cb, current->decoded_cb, Fsize_y/2, Fsize_x/2,
  336.            &snr[1], &psnr[1]);
  337.         ComputeSNR(current->orig_cr, current->decoded_cr, Fsize_y/2, Fsize_x/2,
  338.            &snr[2], &psnr[2]);
  339.  
  340.     totalSNR += snr[0];
  341.     totalPSNR += psnr[0];
  342.     }
  343. #ifdef BLEAH
  344.  
  345. if ( decodeRefFrames ) {
  346.     FILE    *fpointer;
  347.     char    fileName[256];
  348.     int    width, height;
  349.  
  350.     /* output the decoded frame */
  351.  
  352.     width = Fsize_x;
  353.     height = Fsize_y;
  354.  
  355.     sprintf(fileName, "/tmp/decoded%d.yuv", current->id);
  356.     fprintf(stdout, "outputting to %s\n", fileName);
  357.  
  358.     fpointer = fopen(fileName, "wb");
  359.  
  360.     for ( y = 0; y < height; y++ ) {
  361.         fwrite(current->decoded_y[y], 1, width, fpointer);
  362.     }
  363.  
  364.     for (y = 0; y < height / 2; y++) {            /* U */
  365.         fwrite(current->decoded_cb[y], 1, width / 2, fpointer);
  366.     }
  367.  
  368.     for (y = 0; y < height / 2; y++) {            /* V */
  369.         fwrite(current->decoded_cr[y], 1, width / 2, fpointer);
  370.     }
  371.  
  372.     fclose(fpointer);
  373. }
  374. #endif
  375.  
  376.     numBits += (bb->cumulativeBits-totalBits);
  377.  
  378.     DBG_PRINT(("End of frame\n"));
  379.  
  380.     Mhead_GenSliceEnder(bb);
  381.  
  382.     times(&timeBuffer);
  383.     endTime = timeBuffer.tms_utime + timeBuffer.tms_stime;
  384.     totalTime += (endTime-startTime);
  385.  
  386.     numFrameBits += (bb->cumulativeBits-totalFrameBits);
  387.  
  388.     if ( (! childProcess) && frameSummary ) {
  389.     fprintf(stdout, "FRAME %d (I):  %ld seconds\n", 
  390.         current->id, (long)((endTime-startTime)/60));
  391.     if ( printSNR ) {
  392.         fprintf(stdout, "FRAME %d:  SNR:  %.1f\t%.1f\t%.1f\tPSNR:  %.1f\t%.1f\t%.1f\n",
  393.             current->id, snr[0], snr[1], snr[2],
  394.             psnr[0], psnr[1], psnr[2]);
  395.     }
  396.     }
  397. }
  398.  
  399.  
  400. /*===========================================================================*
  401.  *
  402.  * ResetIFrameStats
  403.  *
  404.  *    reset the I-frame statistics
  405.  *
  406.  * RETURNS:    nothing
  407.  *
  408.  * SIDE EFFECTS:    none
  409.  *
  410.  *===========================================================================*/
  411. void
  412. ResetIFrameStats()
  413. {
  414.     numBlocks = 0;
  415.     numBits = 0;
  416.     numFrames = 0;
  417.     numFrameBits = 0;
  418.     totalTime = 0;
  419. }
  420.  
  421.  
  422. /*===========================================================================*
  423.  *
  424.  * ShowIFrameSummary
  425.  *
  426.  *    prints out statistics on all I-frames
  427.  *
  428.  * RETURNS:    nothing
  429.  *
  430.  * SIDE EFFECTS:    none
  431.  *
  432.  *===========================================================================*/
  433. void
  434. ShowIFrameSummary(inputFrameBits, totalBits, fpointer)
  435.     int inputFrameBits;
  436.     int32 totalBits;
  437.     FILE *fpointer;
  438. {
  439.     if ( numFrames == 0 ) {
  440.     return;
  441.     }
  442.  
  443.     fprintf(fpointer, "-------------------------\n");
  444.     fprintf(fpointer, "*****I FRAME SUMMARY*****\n");
  445.     fprintf(fpointer, "-------------------------\n");
  446.  
  447.     fprintf(fpointer, "  Blocks:    %5d     (%6d bits)     (%5d bpb)\n",
  448.         numBlocks, numBits, numBits/numBlocks);
  449.     fprintf(fpointer, "  Frames:    %5d     (%6d bits)     (%5d bpf)     (%2.1f%% of total)\n",
  450.         numFrames, numFrameBits, numFrameBits/numFrames,
  451.         100.0*(float)numFrameBits/(float)totalBits);
  452.     fprintf(fpointer, "  Compression:  %3d:1\n",
  453.         numFrames*inputFrameBits/numFrameBits);
  454.     if ( printSNR )
  455.     fprintf(fpointer, "  Avg Y SNR/PSNR:  %.1f     %.1f\n",
  456.         totalSNR/(float)numFrames, totalPSNR/(float)numFrames);
  457.     fprintf(fpointer, "  Seconds:  %9ld     (%9ld spf)     (%9ld bps)\n",
  458.         (long)(totalTime/60), (long)(totalTime/(60*numFrames)),
  459.         (long)(60.0*(float)numFrames*(float)inputFrameBits/(float)totalTime));
  460. }
  461.  
  462.  
  463. /*===========================================================================*
  464.  *
  465.  * EstimateSecondsPerIFrame
  466.  *
  467.  *    estimates the number of seconds required per I-frame
  468.  *
  469.  * RETURNS:    seconds (floating point value)
  470.  *
  471.  * SIDE EFFECTS:    none
  472.  *
  473.  *===========================================================================*/
  474. float
  475. EstimateSecondsPerIFrame()
  476. {
  477.     return (float)totalTime/(60.0*(float)numFrames);
  478. }
  479.  
  480.  
  481. /*===========================================================================*
  482.  *
  483.  * EncodeYDC
  484.  *
  485.  *    Encode the DC portion of a DCT of a luminance block
  486.  *
  487.  * RETURNS:    result appended to bb
  488.  *
  489.  * SIDE EFFECTS:    updates pred_term
  490.  *
  491.  *===========================================================================*/
  492. void
  493. EncodeYDC(dc_term, pred_term, bb)
  494.     int16 dc_term;
  495.     int32 *pred_term;
  496.     BitBucket *bb;
  497. {
  498.     int ydiff, ydiff_abs;
  499.  
  500.     ydiff = (dc_term - (*pred_term));
  501.     if (ydiff > 255) {
  502.     ydiff = 255;
  503.     } else if (ydiff < -255) {
  504.     ydiff = -255;
  505.     }
  506.  
  507.     ydiff_abs = ABS(ydiff);
  508.  
  509.     if (ydiff_abs == 0) {
  510.     Bitio_Write(bb, 0x4, 3);
  511.     } else if (ydiff_abs & 0x80) {
  512.     Bitio_Write(bb, 0x7e, 7);
  513.     if (ydiff > 0) {
  514.         Bitio_Write(bb, ydiff_abs, 8);
  515.     } else
  516.         Bitio_Write(bb, ~ydiff_abs, 8);
  517.     } else if (ydiff_abs & 0x40) {
  518.     Bitio_Write(bb, 0x3e, 6);
  519.     if (ydiff > 0) {
  520.         Bitio_Write(bb, ydiff_abs, 7);
  521.     } else {
  522.         Bitio_Write(bb, ~ydiff_abs, 7);
  523.     }
  524.     } else if (ydiff_abs & 0x20) {
  525.     Bitio_Write(bb, 0x1e, 5);
  526.     if (ydiff > 0) {
  527.         Bitio_Write(bb, ydiff_abs, 6);
  528.     } else {
  529.         Bitio_Write(bb, ~ydiff_abs, 6);
  530.     }
  531.     } else if (ydiff_abs & 0x10) {
  532.     Bitio_Write(bb, 0xe, 4);
  533.     if (ydiff > 0) {
  534.         Bitio_Write(bb, ydiff_abs, 5);
  535.     } else {
  536.         Bitio_Write(bb, ~ydiff_abs, 5);
  537.     }
  538.     } else if (ydiff_abs & 0x08) {
  539.     Bitio_Write(bb, 0x6, 3);
  540.     if (ydiff > 0) {
  541.         Bitio_Write(bb, ydiff_abs, 4);
  542.     } else {
  543.         Bitio_Write(bb, ~ydiff_abs, 4);
  544.     }
  545.     } else if (ydiff_abs & 0x04) {
  546.     Bitio_Write(bb, 0x5, 3);
  547.     if (ydiff > 0) {
  548.         Bitio_Write(bb, ydiff_abs, 3);
  549.     } else {
  550.         Bitio_Write(bb, ~ydiff_abs, 3);
  551.     }
  552.     } else if (ydiff_abs & 0x02) {
  553.     Bitio_Write(bb, 0x1, 2);
  554.     if (ydiff > 0) {
  555.         Bitio_Write(bb, ydiff_abs, 2);
  556.     } else {
  557.         Bitio_Write(bb, ~ydiff_abs, 2);
  558.     }
  559.     } else if (ydiff_abs & 0x01) {
  560.     Bitio_Write(bb, 0x0, 2);
  561.     if (ydiff > 0) {
  562.         Bitio_Write(bb, ydiff_abs, 1);
  563.     } else {
  564.         Bitio_Write(bb, ~ydiff_abs, 1);
  565.     }
  566.     } else {
  567.     fprintf(stderr, "ERROR in EncodeYDC\n");
  568.     exit(1);
  569.     }
  570.  
  571.     (*pred_term) += ydiff;
  572. }
  573.  
  574.  
  575. /*===========================================================================*
  576.  *
  577.  * EncodeCDC
  578.  *
  579.  *    Encode the DC portion of a DCT of a chrominance block
  580.  *
  581.  * RETURNS:    result appended to bb
  582.  *
  583.  * SIDE EFFECTS:    updates pred_term
  584.  *
  585.  *===========================================================================*/
  586. void
  587. EncodeCDC(dc_term, pred_term, bb)
  588.     int16 dc_term;
  589.     int32 *pred_term;
  590.     BitBucket *bb;
  591. {
  592.     int cdiff, cdiff_abs;
  593.  
  594.     cdiff = (dc_term - (*pred_term));
  595.     if (cdiff > 255) {
  596.     cdiff = 255;
  597.     } else if (cdiff < -255) {
  598.     cdiff = -255;
  599.     }
  600.  
  601.     cdiff_abs = ABS(cdiff);
  602.  
  603.     if (cdiff_abs == 0) {
  604.     Bitio_Write(bb, 0x0, 2);
  605.     } else if (cdiff_abs & 0x80) {
  606.     Bitio_Write(bb, 0xfe, 8);
  607.     if (cdiff > 0) {
  608.         Bitio_Write(bb, cdiff_abs, 8);
  609.     } else {
  610.         Bitio_Write(bb, ~cdiff_abs, 8);
  611.     }
  612.     } else if (cdiff_abs & 0x40) {
  613.     Bitio_Write(bb, 0x7e, 7);
  614.     if (cdiff > 0) {
  615.         Bitio_Write(bb, cdiff_abs, 7);
  616.     } else {
  617.         Bitio_Write(bb, ~cdiff_abs, 7);
  618.     }
  619.     } else if (cdiff_abs & 0x20) {
  620.     Bitio_Write(bb, 0x3e, 6);
  621.     if (cdiff > 0) {
  622.         Bitio_Write(bb, cdiff_abs, 6);
  623.     } else {
  624.         Bitio_Write(bb, ~cdiff_abs, 6);
  625.     }
  626.     } else if (cdiff_abs & 0x10) {
  627.     Bitio_Write(bb, 0x1e, 5);
  628.     if (cdiff > 0) {
  629.         Bitio_Write(bb, cdiff_abs, 5);
  630.     } else {
  631.         Bitio_Write(bb, ~cdiff_abs, 5);
  632.     }
  633.     } else if (cdiff_abs & 0x08) {
  634.     Bitio_Write(bb, 0xe, 4);
  635.     if (cdiff > 0) {
  636.         Bitio_Write(bb, cdiff_abs, 4);
  637.     } else {
  638.         Bitio_Write(bb, ~cdiff_abs, 4);
  639.     }
  640.     } else if (cdiff_abs & 0x04) {
  641.     Bitio_Write(bb, 0x6, 3);
  642.     if (cdiff > 0) {
  643.         Bitio_Write(bb, cdiff_abs, 3);
  644.     } else {
  645.         Bitio_Write(bb, ~cdiff_abs, 3);
  646.     }
  647.     } else if (cdiff_abs & 0x02) {
  648.     Bitio_Write(bb, 0x2, 2);
  649.     if (cdiff > 0) {
  650.         Bitio_Write(bb, cdiff_abs, 2);
  651.     } else {
  652.         Bitio_Write(bb, ~cdiff_abs, 2);
  653.     }
  654.     } else if (cdiff_abs & 0x01) {
  655.     Bitio_Write(bb, 0x1, 2);
  656.     if (cdiff > 0) {
  657.         Bitio_Write(bb, cdiff_abs, 1);
  658.     } else {
  659.         Bitio_Write(bb, ~cdiff_abs, 1);
  660.     }
  661.     } else {
  662.     fprintf(stderr, "ERROR in EncodeCDC\n");
  663.     exit(1);
  664.     }
  665.  
  666.     (*pred_term) += cdiff;
  667. }
  668.  
  669.  
  670. void
  671. ComputeSNR(origData, newData, ySize, xSize, snr, psnr)
  672.      register uint8 **origData;
  673.      register uint8 **newData;
  674.      int ySize;
  675.      int xSize;
  676.      float *snr;
  677.      float *psnr;
  678. {
  679.     register int32    tempInt;
  680.     register int y, x;
  681.     int32    varOrig = 0;
  682.     int32    varDiff = 0;
  683.  
  684.     /* compute Y-plane SNR */
  685.     for ( y = 0; y < ySize; y++ ) {
  686.     for ( x = 0; x < xSize; x++ ) {
  687.         tempInt = origData[y][x];
  688.         varOrig += (tempInt*tempInt);
  689.     }
  690.     }
  691.  
  692.     for ( y = 0; y < ySize; y++ ) {
  693.     for ( x = 0; x < xSize; x++ ) {
  694.         tempInt = (origData[y][x]-newData[y][x]);
  695.         varDiff += (tempInt*tempInt);
  696.     }
  697.     }
  698.  
  699.     *snr = 10.0*log10((double)varOrig/(double)varDiff);
  700.     *psnr = 20.0*log10(255.0/sqrt((double)varDiff/(double)(ySize*xSize)));
  701. }
  702.