Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members

mxcpcFramewiseMxPEGScanToJPEGConverterSoftwareOnly.h

00001 //           ///          //                                        Mx clientSDK
00002 //          /////        ////                    Mx Crossplatform Client Library
00003 //         /// XXX     XXX ///
00004 //        ///    XXX XXX    ///     $RCSfile: mxcpcFramewiseMxPEGScanToJPEGConverterSoftwareOnly.h,v $
00005 //       ///       XXX       ///     $Revision: 1.4 $
00006 //      ///      XXX XXX      ///     $Date: 2005/12/20 16:41:55 $
00007 //     ////    XXX     XXX    ////     $Author: cvs-kai $
00008 //    ////                     ////
00009 //   ////  M  O  B  O  T  I  X  ////////////////////////////////////////////////
00010 //  //// Security Vision Systems //////////////////////////////////////////////
00011 //                                                                          //
00012 //  Copyright (C) 2005 - 2006, MOBOTIX AG, Germany                         //
00013 //  This software is made available under the BSD licence. Please refer   //
00014 //  to the file LICENCE.TXT contained in this distribution for details.  //
00015 //                                                                      //
00016 //  /////////////////////////////////////////////////////////////////////
00017 
00018 
00019 
00020 #ifndef __MXCPC_FRAMEWISEMXPEGSCANTOJPEGCONVERTERSOFTWAREONLY_H__
00021 #define __MXCPC_FRAMEWISEMXPEGSCANTOJPEGCONVERTERSOFTWAREONLY_H__
00022 
00023 
00024 
00025 #include <mxcpcFramewiseMxPEGScanToJPEGConverter.h>
00026 #include <mxcpcHuffmanTree.h>
00027 #include <mxcpc_mxpeg_namespace.h>
00028 
00029 #include <cstdio>
00030 #include <cstring>
00031 #include <cstdlib>
00032 
00033 
00034 
00035 #define MXCPC_FRAMEWISEMXPEGSCANTOJPEGCONVERTER_BITSTREAM_BUFFSIZE 0x100000
00036 
00037 
00038 
00039 class mxcpcJPEGReceiver;
00040 
00041 
00042 
00043 //! Framewise scan decoder converting an <tt>MxPEG</tt> stream to a sequence of
00044 //! JPEG images using no external hardware-optimized acceleration routines. 
00045 /*! 
00046  *  \ingroup mxcpc_core
00047  *
00048  *  Does not really use the regular <i>decoder</i> backend, therefore install 
00049  *  the mxcpcDefaultMxPEGDecoderBackEnd with your decoder 
00050  *  
00051  *  You can choose among various mxcpcJPEGReceiver s though, doing all sorts of 
00052  *  stuff with your generated JPEG images.
00053  *
00054  *  \warning In its current version, this class is not threadable.
00055  *
00056  *  \author Gruys
00057 */
00058 class mxcpcFramewiseMxPEGScanToJPEGConverterSoftwareOnly 
00059        : public mxcpcFramewiseMxPEGScanToJPEGConverter   {
00060 
00061  private:
00062   static const unsigned char ZigZag_StoreMap[64];
00063   static const int           ZigZagMap[64];
00064         
00065   //! One DC huffman table - rules for one component (Y or UV) 
00066   typedef struct { 
00067     //! bits_dc[x] = how many length-codes are encoded with a symbol of length x
00068     //!              - 0 is missing!
00069     mxcpc::u8 bits_dc[16];      
00070     //! the actual codes for coefficient-lengths from 0 to 11 bits. The length
00071     //! is the number of bits that are not zero
00072     mxcpc::u8 val_dc[12];               
00073   } HuffCompDC;
00074         
00075   //! One AC huffman table - rules for one component (Y or UV) 
00076   typedef struct { 
00077     //! max length of code is 16 bits - in fact, 119 of 162 possible 
00078     //! combinations are 16 bits !
00079     //! - including up to 11 significant data bits, 
00080     //! - a single non-zero dc-coefficient could therefore 
00081     //! - generate up to 27 bits of huffman data
00082     mxcpc::u8 bits_ac[16];
00083     mxcpc::u8 val_ac[162];
00084   } HuffCompAC;
00085         
00086         static const HuffCompDC HuffTbl_Y_UV_DC[2];     
00087         
00088         static const HuffCompAC HuffTbl_Y_UV_AC[2];
00089         
00090         
00091   //!  Single entry in table
00092   typedef struct {
00093     //! mask, made of rll-encoded symbol(2..16bits) shifted left by (num. of
00094     //! mantissa-bits) 
00095     unsigned int code_msk:  26;
00096     //! always 0
00097     unsigned int fill_0bit:  1;
00098     //! 2..26, sum of len of rll-encoded symbol + len of mantissa-bits 
00099     unsigned int bit_len:    5;
00100   } HuffCodeTblEntry;
00101         
00102         
00103   //! Used to convert a HuffCodeTblEntry -> mxcpc::u32 ! 
00104   typedef union {
00105     HuffCodeTblEntry table_entry;
00106     mxcpc::u32       u32_word;
00107   } u32t;
00108                 
00109   /*! One AC huffman table for either Y or UV */
00110   typedef struct {
00111     //! We index this with symbols 00, 0F, 10..AF and hope gcc won't notice!
00112     HuffCodeTblEntry ac_tbl[1];
00113     //! Add 1 to length to be able to use same ptr as for ac-table
00114     HuffCodeTblEntry dc_tbl[12];
00115     //! Ununsed entry  
00116     int free_13;
00117     //! Second unused entry [14] is still free    
00118     int free_14;
00119     //! The valid entries for the ac-table continue here at [15]    
00120     HuffCodeTblEntry dc_tbl_0FtoAF[161];  
00121   } FoldedHuffTbl_DC_AC;
00122 
00123   //! Array of two tables, size = 2*0xB0 words = 1408 bytes : */
00124   static FoldedHuffTbl_DC_AC Huff_Y_UV[2];
00125         
00126   //! This structure holds the buffer state for huffman encoding ...
00127   typedef struct {
00128     mxcpc::u8* buf_start;         // Addr of buf in memory, word-aligned 
00129     mxcpc::u8* buf_end1;          // End of buffer + 1, word-aligned */
00130     mxcpc::u8* buf_current_w_pos; // Current buffer pointer, word-aligned if 
00131                                   //  huf_accu is valid,
00132                                   //  may be odd after jd_close_huf_buf_stateb
00133                                   //  was called */       
00134     mxcpc::u32 huf_accu;          // Left justified bits not yet emitted
00135     unsigned int huf_bits_used;   // Number of valid bits in huf_accu not yet
00136                                   //  emitted
00137   } HuffmanBufferStateStructure;
00138         
00139   //! Instance of HuffmanBufferStateStructure hold once!
00140   static HuffmanBufferStateStructure HuffmanBufferState;
00141                         
00142   //! Pointer to Huffman encode buffer
00143   mxcpc::u8* HuffmanEncoderBuffer;
00144                         
00145  private:
00146   mxcpcHuffmanTree *HuffmanTree_Y_DC, 
00147                    *HuffmanTree_Y_AC; 
00148   mxcpcHuffmanTree *HuffmanTree_UV_DC, 
00149                    *HuffmanTree_UV_AC;
00150   mxcpc::s16 QuantizationTable_Y[64],
00151              QuantizationTable_UV[64];
00152   //! Ptr. to decoded frame!
00153   mxcpc::s16* CoeffBuffer;
00154   //! Nb. of tiles to handle per frame!
00155   int TileNumX, TileNumY;
00156 
00157   // The following fields' state is defined to only be valid during scan sweeps
00158   //  - so they won't show up in the constructor...
00159   unsigned char *CurrentScanByte,
00160                 ScanMask;
00161   int ScanBytesLeft;
00162   int CoeffInAdditionalBits;
00163   mxcpc_mxpeg::APP0 APP0_Block;
00164   mxcpc_mxpeg::SOF0 SOF0_Block;
00165   mxcpc_mxpeg::SOS  SOS_Block;         
00166   int FramesProcessed;
00167         
00168  public:
00169   //! The converter assumes ownership over the JPEG receiver.
00170   mxcpcFramewiseMxPEGScanToJPEGConverterSoftwareOnly(
00171    mxcpcJPEGReceiver *receiver
00172   );
00173   ~mxcpcFramewiseMxPEGScanToJPEGConverterSoftwareOnly();
00174   
00175  public:
00176   //! (Re)implemented.
00177   const char *getAccelerationTypeString(void);
00178   //! (Re)implemented.
00179   void setYQuantizationTable(unsigned char *data_bytes);
00180   //! (Re)implemented.
00181   void setUVQuantizationTable(unsigned char *data_bytes);
00182   //! (Re)implemented.
00183   void performScanSweep(mxcpcFramewiseMxPEGDecoder::UndecodedFrameDescriptor
00184                          *frame_descriptor
00185                        );
00186         
00187  private:
00188   //! Calculate the huffman tables ..
00189   void calcFoldedHuffTables(void);
00190   //! Create a huffman lookup table.
00191   /*!
00192    * \param bits_tbl_off1 Entries 0..15 count no. of symbols 
00193    *        with 1..16 bits, respectively.
00194    * \param val_tbl Table of symbols that need to be encoded, 
00195    *        size = sum of entries in bits_tbl_off1.
00196    * \param swap_symbol Set if the swapped symbol is used to access the 
00197    *        generated folded table (for ac-coefs).
00198    * \param folded_tbl_p Holds the generated huffman tables!
00199    */
00200   void generateHuffTables1(const mxcpc::u8 * bits_tbl_off1,
00201                            const mxcpc::u8 * val_tbl,        
00202                            int swap_symbol,    
00203                            HuffCodeTblEntry * folded_tbl_p);
00204   //! Init the Buffer.
00205   void initHuffmanEncoderBufferState();
00206   void resetHuffmanEncoderBufferState(); 
00207 
00208   //! We need this often in inner loops of performScanSweep(), so we 
00209   //! request inline substitution and hope the compiler sufficiently rocks.
00210   /*!
00211    *  Only to be called if <tt>ScanBytesLeft > 0</tt>.
00212    *
00213    *  Returns whether or not the bit just consumed was set.
00214    */
00215   inline bool consumeScanBit(void) {
00216     
00217     bool bit_was_set;
00218     unsigned char last_scan_byte;
00219     
00220     bit_was_set = *CurrentScanByte & ScanMask;
00221     
00222     ScanMask /= 2;
00223     if(!ScanMask) {
00224      
00225       last_scan_byte = *CurrentScanByte;
00226     
00227       CurrentScanByte++;
00228       ScanBytesLeft--;
00229       if(last_scan_byte == 0xff) {
00230         if(*CurrentScanByte == 0x00) {
00231           if(!ScanBytesLeft) {
00232             mxcpc::sendStatusMsg("not more scan bytes!");
00233             std::exit(666);
00234           }
00235           else {
00236             CurrentScanByte++;
00237             ScanBytesLeft--;
00238           }
00239         }
00240         else {
00241           mxcpc::sendStatusMsg("unexpected marker encountered!");
00242           std::exit(666);
00243         }
00244       
00245         // mxcpc::sendStatusMsg("warning: 0xff in datastream, "
00246         //                      "feeding now, checking later!");
00247       }
00248       
00249       ScanMask = 128;
00250     }
00251     
00252     return(bit_was_set);
00253   }
00254         
00255   //! We need this often in inner loops of performScanSweep(), so we 
00256   //! request inline substitution and hope the compiler sufficiently rocks.
00257   /*!
00258    *  Specify as argument the root of the Huffman tree to be used for codeword
00259    *  recognition.
00260    * 
00261    *  Internally checks for <tt>ScanBytesLeft > 0</tt>.
00262    *
00263    *  Returns the Huffman leaf node corresponding to the codeword just
00264    *  consumed or <tt>0</tt> in case of failure. Failure conditions can be
00265    *  - an invalid bitstring was encountered
00266    *  - all scan bytes were cosumed before a valid codeword was detected 
00267    */
00268   inline const mxcpcHuffmanTree
00269                  ::Node *consumeHuffmanCodeword(
00270                           const mxcpcHuffmanTree::Node *current_huffman_node) {
00271   
00272     const mxcpcHuffmanTree::Node *last_huffman_node;
00273     
00274     do {
00275          
00276       if(!ScanBytesLeft) return(0);
00277      
00278       last_huffman_node = current_huffman_node;
00279           
00280       if(consumeScanBit())
00281         current_huffman_node = current_huffman_node->Child1;
00282       else 
00283         current_huffman_node = current_huffman_node->Child0; 
00284         
00285       if(current_huffman_node == last_huffman_node) {
00286         std::printf(" !!! invalid codeword !!!\n");
00287         std::exit(666);
00288         return(0);
00289       }
00290               
00291     } while(!current_huffman_node->IsLeaf);
00292     
00293     return(current_huffman_node);
00294   }
00295 
00296         
00297   //! We need this often in inner loops of performScanSweep(), so we 
00298   //! request inline substitution and hope the compiler sufficiently rocks.
00299   /*!
00300    *  Specify as argument the number <tt>n >= 1</tt> of additional bits to 
00301    *  read. 
00302    *  
00303    *  The coefficient represented by the read bits will be stored to the
00304    *  class member variable <tt>CoeffInAdditionalBits</tt>.
00305    *
00306    *  The method internally checks for <tt>ScanBytesLeft > 0</tt>.
00307    *
00308    *  It returns <tt>false</tt> on success, and <tt>true</tt> if all scan
00309    *  bytes were cosumed before a valid codeword was detected. 
00310    */
00311   inline bool consumeAdditionalBits(int n) {
00312   
00313     bool positive;
00314     int base;
00315     static int bases[] = { -666, -666, 2, 4, 8, 16, 32, 64, 128, 256, 512 };    
00316     
00317     // read first bit...
00318     if(!ScanBytesLeft) return(true);
00319     positive = consumeScanBit();
00320     if(n == 1) {
00321       if(positive) CoeffInAdditionalBits =  1;
00322       else         CoeffInAdditionalBits = -1;
00323       return(false);
00324     }
00325     
00326     // read remaining bits...
00327     base = bases[n];
00328     if(!positive) {
00329       base *= 2;
00330       base = -base;
00331       base++;
00332     }
00333     n--;
00334     CoeffInAdditionalBits = 0;
00335     while(n) {
00336     
00337       if(!ScanBytesLeft) return(true);
00338       
00339       CoeffInAdditionalBits *= 2;
00340       
00341       if(consumeScanBit()) 
00342         CoeffInAdditionalBits += 1;
00343        
00344       n--;
00345     }
00346     CoeffInAdditionalBits += base;  
00347     
00348     return(false);
00349   }
00350 
00351         
00352   //! This Method takes a 8x8 sub-MCU and preforms a swift Huffman Encoding.
00353   /*!
00354    *  \param coef_matrix
00355    *  The 8x8 input coefficient matrix!
00356    *  \param last_dc_coeff
00357    *  Ptr to a list of the last DC coefficients.
00358    *  \param huff_code_tbl_entry
00359    *  A huffman table.
00360    *  \param hbuf_state_ptr
00361    *  Ptr to global buffer state.
00362    */
00363   inline void encodeSubMCUTiles(mxcpc::s16* coef_matrix,
00364                                 mxcpc::s16* last_dc_coeff,
00365                                 FoldedHuffTbl_DC_AC* huff_code_tbl_entry,
00366                                 HuffmanBufferStateStructure* hbuf_state_ptr) {
00367                                                 
00368     // Fetch settings state from global context!
00369     unsigned int huff_bits_used = hbuf_state_ptr->huf_bits_used;
00370     mxcpc::u32   huff_accu_32   = hbuf_state_ptr->huf_accu;
00371     u32t union_accu_tmp;
00372     int total_bits = 0;
00373     int bits = 0; 
00374                 
00375     /*
00376      *     Convert coefficients in Huffman codewords ...
00377      *
00378      *    ___ DC coefficient
00379      *    | 
00380      *    v
00381      *    34 12 3 0 0 5 0 4 0 1 ....
00382      *    ^        ^
00383      *    |        |_______ "3" AC coefficients != 0,  
00384      *    |                 two(R) 0-coefficients before that -> RB = 23
00385      *    |                 Bitlength(B) from 5=101_b = 3
00386      *    |
00387      *    |
00388      *    |___ "1" AC coefficient
00389      */
00390                 
00391     //-------------------------------------------------------------------------
00392     // first start encoding DC component ...                                                                    
00393     //-------------------------------------------------------------------------
00394                 
00395     // Container for the current huffman codeword indexed by the value of delta.
00396     mxcpc::u32 dc_encoded_word;
00397     // First element in list is always the DC coefficient!
00398     mxcpc::s16 delta = coef_matrix[0] - (*last_dc_coeff);
00399     *last_dc_coeff = coef_matrix[0];
00400                         
00401     // Delta should be in boundaries ...
00402     if((delta < -2046) || (delta > 2046)) {
00403       mxcpc::sendStatusMsg("Out of Range");
00404       std::exit(666);
00405     }
00406                 
00407     /* 0000 bbbb , 1 <= b <= 10 */
00408     if( delta ==0 ) bits=0;
00409     if(delta  > 0 )bits = returnBitsInCoef(delta );
00410     if(delta  < 0 )bits = returnBitsInCoef(-delta ); 
00411                 
00412     union_accu_tmp.table_entry = (*huff_code_tbl_entry).dc_tbl[bits];
00413     dc_encoded_word = union_accu_tmp.table_entry.code_msk
00414                        + (union_accu_tmp.table_entry.bit_len << 27);
00415     
00416     /* build one's complement */
00417     if(delta  < 0) delta = (delta  -1 ) & (0x7fffffff >> (31 - bits)); 
00418      /* 1111 1011 -> ____ _010 */
00419                 
00420     /* tttt.t0hh_hhhh.hhhh_hhhh.hhoo.oooo.oooo 
00421      *      ^      ^                   ^
00422      *      |      |                   |___ooo = <bits> zeros, will be 
00423      *        |      |                       overwritten with mantissa later 
00424      *        hhhhh=huffman-code
00425      *             
00426      * tttt.t _____ number of hhh + ooo bits, 
00427      *              2 <= h <= 16, 0 <= o <= 10, 2 <= ttttt <= 26 
00428      */
00429   
00430     dc_encoded_word = dc_encoded_word | delta ;    /* ...000hhhhhccc */
00431     total_bits   = dc_encoded_word >> 27;
00432                 
00433     // kill tttt.t(32-total_bits always > 5) and left align the new bit stream ...
00434     dc_encoded_word = dc_encoded_word << (32 - total_bits);
00435      /* hhhh.hccc_0000.0000_0000.0000_0000.000 */
00436                 
00437     /*   ####.## -> huff_bits_used = 6           */       
00438     huff_accu_32 = huff_accu_32 | (dc_encoded_word >> huff_bits_used);
00439      /* aaaa.aaoo_oooo.oooo_oooo.oooo_oooo.oooo *
00440       * | 0000.00hh_hhhc.cc00_0000.0000_0000.0000 
00441       * -------------------------------------------
00442       * = aaaa.aahh_hhhc.cc00_0000.0000_0000.0000
00443       *   ####.####_####.## -> new huff_bits_used = 6+8 = 14
00444       */
00445 
00446     huff_bits_used += total_bits;
00447 
00448     // Special case accu full ...
00449     if(huff_bits_used >= 32) {
00450       // Write accu (32 bit) to output_bitstream_buff ...
00451       // this may generate more than 4 bytes becuase of zero-stuffing
00452       copyAccuToGlobalHuffBuffer(huff_accu_32, hbuf_state_ptr);
00453       huff_bits_used -= 32;
00454       huff_accu_32 = dc_encoded_word << (total_bits - huff_bits_used); 
00455        /* (hhhh) <-  hccc.oooo_oooo.oooo_oooo.oooo_oooo.oooo */
00456     }
00457                                                                         
00458   
00459     //-------------------------------------------------------------------------                                                                                                                                         
00460     // Now start encoding AC coeff ...
00461     //-------------------------------------------------------------------------
00462                 
00463     int run_len = 0;   /* count zeros */
00464     for(int ac_coef = 1; ac_coef <= 63; ac_coef++) {
00465       mxcpc::u32 new_bit_accu;   // used to "or" symbol and mantissa, must be u32
00466                                  //  rather than int, so a (new_bit_accu >> n) 
00467                                  //  never shifts in 1 from bit 31
00468       bits = 0;                  // number of bits in coef, 0000 bbbb,
00469                                  //  1 <= b <= 10 
00470       int symbol = 0;            // symbol, 
00471                                  // (run_len << 4) | bits = ..00 rrrr bbbb,
00472                                  // 0 <= rr <= 15
00473       int c = coef_matrix[ZigZagMap[ac_coef]];
00474       
00475       if(c == 0) {
00476         run_len +=1;
00477       }
00478       else{
00479         // max number of zeros to encoding table is 15
00480         while(run_len > 15) {
00481           mxcpc::u32 u32_zero_lenght;
00482           union_accu_tmp.table_entry = (*huff_code_tbl_entry).ac_tbl[0x0f];
00483           u32_zero_lenght = union_accu_tmp.table_entry.code_msk
00484                              + (union_accu_tmp.table_entry.bit_len << 27);                                                      
00485           total_bits   = u32_zero_lenght >> 27;
00486           u32_zero_lenght = u32_zero_lenght << (32 - total_bits);
00487           huff_accu_32 = huff_accu_32 | ( u32_zero_lenght >> huff_bits_used);   
00488           huff_bits_used += total_bits;
00489           if(huff_bits_used >= 32) {
00490             copyAccuToGlobalHuffBuffer(huff_accu_32, hbuf_state_ptr);
00491              /* ex: huff_bits_used = 4, total_bits=8 */
00492             huff_bits_used -= 32;
00493              /* (hhhh) <-  hccc.oooo_oooo.oooo_oooo.oooo_oooo.oooo */
00494             huff_accu_32 = u32_zero_lenght << (total_bits - huff_bits_used); 
00495           }
00496           run_len -= 16;
00497         }
00498                                 
00499         /* 0000 bbbb , 1 <= b <= 10 */
00500         if(c >= 0)
00501          bits = returnBitsInCoef(c);
00502         else
00503          bits = returnBitsInCoef(-c);
00504                                                             
00505         /* symbol, (run_len << 4) | bits = ..00 rrrr bbbb , 0 <= rr <= 15   */  
00506         symbol = (bits << 4) + run_len;
00507                         
00508         /*   tttt.t0hh_hhhh.hhhh_hhhh.hhoo.oooo.oooo 
00509          *          ^      ^                   ^
00510          *          |      |                   |___ooo = <bits> zeros, will be
00511          *          |      |                       overwritten with mantissa
00512          *          |      |                       later 
00513          *          hhhhh=huffman-code,
00514          *   tttt.t _____ number of hhh + ooo bits, 
00515          *                2 <= h <= 16, 0 <= o <= 10, 
00516          *                2 <= ttttt <= 26 
00517          */
00518 
00519         union_accu_tmp.table_entry = (*huff_code_tbl_entry).ac_tbl[symbol]; 
00520         new_bit_accu = union_accu_tmp.table_entry.code_msk
00521                         + (union_accu_tmp.table_entry.bit_len << 27);
00522                                 
00523         /* build one's complement */
00524         if(c < 0) c = (c -1 ) & (0x7fffffff >> (31 - bits)); 
00525          /* 1111 1011 -> ____ _010 */
00526         new_bit_accu = new_bit_accu | c;   /* ...000hhhhhccc */
00527         total_bits = new_bit_accu >> 27;   /* total_bits = ..00t.tttt (2..26) */
00528                                 
00529         // kill tttt.t(32-total_bits always > 5) and left align the new bit stream ...
00530         new_bit_accu = new_bit_accu << (32 - total_bits);
00531          /*   hhhh.hccc_0000.0000_0000.0000_0000.000 */
00532 
00533         /* now we must append the new bit-stream of <total_bits> length in 
00534            new_bit_accu to the huffman bitstream */
00535         /*   ####.## -> huff_bits_used = 6           */       
00536         huff_accu_32 = huff_accu_32 | (new_bit_accu >> huff_bits_used);
00537          /*   aaaa.aaoo_oooo.oooo_oooo.oooo_oooo.oooo *
00538           * | 0000.00hh_hhhc.cc00_0000.0000_0000.0000 
00539           * -------------------------------------------
00540           * = aaaa.aahh_hhhc.cc00_0000.0000_0000.0000
00541           *   ####.####_####.## -> new huff_bits_usded = 6+8 = 14
00542           */
00543 
00544         huff_bits_used += total_bits;
00545         if(huff_bits_used >= 32) {
00546           copyAccuToGlobalHuffBuffer(huff_accu_32, hbuf_state_ptr);
00547           huff_bits_used -= 32;   
00548            /* ex: huff_bits_used = 4, total_bits=8 */
00549           huff_accu_32 = new_bit_accu << (total_bits - huff_bits_used); 
00550            /* (hhhh) <-  hccc.oooo_oooo.oooo_oooo.oooo_oooo.oooo */
00551         }
00552                         
00553         run_len = 0;                    
00554       }
00555     }
00556                 
00557     // write EOB ...
00558     if(run_len != 0) {
00559       mxcpc::u32 eob_tag;
00560       union_accu_tmp.table_entry = (*huff_code_tbl_entry).ac_tbl[0x00];
00561       eob_tag = union_accu_tmp.table_entry.code_msk
00562                  + (union_accu_tmp.table_entry.bit_len << 27);                                  
00563       total_bits = eob_tag >> 27;
00564       eob_tag = eob_tag << (32 - total_bits);
00565       huff_accu_32 = huff_accu_32 | (eob_tag >> huff_bits_used); 
00566       huff_bits_used += total_bits;
00567       if(huff_bits_used >= 32) {
00568         copyAccuToGlobalHuffBuffer(huff_accu_32, hbuf_state_ptr);
00569         huff_bits_used -= 32;
00570          /* ex: huff_bits_used = 4, total_bits=8 */
00571         huff_accu_32 = eob_tag << (total_bits - huff_bits_used);
00572          /* (hhhh) <-  hccc.oooo_oooo.oooo_oooo.oooo_oooo.oooo */
00573       }
00574     }
00575     
00576     // update global buffer ..
00577     hbuf_state_ptr->huf_bits_used = huff_bits_used;
00578     hbuf_state_ptr->huf_accu      = huff_accu_32;
00579   }
00580 
00581 
00582   //! Copies a word into the global huffman encoding buffer!
00583   /*!
00584    *  \param huff_accu_32 
00585    *  Input word.
00586    *  \param huff_buf_state_ptr
00587    *  Ptr. to global buffer.
00588    */
00589   static inline void copyAccuToGlobalHuffBuffer(
00590                       mxcpc::u32 huff_accu_32,
00591                       HuffmanBufferStateStructure* huff_buf_state_ptr
00592                      )                                                {
00593     mxcpc::u8  b;
00594     mxcpc::u8* p = huff_buf_state_ptr->buf_current_w_pos;
00595 
00596     if((p+8) >= huff_buf_state_ptr->buf_end1) {
00597        mxcpc::sendStatusMsg("Huffman Buffer Overflow!");
00598        std::exit(666);
00599     }
00600                 
00601     /* Output four bytes from huff_accu_32 with MSByte first, pad each 0xff with
00602      * 0x00 (zero-stuffing) so that control-codes beginning with 0xff can be
00603      * distinguished from bitstream 
00604      */
00605     
00606     b = (huff_accu_32 >> 24);
00607     *p++ = b;   /* b = 0x76 */
00608     if(b == 0xff) *p++ = 0x00;
00609     
00610     b = (huff_accu_32 >> 16) & 0xff;
00611     *p++ = b;   /* b = 0x54 */
00612     if(b == 0xff) *p++ = 0x00;
00613                                                                                                                                                  
00614     b = (huff_accu_32 >>  8) & 0xff;
00615     *p++ = b;   /* b = 0x32 */
00616     if (b == 0xff) *p++ = 0x00; 
00617                  
00618     b = (huff_accu_32      ) & 0xff;
00619     *p++ = b;   /* b = 0x10 */
00620     if (b == 0xff) *p++ = 0x00;
00621                                                                                                                                          
00622     huff_buf_state_ptr->buf_current_w_pos = p;
00623   }
00624 
00625   
00626   //! Closes down huffman encoding stream.
00627   static int shutDownHuffAccu(void) {
00628     mxcpc::u8  b;
00629     mxcpc::u8* p = HuffmanBufferState.buf_current_w_pos;
00630 
00631     if((p+8) >= HuffmanBufferState.buf_end1) {
00632       mxcpc::sendStatusMsg("Huffman Buffer Overflow!");
00633       std::exit(666);
00634     }
00635                 
00636     if(   (HuffmanBufferState.huf_bits_used == 2)
00637        && (HuffmanBufferState.huf_accu == 0))     {
00638       b = 0x0 ;                 
00639       *p++ = b;         
00640       HuffmanBufferState.buf_current_w_pos = p;                                                                                                                                                                                         
00641     }                                                                                           
00642     else {
00643       while(HuffmanBufferState.huf_accu) {
00644         b = (HuffmanBufferState.huf_accu >> 24);
00645         *p++ = b;
00646         if (b == 0xff) *p++ = 0x00;
00647         HuffmanBufferState.huf_accu <<= 8;
00648       }
00649       HuffmanBufferState.buf_current_w_pos = p;
00650     }
00651         
00652     return(0);
00653   }
00654 
00655 
00656   //! Number of bits from ....
00657   /*!
00658    *  \param c 
00659    *  <- this!
00660    */
00661   static inline int returnBitsInCoef(mxcpc::s16 c) {
00662     int bits = 1;
00663                 
00664     while(c >>= 1 ) bits += 1;
00665                 
00666     return (bits);
00667   }
00668                 
00669 };
00670 
00671 
00672 #endif   // __MXCPC_FRAMEWISEMXPEGSCANTOJPEGCONVERTERSOFTWAREONLY_H__

Generated on Mon Jan 30 15:52:43 2006 for mxcpc by  doxygen 1.4.4