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

mxcpcFramewiseMxPEGScanDecoderSoftwareOnly.cpp

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

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