Main Page | Namespace List | Compound List | File List | Compound Members | File Members

vld.cc

Go to the documentation of this file.
00001 /*--------------------------------------------------------------------
00002  *
00003  * (C) Copyright Koninklijke Philips Electronics NV 2006. 
00004  * All rights reserved. This software is licensed under the terms of
00005  * version 2.1 of the GNU Lesser General Public License as published 
00006  * by the Free Software Foundation. For licensing and warranty
00007  * information, see the file COPYING in the main directory.
00008  *
00009  *------------------------------------------------------------------*/
00010 
00011 #include "vld.h"
00012 #include <stdio.h>
00013 
00014 /*--------------------------------------*/
00015 /* private huffman.c defines and macros */
00016 /*--------------------------------------*/
00017 
00018 #define HUFF_EOB    0x00
00019 #define HUFF_ZRL    0xF0
00020 
00021 #define HUFF_ID(class, id)       (2*(class)+(id))
00022 
00023 #define DC_CLASS        0
00024 #define AC_CLASS        1
00025 
00026 VLD::VLD(
00027   const Id&     n, 
00028   In<Marker>&   markerIn,
00029   In<Bits>&   restartIntervalBitsIn,
00030   In<Bits>&   Cin,
00031   In<VYAimageDepth>&  imageDepthIn,
00032   In<VYAimageComponent>&  imageComponentIdIn,
00033   In<VYAimageH>&    imageHIn,
00034   In<VYAimageV>&    imageVIn,
00035   In<VYAimageDepth>&  scanDepthIn,
00036   In<VYAimageComponent>&  scanComponentIdIn,
00037   In<Bits>&   HuffmanTableIn,
00038   In<VYAid>&    HuffmanTableIdIn,
00039   Out<VYApixel>&    Cout)
00040 :
00041         Process(n),
00042         markerInP(    id("markerInP"),      markerIn),
00043         restartIntervalBitsInP( id("restartIntervalBitsInP"), restartIntervalBitsIn),
00044         CinP(     id("CinP"),       Cin),
00045         imageDepthInP(    id("imageDepthInP"),    imageDepthIn),
00046         imageComponentIdInP(  id("imageComponentIdInP"),  imageComponentIdIn),
00047         imageHInP(    id("imageHInP"),    imageHIn),
00048         imageVInP(    id("imageVInP"),    imageVIn),
00049         scanDepthInP(   id("scanDepthInP"),     scanDepthIn),
00050         scanComponentIdInP( id("scanComponentIdInP"),   scanComponentIdIn),
00051         HuffmanTableInP(  id("HuffmanTableInP"),    HuffmanTableIn),
00052         HuffmanTableIdInP(  id("HuffmanTableIdInP"),  HuffmanTableIdIn),
00053         CoutP(      id("CoutP"),      Cout)
00054 {
00055   window = 0;
00056   restartInterval = 0;
00057 }
00058 
00059 void VLD::abort()
00060 {
00061   printf("\n");
00062     printf("%s:\n", fullName());
00063   printf("\tERROR:\tAbnormal end of decompression process!\n");
00064   exit(1);
00065 }
00066 
00067 #define GLOB_SIZE   32
00068 /* number of HTable words sacrificed to bookkeeping */
00069 
00070 #define MAX_SIZE(group)   ((group)?384:64)
00071 /* Memory size of HTables */
00072 #define MAX_CELLS(group)  (MAX_SIZE(group) - GLOB_SIZE)
00073 /* Available cells, top of storage */
00074 
00075 /* for Huffman tree descent */
00076 /* lower 8 bits are for value/left son */
00077 
00078 #define GOOD_NODE_FLAG    0x100
00079 #define GOOD_LEAF_FLAG    0x200
00080 #define BAD_LEAF_FLAG   0x300
00081 #define SPECIAL_FLAG    0x000
00082 #define HUFF_FLAG_MSK   0x300
00083 
00084 #define HUFF_FLAG(c)    ((c) & HUFF_FLAG_MSK)
00085 #define HUFF_VALUE(c)   ((unsigned char)( (c) & (~HUFF_FLAG_MSK) ))
00086 
00087 /*--------------------------------------*/
00088 /* some static structures for storage */
00089 /*--------------------------------------*/
00090 
00091 static unsigned int DC_Table0[MAX_SIZE(DC_CLASS)],
00092     DC_Table1[MAX_SIZE(DC_CLASS)];
00093 
00094 static unsigned int AC_Table0[MAX_SIZE(AC_CLASS)],
00095     AC_Table1[MAX_SIZE(AC_CLASS)];
00096 
00097 static unsigned int    *HTable[4] = {
00098     &DC_Table0[0], &DC_Table1[0],
00099     &AC_Table0[0], &AC_Table1[0]
00100 };
00101 
00102 
00103 /*----------------------------------------------------------*/
00104 /* Loading of Huffman table, with leaves drop ability     */
00105 /*----------------------------------------------------------*/
00106 
00107 int VLD::load_huff_tables()
00108 {
00109   Bits aux;
00110   Bits c;
00111   int size, group, id;
00112   int LeavesN, NodesN, CellsN;
00113   int MaxDepth, i, k, done;
00114   int NextCellPt; /* where shall we put next cell */
00115   int NextLevelPt;  /* where shall node point to */
00116   unsigned int flag;
00117 
00118   size = get_size(); /* this is the tables' size */
00119 
00120   size -= 2;
00121 
00122   while(size>0) 
00123   {
00124           read(HuffmanTableInP, c);
00125     aux = c;
00126           group = first_quad(aux);  /* AC or DC */
00127           id = second_quad(aux);    /* table no */
00128           if (id>1) 
00129     {
00130                 printf("%s:\n\tERROR:\tBad HTable identity %d!\n",fullName(),id);
00131                 return -1;
00132           }
00133           id = HUFF_ID(group, id);
00134     #ifdef VERBOSE
00135       printf("%s:\n\tLoading Huffman Table %d\n", fullName(), id);
00136     #endif
00137           size--;
00138           CellsN = NodesN = 1;        /* the root one */
00139           LeavesN = 0;
00140 
00141           for(i=0; i<MAX_CELLS(group); i++)
00142     {
00143                 HTable[id][i] = SPECIAL_FLAG; /* secure memory with crash value */
00144     }
00145 
00146           /* first load the sizes of code elements */
00147     /* and compute contents of each tree level */
00148           /* Adress Content   */
00149           /* Top    Leaves 0  */
00150           /* Top-1  Nodes  0  */
00151           /* ...... .......   */
00152           /* Top-2k Leaves k  */
00153           /* Top-2k-1 Nodes  k  */
00154 
00155           MaxDepth = 0;
00156           for(i=0; i<16; i++) 
00157     {
00158                 read(HuffmanTableInP, c);
00159                 LeavesN = HTable[id][MAX_SIZE(group)-2*i-1] = c;
00160                 CellsN = 2*NodesN; /* nodes is old */
00161                 NodesN = HTable[id][MAX_SIZE(group)-2*i-2] = CellsN-LeavesN;
00162                 if (LeavesN) MaxDepth = i;
00163           }
00164           size-=16;
00165 
00166           /* build root at address 0, then deeper levels at */
00167           /* increasing addresses until MAX_CELLS reached */
00168 
00169           HTable[id][0] = 1 | GOOD_NODE_FLAG;   /* points to cell _2_ ! */
00170           /* we give up address one to keep left brothers on even adresses */
00171           NextCellPt = 2;
00172           i = 0;      /* this is actually length 1 */
00173 
00174           done = 0;
00175 
00176           while (i<= MaxDepth) 
00177     {
00178 
00179                 /* then load leaves for other levels */
00180                 LeavesN = HTable[id][MAX_SIZE(group)-2*i-1];
00181                 for(k = 0; k<LeavesN; k++) 
00182       {
00183                     if (!done) 
00184         {
00185                           read(HuffmanTableInP, c);
00186                           HTable[id][NextCellPt++] = c | GOOD_LEAF_FLAG;
00187                           if (NextCellPt >= MAX_CELLS(group)) 
00188           {
00189             done = 1;
00190             printf("%s:\n\tWARNING:\tTruncating Table at depth %d\n",fullName(), i+1);
00191                           }
00192                     } else {
00193                           read(HuffmanTableInP, c); /* throw it away, just to keep file sync */
00194                     }
00195                 }
00196                 size -= LeavesN;
00197 
00198                 if (done || (i == MaxDepth)) { i++; continue; }
00199                 /* skip useless node building */
00200 
00201                 /* then build nodes at that level */
00202                 NodesN = HTable[id][MAX_SIZE(group)-2*i-2];
00203     
00204                 NextLevelPt = NextCellPt+NodesN;
00205                 for(k = 0; k<NodesN; k++) 
00206       {
00207                     if (NextCellPt >= MAX_CELLS(group)) { done = 1; break; }
00208 
00209                     flag = ((NextLevelPt|1)>=MAX_CELLS(group))?BAD_LEAF_FLAG:GOOD_NODE_FLAG;
00210                     /* we OR by 1 to check even right brother within range */
00211                     HTable[id][NextCellPt++] = (NextLevelPt/2) | flag;
00212                     NextLevelPt += 2;
00213                 }
00214 
00215                 i++;  /* now for next level */
00216           } /* nothing left to read from file after maxdepth */
00217     #ifdef VERBOSE
00218       printf("%s:\n\tUsing %d words of table memory\n", fullName(), NextCellPt);
00219     #endif
00220       } /* loop on tables */
00221 
00222       /*-- this is useful for displaying the uploaded tree --*/
00223 /*       for(i=0; i<NextCellPt; i++) {
00224       switch (HUFF_FLAG(HTable[id][i])) {
00225       case GOOD_NODE_FLAG:
00226       printf("Cell %X: Node to %X and %X\n", i,
00227       HUFF_VALUE(HTable[id][i])*2,
00228       HUFF_VALUE(HTable[id][i])*2 +1);
00229       break;
00230       case GOOD_LEAF_FLAG:
00231       printf("Cell %X: Leaf with value %X\n", i,
00232       HUFF_VALUE(HTable[id][i]) );
00233       break;
00234       case SPECIAL_FLAG:
00235       printf("Cell %X: Special flag\n", i);
00236       break;
00237       case BAD_LEAF_FLAG:
00238       printf("Cell %X: Bad leaf\n", i);
00239       break;
00240       }
00241       }
00242 */
00243   return 0;
00244 }
00245 
00246 unsigned int VLD::get_size(void)
00247 {
00248   Bits    firstc;
00249   Bits    nextc;
00250   unsigned int  size;
00251 
00252   read(HuffmanTableInP, firstc);
00253   size = firstc;
00254   read(HuffmanTableInP, nextc);
00255   size = (size<<8) | nextc; /* big endian */
00256   
00257   return size;
00258 }
00259 
00260 void VLD::main()
00261 {
00262   VYAimageDepth   nrOfImageComponents;
00263   VYAimageComponent*  imageComponent;
00264   VYAimageH*    H;
00265   VYAimageV*    V;
00266   Marker      marker;
00267   unsigned int    numberOfMCU;
00268 
00269   read(markerInP, marker);
00270   while (marker != SOS_MK)
00271   {
00272     if (marker == DHT_MK)
00273     {
00274       load_huff_tables();
00275     } else
00276     if (marker == DRI_MK)
00277     {
00278       load_restart_interval();
00279     }
00280     read(markerInP, marker);
00281   }
00282 
00283   read(imageDepthInP, nrOfImageComponents);
00284 
00285   imageComponent = new VYAimageComponent[nrOfImageComponents];
00286   H = new VYAimageH[nrOfImageComponents];
00287   V = new VYAimageV[nrOfImageComponents];
00288   
00289   for(unsigned int i=0; i<nrOfImageComponents; i++)
00290   {
00291     read(imageComponentIdInP, imageComponent[i]);
00292     read(imageHInP, H[i]);
00293     read(imageVInP, V[i]);
00294   }
00295 
00296   while (true)
00297   {
00298     VYAimageDepth   nrOfScanComponents;
00299     VYAimageComponent*  scanComponentId;
00300     VYAid*      huffmanTableId;
00301     VYApixel*   prediction;
00302     
00303     read(scanDepthInP, nrOfScanComponents);
00304   
00305     scanComponentId = new VYAimageComponent[nrOfScanComponents];
00306     huffmanTableId = new VYAid[nrOfScanComponents];
00307     prediction = new VYApixel[nrOfScanComponents];
00308     
00309     for(unsigned int i=0; i<nrOfScanComponents; i++)
00310     {
00311       read(scanComponentIdInP, scanComponentId[i]);
00312       read(HuffmanTableIdInP, huffmanTableId[i]);
00313       prediction[i] = 0;
00314     }
00315 
00316     bit_count = 0; 
00317     numberOfMCU = 0;
00318     while (true)
00319     {
00320       for(unsigned int i=0; i<nrOfScanComponents; i++)
00321       {
00322         int     hi = H[scanComponentId[i]];
00323         int     vi = V[scanComponentId[i]];
00324         VYApixel  value;
00325         unsigned int  cat, run;
00326               unsigned char   DC_HT = first_quad(huffmanTableId[i]);
00327               unsigned char   AC_HT = second_quad(huffmanTableId[i]);
00328         unsigned char   symbol;
00329             
00330         for(int j=0; j<hi; j++)
00331         {
00332           for(int k=0; k<vi; k++)
00333           {
00334             // decode DC coefficient
00335             symbol = get_symbol(HUFF_ID(DC_CLASS, DC_HT));
00336             value = reformat(get_bits(symbol), symbol);
00337             value += prediction[scanComponentId[i]];
00338             write(CoutP, value);
00339             prediction[scanComponentId[i]] = value;
00340 
00341             // decode AC coefficients
00342             unsigned int l;
00343             unsigned int m;
00344             for (l=1; l<64; l++)
00345             {
00346               symbol = get_symbol(HUFF_ID(AC_CLASS, AC_HT));
00347               if (symbol == HUFF_EOB) break;
00348               if (symbol == HUFF_ZRL) 
00349               { 
00350                 for (m=l; m<=l+15; m++)
00351                 {
00352                   write(CoutP, (VYApixel)0);
00353                 }
00354                 l += 15; 
00355               } else {
00356                 cat = symbol & 15;
00357                 run = (symbol>>4) & 15;
00358                 for (m=l; m<l+run; m++)
00359                 {
00360                   write(CoutP, (VYApixel)0);
00361                 }
00362                 l += run;
00363                 value = reformat(get_bits(cat), cat);
00364                   write(CoutP, value);
00365               }
00366             }
00367             for (m=l; m<64; m++)
00368             {
00369               write(CoutP, (VYApixel)0);
00370             }
00371           }
00372         }
00373       }
00374       numberOfMCU++;
00375       
00376       if (numberOfMCU == restartInterval)
00377       { 
00378         Bits aux;
00379         read(CinP, aux);
00380         if (aux == 0xFF)
00381         {
00382           read(CinP, aux);    
00383                             if (RST_MK(0xFF00 | aux))
00384           {
00385             bit_count = 0;
00386             for(unsigned int i=0; i<nrOfScanComponents; i++)
00387             {
00388               prediction[i] = 0;
00389             }
00390             numberOfMCU = 0;
00391           } else {
00392                                   printf("%s:\n\tERROR:\tDid not find restart marker!\n",fullName());
00393             abort();
00394           }
00395         }
00396         
00397       }
00398     }
00399     delete [] scanComponentId;
00400     delete [] huffmanTableId;
00401     delete [] prediction;
00402   }
00403       
00404   delete [] imageComponent;
00405   delete [] H;
00406   delete [] V;    
00407 }
00408 
00409 
00410 /* transform JPEG number format into usual 2's complement format */
00411 VYApixel VLD::reformat(unsigned long S, int good)
00412 {
00413       unsigned int St;
00414 
00415       if (!good) 
00416     return 0;
00417       St = 1 << (good-1); /* 2^(good-1) */
00418       if (S < St) 
00419     return (S+1+((-1)<<good));
00420       else 
00421     return S;
00422 }
00423 
00424 /*---------------------------------------------------------------------*/
00425 
00426 int VLD::get_bits(int number)
00427 {
00428   int i, newbit;
00429   int result = 0;
00430   Bits wwindow;
00431   Bits aux;
00432   
00433   if (!number)
00434     return 0;
00435   for (i=0; i<number; i++) 
00436   {
00437           if (bit_count == 0) 
00438     {
00439                 read(CinP, wwindow);
00440                 if (wwindow == 0xFF)  
00441       {
00442                     read(CinP, aux);
00443                     switch (aux) 
00444         { /* skip stuffer 0 byte */
00445                         case EOF:
00446                         case 0xFF:
00447                             printf("%s:\n\tERROR:\tRan out of bit stream\n",fullName());
00448                             abort();
00449                             break;
00450           
00451                         case 0x00:
00452 //                            stuffers++;
00453                             break;
00454           
00455                         default:
00456                             if (RST_MK(0xFF00 | aux))
00457                                   printf("%s:\n\tERROR:\tSpontaneously found restart marker!\n",fullName());
00458                             printf("\tERROR:\tLost sync in bit stream\n");
00459                             abort();
00460                             break;
00461                     }
00462                 }
00463                 bit_count = 8;
00464           } else {
00465                 wwindow = window;
00466     }
00467           newbit = (wwindow>>7) & 1;
00468           window = wwindow << 1;
00469           bit_count--;
00470           result = (result << 1) | newbit;
00471       }
00472   return result;
00473 }
00474 
00475 unsigned char VLD::get_symbol(int select)
00476 {
00477   int cellPt;
00478 
00479   cellPt = 0; /* this is the root cell */
00480 
00481   while(HUFF_FLAG(HTable[select][cellPt]) == GOOD_NODE_FLAG)
00482   {
00483     cellPt = get_bits(1) | (HUFF_VALUE(HTable[select][cellPt])<<1);
00484   }
00485   
00486       switch (HUFF_FLAG(HTable[select][cellPt])) 
00487   {
00488         case SPECIAL_FLAG:
00489               printf("%s:\n\tERROR:\tFound forbidden Huffman symbol !\n", fullName());
00490               abort();
00491               break;
00492 
00493         case GOOD_LEAF_FLAG:
00494               return HUFF_VALUE(HTable[select][cellPt]);
00495               break;
00496 
00497         case BAD_LEAF_FLAG:
00498               /* how do we fall back in case of truncated tree ? */
00499               /* suggest we send an EOB and warn */
00500               printf("%s:\n\tWARNING:\tFalling out of truncated tree !\n", fullName());
00501               return 0;
00502               break;
00503 
00504         default:
00505               break;
00506   }
00507   return 0;
00508 }
00509 
00510 void VLD::load_restart_interval()
00511 {
00512   Bits firstc;
00513   Bits nextc;
00514 
00515   read(restartIntervalBitsInP, firstc);
00516   restartInterval = firstc;
00517   read(restartIntervalBitsInP, nextc);
00518   restartInterval = (restartInterval<<8) | nextc; // big endian
00519 }

Generated on Wed Feb 15 14:52:45 2006 for jpegdec by doxygen 1.3.2