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

mxcpcFramewiseMxPEGScanToJPEGConverterSoftwareOnly.cpp

00001 //           ///          //                                        Mx clientSDK
00002 //          /////        ////                    Mx Crossplatform Client Library
00003 //         /// XXX     XXX ///
00004 //        ///    XXX XXX    ///     $RCSfile: mxcpcFramewiseMxPEGScanToJPEGConverterSoftwareOnly.cpp,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 #include <mxcpcFramewiseMxPEGScanToJPEGConverterSoftwareOnly.h>
00021 #include <mxcpcMxPEGDecoderBackEnd.h>
00022 #include <mxcpcJPEGReceiver.h>
00023 #include <mxcpc_exceptions.h>
00024 
00025 #include <memory>
00026 
00027 
00028 
00029 const int mxcpcFramewiseMxPEGScanToJPEGConverterSoftwareOnly::ZigZagMap[64] = {  
00030                                                   0,  1,  8, 16,  9,  2,  3, 10, 
00031                                                  17, 24, 32, 25, 18, 11,  4,  5,
00032                                                  12, 19, 26, 33, 40, 48, 41, 34, 
00033                                                  27, 20, 13,  6,  7, 14, 21, 28,
00034                                                  35, 42, 49, 56, 57, 50, 43, 36,
00035                                                  29, 22, 15, 23, 30, 37, 44, 51, 
00036                                                  58, 59, 52, 45, 38, 31, 39, 46, 
00037                                                  53, 60, 61, 54, 47, 55, 62, 63 
00038                                                 };
00039 
00040 const unsigned char mxcpcFramewiseMxPEGScanToJPEGConverterSoftwareOnly
00041                      ::ZigZag_StoreMap[64] = {
00042                                                   0,  1,  5,  6, 14, 15, 27, 28,
00043                                                   2,  4,  7, 13, 16, 26, 29, 42,
00044                                                   3,  8, 12, 17, 25, 30, 41, 43,
00045                                                   9, 11, 18, 24, 31, 40, 44, 53,
00046                                                  10, 19, 23, 32, 39, 45, 52, 54,
00047                                                  20, 22, 33, 38, 46, 51, 55, 60,
00048                                                  21, 34, 37, 47, 50, 56, 59, 61,
00049                                                  35, 36, 48, 49, 57, 58, 62, 63
00050                                              };
00051 
00052 const mxcpcFramewiseMxPEGScanToJPEGConverterSoftwareOnly::HuffCompDC
00053        mxcpcFramewiseMxPEGScanToJPEGConverterSoftwareOnly::HuffTbl_Y_UV_DC[2] ={
00054   { 
00055     { 0, 1, 5, 1, 1, 1, 1, 1, 1, 0,  0,  0, 0, 0, 0, 0 }, 
00056      /*!< dc-bits[1..16]: index 0 is missing, 1..16 only ! */
00057     { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 },                                           
00058      /*!< dc-val[0..11]: */   
00059   },
00060   { 
00061     { 0, 3, 1, 1, 1, 1, 1, 1, 1, 1,  1,  0, 0, 0, 0, 0 }, 
00062      /*!< bits_dc[1..16]: index 0 is missing, 1..16 only ! */
00063     { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 },
00064      /*!< val_dc[0..11]: */   
00065   }
00066 };
00067         
00068 const mxcpcFramewiseMxPEGScanToJPEGConverterSoftwareOnly::HuffCompAC 
00069        mxcpcFramewiseMxPEGScanToJPEGConverterSoftwareOnly::HuffTbl_Y_UV_AC[2] ={
00070   { 
00071     { 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d }, 
00072     { 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, 
00073       0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07,
00074       0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08,
00075       0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0,      
00076       0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16,
00077       0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28,
00078       0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
00079       0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
00080       0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
00081       0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
00082       0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
00083       0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,      
00084       0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
00085       0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
00086       0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
00087       0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5,         
00088       0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4,
00089       0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2,
00090       0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea,
00091       0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,      
00092       0xf9, 0xfa 
00093     },                                          
00094   },
00095   { 
00096     { 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 0x77 },
00097     { 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21, 
00098       0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
00099       0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91,
00100       0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0,
00101       0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34,
00102       0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26,
00103       0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38,
00104       0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
00105       0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
00106       0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
00107       0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
00108       0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
00109       0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96,
00110       0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5,
00111       0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4,
00112       0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3,
00113       0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2,
00114       0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda,
00115       0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
00116       0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
00117       0xf9, 0xfa 
00118     },                                          
00119   } 
00120 };
00121 
00122 mxcpcFramewiseMxPEGScanToJPEGConverterSoftwareOnly::FoldedHuffTbl_DC_AC 
00123  mxcpcFramewiseMxPEGScanToJPEGConverterSoftwareOnly::Huff_Y_UV[2];
00124                                                                                                                                                                                                                                                                                                                 
00125 mxcpcFramewiseMxPEGScanToJPEGConverterSoftwareOnly::HuffmanBufferStateStructure 
00126  mxcpcFramewiseMxPEGScanToJPEGConverterSoftwareOnly::HuffmanBufferState;
00127         
00128                                                                                                                                 
00129 mxcpcFramewiseMxPEGScanToJPEGConverterSoftwareOnly
00130  ::mxcpcFramewiseMxPEGScanToJPEGConverterSoftwareOnly(
00131     mxcpcJPEGReceiver *receiver
00132    ) : mxcpcFramewiseMxPEGScanToJPEGConverter(receiver) {       
00133         
00134   char txt[100];
00135         
00136   // Init the encoder buffer structure ...
00137   HuffmanEncoderBuffer 
00138    = new mxcpc::u8[MXCPC_FRAMEWISEMXPEGSCANTOJPEGCONVERTER_BITSTREAM_BUFFSIZE];
00139   initHuffmanEncoderBufferState();
00140         
00141   // Create encode huffman tables ...
00142   calcFoldedHuffTables();
00143          
00144   // Build Huffman Tree from Huffman tables. The tables are defined 
00145   // in mxcpcFramewiseMxPEGScanDecoder
00146   HuffmanTree_Y_DC  = 0, 
00147   HuffmanTree_Y_AC  = 0;         
00148   HuffmanTree_UV_DC = 0, 
00149   HuffmanTree_UV_AC = 0;
00150         
00151   try {
00152   
00153     HuffmanTree_Y_DC = new mxcpcHuffmanTree();
00154     if(HuffmanTree_Y_DC->configureFromTable(DefaultHuffmanTable_Y_DC))
00155       throw mxcpcDidntWorkOutException();
00156     HuffmanTree_Y_AC = new mxcpcHuffmanTree();
00157     if(HuffmanTree_Y_AC->configureFromTable(DefaultHuffmanTable_Y_AC))
00158       throw mxcpcDidntWorkOutException();
00159     HuffmanTree_UV_DC = new mxcpcHuffmanTree();
00160     if(HuffmanTree_UV_DC->configureFromTable(DefaultHuffmanTable_UV_DC))
00161       throw mxcpcDidntWorkOutException();
00162     HuffmanTree_UV_AC = new mxcpcHuffmanTree();
00163     if(HuffmanTree_UV_AC->configureFromTable(DefaultHuffmanTable_UV_AC))
00164       throw mxcpcDidntWorkOutException();  
00165                 
00166   } catch(std::exception &e) {
00167                 
00168       MXCPC_RETHROW_UNHANDLED_EXCEPTION(e);
00169     
00170       delete HuffmanTree_Y_DC; 
00171       delete HuffmanTree_Y_AC;         
00172       delete HuffmanTree_UV_DC; 
00173       delete HuffmanTree_UV_AC;
00174       
00175       throw;
00176     }
00177   
00178   // Init Quantization tables ...
00179   int i;
00180   for(i = 0; i < 64; i++) {
00181     QuantizationTable_Y[i]  = 0;
00182     QuantizationTable_UV[i] = 0;
00183   }
00184   
00185   std::sprintf(txt, "symbols in Y/DC Huffman table : %d", 
00186                HuffmanTree_Y_DC->countLeaves());
00187   mxcpc::sendStatusMsg(txt, this);
00188   std::sprintf(txt, "symbols in Y/AC Huffman table : %d", 
00189                HuffmanTree_Y_AC->countLeaves());
00190   mxcpc::sendStatusMsg(txt, this);
00191   std::sprintf(txt, "symbols in UV/DC Huffman table : %d", 
00192                HuffmanTree_UV_DC->countLeaves());
00193   mxcpc::sendStatusMsg(txt, this);
00194   std::sprintf(txt, "symbols in UV/AC Huffman table : %d", 
00195                HuffmanTree_UV_AC->countLeaves());
00196   mxcpc::sendStatusMsg(txt, this);
00197                                                                                                                                                                          
00198   // Init member var ...
00199   CoeffBuffer = 0;           // This buffer holds the DCT-JPEG image
00200   TileNumX = TileNumY = 0;
00201   
00202   FramesProcessed = 0;
00203     
00204   // init APP0 - taken from Klaus' jp-hdr.c (20050422)...
00205   APP0_Block.ff          = 0xff;
00206   APP0_Block.app0_marker = mxcpc_mxpeg::MarkerId_APP0;
00207   APP0_Block.len_hi      = (sizeof(mxcpc_mxpeg::APP0) - 2) / 256;
00208   APP0_Block.len_lo      = (sizeof(mxcpc_mxpeg::APP0) - 2) % 256;
00209   std::strcpy(APP0_Block.id, "JFIF"); 
00210   APP0_Block.major_vers  = 0x01; 
00211   APP0_Block.minor_vers  = 0x01;
00212   APP0_Block.units       = 0x00;
00213   APP0_Block.xdpu_hi     = 0;
00214   APP0_Block.xdpu_lo     = 1;
00215   APP0_Block.ydpu_hi     = 0;
00216   APP0_Block.ydpu_lo     = 1;
00217   APP0_Block.thumbnail_x = 0;
00218   APP0_Block.thumbnail_y = 0;
00219   
00220   // init SOF0, image size is zeroed out...
00221   SOF0_Block.ff                         = 0xff;
00222   SOF0_Block.marker                     = mxcpc_mxpeg::MarkerId_SOF0;
00223   SOF0_Block.len_hi                     = (sizeof(mxcpc_mxpeg::SOF0) - 2) / 256;
00224   SOF0_Block.len_lo                     = (sizeof(mxcpc_mxpeg::SOF0) - 2) % 256;
00225   SOF0_Block.data_precision             = 0x08;
00226   SOF0_Block.y_sz_hi                    = 0;
00227   SOF0_Block.y_sz_lo                    = 0;
00228   SOF0_Block.x_sz_hi                    = 0;
00229   SOF0_Block.x_sz_lo                    = 0;
00230   SOF0_Block.num_components             = 3;
00231   SOF0_Block.components[0].component_id = 1;   // Y
00232   SOF0_Block.components[0].sampl_fact   = 0x22;
00233   SOF0_Block.components[0].quant_tbl_no = 0;
00234   SOF0_Block.components[1].component_id = 2;   // U
00235   SOF0_Block.components[1].sampl_fact   = 0x11;
00236   SOF0_Block.components[1].quant_tbl_no = 1;
00237   SOF0_Block.components[2].component_id = 3;   // V
00238   SOF0_Block.components[2].sampl_fact   = 0x11;
00239   SOF0_Block.components[2].quant_tbl_no = 1;
00240   
00241   // init SOF0, image size is zeroed out...
00242   SOS_Block.ff                    = 0xff;
00243   SOS_Block.sos_marker            = mxcpc_mxpeg::MarkerId_SOS;
00244   SOS_Block.sz_hi                 = (sizeof(mxcpc_mxpeg::SOS) - 2) / 256;
00245   SOS_Block.sz_lo                 = (sizeof(mxcpc_mxpeg::SOS) - 2) % 256;
00246   SOS_Block.comps_in_scan         = 3;
00247   SOS_Block.components[0].comp_id = 1;
00248   SOS_Block.components[0].td_ta   = 0x00;
00249   SOS_Block.components[1].comp_id = 2;
00250   SOS_Block.components[1].td_ta   = 0x11;
00251   SOS_Block.components[2].comp_id = 3;
00252   SOS_Block.components[2].td_ta   = 0x11;
00253   SOS_Block.Ss                    = 0x00;
00254   SOS_Block.Se                    = 0x3f;
00255   SOS_Block.Ah_Al                 = 0x00;
00256 }   
00257 
00258 
00259 mxcpcFramewiseMxPEGScanToJPEGConverterSoftwareOnly
00260  ::~mxcpcFramewiseMxPEGScanToJPEGConverterSoftwareOnly() {
00261 
00262   delete HuffmanTree_Y_DC; 
00263   delete HuffmanTree_Y_AC;         
00264   delete HuffmanTree_UV_DC; 
00265   delete HuffmanTree_UV_AC;
00266 
00267   delete[] CoeffBuffer;
00268   delete[] HuffmanEncoderBuffer;        
00269 }   
00270 
00271 
00272 
00273 const char *mxcpcFramewiseMxPEGScanToJPEGConverterSoftwareOnly
00274             ::getAccelerationTypeString(void) {
00275                     
00276   return("none");
00277 }
00278 
00279 
00280 void mxcpcFramewiseMxPEGScanToJPEGConverterSoftwareOnly
00281       ::setYQuantizationTable(unsigned char *data_bytes) {
00282 
00283   int i;
00284   
00285   for(i = 0; i < 64; i++) QuantizationTable_Y[ZigZagMap[i]] = *data_bytes++;
00286 }
00287 
00288  
00289 void mxcpcFramewiseMxPEGScanToJPEGConverterSoftwareOnly
00290       ::setUVQuantizationTable(unsigned char *data_bytes) {
00291 
00292   int i;
00293 
00294   for(i = 0; i < 64; i++) QuantizationTable_UV[ZigZagMap[i]] = *data_bytes++;
00295 }
00296 
00297 
00298 void mxcpcFramewiseMxPEGScanToJPEGConverterSoftwareOnly
00299       ::performScanSweep(mxcpcFramewiseMxPEGDecoder::UndecodedFrameDescriptor 
00300                           *frame_descriptor)                                  {
00301                             
00302   // init local data and lookup tables...
00303   const mxcpcHuffmanTree::Node *Huffman_DC_Roots[6] = { 
00304                                                     HuffmanTree_Y_DC->getRoot(),
00305                                                     HuffmanTree_Y_DC->getRoot(),
00306                                                     HuffmanTree_Y_DC->getRoot(),
00307                                                     HuffmanTree_Y_DC->getRoot(),
00308                                                     HuffmanTree_UV_DC->getRoot(),
00309                                                     HuffmanTree_UV_DC->getRoot()
00310                                                    },
00311                                *Huffman_AC_Roots[6] = { 
00312                                                     HuffmanTree_Y_AC->getRoot(),
00313                                                     HuffmanTree_Y_AC->getRoot(),
00314                                                     HuffmanTree_Y_AC->getRoot(),
00315                                                     HuffmanTree_Y_AC->getRoot(),
00316                                                     HuffmanTree_UV_AC->getRoot(),
00317                                                     HuffmanTree_UV_AC->getRoot()
00318                                                    };
00319                                                    
00320   // remaining local data...
00321   
00322   bool use_bitmask;
00323   int tilebits_left;
00324   unsigned char *tilebit_ptr, tilebit_mask;
00325   int x, y;
00326   bool next_tile_right_here;
00327   int tiles_to_write;
00328         
00329   // needed for Huffman decoding
00330   const mxcpcHuffmanTree::Node *huffman_leaf_node;                                                                                                                        
00331   int additional_bit_num;
00332   int ac_coeffs_needed;
00333   int ac_coeffs_to_output;
00334         
00335   // For handling the predictively coded dc ... 
00336   mxcpc::s16 dc_coeffs[3] = { 0, 0, 0};
00337   mxcpc::s16 *dc_coeff_ptrs[6] = { &dc_coeffs[0],
00338                                    &dc_coeffs[0],
00339                                    &dc_coeffs[0],
00340                                    &dc_coeffs[0],
00341                                    &dc_coeffs[1],
00342                                    &dc_coeffs[2]
00343                                  };
00344 
00345         
00346   int coeff_i;
00347         
00348   mxcpc::s16 *sub_mcu_coeffs;
00349   mxcpc::u8 quantization_table_to_write[64];
00350   mxcpc::s16 *quant_coeff;
00351   const unsigned char *huffman_table_to_write;
00352   int                  huffman_table_to_write_size;
00353   
00354   int i, j;
00355   
00356   mxcpc::u8 write_buffer[10];
00357         
00358   // points to the current Tile (6*64 ~> YYYYUV )
00359   mxcpc::s16 *coeff_buffer=0;
00360 
00361   // guard against missing backend
00362   if(!BackEnd) return;
00363   
00364   // check coeff buffer and its dimensions...
00365   if(   (frame_descriptor->TileNumX != TileNumX)
00366      || (frame_descriptor->TileNumY != TileNumY)) {
00367   
00368     delete[] CoeffBuffer;
00369     
00370     try {
00371     
00372       CoeffBuffer = new mxcpc::s16[frame_descriptor->TileNumX 
00373                                     * frame_descriptor->TileNumY
00374                                     * 6 * 64
00375                                   ];
00376                                                                                                 
00377       TileNumX = frame_descriptor->TileNumX;
00378       TileNumY = frame_descriptor->TileNumY;
00379       
00380       mxcpc::sendStatusMsg("JPG converter : reallocated coeff buffer");
00381                                 
00382     } catch(std::bad_alloc) {
00383         
00384         mxcpc::sendStatusMsg("JPG converter : "
00385                              "reallocation of coeff buffer failed!");   
00386                         
00387         CoeffBuffer = 0;
00388         TileNumX = TileNumY = 0;
00389       }
00390   }  
00391   
00392   if(!CoeffBuffer) {
00393     mxcpc::sendStatusMsg("JPG converter : CoeffBuffer == NULL!");
00394     BackEnd->errorEncountered();
00395     return;
00396   } 
00397       
00398     
00399   // decide for bitmask mode...
00400   CurrentScanByte = frame_descriptor->ScanBytes;
00401   ScanMask        = 128;
00402   ScanBytesLeft   = frame_descriptor->ScanLength;
00403   if(!CurrentScanByte || !ScanBytesLeft) {
00404     BackEnd->errorEncountered();
00405     return;
00406   }    
00407   tilebits_left = frame_descriptor->TileNumX * frame_descriptor->TileNumY;
00408   tilebit_ptr   = frame_descriptor->TileBits;
00409   tilebit_mask  = 128;
00410   x = -1;
00411   y = 0;
00412   next_tile_right_here = true;   // default for bitmask-less mode
00413   if(tilebit_ptr) 
00414     use_bitmask = true;
00415   else
00416     use_bitmask = false;
00417                 
00418     
00419   // iterate over all tiles (MCUs)...
00420   while(tilebits_left) {
00421                                                 
00422     // advance target tile coordinates...
00423     x++;
00424     if(x == frame_descriptor->TileNumX) {
00425       x = 0;
00426       y++;
00427     }
00428   
00429     // if in bitmask mode, consume and honor current tile bit...
00430     if(use_bitmask) {
00431       next_tile_right_here = (*tilebit_ptr & tilebit_mask) != 0;
00432       tilebit_mask /= 2;
00433       if(!tilebit_mask) {
00434         tilebit_mask = 128;
00435         tilebit_ptr++;
00436       }
00437     }
00438                 
00439 
00440    
00441     if(next_tile_right_here) {   // decode tile...
00442       
00443       // iterate over the 6 sub-MCUs (Y,Y,Y,Y,U,V)...
00444       for(i = 0; i < 6; i++) {
00445                 
00446         coeff_buffer 
00447          = &CoeffBuffer[y * TileNumX * 6*64  +  x * 6*64  +  i * 64];
00448                                                                                                 
00449         // --- decode the DC coeff... ---
00450         
00451         // recognize Huffman codeword...
00452         huffman_leaf_node = consumeHuffmanCodeword(Huffman_DC_Roots[i]);
00453                                                                 
00454         if(!huffman_leaf_node) {
00455                                         
00456           BackEnd->errorEncountered();
00457           mxcpc::sendStatusMsg("JPG converter : "
00458                                "1) huffman_leaf_node DC == NULL");
00459           return;
00460         }
00461  
00462         // deal with additional bits to be read for this coeff...
00463         additional_bit_num = (int)(  (unsigned int)huffman_leaf_node->Value
00464                                    & (unsigned int)0x0f);
00465         if(additional_bit_num) {
00466           if(consumeAdditionalBits(additional_bit_num)) {
00467                                         
00468             mxcpc::sendStatusMsg("JPG converter : Return val consumeAdditionalBits() == NULL");
00469             BackEnd->errorEncountered();
00470             return;
00471           }
00472           coeff_buffer[0] = CoeffInAdditionalBits;
00473         }
00474         else {
00475           coeff_buffer[0] = 0;
00476         }
00477         
00478         // do delta stuff...
00479         coeff_buffer[0] += *dc_coeff_ptrs[i];
00480         *dc_coeff_ptrs[i] = coeff_buffer[0];
00481         
00482         
00483         // --- decode 63 AC coeffs... ---
00484         coeff_i = 1;
00485         ac_coeffs_needed = 63;
00486         while(ac_coeffs_needed) {
00487         
00488           // recognize Huffman codeword...
00489           huffman_leaf_node = consumeHuffmanCodeword(Huffman_AC_Roots[i]);
00490           if(!huffman_leaf_node) {
00491                                         
00492             mxcpc::sendStatusMsg("JPG converter : "
00493                                  "2)huffman_leaf_node AC == NULL");             
00494             BackEnd->errorEncountered();
00495             return;
00496           } 
00497           
00498           // check for EOB...
00499           if(huffman_leaf_node->Value == 0x00) {
00500             while(ac_coeffs_needed) {   // zero out the remaining matrix cells 
00501               coeff_buffer[ZigZagMap[coeff_i]] = 0;
00502               coeff_i++;
00503               ac_coeffs_needed--;
00504             }
00505             continue;   // ac_coeffs_needed is 0
00506           }
00507           
00508           // deal with additional bits to be read for this coeff...
00509           additional_bit_num = (int)(  (unsigned int)huffman_leaf_node->Value
00510                                      & (unsigned int)0x0f);                            
00511           if(additional_bit_num) {
00512             if(consumeAdditionalBits(additional_bit_num)) {
00513               mxcpc::sendStatusMsg("JPG converter : "
00514                                    "return val consumeAdditionalBits() == "
00515                                    "NULL");
00516               BackEnd->errorEncountered();                                                                                                                                                      
00517               return;
00518             }
00519           }
00520           else
00521             CoeffInAdditionalBits = 0;
00522           
00523           // deal with AC coeffs to output and check break condition...
00524           ac_coeffs_to_output = huffman_leaf_node->Value/16 + 1;
00525           if(ac_coeffs_to_output > ac_coeffs_needed) {
00526             mxcpc::sendStatusMsg("too many AC coeffs!");
00527             BackEnd->errorEncountered();
00528             return;
00529           }
00530           for(j = 0; j < ac_coeffs_to_output-1; j++) {   // fill zeroes...
00531             coeff_buffer[ZigZagMap[coeff_i]] = 0;
00532             coeff_i++;
00533           }
00534           coeff_buffer[ZigZagMap[coeff_i]] = CoeffInAdditionalBits;
00535           coeff_i++;
00536           if(coeff_i > 64) {
00537             mxcpc::sendStatusMsg("coeff buffer overflow!");
00538             BackEnd->errorEncountered();
00539             return;
00540           }
00541           
00542           ac_coeffs_needed -= ac_coeffs_to_output;
00543         }     
00544                                 
00545       }
00546                                               
00547       // got all 6 sub-MCUs!
00548             
00549       BackEnd->videoTileReceived();
00550     } 
00551     
00552     tilebits_left--;
00553   }
00554   
00555   // ok, we've got a frame, generate some JPEG...
00556   
00557   Receiver->beginFrame();
00558          
00559   // write SOI...
00560   write_buffer[0] = 0xff;
00561   write_buffer[1] = mxcpc_mxpeg::MarkerId_SOI;
00562   Receiver->receiveJPEGBytes(write_buffer, 2);
00563   
00564   // write APP0...
00565   Receiver->receiveJPEGBytes((mxcpc::u8 *)&APP0_Block, 
00566                              sizeof(mxcpc_mxpeg::APP0));
00567   
00568   // write quantization tables, Y(0) and UV(1)...
00569   for(i = 0; i < 2; i++) {   // got two of them 
00570     write_buffer[0] = 0xff;
00571     write_buffer[1] = mxcpc_mxpeg::MarkerId_DQT;
00572     write_buffer[2] = 0;
00573     write_buffer[3] = 67;
00574     write_buffer[4] = i;
00575     Receiver->receiveJPEGBytes(write_buffer, 5);
00576   
00577     if(!i) quant_coeff = QuantizationTable_Y;
00578     else   quant_coeff = QuantizationTable_UV;
00579     for(j = 0; j < 64; j++) 
00580      quantization_table_to_write[ZigZag_StoreMap[j]] 
00581       = ((mxcpc::u8)*quant_coeff++);
00582     Receiver->receiveJPEGBytes(quantization_table_to_write, 64);
00583   }
00584   
00585   // write SOF0...
00586   SOF0_Block.x_sz_hi = frame_descriptor->Width / 256;
00587   SOF0_Block.x_sz_lo = frame_descriptor->Width % 256;
00588   SOF0_Block.y_sz_hi = frame_descriptor->Height / 256;
00589   SOF0_Block.y_sz_lo = frame_descriptor->Height % 256;
00590   Receiver->receiveJPEGBytes((mxcpc::u8 *)&SOF0_Block, 
00591                              sizeof(mxcpc_mxpeg::SOF0));
00592                                                                                                                                                          
00593   // write huffman tables...
00594   for(i = 0; i < 4; i++) {   // got four of them  
00595     write_buffer[0] = 0xff;
00596     write_buffer[1] = mxcpc_mxpeg::MarkerId_DHT;
00597     if(i == 0) {
00598       write_buffer[4] = 0x00;
00599       huffman_table_to_write      = DefaultHuffmanTable_Y_DC;
00600       huffman_table_to_write_size = DefaultHuffmanTable_Y_DC_Size;
00601     }
00602     else if(i == 1) {
00603       write_buffer[4] = 0x10;
00604       huffman_table_to_write      = DefaultHuffmanTable_Y_AC;
00605       huffman_table_to_write_size = DefaultHuffmanTable_Y_AC_Size;
00606     }
00607     else if(i == 2) {
00608       write_buffer[4] = 0x01;
00609       huffman_table_to_write      = DefaultHuffmanTable_UV_DC;
00610       huffman_table_to_write_size = DefaultHuffmanTable_UV_DC_Size;
00611     }
00612     else {
00613       write_buffer[4] = 0x11;
00614       huffman_table_to_write      = DefaultHuffmanTable_UV_AC;
00615       huffman_table_to_write_size = DefaultHuffmanTable_UV_AC_Size;
00616     }
00617     write_buffer[2] = (huffman_table_to_write_size + 3) / 256;
00618     write_buffer[3] = (huffman_table_to_write_size + 3) % 256;
00619     Receiver->receiveJPEGBytes(write_buffer, 5);
00620     Receiver->receiveJPEGBytes((mxcpc::u8 *)huffman_table_to_write, 
00621                                huffman_table_to_write_size);
00622   }  
00623   
00624   // write SOS...
00625   Receiver->receiveJPEGBytes((mxcpc::u8 *)&SOS_Block, 
00626                              sizeof(mxcpc_mxpeg::SOS));
00627                                                                                                                                                  
00628   // init dc_coeff_ptrs[i]
00629   for(i=0; i < 3; i++) dc_coeffs[i] = 0;
00630   dc_coeff_ptrs[0] = &dc_coeffs[0];
00631   dc_coeff_ptrs[1] = &dc_coeffs[0];
00632   dc_coeff_ptrs[2] = &dc_coeffs[0];
00633   dc_coeff_ptrs[3] = &dc_coeffs[0];
00634   dc_coeff_ptrs[4] = &dc_coeffs[1];
00635   dc_coeff_ptrs[5] = &dc_coeffs[2];
00636         
00637   // define huffman code table list ..
00638   FoldedHuffTbl_DC_AC* huff_code_table_list[6];
00639         
00640   // Y -Table ...
00641   huff_code_table_list[0] = &Huff_Y_UV[0]; 
00642   huff_code_table_list[1] = &Huff_Y_UV[0];
00643   huff_code_table_list[2] = &Huff_Y_UV[0];                                                                                                                                                                                                                                                                                               
00644   huff_code_table_list[3] = &Huff_Y_UV[0];
00645         
00646   // UV -Table
00647   huff_code_table_list[4] = &Huff_Y_UV[1];                                                                                                                                                                                                                                                                                               
00648   huff_code_table_list[5] = &Huff_Y_UV[1];
00649                                                                                                                                                          
00650   // write out scan...
00651   sub_mcu_coeffs = CoeffBuffer;
00652   tiles_to_write = TileNumX * TileNumY;
00653         
00654   int nb_of_bytes_to_write = 0; 
00655   while(tiles_to_write) {
00656   
00657     // iterate over sub-MCUs of current tile YYYYUV ...
00658     for(i = 0; i < 6; i++) {
00659       encodeSubMCUTiles(sub_mcu_coeffs,
00660                         dc_coeff_ptrs[i],
00661                         huff_code_table_list[i],
00662                         &HuffmanBufferState);                                                                                                                                                                                                       
00663       sub_mcu_coeffs += 64;
00664     }
00665   
00666     tiles_to_write--;
00667   }
00668 
00669   // write last byte ...        
00670   shutDownHuffAccu();
00671 
00672   // pump out data ...
00673   nb_of_bytes_to_write 
00674    = HuffmanBufferState.buf_current_w_pos - HuffmanBufferState.buf_start;
00675   Receiver->receiveJPEGBytes(HuffmanBufferState.buf_start, 
00676                              nb_of_bytes_to_write);
00677  
00678   // Reset global encoding buffer ...
00679   resetHuffmanEncoderBufferState();
00680   
00681   // write EOI...
00682   write_buffer[0] = 0xff;
00683   write_buffer[1] = mxcpc_mxpeg::MarkerId_EOI;
00684   Receiver->receiveJPEGBytes(write_buffer, 2);
00685    
00686   
00687   // ok, we've done it!
00688   Receiver->endFrame();
00689   
00690   FramesProcessed++;
00691 }
00692 
00693 
00694 /*! 
00695                 Calculates huffman tables a la mobotix!
00696 */
00697 void mxcpcFramewiseMxPEGScanToJPEGConverterSoftwareOnly
00698       ::calcFoldedHuffTables(void){
00699 
00700   int y_uv;
00701 
00702   static int firstcall = 0;
00703   if (firstcall) return;
00704 
00705   firstcall++;
00706 
00707   // Generate two sets of tables, for Y and UV 
00708   for (y_uv = 0; y_uv < 2; y_uv++) {  
00709                         
00710     /* first generate DC-table */
00711     generateHuffTables1(
00712      /* u8 * bits_tbl_off1, entries 0..15 count no. of symbols with 1..16 bits, 
00713         respectively */ 
00714      &HuffTbl_Y_UV_DC[y_uv].bits_dc[0],
00715      /* u8 * val_tbl,       table of symbols that need to be encoded, 
00716         size = sum of entries in bits_tbl_off1 */ 
00717      &HuffTbl_Y_UV_DC[y_uv].val_dc[0],
00718      /* int swap_symbol, set if the swapped symbol is used to access the generated
00719         folded table (for ac-coefs) */  
00720      0,                                 
00721      &Huff_Y_UV[y_uv].dc_tbl[0]
00722     );
00723         
00724     /* then AC-table */
00725     generateHuffTables1(
00726      /* u8 * bits_tbl_off1, entries 0..15 count no. of symbols with 1..16 bits,
00727         respectively */ 
00728      &HuffTbl_Y_UV_AC[y_uv].bits_ac[0],
00729      /* u8 * val_tbl, table of symbols that need to be encoded, size = sum of 
00730         entries in bits_tbl_off1 */ 
00731      &HuffTbl_Y_UV_AC[y_uv].val_ac[0],
00732      /* int swap_symbol, set if the swapped symbol is used to access the 
00733         generated folded table (for ac-coefs) */  
00734      1,
00735      /* jd_huf_code_tbl_entry_t * folded_tbl_p; */                                 
00736      &Huff_Y_UV[y_uv].ac_tbl[0]
00737     );
00738   }
00739 }       
00740 
00741 
00742 /*!   
00743   Generate a run-length-coded huffman-code-tree for all symbols in
00744   val_tabl.
00745  
00746   The huffman-codes for each symbol are stored in a "folded" table
00747   that can be indexed by a symbol and yields a word that contains
00748   the pre-shifted code in the lower 26 bits and the length of the combination 
00749   of the rll-coded symbol and the mantissa in the upper 5 bits
00750 
00751   \param bits_tbl_off1 
00752   Entries 0..15 count no. of symbols with 1..16 bits, respectively.
00753   \param val_tbl 
00754   Table of symbols that need to be encoded, size = sum of entries in 
00755   bits_tbl_off1.
00756   \param swap_symbol set if the swapped symbol is used to access the generated
00757   folded table (for ac-coefs).
00758 */
00759 void mxcpcFramewiseMxPEGScanToJPEGConverterSoftwareOnly::generateHuffTables1(
00760       const mxcpc::u8 * bits_tbl_off1,  
00761       const mxcpc::u8 * val_tbl,   
00762       int swap_symbol,    
00763       HuffCodeTblEntry * folded_tbl_p
00764      )                                                                        {
00765 
00766   int len, codes_of_len, mantissa_len;
00767 
00768   int code = 0;
00769   for(len = 1; len <= 16; len ++) {
00770   
00771     for(codes_of_len = 1; 
00772         codes_of_len <= bits_tbl_off1[len - 1];
00773         codes_of_len++)                         {
00774     
00775       int symbol = *val_tbl++;     /* get unswapped symbol from the table in the 
00776                                       Jpeg-header */
00777       mantissa_len = symbol & 0xf; /* top nibble is run-length, 
00778                                       low nibble is number of significant bits
00779                                       in coefficient */
00780       if(swap_symbol) {            /* 0xRS -> 0xSR */ 
00781         symbol = (symbol >> 4) + ((symbol & 0xf) << 4);  
00782       }
00783       folded_tbl_p[symbol].code_msk  = code << mantissa_len;
00784       folded_tbl_p[symbol].fill_0bit = 0;
00785       folded_tbl_p[symbol].bit_len   = len + mantissa_len;
00786       code++;
00787     }
00788     
00789     code <<= 1;
00790   }
00791 }
00792 
00793 
00794 /*!
00795    Take care of initialisierung!
00796 */
00797 void mxcpcFramewiseMxPEGScanToJPEGConverterSoftwareOnly
00798       ::initHuffmanEncoderBufferState()                 {
00799 
00800   HuffmanBufferState.buf_start         = &HuffmanEncoderBuffer[0];
00801   HuffmanBufferState.buf_current_w_pos = &HuffmanEncoderBuffer[0];
00802   HuffmanBufferState.buf_end1
00803    = &HuffmanEncoderBuffer[
00804        MXCPC_FRAMEWISEMXPEGSCANTOJPEGCONVERTER_BITSTREAM_BUFFSIZE + 1
00805       ];
00806                                                                                                                                                                                 
00807   HuffmanBufferState.huf_accu          = 0;
00808   HuffmanBufferState.huf_bits_used     = 0;
00809 }
00810 
00811 
00812 /*!
00813     Reset HuffmanEncoderBufferState in order to fetch next frame!
00814 */
00815 void mxcpcFramewiseMxPEGScanToJPEGConverterSoftwareOnly
00816       ::resetHuffmanEncoderBufferState()                {
00817 
00818   HuffmanBufferState.buf_start         = &HuffmanEncoderBuffer[0];
00819   HuffmanBufferState.buf_current_w_pos = &HuffmanEncoderBuffer[0];
00820 
00821   HuffmanBufferState.huf_accu          = 0;
00822   HuffmanBufferState.huf_bits_used     = 0;
00823 }
00824 

Generated on Fri Jan 20 13:33:32 2006 for mxcpc by  doxygen 1.4.4