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

mxcpcFramewiseMxPEGScanDecoderSoftwareOnly.cpp

00001 //           ///          //                                        Mx clientSDK
00002 //          /////        ////                    Mx Crossplatform Client Library
00003 //         /// XXX     XXX ///
00004 //        ///    XXX XXX    ///     $RCSfile: mxcpcFramewiseMxPEGScanDecoderSoftwareOnly.cpp,v $
00005 //       ///       XXX       ///     $Revision: 1.3 $
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 <mxcpcFramewiseMxPEGScanDecoderSoftwareOnly.h>
00021 #include <mxcpcMxPEGDecoderBackEnd.h>
00022 #include <mxcpc_namespace.h>
00023 #include <mxcpc_exceptions.h>
00024 
00025 #include <cstring>
00026 #include <cstdio>
00027 
00028 
00029 
00030 const int mxcpcFramewiseMxPEGScanDecoderSoftwareOnly
00031            ::ZigZagMap[64] = {  0,  1,  8, 16,  9,  2,  3, 10, 
00032                                17, 24, 32, 25, 18, 11,  4,  5,
00033                                12, 19, 26, 33, 40, 48, 41, 34, 
00034                                27, 20, 13,  6,  7, 14, 21, 28,
00035                                35, 42, 49, 56, 57, 50, 43, 36,
00036                                29, 22, 15, 23, 30, 37, 44, 51, 
00037                                58, 59, 52, 45, 38, 31, 39, 46, 
00038                                53, 60, 61, 54, 47, 55, 62, 63 
00039                              };
00040 short mxcpcFramewiseMxPEGScanDecoderSoftwareOnly::iclip[1024];
00041 short *mxcpcFramewiseMxPEGScanDecoderSoftwareOnly::iclp;                         
00042     
00043 
00044 
00045 mxcpcFramewiseMxPEGScanDecoderSoftwareOnly::mxcpcFramewiseMxPEGScanDecoderSoftwareOnly() {
00046   
00047   char txt[100];
00048   int i;
00049   
00050   HuffmanTree_Y_DC  = 0, 
00051   HuffmanTree_Y_AC  = 0;         
00052   HuffmanTree_UV_DC = 0, 
00053   HuffmanTree_UV_AC = 0;
00054   
00055   try {
00056   
00057     HuffmanTree_Y_DC = new mxcpcHuffmanTree();
00058     if(HuffmanTree_Y_DC->configureFromTable(DefaultHuffmanTable_Y_DC))
00059       throw mxcpcDidntWorkOutException();
00060     HuffmanTree_Y_AC = new mxcpcHuffmanTree();
00061     if(HuffmanTree_Y_AC->configureFromTable(DefaultHuffmanTable_Y_AC))
00062       throw mxcpcDidntWorkOutException();
00063     HuffmanTree_UV_DC = new mxcpcHuffmanTree();
00064     if(HuffmanTree_UV_DC->configureFromTable(DefaultHuffmanTable_UV_DC))
00065       throw mxcpcDidntWorkOutException();
00066     HuffmanTree_UV_AC = new mxcpcHuffmanTree();
00067     if(HuffmanTree_UV_AC->configureFromTable(DefaultHuffmanTable_UV_AC))
00068       throw mxcpcDidntWorkOutException();  
00069   
00070   } catch(std::exception &e) {
00071     
00072       MXCPC_RETHROW_UNHANDLED_EXCEPTION(e);
00073     
00074       delete HuffmanTree_Y_DC; 
00075       delete HuffmanTree_Y_AC;         
00076       delete HuffmanTree_UV_DC; 
00077       delete HuffmanTree_UV_AC;
00078       
00079       throw;
00080     }
00081     
00082   for(i = 0; i < 64; i++) {
00083     QuantizationTable_Y[i]  = 0;
00084     QuantizationTable_UV[i] = 0;
00085   }
00086   
00087   iclp = iclip + 512;
00088   for(i = -512; i < 512; i++) iclp[i] = (i < -256) ? -256 : ((i > 255) ? 255 : i);
00089     
00090   std::sprintf(txt, "symbols in Y/DC Huffman table : %d", 
00091                HuffmanTree_Y_DC->countLeaves());
00092   mxcpc::sendStatusMsg(txt, this);
00093   std::sprintf(txt, "symbols in Y/AC Huffman table : %d", 
00094                HuffmanTree_Y_AC->countLeaves());
00095   mxcpc::sendStatusMsg(txt, this);
00096   std::sprintf(txt, "symbols in UV/DC Huffman table : %d", 
00097                HuffmanTree_UV_DC->countLeaves());
00098   mxcpc::sendStatusMsg(txt, this);
00099   std::sprintf(txt, "symbols in UV/AC Huffman table : %d", 
00100                HuffmanTree_UV_AC->countLeaves());
00101   mxcpc::sendStatusMsg(txt, this);
00102 }
00103 
00104 
00105 mxcpcFramewiseMxPEGScanDecoderSoftwareOnly::~mxcpcFramewiseMxPEGScanDecoderSoftwareOnly() {
00106  
00107   delete HuffmanTree_Y_DC; 
00108   delete HuffmanTree_Y_AC;         
00109   delete HuffmanTree_UV_DC; 
00110   delete HuffmanTree_UV_AC;
00111 }
00112 
00113 
00114 
00115 const char *mxcpcFramewiseMxPEGScanDecoderSoftwareOnly
00116             ::getAccelerationTypeString(void) {
00117                     
00118   return("none");
00119 }
00120 
00121 
00122 void mxcpcFramewiseMxPEGScanDecoderSoftwareOnly
00123       ::setYQuantizationTable(unsigned char *data_bytes) {
00124       
00125   int i;
00126   
00127   for(i = 0; i < 64; i++) QuantizationTable_Y[ZigZagMap[i]] = *data_bytes++;
00128 }
00129   
00130   
00131 void mxcpcFramewiseMxPEGScanDecoderSoftwareOnly
00132       ::setUVQuantizationTable(unsigned char *data_bytes) {
00133     
00134   int i;
00135   
00136   for(i = 0; i < 64; i++) QuantizationTable_UV[ZigZagMap[i]] = *data_bytes++;
00137 }
00138 
00139   
00140 void mxcpcFramewiseMxPEGScanDecoderSoftwareOnly
00141       ::performScanSweep(mxcpcFramewiseMxPEGDecoder::UndecodedFrameDescriptor
00142                           *frame_descriptor)                                  {
00143                        
00144   // init local data and lookup tables...
00145   const mxcpcHuffmanTree::Node *Huffman_DC_Roots[6] = { HuffmanTree_Y_DC->getRoot(),
00146                                                         HuffmanTree_Y_DC->getRoot(),
00147                                                         HuffmanTree_Y_DC->getRoot(),
00148                                                         HuffmanTree_Y_DC->getRoot(),
00149                                                         HuffmanTree_UV_DC->getRoot(),
00150                                                         HuffmanTree_UV_DC->getRoot()
00151                                                       },
00152                                *Huffman_AC_Roots[6] = { HuffmanTree_Y_AC->getRoot(),
00153                                                         HuffmanTree_Y_AC->getRoot(),
00154                                                         HuffmanTree_Y_AC->getRoot(),
00155                                                         HuffmanTree_Y_AC->getRoot(),
00156                                                         HuffmanTree_UV_AC->getRoot(),
00157                                                         HuffmanTree_UV_AC->getRoot()
00158                                                       };
00159   mxcpc::s16 *quantization_table_ptrs[6] = { &QuantizationTable_Y[0],
00160                                              &QuantizationTable_Y[0],
00161                                              &QuantizationTable_Y[0],
00162                                              &QuantizationTable_Y[0],
00163                                              &QuantizationTable_UV[0],
00164                                              &QuantizationTable_UV[0]
00165                                            };
00166   bool use_bitmask;
00167   int tilebits_left;
00168   unsigned char *tilebit_ptr, tilebit_mask;
00169   int x, y;
00170   bool next_tile_right_here;
00171   const mxcpcHuffmanTree::Node *huffman_leaf_node;
00172   int additional_bit_num;
00173   int ac_coeffs_needed;
00174   int ac_coeffs_to_output;
00175   mxcpc::s16 coeff_buffers[6][64];
00176   mxcpc::s16 dc_coeffs[3] = { 0, 0, 0};
00177   mxcpc::s16 *dc_coeff_ptrs[6] = { &dc_coeffs[0],
00178                                    &dc_coeffs[0],
00179                                    &dc_coeffs[0],
00180                                    &dc_coeffs[0],
00181                                    &dc_coeffs[1],
00182                                    &dc_coeffs[2]
00183                                  };
00184   mxcpc::s16 *coeff_buffer;
00185   mxcpc::s16 *src_ptr, *dest_ptr;
00186   int coeff_i;
00187   int color_y, color_u, color_v,
00188       color_r, color_g, color_b;
00189   mxcpc::u32 *pixel_target;
00190   int target_row_stepping;
00191   unsigned char *target_ptr;
00192   int i, j;
00193   unsigned int ii, jj;
00194                                   
00195                       
00196   // guard against missing backend
00197   if(!BackEnd) return;   
00198  
00199   
00200   // initialize and decide for bitmask mode...
00201   CurrentScanByte = frame_descriptor->ScanBytes;
00202   ScanMask        = 128;
00203   ScanBytesLeft   = frame_descriptor->ScanLength;
00204   if(!CurrentScanByte || !ScanBytesLeft) {
00205     BackEnd->errorEncountered();
00206     return;
00207   }    
00208   tilebits_left = frame_descriptor->TileNumX * frame_descriptor->TileNumY;
00209   tilebit_ptr   = frame_descriptor->TileBits;
00210   tilebit_mask  = 128;
00211   x = -1;
00212   y = 0;
00213   next_tile_right_here = true;   // default for bitmask-less mode
00214   if(tilebit_ptr) 
00215     use_bitmask = true;
00216   else
00217     use_bitmask = false;
00218    
00219     
00220   // iterate over all tiles (MCUs)...
00221   while(tilebits_left) {
00222   
00223     // advance target tile coordinates...
00224     x++;
00225     if(x == frame_descriptor->TileNumX) {
00226       x = 0;
00227       y++;
00228     }
00229   
00230     // if in bitmask mode, consume and honor current tile bit...
00231     if(use_bitmask) {
00232       next_tile_right_here = (*tilebit_ptr & tilebit_mask) != 0;
00233       tilebit_mask /= 2;
00234       if(!tilebit_mask) {
00235         tilebit_mask = 128;
00236         tilebit_ptr++;
00237       }
00238     }
00239    
00240     if(next_tile_right_here) {   // decode tile...
00241       
00242       // iterate over the 6 sub-MCUs (Y,Y,Y,Y,U,V)...
00243       for(i = 0; i < 6; i++) {
00244        
00245         coeff_buffer = coeff_buffers[i];
00246       
00247         // --- decode the DC coeff... ---
00248         
00249         // recognize Huffman codeword...
00250         huffman_leaf_node = consumeHuffmanCodeword(Huffman_DC_Roots[i]);
00251         if(!huffman_leaf_node) {
00252           BackEnd->errorEncountered();
00253           return;
00254         }
00255  
00256         // deal with additional bits to be read for this coeff...
00257         additional_bit_num = (int)(  (unsigned int)huffman_leaf_node->Value
00258                                    & (unsigned int)0x0f);
00259         if(additional_bit_num) {
00260           if(consumeAdditionalBits(additional_bit_num)) {
00261             BackEnd->errorEncountered();
00262             return;
00263           }
00264           coeff_buffer[0] = CoeffInAdditionalBits;
00265         }
00266         else {
00267           coeff_buffer[0] = 0;
00268         }
00269         
00270         // do delta stuff...
00271         coeff_buffer[0] += *dc_coeff_ptrs[i];
00272         *dc_coeff_ptrs[i] = coeff_buffer[0];
00273         
00274         
00275         // --- decode 63 AC coeffs... ---
00276         coeff_i = 1;
00277         ac_coeffs_needed = 63;
00278         while(ac_coeffs_needed) {
00279         
00280           // recognize Huffman codeword...
00281           huffman_leaf_node = consumeHuffmanCodeword(Huffman_AC_Roots[i]);
00282           if(!huffman_leaf_node) {
00283             BackEnd->errorEncountered();
00284             return;
00285           } 
00286           
00287           // check for EOB...
00288           if(huffman_leaf_node->Value == 0x00) {
00289             while(ac_coeffs_needed) {   // zero out the remaining matrix cells 
00290               coeff_buffer[ZigZagMap[coeff_i]] = 0;
00291               coeff_i++;
00292               ac_coeffs_needed--;
00293             }
00294             continue;   // ac_coeffs_needed is 0
00295           }
00296           
00297           // deal with additional bits to be read for this coeff...
00298           additional_bit_num = (int)(  (unsigned int)huffman_leaf_node->Value
00299                                      & (unsigned int)0x0f);                            
00300           if(additional_bit_num) {
00301             if(consumeAdditionalBits(additional_bit_num)) {
00302               BackEnd->errorEncountered();
00303               return;
00304             }
00305           }
00306           else
00307             CoeffInAdditionalBits = 0;
00308           
00309           // deal with AC coeffs to output and check break condition...
00310           ac_coeffs_to_output = huffman_leaf_node->Value/16 + 1;
00311           if(ac_coeffs_to_output > ac_coeffs_needed) {
00312             mxcpc::sendStatusMsg("too many AC coeffs!");
00313             BackEnd->errorEncountered();
00314             return;
00315           }
00316           for(j = 0; j < ac_coeffs_to_output-1; j++) {   // fill zeroes...
00317             coeff_buffer[ZigZagMap[coeff_i]] = 0;
00318             coeff_i++;
00319           }
00320           coeff_buffer[ZigZagMap[coeff_i]] = CoeffInAdditionalBits;
00321           coeff_i++;
00322           if(coeff_i > 64) {
00323             mxcpc::sendStatusMsg("coeff buffer overflow!");
00324             BackEnd->errorEncountered();
00325             return;
00326           }
00327           
00328           ac_coeffs_needed -= ac_coeffs_to_output;
00329         }     
00330         
00331         // we have all coefficients for this 8x8 coeff block
00332                                            
00333         // perform dequantization...
00334         src_ptr  = quantization_table_ptrs[i];
00335         dest_ptr = coeff_buffer;
00336         j = 64;
00337         while(j) {
00338           *dest_ptr++ = *dest_ptr * *src_ptr++;
00339           j--;
00340         }
00341         
00342         // perform inverse discrete cosine transform...
00343         //   (using code cunningly ripped from da internet...)
00344         idct((short *)coeff_buffer);  
00345                 
00346         // perform level shift...
00347         dest_ptr = coeff_buffer;
00348         j = 64;
00349         while(j) {
00350           mxcpc::clamp_s16(dest_ptr, -128, 127);
00351           *dest_ptr++ += (mxcpc::s16)128; 
00352           j--;
00353         }
00354                 
00355       }
00356       
00357       // got all 6 sub-MCUs
00358       
00359       // --- finally negotiate with backend and write decoded pixel data... ---
00360       //     (we're doing the colorspace conversion on the fly)
00361       
00362       BackEnd->provideVideoTilePixelTarget(x, y, &pixel_target, &target_row_stepping);
00363       target_ptr = (unsigned char *)pixel_target;
00364       
00365       for(jj = 0; jj < 16; jj++) {
00366         for(ii = 0; ii < 16; ii++) {
00367         
00368           // cunningly, shiftingly, retrieve YUV color values...
00369           color_y = (int)(*(&coeff_buffers[0][0]
00370                              + ((((jj>>3)<<1) + (ii>>3)) << 6)
00371                              + ((jj & 0x07) << 3)
00372                              + (ii & 0x07)
00373                            )
00374                          );
00375           color_u = (int)(*(coeff_buffers[4]
00376                              + ((jj>>1) << 3)
00377                              + (ii>>1)
00378                            )
00379                          ) - 128;
00380           color_v = (int)(*(coeff_buffers[5]
00381                              + ((jj>>1) << 3)
00382                              + (ii >> 1)
00383                            )
00384                          ) - 128;
00385                                   
00386           // the coefficients used here result from conversion to our 
00387           // fixed-point integer arithmetic situation and consequently are 
00388           // unlikely to show up in any literature consulted...
00389           color_r = ((color_y<<10)                + 1167*color_v) >> 10;
00390           color_g = ((color_y<<10) -  403*color_u -  595*color_v) >> 10;
00391           color_b = ((color_y<<10) + 2081*color_u               ) >> 10;
00392           
00393           mxcpc::clamp_int(&color_r, 0, 255);
00394           mxcpc::clamp_int(&color_g, 0, 255);
00395           mxcpc::clamp_int(&color_b, 0, 255);
00396           
00397           *target_ptr++ = color_r;
00398           *target_ptr++ = color_g;
00399           *target_ptr++ = color_b;
00400         }
00401         
00402         target_ptr += target_row_stepping*4;
00403       }
00404       
00405       BackEnd->videoTileReceived();
00406     } 
00407     
00408     tilebits_left--;
00409   }
00410   
00411 }
00412 
00413 
00414 
00415 // ---------- IDCT code -------------------------------------------------------
00416 
00417 #define W1 2841
00418 #define W2 2676 
00419 #define W3 2408 
00420 #define W5 1609 
00421 #define W6 1108 
00422 #define W7 565  
00423 
00424 
00425 void mxcpcFramewiseMxPEGScanDecoderSoftwareOnly::idctrow(short *blk) {
00426 
00427   int x0, x1, x2, x3, x4, x5, x6, x7, x8;
00428 
00429   /* shortcut */
00430 
00431   if (!((x1 = blk[4]<<11) | (x2 = blk[6]) | (x3 = blk[2]) |
00432       (x4 = blk[1]) | (x5 = blk[7]) | (x6 = blk[5]) | (x7 = blk[3]))) {
00433 
00434     blk[0]=blk[1]=blk[2]=blk[3]=blk[4]=blk[5]=blk[6]=blk[7]=blk[0]<<3;
00435     return;
00436   }
00437 
00438   x0 = (blk[0]<<11) + 128; /* for proper rounding in the fourth stage */
00439 
00440   /* first stage */
00441   x8 = W7*(x4+x5);
00442   x4 = x8 + (W1-W7)*x4;
00443   x5 = x8 - (W1+W7)*x5;
00444   x8 = W3*(x6+x7);
00445   x6 = x8 - (W3-W5)*x6;
00446   x7 = x8 - (W3+W5)*x7;
00447 
00448   /* second stage */
00449   x8 = x0 + x1;
00450   x0 -= x1;
00451   x1 = W6*(x3+x2);
00452   x2 = x1 - (W2+W6)*x2;
00453   x3 = x1 + (W2-W6)*x3;
00454   x1 = x4 + x6;
00455   x4 -= x6;
00456   x6 = x5 + x7;
00457   x5 -= x7;
00458 
00459   /* third stage */
00460   x7 = x8 + x3;
00461   x8 -= x3;
00462   x3 = x0 + x2;
00463   x0 -= x2;
00464   x2 = (181*(x4+x5)+128)>>8;
00465   x4 = (181*(x4-x5)+128)>>8;
00466 
00467   /* fourth stage */
00468   blk[0] = (x7+x1)>>8;  
00469   blk[1] = (x3+x2)>>8;
00470   blk[2] = (x0+x4)>>8;
00471   blk[3] = (x8+x6)>>8;
00472   blk[4] = (x8-x6)>>8;
00473   blk[5] = (x0-x4)>>8;
00474   blk[6] = (x3-x2)>>8;
00475   blk[7] = (x7-x1)>>8;
00476 }
00477 
00478 
00479 void mxcpcFramewiseMxPEGScanDecoderSoftwareOnly::idctcol(short *blk) {
00480 
00481   int x0, x1, x2, x3, x4, x5, x6, x7, x8;
00482 
00483   if (!((x1 = (blk[8*4]<<8)) | (x2 = blk[8*6]) | (x3 = blk[8*2]) |
00484       (x4 = blk[8*1]) | (x5 = blk[8*7]) | (x6 = blk[8*5]) | (x7 = blk[8*3]))) {
00485       
00486     blk[8*0]=blk[8*1]=blk[8*2]=blk[8*3]=blk[8*4]=blk[8*5]=blk[8*6]=blk[8*7]
00487      = iclp[(blk[8*0]+32)>>6];
00488 
00489     return;
00490   }
00491 
00492   x0 = (blk[8*0]<<8) + 8192;
00493 
00494   /* first stage */
00495   x8 = W7*(x4+x5) + 4;
00496   x4 = (x8+(W1-W7)*x4)>>3;
00497   x5 = (x8-(W1+W7)*x5)>>3;
00498   x8 = W3*(x6+x7) + 4;
00499   x6 = (x8-(W3-W5)*x6)>>3;
00500   x7 = (x8-(W3+W5)*x7)>>3;
00501 
00502   /* second stage */
00503   x8 = x0 + x1;
00504   x0 -= x1;
00505   x1 = W6*(x3+x2) + 4;
00506   x2 = (x1-(W2+W6)*x2)>>3;
00507   x3 = (x1+(W2-W6)*x3)>>3;
00508   x1 = x4 + x6;
00509   x4 -= x6;
00510   x6 = x5 + x7;
00511   x5 -= x7;
00512 
00513   /* third stage */
00514   x7 = x8 + x3;
00515   x8 -= x3;
00516   x3 = x0 + x2;
00517   x0 -= x2;
00518   x2 = (181*(x4+x5)+128)>>8;
00519   x4 = (181*(x4-x5)+128)>>8;
00520 
00521   /* fourth stage */
00522   blk[8*0] = iclp[(x7+x1)>>14];
00523   blk[8*1] = iclp[(x3+x2)>>14];
00524   blk[8*2] = iclp[(x0+x4)>>14];
00525   blk[8*3] = iclp[(x8+x6)>>14];
00526   blk[8*4] = iclp[(x8-x6)>>14];
00527   blk[8*5] = iclp[(x0-x4)>>14];
00528   blk[8*6] = iclp[(x3-x2)>>14];
00529   blk[8*7] = iclp[(x7-x1)>>14];
00530 }
00531 
00532 
00533 void mxcpcFramewiseMxPEGScanDecoderSoftwareOnly::idct(short *block) {
00534 
00535   int i;
00536 
00537   for(i = 0; i < 8; i++) idctrow(block+8*i);
00538   for(i = 0; i < 8; i++) idctcol(block+i);
00539 }

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