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

  1. /*===========================================================================*
  2.  * postdct.c                                     *
  3.  *                                         *
  4.  *    Procedures concerned with MPEG post-DCT processing:             *
  5.  *        quantization and RLE Huffman encoding                 *
  6.  *                                         *
  7.  * EXPORTED PROCEDURES:                                 *
  8.  *    Mpost_QuantZigBlock                             *
  9.  *    Mpost_RLEHuffIBlock                             *
  10.  *    Mpost_RLEHuffPBlock                             *
  11.  *    Mpost_UnQuantZigBlock                             *
  12.  *                                         *
  13.  *===========================================================================*/
  14.  
  15. /*
  16.  * Copyright (c) 1993 The Regents of the University of California.
  17.  * All rights reserved.
  18.  *
  19.  * Permission to use, copy, modify, and distribute this software and its
  20.  * documentation for any purpose, without fee, and without written agreement is
  21.  * hereby granted, provided that the above copyright notice and the following
  22.  * two paragraphs appear in all copies of this software.
  23.  *
  24.  * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
  25.  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
  26.  * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
  27.  * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  28.  *
  29.  * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
  30.  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
  31.  * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
  32.  * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
  33.  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
  34.  */
  35.  
  36. /*
  37.  *  $Header: /n/picasso/users/keving/encode/src/RCS/postdct.c,v 1.11 1993/07/22 22:23:43 keving Exp keving $
  38.  *  $Log: postdct.c,v $
  39.  * Revision 1.11  1993/07/22  22:23:43  keving
  40.  * nothing
  41.  *
  42.  * Revision 1.10  1993/06/30  20:06:09  keving
  43.  * nothing
  44.  *
  45.  * Revision 1.9  1993/06/03  21:08:08  keving
  46.  * nothing
  47.  *
  48.  * Revision 1.8  1993/02/24  18:57:19  keving
  49.  * nothing
  50.  *
  51.  * Revision 1.7  1993/02/23  22:58:36  keving
  52.  * nothing
  53.  *
  54.  * Revision 1.6  1993/02/23  22:54:56  keving
  55.  * nothing
  56.  *
  57.  * Revision 1.5  1993/02/17  23:18:20  dwallach
  58.  * checkin prior to keving's joining the project
  59.  *
  60.  * Revision 1.4  1993/01/18  10:20:02  dwallach
  61.  * *** empty log message ***
  62.  *
  63.  * Revision 1.3  1993/01/18  10:17:29  dwallach
  64.  * RCS headers installed, code indented uniformly
  65.  *
  66.  * Revision 1.3  1993/01/18  10:17:29  dwallach
  67.  * RCS headers installed, code indented uniformly
  68.  *
  69.  */
  70.  
  71.  
  72. /*==============*
  73.  * HEADER FILES *
  74.  *==============*/
  75.  
  76. #include <assert.h>
  77. #include "all.h"
  78. #include "mtypes.h"
  79. #include "bitio.h"
  80. #include "huff.h"
  81. #include "postdct.h"
  82.  
  83.  
  84. /*==================*
  85.  * STATIC VARIABLES *
  86.  *==================*/
  87.  
  88. /* ZAG[i] is the natural-order position of the i'th element of zigzag order. */
  89. static int ZAG[] = {
  90.     0, 1, 8, 16, 9, 2, 3, 10,
  91.     17, 24, 32, 25, 18, 11, 4, 5,
  92.     12, 19, 26, 33, 40, 48, 41, 34,
  93.     27, 20, 13, 6, 7, 14, 21, 28,
  94.     35, 42, 49, 56, 57, 50, 43, 36,
  95.     29, 22, 15, 23, 30, 37, 44, 51,
  96.     58, 59, 52, 45, 38, 31, 39, 46,
  97.     53, 60, 61, 54, 47, 55, 62, 63
  98. };
  99.  
  100.  
  101. /*
  102.  * possible optimization: reorder the qtable in the correct zigzag order, to
  103.  * reduce the number of necessary lookups
  104.  *
  105.  * this table comes from the MPEG draft, p. D-16, Fig. 2-D.15.
  106.  */
  107. static int qtable[] = {
  108.     8, 16, 19, 22, 26, 27, 29, 34,
  109.     16, 16, 22, 24, 27, 29, 34, 37,
  110.     19, 22, 26, 27, 29, 34, 34, 38,
  111.     22, 22, 26, 27, 29, 34, 37, 40,
  112.     22, 26, 27, 29, 32, 35, 40, 48,
  113.     26, 27, 29, 32, 35, 40, 48, 58,
  114.     26, 27, 29, 34, 38, 46, 56, 69,
  115.     27, 29, 35, 38, 46, 56, 69, 83
  116. };
  117.  
  118.  
  119. /*=====================*
  120.  * EXPORTED PROCEDURES *
  121.  *=====================*/
  122.  
  123. /*===========================================================================*
  124.  *
  125.  * Mpost_UnQuantZigBlock
  126.  *
  127.  *    unquantize and zig-zag (decode) a single block
  128.  *
  129.  * RETURNS:    nothing
  130.  *
  131.  * SIDE EFFECTS:    none
  132.  *
  133.  *===========================================================================*/
  134. void
  135. Mpost_UnQuantZigBlock(in, out, qscale, iblock)
  136.     FlatBlock in;
  137.     Block out;
  138.     int qscale;
  139.     boolean iblock;
  140. {
  141.     register int index;
  142.     int        start;
  143.     int        position;
  144.     register int        qentry;
  145.     int        level, coeff;
  146.  
  147.     if ( iblock ) {
  148.     ((int16 *)out)[0] = (int16)(in[0]*qtable[0]);
  149.  
  150.     start = 1;
  151.     } else {
  152.     start = 0;
  153.     }
  154.  
  155.     for ( index = start; index < DCTSIZE_SQ; index++ ) {
  156.     position = ZAG[index];
  157.  
  158.     if (iblock) {
  159.         qentry = qtable[position] * qscale;
  160.     } else {
  161.         qentry = 16 * qscale;
  162.     }
  163.  
  164.     level = in[index];
  165.  
  166.     if ( iblock ) {
  167.         coeff = (2*level*qentry) >> 4;
  168.         if ( (coeff & 1) == 0 ) {
  169.         if ( coeff < 0 ) {
  170.             coeff++;
  171.         } else if ( coeff > 0 ) {
  172.             coeff--;
  173.         }
  174.         }
  175.  
  176.         if ( coeff > 2047 ) {
  177.         coeff = 2047;
  178.         } else if ( coeff < -2048 ) {
  179.         coeff = -2048;
  180.         }
  181.     } else {
  182.         if ( level == 0 ) {
  183.         coeff = 0;
  184.         } else if ( level < 0 ) {
  185.         coeff = (((2*level)-1)*qentry) >> 4;
  186.         if ( (coeff & 1) == 0 ) {
  187.             coeff++;
  188.         }
  189.         } else {
  190.         coeff = (((2*level)+1)*qentry) >> 4;
  191.         if ( (coeff & 1) == 0 ) {
  192.             coeff--;
  193.         }
  194.         }
  195.  
  196.         if ( coeff > 2047 ) {
  197.         coeff = 2047;
  198.         } else if ( coeff < -2048 ) {
  199.         coeff = -2048;
  200.         }
  201.     }
  202.  
  203.     ((int16 *)out)[position] = coeff;
  204.     }
  205.  
  206. #ifdef BLEAH
  207.     for ( index = 0; index < 64; index++ ) {
  208.     fprintf(stdout, "DCT[%d] = %d\n", index, 
  209.         ((int16 *)out)[index]);
  210.     }
  211. #endif
  212. }
  213.  
  214.  
  215. /*===========================================================================*
  216.  *
  217.  * Mpost_QuantZigBlock
  218.  *
  219.  *    quantize and zigzags a block
  220.  *
  221.  * RETURNS:    TRUE iff resulting output is non-zero, FALSE if all zero
  222.  *
  223.  * SIDE EFFECTS:    none
  224.  *
  225.  *===========================================================================*/
  226. boolean
  227. Mpost_QuantZigBlock(in, out, qscale, iblock)
  228.     Block in;
  229.     FlatBlock out;
  230.     register int qscale;
  231.     int iblock;
  232. {
  233.     register int i;
  234.     register int16 temp;
  235.     register int qentry;
  236.     register int position;
  237.     boolean nonZero = FALSE;
  238.  
  239.     DBG_PRINT(("Mpost_QuantZigBlock...\n"));
  240.     if (iblock) {
  241.     /*
  242.      * the DC coefficient is handled specially -- it's not
  243.      * sensitive to qscale, but everything else is
  244.      */
  245.     temp = ((int16 *) in)[ZAG[0]];
  246.     qentry = qtable[ZAG[0]];
  247.  
  248.         if (temp < 0) {
  249.             temp = -temp;
  250.             temp += qentry >> 1;
  251.             temp /= qentry;
  252.             temp = -temp;
  253.     } else {
  254.             temp += qentry >> 1;
  255.             temp /= qentry;
  256.     }
  257.     if ( temp != 0 ) {
  258.         nonZero = TRUE;
  259.     }
  260.     out[0] = temp;
  261.  
  262.     for (i = 1; i < DCTSIZE_SQ; i++) {
  263.         position = ZAG[i];
  264.         temp = ((int16 *) in)[position];
  265.  
  266.         qentry = qtable[position] * qscale;
  267.  
  268.         /* see 1993 MPEG doc, section D.6.3.4 */
  269.         if (temp < 0) {
  270.         temp = -temp;
  271.         temp = (temp << 3);
  272.         temp += (qentry >> 1);
  273.         temp /= qentry;
  274.         temp = -temp;
  275.         } else {
  276.         temp = (temp << 3);
  277.         temp += (qentry >> 1);
  278.         temp /= qentry;
  279.         }
  280.  
  281.         if ( temp != 0 ) {
  282.         nonZero = TRUE;
  283.         }
  284.         out[i] = temp;
  285.     }
  286.     } else {
  287.     for (i = 0; i < DCTSIZE_SQ; i++) {
  288.         position = ZAG[i];
  289.         temp = ((int16 *) in)[position];
  290.  
  291.         /* multiply by 16 */
  292.         qentry = qscale << 4;
  293.  
  294.         /* see 1993 MPEG doc, D.6.4.5 */
  295.         temp = (temp << 3);
  296.         temp /= qentry;
  297.  
  298.         if ( temp != 0 ) {
  299.         nonZero = TRUE;
  300.         }
  301.         out[i] = temp;
  302.     }
  303.     }
  304.  
  305.     return nonZero;
  306. }
  307.  
  308.  
  309.  
  310. /*===========================================================================*
  311.  *
  312.  * Mpost_RLEHuffIBlock
  313.  *
  314.  *    generate the huffman bits from an I-block
  315.  *
  316.  * RETURNS:    nothing
  317.  *
  318.  * SIDE EFFECTS:    none
  319.  *
  320.  *===========================================================================*/
  321. void
  322. Mpost_RLEHuffIBlock(in, out)
  323.     FlatBlock in;
  324.     BitBucket *out;
  325. {
  326.     register int i;
  327.     register int nzeros = 0;
  328.     register int16 cur;
  329.     register int16 acur;
  330.     register uint32 code;
  331.     register int nbits;
  332.  
  333.     /*
  334.      * yes, Virginia, we start at 1.  The DC coefficient is handled
  335.      * specially, elsewhere.  Not here.
  336.      */
  337.     for (i = 1; i < DCTSIZE_SQ; i++) {
  338.     cur = in[i];
  339.     acur = ABS(cur);
  340.     if (cur) {
  341.         if ( (nzeros < HUFF_MAXRUN) && (acur < huff_maxlevel[nzeros])) {
  342.             /*
  343.          * encode using the Huffman tables
  344.          */
  345.  
  346.         code = (huff_table[nzeros])[acur];
  347.         nbits = (huff_bits[nzeros])[acur];
  348.  
  349.         if (cur < 0) {
  350.             code |= 1;    /* the sign bit */
  351.         }
  352.         Bitio_Write(out, code, nbits);
  353.         } else {
  354.         /*
  355.          * encode using the escape code
  356.          */
  357.         Bitio_Write(out, 0x1, 6);    /* ESCAPE */
  358.         Bitio_Write(out, nzeros, 6);    /* Run-Length */
  359.  
  360.         /*
  361.              * this shouldn't happen, but the other
  362.              * choice is to bomb out and dump core...
  363.              */
  364.         if (cur < -255) {
  365.             cur = -255;
  366.         } else if (cur > 255) {
  367.             cur = 255;
  368.         }
  369.  
  370.         DBG_PRINT(("Level\n"));
  371.         if (acur < 128) {
  372.             Bitio_Write(out, cur, 8);
  373.         } else {
  374.             if (cur < 0) {
  375.             Bitio_Write(out, 0x8001 + cur + 255, 16);
  376.             } else {
  377.             Bitio_Write(out, cur, 16);
  378.             }
  379.         }
  380.         }
  381.         nzeros = 0;
  382.     } else {
  383.         nzeros++;
  384.     }
  385.     }
  386.     DBG_PRINT(("End of block\n"));
  387.     Bitio_Write(out, 0x2, 2);    /* end of block marker */
  388. }
  389.  
  390.  
  391. /*===========================================================================*
  392.  *
  393.  * Mpost_RLEHuffPBlock
  394.  *
  395.  *    generate the huffman bits from an P-block
  396.  *
  397.  * RETURNS:    nothing
  398.  *
  399.  * SIDE EFFECTS:    none
  400.  *
  401.  *===========================================================================*/
  402. void
  403. Mpost_RLEHuffPBlock(in, out)
  404.     FlatBlock in;
  405.     BitBucket *out;
  406. {
  407.     register int i;
  408.     register int nzeros = 0;
  409.     register int16 cur;
  410.     register int16 acur;
  411.     register uint32 code;
  412.     register int nbits;
  413.     boolean first_dct = TRUE;
  414.  
  415.     /*
  416.      * yes, Virginia, we start at 0.
  417.      */
  418.     for (i = 0; i < DCTSIZE_SQ; i++) {
  419.     cur = in[i];
  420.     acur = ABS(cur);
  421.     if (cur) {
  422.         if (nzeros < HUFF_MAXRUN && acur < huff_maxlevel[nzeros]) {
  423.             /*
  424.          * encode using the Huffman tables
  425.          */
  426.  
  427.         DBG_PRINT(("rle_huff %02d: Run %02d, Level %02d\n", i, nzeros, cur));
  428.         assert(cur);
  429.  
  430.         if ( first_dct && (nzeros == 0) && (acur == 1) ) {
  431.             /* actually, only needs = 0x2 */
  432.             code = (cur == 1) ? 0x2 : 0x3;
  433.             nbits = 2;
  434.         } else {
  435.             code = (huff_table[nzeros])[acur];
  436.             nbits = (huff_bits[nzeros])[acur];
  437.         }
  438.  
  439.         assert(nbits);
  440.  
  441.         if (cur < 0) {
  442.             code |= 1;    /* the sign bit */
  443.         }
  444.         Bitio_Write(out, code, nbits);
  445.         first_dct = FALSE;
  446.         } else {
  447.         /*
  448.          * encode using the escape code
  449.          */
  450.         DBG_PRINT(("Escape\n"));
  451.         Bitio_Write(out, 0x1, 6);    /* ESCAPE */
  452.         DBG_PRINT(("Run Length\n"));
  453.         Bitio_Write(out, nzeros, 6);    /* Run-Length */
  454.  
  455.         assert(cur != 0);
  456.  
  457.         /*
  458.              * this shouldn't happen, but the other
  459.              * choice is to bomb out and dump core...
  460.              */
  461.         if (cur < -255) {
  462.             cur = -255;
  463.         } else if (cur > 255) {
  464.             cur = 255;
  465.         }
  466.  
  467.         DBG_PRINT(("Level\n"));
  468.         if (acur < 128) {
  469.             Bitio_Write(out, cur, 8);
  470.         } else {
  471.             if (cur < 0) {
  472.             Bitio_Write(out, 0x8001 + cur + 255, 16);
  473.             } else {
  474.             Bitio_Write(out, cur, 16);
  475.             }
  476.         }
  477.  
  478.         first_dct = FALSE;
  479.         }
  480.         nzeros = 0;
  481.     } else {
  482.         nzeros++;
  483.     }
  484.     }
  485.  
  486.     /* actually, should REALLY return FALSE and not use this! */
  487.     if ( first_dct ) {    /* have to give a first_dct even if all 0's */
  488.     fprintf(stdout, "HUFF called with all-zero coefficients\n");
  489.     fprintf(stdout, "exiting...\n");
  490.     exit(1);
  491.     }
  492.  
  493.     DBG_PRINT(("End of block\n"));
  494.     Bitio_Write(out, 0x2, 2);    /* end of block marker */
  495. }
  496.