| 1 | //////////////////////////////////////////////////////////////////////////////////////// | 
|---|
| 2 | // File   : vld.c   | 
|---|
| 3 | // Date   : octobre 2015 | 
|---|
| 4 | // author : Alain Greiner | 
|---|
| 5 | //////////////////////////////////////////////////////////////////////////////////////// | 
|---|
| 6 | // This file define the code of the VLD (Variable Length Decoder) thread for the MJPEG | 
|---|
| 7 | // application. This function makes the analysis of the variable length bit stream,  | 
|---|
| 8 | // resulting from the Huffman entropy coder. | 
|---|
| 9 | // For each image: | 
|---|
| 10 | // - It read the Huffman Table parameters from the <in_huff> MWMR channel. | 
|---|
| 11 | // - It read the bit stream from the <in_data> MWMR channel. | 
|---|
| 12 | // - It write output pixels (two bytes per pixel) to the <out> MWMR channel. | 
|---|
| 13 | // It uses MWMR_BUFIO buffers for the input channels, but not for the output channel. | 
|---|
| 14 | //////////////////////////////////////////////////////////////////////////////////////// | 
|---|
| 15 |  | 
|---|
| 16 | #include <stdio.h> | 
|---|
| 17 | #include <stdint.h> | 
|---|
| 18 | #include <mwmr_channel.h> | 
|---|
| 19 | #include "mjpeg.h" | 
|---|
| 20 |  | 
|---|
| 21 | #define HUFF_EOB               0x00 | 
|---|
| 22 | #define HUFF_ZRL               0xF0 | 
|---|
| 23 |  | 
|---|
| 24 | // macro to use a shared TTY | 
|---|
| 25 | #define PRINTF(...)    lock_acquire( &tty_lock ); \ | 
|---|
| 26 |                        giet_tty_printf(__VA_ARGS__);  \ | 
|---|
| 27 |                        lock_release( &tty_lock ); | 
|---|
| 28 |  | 
|---|
| 29 | //////////////////////////////////////////////////////////////////////////////////////// | 
|---|
| 30 | // bitreader_t : data structure and access functions to analyse a bit-stream. | 
|---|
| 31 | //////////////////////////////////////////////////////////////////////////////////////// | 
|---|
| 32 |  | 
|---|
| 33 | typedef struct  | 
|---|
| 34 | { | 
|---|
| 35 |     mwmr_bufio_t*     bufio;         // associated bufio  | 
|---|
| 36 |     uint8_t           current;       // temporary buffer of one byte | 
|---|
| 37 |     uint8_t           available;     // number of bits to read in current byte | 
|---|
| 38 | } bitreader_t; | 
|---|
| 39 |  | 
|---|
| 40 | //////////////////////////////////////////////////// | 
|---|
| 41 | // returns <number> bits from the associated bufio. | 
|---|
| 42 | //////////////////////////////////////////////////// | 
|---|
| 43 | uint32_t bitreader_get( bitreader_t*  stream, | 
|---|
| 44 |                         uint32_t      number ) | 
|---|
| 45 | { | 
|---|
| 46 |     uint32_t  ret = 0; | 
|---|
| 47 |  | 
|---|
| 48 |     giet_pthread_assert( (number <= 16) , | 
|---|
| 49 |     "ERROR in bitreader_get() : illegal number argument"); | 
|---|
| 50 |  | 
|---|
| 51 |     if (stream->available)  | 
|---|
| 52 |     { | 
|---|
| 53 |         stream->current &= (1<<stream->available)-1; | 
|---|
| 54 |     } | 
|---|
| 55 |  | 
|---|
| 56 |     while (number)  | 
|---|
| 57 |     { | 
|---|
| 58 |         if ( stream->available == 0 )  // current buffer empty => refill | 
|---|
| 59 |         { | 
|---|
| 60 |             stream->current = mwmr_bufio_read_byte( stream->bufio ); | 
|---|
| 61 |             stream->available = 8; | 
|---|
| 62 |         } | 
|---|
| 63 |         if ( number == stream->available )  | 
|---|
| 64 |         { | 
|---|
| 65 |             stream->available = 0; | 
|---|
| 66 |             ret = (ret<<number) | stream->current; | 
|---|
| 67 |             break; | 
|---|
| 68 |         } | 
|---|
| 69 |         if ( number < stream->available )  | 
|---|
| 70 |         { | 
|---|
| 71 |             ret = (ret<<number) | (stream->current>>(stream->available-number)); | 
|---|
| 72 |             stream->available -= number; | 
|---|
| 73 |             break; | 
|---|
| 74 |         } | 
|---|
| 75 |         if ( number > stream->available )  | 
|---|
| 76 |         { | 
|---|
| 77 |             ret = (ret<<stream->available) | stream->current; | 
|---|
| 78 |             number -= stream->available; | 
|---|
| 79 |             stream->available = 0; | 
|---|
| 80 |         } | 
|---|
| 81 |     } | 
|---|
| 82 |  | 
|---|
| 83 |     return ret; | 
|---|
| 84 | } | 
|---|
| 85 |  | 
|---|
| 86 | /////////////////////////////////////////////// | 
|---|
| 87 | // returns one bit from the associated bufio. | 
|---|
| 88 | /////////////////////////////////////////////// | 
|---|
| 89 | uint8_t bitreader_get_one( bitreader_t*  stream ) | 
|---|
| 90 | { | 
|---|
| 91 |     if ( stream->available == 0 ) // current buffer empty => refill | 
|---|
| 92 |     { | 
|---|
| 93 |         stream->current = mwmr_bufio_read_byte( stream->bufio ); | 
|---|
| 94 |         stream->available = 7; | 
|---|
| 95 |     } | 
|---|
| 96 |     else | 
|---|
| 97 |     { | 
|---|
| 98 |         --(stream->available); | 
|---|
| 99 |     } | 
|---|
| 100 |  | 
|---|
| 101 |     uint32_t tmp = 1<<(stream->available); | 
|---|
| 102 |  | 
|---|
| 103 |     return ( !!(stream->current & tmp) ); | 
|---|
| 104 | } | 
|---|
| 105 |  | 
|---|
| 106 | ///////////////////////////////////////// | 
|---|
| 107 | void bitreader_init( bitreader_t*   stream, | 
|---|
| 108 |                      mwmr_bufio_t*  bufio ) | 
|---|
| 109 | { | 
|---|
| 110 |     stream->available = 0; | 
|---|
| 111 |     stream->current   = 0; | 
|---|
| 112 |     stream->bufio     = bufio; | 
|---|
| 113 | } | 
|---|
| 114 |  | 
|---|
| 115 | ////////////////////////////////////////////////////////////////////////////////////////// | 
|---|
| 116 | //       data structures and access functions for the Huffman tables | 
|---|
| 117 | // - We have two tables (DC and AC), and 16 possible code lengths (from 1 to 16). | 
|---|
| 118 | // - DC_Table[12]  : 12 possible symbol values for the DC Table. | 
|---|
| 119 | // - AC_Table[162] : 162 possible symbol values for the AC Table. | 
|---|
| 120 | // - ValPtr[t][l]  : index in Table <t> for the first code of length <l> | 
|---|
| 121 | // - MinCode[t][l] : min value for codes of length <l>  | 
|---|
| 122 | // - MaxCode[t][l] : max value for codes of length <l> / (-1) if no code of length <l>  | 
|---|
| 123 | ////////////////////////////////////////////////////////////////////////////////////////// | 
|---|
| 124 |  | 
|---|
| 125 | typedef struct  | 
|---|
| 126 | { | 
|---|
| 127 |     uint8_t*  HT[2];                  // HT[0] == DC_Table / HT[1] == AC_Table  | 
|---|
| 128 |     int32_t   MinCode[2][16];         // two types of tables / 16 code lengths | 
|---|
| 129 |     int32_t   MaxCode[2][16];         // two types of tables / 16 code lengths | 
|---|
| 130 |     int32_t   ValPtr[2][16];          // two types of tables / 16 code lengths | 
|---|
| 131 |     uint8_t   DC_Table[12];           // at most 12 values | 
|---|
| 132 |     uint8_t   AC_Table[162];          // at most 162 values | 
|---|
| 133 | } huff_tables_t; | 
|---|
| 134 |  | 
|---|
| 135 | ///////////////////////////////////////////// | 
|---|
| 136 | void huff_tables_init( huff_tables_t*  huff ) | 
|---|
| 137 | { | 
|---|
| 138 |     int32_t i, j; | 
|---|
| 139 |  | 
|---|
| 140 |     for ( j=0; j<16; ++j )  | 
|---|
| 141 |     { | 
|---|
| 142 |         for ( i=0; i<2; ++i )  | 
|---|
| 143 |         { | 
|---|
| 144 |             huff->MinCode[i][j] = 0; | 
|---|
| 145 |             huff->MaxCode[i][j] = 0; | 
|---|
| 146 |             huff->ValPtr[i][j] = 0; | 
|---|
| 147 |         } | 
|---|
| 148 |     } | 
|---|
| 149 |  | 
|---|
| 150 |     for ( i=0; i<14; ++i )    huff->DC_Table[i] = 0; | 
|---|
| 151 |  | 
|---|
| 152 |     for ( i=0; i<162; ++i )   huff->AC_Table[i] = 0; | 
|---|
| 153 |  | 
|---|
| 154 |     huff->HT[0] = huff->DC_Table; | 
|---|
| 155 |     huff->HT[1] = huff->AC_Table; | 
|---|
| 156 | } | 
|---|
| 157 |  | 
|---|
| 158 | //////////////////////////////////////////// | 
|---|
| 159 | void huff_tables_dump( huff_tables_t* huff, | 
|---|
| 160 |                        uint32_t       is_ac ) | 
|---|
| 161 | { | 
|---|
| 162 |     uint32_t j; | 
|---|
| 163 |     int32_t  code; | 
|---|
| 164 |  | 
|---|
| 165 |     uint32_t max  = ( is_ac ) ? 162 : 12; | 
|---|
| 166 |     uint32_t type = ( is_ac ) ? 1 : 0; | 
|---|
| 167 |  | 
|---|
| 168 |     if ( is_ac ) { PRINTF("\n AC Huffman Table\n\n") } | 
|---|
| 169 |     else         { PRINTF("\n DC Huffman Table\n\n") } | 
|---|
| 170 |  | 
|---|
| 171 |     for ( j = 0; j < 16; j++ ) // j = code_length - 1 | 
|---|
| 172 |     { | 
|---|
| 173 |         PRINTF(" length = %d / mincode = %x / maxcode = %x / valptr = %d\n", | 
|---|
| 174 |         j+1 , huff->MinCode[type][j] , huff->MaxCode[type][j] , huff->ValPtr[type][j] ) | 
|---|
| 175 |     } | 
|---|
| 176 |  | 
|---|
| 177 |     PRINTF("\n") | 
|---|
| 178 |  | 
|---|
| 179 |     for ( j = 0 ; j < 16 ; j++ )  // j == code_length - 1 | 
|---|
| 180 |     { | 
|---|
| 181 |         for ( code = huff->MinCode[type][j] ; code <= huff->MaxCode[type][j] ; code++ ) | 
|---|
| 182 |         { | 
|---|
| 183 |             uint32_t index = huff->ValPtr[type][j] + code - huff->MinCode[type][j]; | 
|---|
| 184 |  | 
|---|
| 185 |             giet_pthread_assert( (index<max) , "ERROR in huff_tables_dump() : overflow"); | 
|---|
| 186 |  | 
|---|
| 187 |             PRINTF(" Symbol[%d] = %x / code[%d] = %x\n",  | 
|---|
| 188 |             index , huff->HT[type][index] , index , code ) | 
|---|
| 189 |         } | 
|---|
| 190 |     } | 
|---|
| 191 |   | 
|---|
| 192 |     PRINTF("\n") | 
|---|
| 193 | } | 
|---|
| 194 |  | 
|---|
| 195 | ///////////////////////////////////////////// | 
|---|
| 196 | void huff_tables_load( uint32_t        index, | 
|---|
| 197 |                        huff_tables_t*  huff, | 
|---|
| 198 |                        mwmr_bufio_t*   bufio ) | 
|---|
| 199 | { | 
|---|
| 200 |     uint8_t    byte; | 
|---|
| 201 |     uint32_t   is_ac;          // AC Table if non zero | 
|---|
| 202 |  | 
|---|
| 203 |     uint8_t    LeavesN;        // number of codes of length N (from 1 to 16) | 
|---|
| 204 |     uint8_t    LeavesT;        // cumulated total number of codes | 
|---|
| 205 |     uint32_t   AuxCode;        // used to compute code values | 
|---|
| 206 |  | 
|---|
| 207 |     // read length (2 bytes) from bufio | 
|---|
| 208 |     uint32_t length = (uint32_t)mwmr_bufio_read_byte( bufio ); | 
|---|
| 209 |     length = (length<<8) | mwmr_bufio_read_byte( bufio ); | 
|---|
| 210 |  | 
|---|
| 211 |     // read Tc/Th  (1 byte) from bufio  | 
|---|
| 212 |     // Th must be null, Tc must be 0 or 1 | 
|---|
| 213 |     byte = mwmr_bufio_read_byte( bufio ); | 
|---|
| 214 |  | 
|---|
| 215 |     giet_pthread_assert( ((byte & 0xEF) == 0) , | 
|---|
| 216 |     "ERROR in huff_load_table() : non supported HT header"); | 
|---|
| 217 |  | 
|---|
| 218 |     if (byte == 0) is_ac = 0; | 
|---|
| 219 |     else           is_ac = 1; | 
|---|
| 220 |   | 
|---|
| 221 |     uint32_t max_size = ( is_ac ) ? 162 : 12; | 
|---|
| 222 |  | 
|---|
| 223 |     // get the 16 LeavesN values from bufio | 
|---|
| 224 |     uint32_t   i; | 
|---|
| 225 |     LeavesT = 0; | 
|---|
| 226 |     AuxCode = 0; | 
|---|
| 227 |     for ( i=0; i<16; i++ )  | 
|---|
| 228 |     { | 
|---|
| 229 |         // read one byte from bufio | 
|---|
| 230 |         LeavesN = mwmr_bufio_read_byte( bufio ); | 
|---|
| 231 |  | 
|---|
| 232 |         huff->ValPtr[is_ac][i] = LeavesT; | 
|---|
| 233 |         huff->MinCode[is_ac][i] = AuxCode<<1; | 
|---|
| 234 |         AuxCode = huff->MinCode[is_ac][i] + LeavesN; | 
|---|
| 235 |         huff->MaxCode[is_ac][i] = (LeavesN) ? (AuxCode - 1) : (-1); | 
|---|
| 236 |         LeavesT += LeavesN; | 
|---|
| 237 |     } | 
|---|
| 238 |  | 
|---|
| 239 |     giet_pthread_assert( (length ==  19 + LeavesT) , | 
|---|
| 240 |     "ERROR in huff_load_table() : illegal HT length"); | 
|---|
| 241 |  | 
|---|
| 242 |     giet_pthread_assert( (LeavesT <= max_size) ,  | 
|---|
| 243 |     "ERROR in huff_load_table() : too much symbols"); | 
|---|
| 244 |  | 
|---|
| 245 |     // get the symbol values from bufio (one byte per symbol) | 
|---|
| 246 |     // complete table with zero values if LeavesT < max_size | 
|---|
| 247 |     for ( i=0 ; i<max_size ; ++i )  | 
|---|
| 248 |            { | 
|---|
| 249 |         if ( i < LeavesT )  huff->HT[is_ac][i] = mwmr_bufio_read_byte( bufio ); | 
|---|
| 250 |         else                huff->HT[is_ac][i] = 0;  | 
|---|
| 251 |     } | 
|---|
| 252 |  | 
|---|
| 253 |     // align bufio pointer on next item | 
|---|
| 254 |     mwmr_bufio_align( bufio ); | 
|---|
| 255 |      | 
|---|
| 256 | #if (DEBUG_VLD > 3)  | 
|---|
| 257 | if ( (index == DEBUG_CLUSTER_INDEX) || (DEBUG_CLUSTER_INDEX == 0XFFFFFFFF) ) | 
|---|
| 258 | huff_tables_dump( huff , is_ac ); | 
|---|
| 259 | #endif | 
|---|
| 260 |  | 
|---|
| 261 | }  // end huff_tables_load() | 
|---|
| 262 |  | 
|---|
| 263 | ////////////////////////////////////////////////////////// | 
|---|
| 264 | // extract a symbol (8 bits) from an Huffman encoded | 
|---|
| 265 | // bit-stream, using the specified huffman table  | 
|---|
| 266 | ///////////////////////////////////////////////////////// | 
|---|
| 267 | int8_t huff_get_symbol( bitreader_t*     stream, | 
|---|
| 268 |                         huff_tables_t*   huff, | 
|---|
| 269 |                         int32_t          select )   // DC if zero / AC if non zero | 
|---|
| 270 | { | 
|---|
| 271 |     uint32_t length; | 
|---|
| 272 |     int32_t  code = 0; | 
|---|
| 273 |  | 
|---|
| 274 |     uint32_t is_ac    = (select) ? 1 : 0; | 
|---|
| 275 |     uint32_t max_size = (select) ? 162 : 12; | 
|---|
| 276 |      | 
|---|
| 277 |     for ( length = 0 ; length < 16 ; ++length )  | 
|---|
| 278 |     { | 
|---|
| 279 |         code = (code<<1) | bitreader_get_one( stream ); | 
|---|
| 280 |         if ( code <= huff->MaxCode[select][length] )   break; | 
|---|
| 281 |     } | 
|---|
| 282 |  | 
|---|
| 283 |     uint32_t index = huff->ValPtr[is_ac][length] + code - huff->MinCode[is_ac][length]; | 
|---|
| 284 |  | 
|---|
| 285 |     giet_pthread_assert( (index <= max_size) , | 
|---|
| 286 |     "ERROR in huff_get_symbol() : Huffman table overflow"); | 
|---|
| 287 |  | 
|---|
| 288 |     return huff->HT[is_ac][index]; | 
|---|
| 289 | }  | 
|---|
| 290 |  | 
|---|
| 291 | /////////////////////////////////////////////////////////////////////////// | 
|---|
| 292 | // transform JPEG encoded positive/negative value coded as ( S , nbits ) | 
|---|
| 293 | // to a standard 16 bits 2's complement number (int16_t). | 
|---|
| 294 | // - nbits is the magnitude (number of significant bits in S | 
|---|
| 295 | // - most significant bit in S is 0 for positive / 1 for negative | 
|---|
| 296 | // - other bits in S define the value in 2**(nbits-1) possible values | 
|---|
| 297 | /////////////////////////////////////////////////////////////////////////// | 
|---|
| 298 | static int16_t reformat( uint32_t S , int32_t nbits ) | 
|---|
| 299 | { | 
|---|
| 300 |     uint32_t  ext; | 
|---|
| 301 |     uint32_t  sign; | 
|---|
| 302 |     int16_t   value; | 
|---|
| 303 |  | 
|---|
| 304 |     if ( nbits == 0 )  return 0; | 
|---|
| 305 |  | 
|---|
| 306 |     sign = !( (1 << (nbits - 1)) & S ); | 
|---|
| 307 |     ext = 0 - (sign << nbits); | 
|---|
| 308 |     value = (S | ext) + sign; | 
|---|
| 309 |  | 
|---|
| 310 |     return value; | 
|---|
| 311 | } | 
|---|
| 312 |  | 
|---|
| 313 | //////////////////////////////////////////////////////// | 
|---|
| 314 | // unpack a 8*8 pixels block with 2 bytes per pixel | 
|---|
| 315 | ////////////////////////////////////////////////////////// | 
|---|
| 316 | static int16_t vld_unpack_block( uint32_t          index,     // cluster index | 
|---|
| 317 |                                  uint32_t          image,     // image index | 
|---|
| 318 |                                  uint32_t          block,     // block index | 
|---|
| 319 |                                  bitreader_t*      stream,    // input bit stream | 
|---|
| 320 |                                  mwmr_channel_t*   mwmr_out,  // output channel | 
|---|
| 321 |                                  huff_tables_t*    huff,      // Huffman Tables | 
|---|
| 322 |                                  int16_t           prev_dc )  // previous DC coef | 
|---|
| 323 | { | 
|---|
| 324 |     uint32_t temp; | 
|---|
| 325 |     uint32_t i; | 
|---|
| 326 |     uint32_t run; | 
|---|
| 327 |     uint32_t cat; | 
|---|
| 328 |     int32_t  value; | 
|---|
| 329 |     uint8_t  symbol; | 
|---|
| 330 |     int16_t  buf[64];       // buffer for the 64 resulting pixels (2 bytes per pixel) | 
|---|
| 331 |  | 
|---|
| 332 |     // set default values | 
|---|
| 333 |     for (i = 0; i < 64; i++) buf[i] = 0; | 
|---|
| 334 |  | 
|---|
| 335 |     // compute the DC coefficient | 
|---|
| 336 |     symbol   = huff_get_symbol( stream , huff , 0 );   // use DC Huffman Table | 
|---|
| 337 |  | 
|---|
| 338 |     temp     = bitreader_get( stream , symbol ); | 
|---|
| 339 |     value    = reformat( temp , symbol ); | 
|---|
| 340 |     buf[0]   = value + prev_dc; | 
|---|
| 341 |  | 
|---|
| 342 | #if (DEBUG_VLD > 2) | 
|---|
| 343 | if ( (index == DEBUG_CLUSTER_INDEX) || (DEBUG_CLUSTER_INDEX == 0XFFFFFFFF) ) | 
|---|
| 344 | { PRINTF("\nVLD[%d] : DC[0] = %d / reformat( %x , %d ) = %d\n", | 
|---|
| 345 |          index , buf[0], temp , symbol , value ) } | 
|---|
| 346 | #endif | 
|---|
| 347 |  | 
|---|
| 348 |     // compute the 63 AC coefficients | 
|---|
| 349 |     for (i = 1; i < 64; i++)  | 
|---|
| 350 |     { | 
|---|
| 351 |         symbol = huff_get_symbol( stream , huff , 1 );   // use AC Huffman Table | 
|---|
| 352 |  | 
|---|
| 353 |         // in case of HUFF_EOB symbol, all other pixels are zero | 
|---|
| 354 |         if ( symbol == HUFF_EOB ) | 
|---|
| 355 |         { | 
|---|
| 356 |  | 
|---|
| 357 | #if (DEBUG_VLD > 2) | 
|---|
| 358 | if ( (index == DEBUG_CLUSTER_INDEX) || (DEBUG_CLUSTER_INDEX == 0XFFFFFFFF) ) | 
|---|
| 359 | { PRINTF("\nVLD[%d] : EOB found at i = %d\n", index , i ) } | 
|---|
| 360 | #endif  | 
|---|
| 361 |             break; | 
|---|
| 362 |         } | 
|---|
| 363 |   | 
|---|
| 364 |         // in case of HUFF_ZRL symbol (0xF0) , 15 next pixels are zero | 
|---|
| 365 |         if (symbol == HUFF_ZRL)  | 
|---|
| 366 |         { | 
|---|
| 367 |             i += 15; | 
|---|
| 368 |             continue; | 
|---|
| 369 |         } | 
|---|
| 370 |  | 
|---|
| 371 |         cat = symbol & 0xf; | 
|---|
| 372 |         run = symbol >> 4; | 
|---|
| 373 |         i += run; | 
|---|
| 374 |  | 
|---|
| 375 |         temp   = bitreader_get (stream , cat ); | 
|---|
| 376 |         value  = reformat( temp , cat ); | 
|---|
| 377 |         buf[i] = value; | 
|---|
| 378 |  | 
|---|
| 379 | #if (DEBUG_VLD > 2) | 
|---|
| 380 | if ( (index == DEBUG_CLUSTER_INDEX) || (DEBUG_CLUSTER_INDEX == 0XFFFFFFFF) ) | 
|---|
| 381 | { PRINTF("\nVLD[%d] : AC[%d] = %d / reformat( %x , %d ) = %d\n", | 
|---|
| 382 |          index , i , buf[i] , temp , cat , value ) } | 
|---|
| 383 | #endif | 
|---|
| 384 |  | 
|---|
| 385 |     } | 
|---|
| 386 |  | 
|---|
| 387 |     // write one block to mwmr_out channel ( 2 bytes per pixel) | 
|---|
| 388 |     mwmr_write( mwmr_out, (uint32_t*)buf , 32 ); | 
|---|
| 389 |  | 
|---|
| 390 | #if (DEBUG_VLD > 1 ) | 
|---|
| 391 | if ( (index == DEBUG_CLUSTER_INDEX) || (DEBUG_CLUSTER_INDEX == 0XFFFFFFFF) ) | 
|---|
| 392 | { PRINTF("\nVLD[%d] completes block %d/%d in image %d\n" | 
|---|
| 393 |          "  %d  %d  %d  %d  %d  %d  %d  %d\n" | 
|---|
| 394 |          "  %d  %d  %d  %d  %d  %d  %d  %d\n" | 
|---|
| 395 |          "  %d  %d  %d  %d  %d  %d  %d  %d\n" | 
|---|
| 396 |          "  %d  %d  %d  %d  %d  %d  %d  %d\n" | 
|---|
| 397 |          "  %d  %d  %d  %d  %d  %d  %d  %d\n" | 
|---|
| 398 |          "  %d  %d  %d  %d  %d  %d  %d  %d\n" | 
|---|
| 399 |          "  %d  %d  %d  %d  %d  %d  %d  %d\n" | 
|---|
| 400 |          "  %d  %d  %d  %d  %d  %d  %d  %d\n", | 
|---|
| 401 |          index , block , nblocks_w*nblocks_h , image , | 
|---|
| 402 |          buf[0] , buf[1] , buf[2] , buf[3] , buf[4] , buf[5] , buf[6] , buf[7] , | 
|---|
| 403 |          buf[8] , buf[9] , buf[10], buf[11], buf[12], buf[13], buf[14], buf[15], | 
|---|
| 404 |          buf[16], buf[17], buf[18], buf[19], buf[20], buf[21], buf[22], buf[23], | 
|---|
| 405 |          buf[24], buf[25], buf[26], buf[27], buf[28], buf[29], buf[30], buf[31], | 
|---|
| 406 |          buf[32], buf[33], buf[34], buf[35], buf[36], buf[37], buf[38], buf[39], | 
|---|
| 407 |          buf[40], buf[41], buf[42], buf[43], buf[44], buf[45], buf[46], buf[47], | 
|---|
| 408 |          buf[48], buf[49], buf[50], buf[51], buf[52], buf[53], buf[54], buf[55], | 
|---|
| 409 |          buf[56], buf[57], buf[58], buf[59], buf[60], buf[61], buf[62], buf[63]) } | 
|---|
| 410 | #endif | 
|---|
| 411 |  | 
|---|
| 412 |     return buf[0]; | 
|---|
| 413 |  | 
|---|
| 414 | } // end vld_unpack_block() | 
|---|
| 415 |  | 
|---|
| 416 |  | 
|---|
| 417 | ////////////////////////////////////////////////////////////// | 
|---|
| 418 | __attribute__ ((constructor)) void vld( uint32_t index ) | 
|---|
| 419 | ////////////////////////////////////////////////////////////// | 
|---|
| 420 | { | 
|---|
| 421 |     mwmr_channel_t*  mwmr_in_data = demux_2_vld_data[index]; | 
|---|
| 422 |     mwmr_channel_t*  mwmr_in_huff = demux_2_vld_huff[index]; | 
|---|
| 423 |     mwmr_channel_t*  mwmr_out     = vld_2_iqzz[index]; | 
|---|
| 424 |  | 
|---|
| 425 |     huff_tables_t    huff;       // huffman tables | 
|---|
| 426 |     bitreader_t      stream;     // bit stream buffer | 
|---|
| 427 |     int16_t          prev_dc;    // previous block DC value | 
|---|
| 428 |     uint32_t         block;      // block index  | 
|---|
| 429 |  | 
|---|
| 430 |     // get platform parameters | 
|---|
| 431 |     uint32_t  x_size; | 
|---|
| 432 |     uint32_t  y_size; | 
|---|
| 433 |     uint32_t  nprocs; | 
|---|
| 434 |     giet_procs_number( &x_size , &y_size , &nprocs ); | 
|---|
| 435 |  | 
|---|
| 436 |     // get processor coordinates | 
|---|
| 437 |     uint32_t         x, y, p; | 
|---|
| 438 |     giet_proc_xyp( &x , &y , &p ); | 
|---|
| 439 |  | 
|---|
| 440 |     // private TTY allocation | 
|---|
| 441 |     // giet_tty_alloc( 0 ); | 
|---|
| 442 |  | 
|---|
| 443 |     PRINTF("\n[MJPEG] thread VLD[%d] starts on P[%d,%d,%d] / trdid = %x\n", | 
|---|
| 444 |            index , x , y , p, (uint32_t)trdid_vld[index] ) | 
|---|
| 445 |  | 
|---|
| 446 |  | 
|---|
| 447 |     // initialise BUFIO for MWMR channel <in_data> | 
|---|
| 448 |     uint8_t       in_data_buffer[64]; | 
|---|
| 449 |     mwmr_bufio_t  bufio_in_data; | 
|---|
| 450 |     mwmr_bufio_init( &bufio_in_data , in_data_buffer , 64 , 1 , mwmr_in_data ); | 
|---|
| 451 |  | 
|---|
| 452 | #if (DEBUG_VLD > 1) | 
|---|
| 453 | if ( (index == DEBUG_CLUSTER_INDEX) || (DEBUG_CLUSTER_INDEX == 0XFFFFFFFF) ) | 
|---|
| 454 | { PRINTF("\nVLD[%d] <in_data> : &mwmr = %x / &bufio = %x\n", | 
|---|
| 455 |          index , mwmr_in_data , &bufio_in_data ) } | 
|---|
| 456 | #endif | 
|---|
| 457 |  | 
|---|
| 458 |     // initialise BUFIO for MWMR channel <in_huff> | 
|---|
| 459 |     uint8_t       in_huff_buffer[64]; | 
|---|
| 460 |     mwmr_bufio_t  bufio_in_huff; | 
|---|
| 461 |     mwmr_bufio_init( &bufio_in_huff , in_huff_buffer , 64 , 1 , mwmr_in_huff ); | 
|---|
| 462 |  | 
|---|
| 463 | #if (DEBUG_VLD > 1) | 
|---|
| 464 | if ( (index == DEBUG_CLUSTER_INDEX) || (DEBUG_CLUSTER_INDEX == 0XFFFFFFFF) ) | 
|---|
| 465 | { PRINTF("\nVLD[%d] <in_huff> : &mwmr = %x / &bufio = %x\n", | 
|---|
| 466 |          index , mwmr_in_huff , &bufio_in_huff ) } | 
|---|
| 467 | #endif | 
|---|
| 468 |  | 
|---|
| 469 |     // initialise Huffman Tables | 
|---|
| 470 |     huff_tables_init( &huff ); | 
|---|
| 471 |  | 
|---|
| 472 |     uint32_t  image = index; | 
|---|
| 473 |     uint32_t  nblocks = nblocks_h * nblocks_w; | 
|---|
| 474 |  | 
|---|
| 475 |     while ( image < MAX_IMAGES )  // one image per iteration | 
|---|
| 476 |     { | 
|---|
| 477 |         // load first Huffman Table from bufio_in_huff | 
|---|
| 478 |         huff_tables_load( index, &huff , &bufio_in_huff ); | 
|---|
| 479 |  | 
|---|
| 480 |         // load second Huffman Table from bufio_in_huff | 
|---|
| 481 |         huff_tables_load( index, &huff , &bufio_in_huff ); | 
|---|
| 482 |  | 
|---|
| 483 | #if (DEBUG_VLD > 1) | 
|---|
| 484 | if ( (index == DEBUG_CLUSTER_INDEX) || (DEBUG_CLUSTER_INDEX == 0XFFFFFFFF) ) | 
|---|
| 485 | { PRINTF("\nVLD[%d] load Huffman tables for image %d\n", index , image ) } | 
|---|
| 486 | #endif | 
|---|
| 487 |  | 
|---|
| 488 |         // (re)initializes DC value for each image | 
|---|
| 489 |         prev_dc = 0; | 
|---|
| 490 |  | 
|---|
| 491 |         // (re)align data bufio for each image | 
|---|
| 492 |         mwmr_bufio_align( &bufio_in_data ); | 
|---|
| 493 |  | 
|---|
| 494 |         // (re)initializes bit-stream for each image | 
|---|
| 495 |         bitreader_init( &stream, &bufio_in_data ); | 
|---|
| 496 |      | 
|---|
| 497 |         // loop on the blocks in current image | 
|---|
| 498 |         for ( block = 0 ; block < nblocks ; block++ ) | 
|---|
| 499 |         { | 
|---|
| 500 |  | 
|---|
| 501 | #if (DEBUG_VLD > 1)  | 
|---|
| 502 | if ( (index == DEBUG_CLUSTER_INDEX) || (DEBUG_CLUSTER_INDEX == 0XFFFFFFFF) ) | 
|---|
| 503 | { PRINTF("\nVLD[%d] uncompress block %d/%d in image %d\n", index, block, nblocks, image ) } | 
|---|
| 504 | #endif | 
|---|
| 505 |             prev_dc = vld_unpack_block( index, | 
|---|
| 506 |                                         image, | 
|---|
| 507 |                                         block, | 
|---|
| 508 |                                         &stream,  | 
|---|
| 509 |                                         mwmr_out,  | 
|---|
| 510 |                                         &huff,  | 
|---|
| 511 |                                         prev_dc ); | 
|---|
| 512 |         }  // end for blocks | 
|---|
| 513 |  | 
|---|
| 514 | #if DEBUG_VLD  | 
|---|
| 515 | if ( (index == DEBUG_CLUSTER_INDEX) || (DEBUG_CLUSTER_INDEX == 0XFFFFFFFF) ) | 
|---|
| 516 | { PRINTF("\nVLD[%d] completes image %d at cycle %d\n", index , image , giet_proctime() ) } | 
|---|
| 517 | #endif | 
|---|
| 518 |         image = image + x_size*y_size; | 
|---|
| 519 |  | 
|---|
| 520 |     }  // end while on images | 
|---|
| 521 |  | 
|---|
| 522 |     giet_pthread_exit( "VLD completed" ); | 
|---|
| 523 |  | 
|---|
| 524 | }  // end vld() | 
|---|
| 525 |  | 
|---|