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

mxcpcFramewiseMxPEGScanToJPEGConverterSoftwareOnly.h

00001 //           ///          //
00002 //          /////        ////
00003 //         /// XXX     XXX ///
00004 //        ///    XXX XXX    ///     $RCSfile: mxcpcFramewiseMxPEGScanToJPEGConverterSoftwareOnly.h,v $  
00005 //       ///       XXX       ///     $Revision: 1.1 $
00006 //      ///      XXX XXX      ///     $Date: 2005/08/09 13:57:26 $
00007 //     ////    XXX     XXX    ////     $Author: cvs-steve $
00008 //    ////                     ////
00009 //   ////  M  O  B  O  T  I  X  ////////////////////////////////////////////////
00010 //  //// Security Vision Systems ///////////////////////////////////////////////
00011 
00012 // Copyright (c) 2005, MOBOTIX AG.
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 #ifndef __MXCPC_FRAMEWISEMXPEGSCANTOJPEGCONVERTERSOFTWAREONLY_H__
00018 #define __MXCPC_FRAMEWISEMXPEGSCANTOJPEGCONVERTERSOFTWAREONLY_H__
00019 
00020 
00021 #define MXCPC_FRAMEWISEMXPEGSCANTOJPEGCONVERTER_BITSTREAM_BUFFSIZE 0x100000
00022 
00023 
00024 #include <mxcpcFramewiseMxPEGScanDecoder.h>
00025 #include <mxcpcHuffmanTree.h>
00026 #include <mxcpc_mxpeg_namespace.h>
00027 
00028 #include <cstdio>
00029 #include <cstring>
00030 #include <cstdlib>
00031 
00032 class mxcpcMxPEGScanToJPEGConverterBackEnd;
00033 
00034 
00035 
00044 class mxcpcFramewiseMxPEGScanToJPEGConverterSoftwareOnly : public mxcpcFramewiseMxPEGScanDecoder {
00045 
00046  private:
00047   static const unsigned char  ZigZag_StoreMap[64];
00048   static const int            ZigZagMap[64];
00049   
00050   
00052   typedef struct { 
00053     
00054     
00057     mxcpc::u8 bits_dc[16];      
00058     
00061     mxcpc::u8 val_dc[12];
00062     
00063   } HuffCompDC;
00064   
00066   typedef struct { 
00067     
00072     mxcpc::u8 bits_ac[16];
00073            
00074     mxcpc::u8 val_ac[162];
00075     
00076   } HuffCompAC;
00077   
00078   static const HuffCompDC HuffTbl_Y_UV_DC[2]; 
00079   
00080   static const HuffCompAC HuffTbl_Y_UV_AC[2];
00081   
00082   
00084   typedef struct {
00085   
00087     unsigned int code_msk:  26;
00089     unsigned int fill_0bit:  1;
00091     unsigned int bit_len:    5;
00092      
00093   } HuffCodeTblEntry;
00094   
00095   
00097   typedef union {
00098   
00099     HuffCodeTblEntry  table_entry;
00100     mxcpc::u32        u32_word;
00101   
00102   } u32t;
00103     
00105   typedef struct {
00106     
00108     HuffCodeTblEntry ac_tbl[1];
00110     HuffCodeTblEntry dc_tbl[12];
00111     
00113     int                     free_13;
00115     int                     free_14;
00117     HuffCodeTblEntry        dc_tbl_0FtoAF[161];  
00118   
00119   } FoldedHuffTbl_DC_AC;
00120 
00122   static FoldedHuffTbl_DC_AC Huff_Y_UV[2];
00123   
00125   typedef struct {
00126     
00127     mxcpc::u8* buf_start;           
00128     mxcpc::u8* buf_end1;            
00129     mxcpc::u8* buf_current_w_pos;  
00132     mxcpc::u32 huf_accu;          
00133     unsigned int huf_bits_used;   
00134       
00135   } HuffmanBufferStateStructure;
00136   
00138   static HuffmanBufferStateStructure HuffmanBufferState;
00139       
00141   mxcpc::u8* HuffmanEncoderBuffer;
00142       
00143  private:
00144   
00145   mxcpcHuffmanTree *HuffmanTree_Y_DC, 
00146                    *HuffmanTree_Y_AC; 
00147                            
00148   mxcpcHuffmanTree *HuffmanTree_UV_DC, 
00149                    *HuffmanTree_UV_AC;
00150        
00151   mxcpc::s16 QuantizationTable_Y[64],
00152              QuantizationTable_UV[64];
00153              
00155   mxcpc::s16* CoeffBuffer;
00156   
00158   int TileNumX, TileNumY;
00159   
00162   unsigned char *CurrentScanByte,
00163                  ScanMask;
00164   
00165   int ScanBytesLeft;
00166   int CoeffInAdditionalBits;
00167   
00168   std::FILE *OutStream;
00169   
00170   mxcpc_mxpeg::APP0 APP0_Block;
00171   mxcpc_mxpeg::SOF0 SOF0_Block;
00172   mxcpc_mxpeg::SOS  SOS_Block;         
00173   int FramesProcessed;
00174   
00176   mxcpcMxPEGScanToJPEGConverterBackEnd *ConverterBackEnd;
00177 
00178   
00179  public:
00181   mxcpcFramewiseMxPEGScanToJPEGConverterSoftwareOnly(mxcpcMxPEGScanToJPEGConverterBackEnd *backend);
00182   ~mxcpcFramewiseMxPEGScanToJPEGConverterSoftwareOnly();
00183   
00184  public:
00186   void setYQuantizationTable(unsigned char *data_bytes);
00188   void setUVQuantizationTable(unsigned char *data_bytes);
00190   void performScanSweep(mxcpcFramewiseMxPEGDecoder::UndecodedFrameDescriptor
00191                          *frame_descriptor);
00192   
00193   private:
00194   
00197     void calcFoldedHuffTables(void);
00198     
00200 
00212     void generateHuffTables1(
00213           const mxcpc::u8 * bits_tbl_off1,   
00214           const mxcpc::u8 * val_tbl,        
00215           int swap_symbol,    
00216           HuffCodeTblEntry * folded_tbl_p);
00217           
00219     void initHuffmanEncoderBufferState();
00220     
00221     void resetHuffmanEncoderBufferState(); 
00222                                                  
00223 
00226 
00231   inline bool consumeScanBit(void) {
00232     
00233     bool bit_was_set;
00234     unsigned char last_scan_byte;
00235     
00236     bit_was_set = *CurrentScanByte & ScanMask;
00237     
00238     ScanMask /= 2;
00239     if(!ScanMask) {
00240      
00241       last_scan_byte = *CurrentScanByte;
00242     
00243       CurrentScanByte++;
00244       ScanBytesLeft--;
00245       if(last_scan_byte == 0xff) {
00246         if(*CurrentScanByte == 0x00) {
00247           if(!ScanBytesLeft) {
00248             mxcpc::sendStatusMsg("not more scan bytes!");
00249             std::exit(666);
00250           }
00251           else {
00252             CurrentScanByte++;
00253             ScanBytesLeft--;
00254           }
00255         }
00256         else {
00257           mxcpc::sendStatusMsg("unexpected marker encountered!");
00258           std::exit(666);
00259         }
00260       
00261         //mxcpc::sendStatusMsg("warning: 0xff in datastream, feeding now, checking later!");
00262       }
00263       
00264       ScanMask = 128;
00265     }
00266     
00267     return(bit_was_set);
00268   }
00269   
00272 
00283   inline const mxcpcHuffmanTree
00284                  ::Node *consumeHuffmanCodeword(
00285                           const mxcpcHuffmanTree::Node *current_huffman_node) {
00286   
00287     const mxcpcHuffmanTree::Node *last_huffman_node;
00288     
00289     do {
00290          
00291       if(!ScanBytesLeft) return(0);
00292      
00293       last_huffman_node = current_huffman_node;
00294           
00295       if(consumeScanBit())
00296         current_huffman_node = current_huffman_node->Child1;
00297       else 
00298         current_huffman_node = current_huffman_node->Child0; 
00299         
00300       if(current_huffman_node == last_huffman_node) {
00301         std::printf(" !!! invalid codeword !!!\n");
00302         std::exit(666);
00303         return(0);
00304       }
00305               
00306     } while(!current_huffman_node->IsLeaf);
00307     
00308     return(current_huffman_node);
00309   }
00310 
00311   
00314 
00326   inline bool consumeAdditionalBits(int n) {
00327   
00328     bool positive;
00329     int base;
00330     static int bases[] = { -666, -666, 2, 4, 8, 16, 32, 64, 128, 256, 512 };    
00331     
00332     // read first bit...
00333     if(!ScanBytesLeft) return(true);
00334     positive = consumeScanBit();
00335     if(n == 1) {
00336       if(positive) CoeffInAdditionalBits =  1;
00337       else         CoeffInAdditionalBits = -1;
00338       return(false);
00339     }
00340     
00341     // read remaining bits...
00342     base = bases[n];
00343     if(!positive) {
00344       base *= 2;
00345       base = -base;
00346       base++;
00347     }
00348     n--;
00349     CoeffInAdditionalBits = 0;
00350     while(n) {
00351     
00352       if(!ScanBytesLeft) return(true);
00353       
00354       CoeffInAdditionalBits *= 2;
00355       
00356       if(consumeScanBit()) 
00357         CoeffInAdditionalBits += 1;
00358        
00359       n--;
00360     }
00361     CoeffInAdditionalBits += base;  
00362     
00363     return(false);
00364   }
00365 
00366   
00375   inline void encodeSubMCUTiles(mxcpc::s16* coef_matrix,
00376                                 mxcpc::s16* last_dc_coeff,
00377                                 FoldedHuffTbl_DC_AC* huff_code_tbl_entry,
00378                                 HuffmanBufferStateStructure* hbuf_state_ptr)        {
00379                                 
00380     
00381     // Fetch settings state from global context!
00382     unsigned int  huff_bits_used  = hbuf_state_ptr->huf_bits_used;
00383     mxcpc::u32    huff_accu_32    = hbuf_state_ptr->huf_accu;
00384     
00385     u32t  union_accu_tmp;
00386     int   total_bits=0;
00387     int   bits=0; 
00388     /*
00389 
00390 
00391       Convert coefficients in Huffman codewords ...
00392 
00393       ___ DC coefficient
00394       | 
00395       v
00396       34 12 3 0 0 5 0 4 0 1 ....
00397          ^        ^
00398          |        |_______ "3" AC coefficients != 0,  two(R) 0-coefficients before that -> RB = 23
00399          |                                            Bitlength(B) from 5=101_b = 3
00400          |
00401          |
00402          |___ "1" AC coefficient
00403         
00404     */
00405     
00406     //-------------------------------------------------------------------------
00407     // First start encoding DC component ...                  
00408     //-------------------------------------------------------------------------
00409     
00410     // Container for the current huffman codeword indexed by the value of delta.
00411     mxcpc::u32 dc_encoded_word;
00412     // First element in list is always the DC coefficient!
00413     mxcpc::s16 delta =  coef_matrix[0] - (*last_dc_coeff);
00414     *last_dc_coeff = coef_matrix[0];
00415       
00416     // Delta should be in boundaries ...
00417     if ((delta < -2046) || (delta > 2046)) {
00418         mxcpc::sendStatusMsg("Out of Range");
00419         std::exit(666);
00420     }
00421     
00422     /* 0000 bbbb , 1 <= b <= 10 */
00423     if( delta ==0 ) bits=0;
00424     if(delta  > 0 )bits = returnBitsInCoef(delta );
00425     if(delta  < 0 )bits = returnBitsInCoef(-delta ); 
00426     
00427     union_accu_tmp.table_entry = (*huff_code_tbl_entry).dc_tbl[bits];
00428     dc_encoded_word              = union_accu_tmp.u32_word;
00429     
00430     /* build one's complement */
00431     if (delta  < 0) delta  = (delta  -1 ) & (0x7fffffff >> (31 - bits)); /* 1111 1011 -> ____ _010 */
00432     
00433     /*  tttt.t0hh_hhhh.hhhh_hhhh.hhoo.oooo.oooo 
00434         ^      ^                   ^
00435         |      |                   |___ooo = <bits> zeros, will be overwritten with mantissa later 
00436               hhhhh=huffman-code,
00437       tttt.t _____ number of hhh + ooo bits, 2 <= h <= 16, 0 <= o <= 10, 2 <= ttttt <= 26 */
00438     dc_encoded_word = dc_encoded_word | delta ;    /* ...000hhhhhccc */
00439     total_bits   = dc_encoded_word >> 27;
00440     
00441     // kill tttt.t(32-total_bits always > 5) and left align the new bit stream ...
00442     dc_encoded_word = dc_encoded_word << (32 - total_bits);           /*   hhhh.hccc_0000.0000_0000.0000_0000.000 */
00443     
00444     
00445                                                                       /*   ####.## -> huff_bits_used = 6           */       
00446     huff_accu_32 = huff_accu_32 | (dc_encoded_word >> huff_bits_used);/*   aaaa.aaoo_oooo.oooo_oooo.oooo_oooo.oooo *
00447                                                                        * | 0000.00hh_hhhc.cc00_0000.0000_0000.0000 
00448                                                                        * -------------------------------------------
00449                                                                        * = aaaa.aahh_hhhc.cc00_0000.0000_0000.0000
00450                                                                        *   ####.####_####.## -> new huff_bits_usded = 6+8 = 14 */
00451     huff_bits_used += total_bits;
00452     
00453     
00454     // Special case accu full ...
00455     if( huff_bits_used >= 32 ){
00456       
00457       // Write accu (32 bit) to output_bitstream_buff ...
00458       // this may generate more than 4 bytes becuase of zero-stuffing
00459       
00460       copyAccuToGlobalHuffBuffer( huff_accu_32, 
00461                                   hbuf_state_ptr);
00462       huff_bits_used -= 32;
00463       huff_accu_32 = dc_encoded_word << (total_bits - huff_bits_used); /* (hhhh) <-  hccc.oooo_oooo.oooo_oooo.oooo_oooo.oooo */
00464       
00465     }
00466                   
00467     //-------------------------------------------------------------------------                                   
00468     // Now start encoding AC coeff ...
00469     //-------------------------------------------------------------------------
00470     
00471     int   run_len=0;            /* count zeros */
00472     
00473     
00474     for(int ac_coef=1; ac_coef<=63; ac_coef++){
00475   
00476     
00477       mxcpc::u32 new_bit_accu;  /* used to "or" symbol and mantissa, must be u32 rather than int
00478                                    so a (new_bit_accu >> n) never shifts in 1 from bit 31 */
00479       bits=0;                   /* number of bits in coef,  0000 bbbb , 1 <= b <= 10 */
00480       int symbol=0;             /* symbol, (run_len << 4) | bits = ..00 rrrr bbbb , 0 <= rr <= 15   */
00481             
00482       int c = coef_matrix[ZigZagMap[ac_coef]];
00483    
00484       if(c == 0 ){
00485       
00486         run_len +=1;
00487             
00488       }
00489       else{
00490 
00491         // max number of zeros to encoding table is 15
00492         while (run_len > 15) {
00493                   
00494           mxcpc::u32 u32_zero_lenght;
00495                     
00496           union_accu_tmp.table_entry  = (*huff_code_tbl_entry).ac_tbl[0x0f];
00497           u32_zero_lenght             = union_accu_tmp.u32_word;
00498                           
00499           total_bits   = u32_zero_lenght >> 27;
00500               
00501           u32_zero_lenght = u32_zero_lenght << (32 - total_bits);
00502           
00503           huff_accu_32 = huff_accu_32 | ( u32_zero_lenght >> huff_bits_used); 
00504       
00505           huff_bits_used += total_bits;
00506                       
00507           if( huff_bits_used >= 32 ){
00508 
00509             copyAccuToGlobalHuffBuffer( huff_accu_32, 
00510                                         hbuf_state_ptr);
00511             
00512             /* ex: huff_bits_used = 4, total_bits=8 */
00513             huff_bits_used -= 32;
00514             /* (hhhh) <-  hccc.oooo_oooo.oooo_oooo.oooo_oooo.oooo */
00515             huff_accu_32 = u32_zero_lenght << (total_bits - huff_bits_used); 
00516             
00517             
00518           }
00519           run_len -= 16;
00520         }
00521         
00522         /* 0000 bbbb , 1 <= b <= 10 */
00523         if(c >=0 )bits = returnBitsInCoef(c);
00524         else { bits = returnBitsInCoef(-c); }
00525         
00526                     
00527         /* symbol, (run_len << 4) | bits = ..00 rrrr bbbb , 0 <= rr <= 15   */  
00528         symbol = (bits << 4) + run_len;
00529       
00530                    
00531         /*   tttt.t0hh_hhhh.hhhh_hhhh.hhoo.oooo.oooo 
00532              ^      ^                   ^
00533              |      |                   |___ooo = <bits> zeros, will be overwritten with mantissa later 
00534                     hhhhh=huffman-code,
00535             tttt.t _____ number of hhh + ooo bits, 2 <= h <= 16, 0 <= o <= 10, 2 <= ttttt <= 26 */
00536         union_accu_tmp.table_entry = (*huff_code_tbl_entry).ac_tbl[symbol]; 
00537         new_bit_accu               = union_accu_tmp.u32_word;
00538         
00539         
00540         /* build one's complement */
00541         if (c < 0) c = (c -1 ) & (0x7fffffff >> (31 - bits)); /* 1111 1011 -> ____ _010 */
00542           
00543         new_bit_accu = new_bit_accu | c;    /* ...000hhhhhccc */
00544         total_bits   = new_bit_accu >> 27;  /* total_bits = ..00t.tttt (2..26) */
00545         
00546         
00547         // kill tttt.t(32-total_bits always > 5) and left align the new bit stream ...
00548         new_bit_accu = new_bit_accu << (32 - total_bits);           /*   hhhh.hccc_0000.0000_0000.0000_0000.000 */
00549 
00550           
00551         /* now we must append the new bit-stream of <total_bits> length in new_bit_accu to the huffman bitstream */
00552 
00553                                                                          /*   ####.## -> huff_bits_used = 6           */       
00554         huff_accu_32 = huff_accu_32 | (new_bit_accu >> huff_bits_used);  /*   aaaa.aaoo_oooo.oooo_oooo.oooo_oooo.oooo *
00555                                                                           * | 0000.00hh_hhhc.cc00_0000.0000_0000.0000 
00556                                                                           * -------------------------------------------
00557                                                                           * = aaaa.aahh_hhhc.cc00_0000.0000_0000.0000
00558                                                                           *   ####.####_####.## -> new huff_bits_usded = 6+8 = 14
00559                                                                           */
00560         huff_bits_used += total_bits;
00561           
00562         if (huff_bits_used >= 32) {
00563           copyAccuToGlobalHuffBuffer( huff_accu_32, 
00564                                       hbuf_state_ptr);
00565           huff_bits_used -= 32;                                         /* ex: huff_bits_used = 4, total_bits=8 */
00566           huff_accu_32 = new_bit_accu << (total_bits - huff_bits_used); /* (hhhh) <-  hccc.oooo_oooo.oooo_oooo.oooo_oooo.oooo */
00567         
00568         }
00569             
00570         run_len =0;     
00571       }
00572       
00573 
00574     }
00575     
00576     // write EOB ...
00577     if(run_len != 0){
00578       
00579       mxcpc::u32 eob_tag;
00580       
00581       union_accu_tmp.table_entry  = (*huff_code_tbl_entry).ac_tbl[0x00];
00582       eob_tag                     = union_accu_tmp.u32_word;
00583           
00584       total_bits   = eob_tag >> 27;
00585       
00586       eob_tag = eob_tag << (32 - total_bits);
00587        
00588       huff_accu_32 = huff_accu_32 | (eob_tag >> huff_bits_used); 
00589       
00590       huff_bits_used += total_bits;
00591       
00592       if (huff_bits_used >= 32) {
00593           copyAccuToGlobalHuffBuffer( huff_accu_32, 
00594                                       hbuf_state_ptr);
00595           huff_bits_used -= 32;                                         /* ex: huff_bits_used = 4, total_bits=8 */
00596           huff_accu_32 = eob_tag << (total_bits - huff_bits_used); /* (hhhh) <-  hccc.oooo_oooo.oooo_oooo.oooo_oooo.oooo */
00597       }   
00598                   
00599     }
00600     
00601     // update global buffer ..
00602     hbuf_state_ptr->huf_bits_used   = huff_bits_used;
00603     hbuf_state_ptr->huf_accu        = huff_accu_32;
00604         
00605   }
00606   
00613   static inline void copyAccuToGlobalHuffBuffer( mxcpc::u32                   huff_accu_32,
00614                                                 HuffmanBufferStateStructure*  huff_buf_state_ptr){
00615                                           
00616     mxcpc::u8  b;
00617     mxcpc::u8* p = huff_buf_state_ptr->buf_current_w_pos;
00618 
00619     if ((p+8) >= huff_buf_state_ptr->buf_end1) {
00620        mxcpc::sendStatusMsg("Huffman Buffer Overflow!");
00621        std::exit(666);
00622     }
00623     
00624     
00625     /* Output four bytes from huff_accu_32 with MSByte first, pad each 0xff with 0x00 (zero-stuffing)
00626      * so that control-codes beginning with 0xff can be distinguished from bitstream 
00627      */
00628     /*                                                              huffaccu = 76543210;          */
00629   
00630     b = (huff_accu_32 >> 24);                       *p++ = b;   /* b = 0x76 */
00631                                      if (b == 0xff) *p++ = 0x00;
00632                                      
00633                                                                       
00634     b = (huff_accu_32 >> 16) & 0xff;                *p++ = b;    /* b = 0x54 */
00635                                      if (b == 0xff) *p++ = 0x00;
00636                                      
00637                                                                         
00638     b = (huff_accu_32 >>  8) & 0xff;                *p++ = b;    /* b = 0x32 */
00639                                      if (b == 0xff) *p++ = 0x00;
00640     
00641      
00642     b = (huff_accu_32      ) & 0xff;                *p++ = b;    /* b = 0x10 */
00643                                      if (b == 0xff) *p++ = 0x00;
00644                                      
00645     huff_buf_state_ptr->buf_current_w_pos = p;
00646     
00647   }
00648 
00653   static int shutDownHuffAccu( ){
00654     
00655     mxcpc::u8  b;
00656     mxcpc::u8* p = HuffmanBufferState.buf_current_w_pos;
00657 
00658     if ((p+8) >= HuffmanBufferState.buf_end1) {
00659        mxcpc::sendStatusMsg("Huffman Buffer Overflow!");
00660        std::exit(666);
00661     }
00662     
00663     if(HuffmanBufferState.huf_bits_used == 2 && HuffmanBufferState.huf_accu == 0 ){
00664 
00665       b = 0x0 ;     
00666       *p++ = b;   
00667       
00668       HuffmanBufferState.buf_current_w_pos = p;                                               
00669       
00670     }                       
00671     else{
00672       while (HuffmanBufferState.huf_accu) {
00673           
00674           b = (HuffmanBufferState.huf_accu >> 24);    *p++ = b;   
00675                                                       if (b == 0xff) *p++ = 0x00;
00676           HuffmanBufferState.huf_accu <<= 8;
00677       }
00678       
00679       HuffmanBufferState.buf_current_w_pos = p;
00680       }
00681     return(0);
00682   }
00683     
00684 /*  static int c_to_bits[0,1,2,2,
00685                        3, 3, 3, 3,
00686                        4, 4, 4, 4, 4, 4, 4, 4] ;*/
00687   
00693   static inline int returnBitsInCoef(mxcpc::s16 c){
00694     
00695 //    if (c <16) return (c_to_bits[c]);
00696     int bits = 1;
00697     
00698     while ( c >>= 1 ){ bits +=1;}
00699     
00700     return (bits);
00701   
00702   }
00703 
00704     
00705 };
00706 
00707 
00708 #endif   // __MXCPC_FRAMEWISEMXPEGSCANTOJPEGCONVERTERSOFTWAREONLY_H__

Generated on Mon Aug 15 03:39:30 2005 for mxcpc by  doxygen 1.4.2-20050421