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

mxcpcFramewiseMxPEGScanToJPEGConverterSoftwareOnly.cpp

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

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