[723] | 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 |
---|
[748] | 25 | #define PRINTF(...) do { lock_acquire( &tty_lock ); \ |
---|
| 26 | giet_tty_printf(__VA_ARGS__); \ |
---|
| 27 | lock_release( &tty_lock ); } while(0); |
---|
[723] | 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 | |
---|
[748] | 168 | if ( is_ac ) |
---|
| 169 | { |
---|
| 170 | PRINTF("\n AC Huffman Table\n\n"); |
---|
| 171 | } |
---|
| 172 | else |
---|
| 173 | { |
---|
| 174 | PRINTF("\n DC Huffman Table\n\n"); |
---|
| 175 | } |
---|
[723] | 176 | |
---|
| 177 | for ( j = 0; j < 16; j++ ) // j = code_length - 1 |
---|
| 178 | { |
---|
| 179 | PRINTF(" length = %d / mincode = %x / maxcode = %x / valptr = %d\n", |
---|
[748] | 180 | j+1 , huff->MinCode[type][j] , huff->MaxCode[type][j] , huff->ValPtr[type][j]); |
---|
[723] | 181 | } |
---|
| 182 | |
---|
[748] | 183 | PRINTF("\n"); |
---|
[723] | 184 | |
---|
| 185 | for ( j = 0 ; j < 16 ; j++ ) // j == code_length - 1 |
---|
| 186 | { |
---|
| 187 | for ( code = huff->MinCode[type][j] ; code <= huff->MaxCode[type][j] ; code++ ) |
---|
| 188 | { |
---|
| 189 | uint32_t index = huff->ValPtr[type][j] + code - huff->MinCode[type][j]; |
---|
| 190 | |
---|
| 191 | giet_pthread_assert( (index<max) , "ERROR in huff_tables_dump() : overflow"); |
---|
| 192 | |
---|
| 193 | PRINTF(" Symbol[%d] = %x / code[%d] = %x\n", |
---|
[748] | 194 | index , huff->HT[type][index] , index , code ); |
---|
[723] | 195 | } |
---|
| 196 | } |
---|
| 197 | |
---|
[748] | 198 | PRINTF("\n"); |
---|
[723] | 199 | } |
---|
| 200 | |
---|
[736] | 201 | ///////////////////////////////////////////// |
---|
| 202 | void huff_tables_load( uint32_t index, |
---|
| 203 | huff_tables_t* huff, |
---|
[723] | 204 | mwmr_bufio_t* bufio ) |
---|
| 205 | { |
---|
| 206 | uint8_t byte; |
---|
| 207 | uint32_t is_ac; // AC Table if non zero |
---|
| 208 | |
---|
| 209 | uint8_t LeavesN; // number of codes of length N (from 1 to 16) |
---|
| 210 | uint8_t LeavesT; // cumulated total number of codes |
---|
| 211 | uint32_t AuxCode; // used to compute code values |
---|
| 212 | |
---|
| 213 | // read length (2 bytes) from bufio |
---|
| 214 | uint32_t length = (uint32_t)mwmr_bufio_read_byte( bufio ); |
---|
| 215 | length = (length<<8) | mwmr_bufio_read_byte( bufio ); |
---|
| 216 | |
---|
| 217 | // read Tc/Th (1 byte) from bufio |
---|
| 218 | // Th must be null, Tc must be 0 or 1 |
---|
| 219 | byte = mwmr_bufio_read_byte( bufio ); |
---|
| 220 | |
---|
| 221 | giet_pthread_assert( ((byte & 0xEF) == 0) , |
---|
| 222 | "ERROR in huff_load_table() : non supported HT header"); |
---|
| 223 | |
---|
| 224 | if (byte == 0) is_ac = 0; |
---|
| 225 | else is_ac = 1; |
---|
| 226 | |
---|
| 227 | uint32_t max_size = ( is_ac ) ? 162 : 12; |
---|
| 228 | |
---|
| 229 | // get the 16 LeavesN values from bufio |
---|
| 230 | uint32_t i; |
---|
| 231 | LeavesT = 0; |
---|
| 232 | AuxCode = 0; |
---|
| 233 | for ( i=0; i<16; i++ ) |
---|
| 234 | { |
---|
| 235 | // read one byte from bufio |
---|
| 236 | LeavesN = mwmr_bufio_read_byte( bufio ); |
---|
| 237 | |
---|
| 238 | huff->ValPtr[is_ac][i] = LeavesT; |
---|
| 239 | huff->MinCode[is_ac][i] = AuxCode<<1; |
---|
| 240 | AuxCode = huff->MinCode[is_ac][i] + LeavesN; |
---|
| 241 | huff->MaxCode[is_ac][i] = (LeavesN) ? (AuxCode - 1) : (-1); |
---|
| 242 | LeavesT += LeavesN; |
---|
| 243 | } |
---|
| 244 | |
---|
| 245 | giet_pthread_assert( (length == 19 + LeavesT) , |
---|
| 246 | "ERROR in huff_load_table() : illegal HT length"); |
---|
| 247 | |
---|
| 248 | giet_pthread_assert( (LeavesT <= max_size) , |
---|
| 249 | "ERROR in huff_load_table() : too much symbols"); |
---|
| 250 | |
---|
| 251 | // get the symbol values from bufio (one byte per symbol) |
---|
| 252 | // complete table with zero values if LeavesT < max_size |
---|
| 253 | for ( i=0 ; i<max_size ; ++i ) |
---|
| 254 | { |
---|
| 255 | if ( i < LeavesT ) huff->HT[is_ac][i] = mwmr_bufio_read_byte( bufio ); |
---|
| 256 | else huff->HT[is_ac][i] = 0; |
---|
| 257 | } |
---|
| 258 | |
---|
| 259 | // align bufio pointer on next item |
---|
| 260 | mwmr_bufio_align( bufio ); |
---|
| 261 | |
---|
[736] | 262 | #if (DEBUG_VLD > 3) |
---|
| 263 | if ( (index == DEBUG_CLUSTER_INDEX) || (DEBUG_CLUSTER_INDEX == 0XFFFFFFFF) ) |
---|
[723] | 264 | huff_tables_dump( huff , is_ac ); |
---|
| 265 | #endif |
---|
| 266 | |
---|
| 267 | } // end huff_tables_load() |
---|
| 268 | |
---|
| 269 | ////////////////////////////////////////////////////////// |
---|
| 270 | // extract a symbol (8 bits) from an Huffman encoded |
---|
| 271 | // bit-stream, using the specified huffman table |
---|
| 272 | ///////////////////////////////////////////////////////// |
---|
| 273 | int8_t huff_get_symbol( bitreader_t* stream, |
---|
| 274 | huff_tables_t* huff, |
---|
| 275 | int32_t select ) // DC if zero / AC if non zero |
---|
| 276 | { |
---|
| 277 | uint32_t length; |
---|
| 278 | int32_t code = 0; |
---|
| 279 | |
---|
| 280 | uint32_t is_ac = (select) ? 1 : 0; |
---|
| 281 | uint32_t max_size = (select) ? 162 : 12; |
---|
| 282 | |
---|
| 283 | for ( length = 0 ; length < 16 ; ++length ) |
---|
| 284 | { |
---|
| 285 | code = (code<<1) | bitreader_get_one( stream ); |
---|
| 286 | if ( code <= huff->MaxCode[select][length] ) break; |
---|
| 287 | } |
---|
| 288 | |
---|
| 289 | uint32_t index = huff->ValPtr[is_ac][length] + code - huff->MinCode[is_ac][length]; |
---|
| 290 | |
---|
| 291 | giet_pthread_assert( (index <= max_size) , |
---|
| 292 | "ERROR in huff_get_symbol() : Huffman table overflow"); |
---|
| 293 | |
---|
| 294 | return huff->HT[is_ac][index]; |
---|
| 295 | } |
---|
| 296 | |
---|
| 297 | /////////////////////////////////////////////////////////////////////////// |
---|
| 298 | // transform JPEG encoded positive/negative value coded as ( S , nbits ) |
---|
| 299 | // to a standard 16 bits 2's complement number (int16_t). |
---|
| 300 | // - nbits is the magnitude (number of significant bits in S |
---|
| 301 | // - most significant bit in S is 0 for positive / 1 for negative |
---|
| 302 | // - other bits in S define the value in 2**(nbits-1) possible values |
---|
| 303 | /////////////////////////////////////////////////////////////////////////// |
---|
| 304 | static int16_t reformat( uint32_t S , int32_t nbits ) |
---|
| 305 | { |
---|
| 306 | uint32_t ext; |
---|
| 307 | uint32_t sign; |
---|
| 308 | int16_t value; |
---|
| 309 | |
---|
| 310 | if ( nbits == 0 ) return 0; |
---|
| 311 | |
---|
| 312 | sign = !( (1 << (nbits - 1)) & S ); |
---|
| 313 | ext = 0 - (sign << nbits); |
---|
| 314 | value = (S | ext) + sign; |
---|
| 315 | |
---|
| 316 | return value; |
---|
| 317 | } |
---|
| 318 | |
---|
| 319 | //////////////////////////////////////////////////////// |
---|
| 320 | // unpack a 8*8 pixels block with 2 bytes per pixel |
---|
| 321 | ////////////////////////////////////////////////////////// |
---|
[736] | 322 | static int16_t vld_unpack_block( uint32_t index, // cluster index |
---|
| 323 | uint32_t image, // image index |
---|
| 324 | uint32_t block, // block index |
---|
| 325 | bitreader_t* stream, // input bit stream |
---|
| 326 | mwmr_channel_t* mwmr_out, // output channel |
---|
| 327 | huff_tables_t* huff, // Huffman Tables |
---|
| 328 | int16_t prev_dc ) // previous DC coef |
---|
[723] | 329 | { |
---|
| 330 | uint32_t temp; |
---|
| 331 | uint32_t i; |
---|
| 332 | uint32_t run; |
---|
| 333 | uint32_t cat; |
---|
| 334 | int32_t value; |
---|
| 335 | uint8_t symbol; |
---|
| 336 | int16_t buf[64]; // buffer for the 64 resulting pixels (2 bytes per pixel) |
---|
| 337 | |
---|
| 338 | // set default values |
---|
| 339 | for (i = 0; i < 64; i++) buf[i] = 0; |
---|
| 340 | |
---|
| 341 | // compute the DC coefficient |
---|
| 342 | symbol = huff_get_symbol( stream , huff , 0 ); // use DC Huffman Table |
---|
| 343 | |
---|
| 344 | temp = bitreader_get( stream , symbol ); |
---|
| 345 | value = reformat( temp , symbol ); |
---|
| 346 | buf[0] = value + prev_dc; |
---|
| 347 | |
---|
[736] | 348 | #if (DEBUG_VLD > 2) |
---|
| 349 | if ( (index == DEBUG_CLUSTER_INDEX) || (DEBUG_CLUSTER_INDEX == 0XFFFFFFFF) ) |
---|
[748] | 350 | PRINTF("\nVLD[%d] : DC[0] = %d / reformat( %x , %d ) = %d\n", |
---|
| 351 | index , buf[0], temp , symbol , value ); |
---|
[723] | 352 | #endif |
---|
| 353 | |
---|
| 354 | // compute the 63 AC coefficients |
---|
| 355 | for (i = 1; i < 64; i++) |
---|
| 356 | { |
---|
| 357 | symbol = huff_get_symbol( stream , huff , 1 ); // use AC Huffman Table |
---|
| 358 | |
---|
| 359 | // in case of HUFF_EOB symbol, all other pixels are zero |
---|
| 360 | if ( symbol == HUFF_EOB ) |
---|
| 361 | { |
---|
| 362 | |
---|
[736] | 363 | #if (DEBUG_VLD > 2) |
---|
| 364 | if ( (index == DEBUG_CLUSTER_INDEX) || (DEBUG_CLUSTER_INDEX == 0XFFFFFFFF) ) |
---|
[748] | 365 | PRINTF("\nVLD[%d] : EOB found at i = %d\n", index , i ); |
---|
[723] | 366 | #endif |
---|
| 367 | break; |
---|
| 368 | } |
---|
| 369 | |
---|
| 370 | // in case of HUFF_ZRL symbol (0xF0) , 15 next pixels are zero |
---|
| 371 | if (symbol == HUFF_ZRL) |
---|
| 372 | { |
---|
| 373 | i += 15; |
---|
| 374 | continue; |
---|
| 375 | } |
---|
| 376 | |
---|
| 377 | cat = symbol & 0xf; |
---|
| 378 | run = symbol >> 4; |
---|
| 379 | i += run; |
---|
| 380 | |
---|
| 381 | temp = bitreader_get (stream , cat ); |
---|
| 382 | value = reformat( temp , cat ); |
---|
| 383 | buf[i] = value; |
---|
| 384 | |
---|
| 385 | #if (DEBUG_VLD > 2) |
---|
[736] | 386 | if ( (index == DEBUG_CLUSTER_INDEX) || (DEBUG_CLUSTER_INDEX == 0XFFFFFFFF) ) |
---|
[748] | 387 | PRINTF("\nVLD[%d] : AC[%d] = %d / reformat( %x , %d ) = %d\n", |
---|
| 388 | index , i , buf[i] , temp , cat , value ); |
---|
[723] | 389 | #endif |
---|
| 390 | |
---|
| 391 | } |
---|
| 392 | |
---|
| 393 | // write one block to mwmr_out channel ( 2 bytes per pixel) |
---|
| 394 | mwmr_write( mwmr_out, (uint32_t*)buf , 32 ); |
---|
| 395 | |
---|
| 396 | #if (DEBUG_VLD > 1 ) |
---|
[736] | 397 | if ( (index == DEBUG_CLUSTER_INDEX) || (DEBUG_CLUSTER_INDEX == 0XFFFFFFFF) ) |
---|
[748] | 398 | PRINTF("\nVLD[%d] completes block %d/%d in image %d\n" |
---|
[736] | 399 | " %d %d %d %d %d %d %d %d\n" |
---|
| 400 | " %d %d %d %d %d %d %d %d\n" |
---|
| 401 | " %d %d %d %d %d %d %d %d\n" |
---|
| 402 | " %d %d %d %d %d %d %d %d\n" |
---|
| 403 | " %d %d %d %d %d %d %d %d\n" |
---|
| 404 | " %d %d %d %d %d %d %d %d\n" |
---|
| 405 | " %d %d %d %d %d %d %d %d\n" |
---|
| 406 | " %d %d %d %d %d %d %d %d\n", |
---|
| 407 | index , block , nblocks_w*nblocks_h , image , |
---|
| 408 | buf[0] , buf[1] , buf[2] , buf[3] , buf[4] , buf[5] , buf[6] , buf[7] , |
---|
| 409 | buf[8] , buf[9] , buf[10], buf[11], buf[12], buf[13], buf[14], buf[15], |
---|
| 410 | buf[16], buf[17], buf[18], buf[19], buf[20], buf[21], buf[22], buf[23], |
---|
| 411 | buf[24], buf[25], buf[26], buf[27], buf[28], buf[29], buf[30], buf[31], |
---|
| 412 | buf[32], buf[33], buf[34], buf[35], buf[36], buf[37], buf[38], buf[39], |
---|
| 413 | buf[40], buf[41], buf[42], buf[43], buf[44], buf[45], buf[46], buf[47], |
---|
| 414 | buf[48], buf[49], buf[50], buf[51], buf[52], buf[53], buf[54], buf[55], |
---|
[748] | 415 | buf[56], buf[57], buf[58], buf[59], buf[60], buf[61], buf[62], buf[63]); |
---|
[723] | 416 | #endif |
---|
| 417 | |
---|
| 418 | return buf[0]; |
---|
| 419 | |
---|
| 420 | } // end vld_unpack_block() |
---|
| 421 | |
---|
| 422 | |
---|
| 423 | ////////////////////////////////////////////////////////////// |
---|
| 424 | __attribute__ ((constructor)) void vld( uint32_t index ) |
---|
| 425 | ////////////////////////////////////////////////////////////// |
---|
| 426 | { |
---|
| 427 | mwmr_channel_t* mwmr_in_data = demux_2_vld_data[index]; |
---|
| 428 | mwmr_channel_t* mwmr_in_huff = demux_2_vld_huff[index]; |
---|
| 429 | mwmr_channel_t* mwmr_out = vld_2_iqzz[index]; |
---|
| 430 | |
---|
| 431 | huff_tables_t huff; // huffman tables |
---|
| 432 | bitreader_t stream; // bit stream buffer |
---|
| 433 | int16_t prev_dc; // previous block DC value |
---|
| 434 | uint32_t block; // block index |
---|
| 435 | |
---|
| 436 | // get platform parameters |
---|
| 437 | uint32_t x_size; |
---|
| 438 | uint32_t y_size; |
---|
| 439 | uint32_t nprocs; |
---|
| 440 | giet_procs_number( &x_size , &y_size , &nprocs ); |
---|
| 441 | |
---|
| 442 | // get processor coordinates |
---|
| 443 | uint32_t x, y, p; |
---|
| 444 | giet_proc_xyp( &x , &y , &p ); |
---|
| 445 | |
---|
| 446 | // private TTY allocation |
---|
| 447 | // giet_tty_alloc( 0 ); |
---|
| 448 | |
---|
[736] | 449 | PRINTF("\n[MJPEG] thread VLD[%d] starts on P[%d,%d,%d] / trdid = %x\n", |
---|
[748] | 450 | index , x , y , p, (uint32_t)trdid_vld[index] ); |
---|
[723] | 451 | |
---|
[736] | 452 | |
---|
[723] | 453 | // initialise BUFIO for MWMR channel <in_data> |
---|
| 454 | uint8_t in_data_buffer[64]; |
---|
| 455 | mwmr_bufio_t bufio_in_data; |
---|
| 456 | mwmr_bufio_init( &bufio_in_data , in_data_buffer , 64 , 1 , mwmr_in_data ); |
---|
| 457 | |
---|
| 458 | #if (DEBUG_VLD > 1) |
---|
[736] | 459 | if ( (index == DEBUG_CLUSTER_INDEX) || (DEBUG_CLUSTER_INDEX == 0XFFFFFFFF) ) |
---|
[748] | 460 | PRINTF("\nVLD[%d] <in_data> : &mwmr = %x / &bufio = %x\n", |
---|
| 461 | index , mwmr_in_data , &bufio_in_data ); |
---|
[723] | 462 | #endif |
---|
| 463 | |
---|
| 464 | // initialise BUFIO for MWMR channel <in_huff> |
---|
| 465 | uint8_t in_huff_buffer[64]; |
---|
| 466 | mwmr_bufio_t bufio_in_huff; |
---|
| 467 | mwmr_bufio_init( &bufio_in_huff , in_huff_buffer , 64 , 1 , mwmr_in_huff ); |
---|
| 468 | |
---|
| 469 | #if (DEBUG_VLD > 1) |
---|
[736] | 470 | if ( (index == DEBUG_CLUSTER_INDEX) || (DEBUG_CLUSTER_INDEX == 0XFFFFFFFF) ) |
---|
[748] | 471 | PRINTF("\nVLD[%d] <in_huff> : &mwmr = %x / &bufio = %x\n", |
---|
[736] | 472 | index , mwmr_in_huff , &bufio_in_huff ) } |
---|
[723] | 473 | #endif |
---|
| 474 | |
---|
| 475 | // initialise Huffman Tables |
---|
| 476 | huff_tables_init( &huff ); |
---|
| 477 | |
---|
| 478 | uint32_t image = index; |
---|
| 479 | uint32_t nblocks = nblocks_h * nblocks_w; |
---|
| 480 | |
---|
| 481 | while ( image < MAX_IMAGES ) // one image per iteration |
---|
| 482 | { |
---|
| 483 | // load first Huffman Table from bufio_in_huff |
---|
[736] | 484 | huff_tables_load( index, &huff , &bufio_in_huff ); |
---|
[723] | 485 | |
---|
| 486 | // load second Huffman Table from bufio_in_huff |
---|
[736] | 487 | huff_tables_load( index, &huff , &bufio_in_huff ); |
---|
[723] | 488 | |
---|
| 489 | #if (DEBUG_VLD > 1) |
---|
[736] | 490 | if ( (index == DEBUG_CLUSTER_INDEX) || (DEBUG_CLUSTER_INDEX == 0XFFFFFFFF) ) |
---|
[748] | 491 | PRINTF("\nVLD[%d] load Huffman tables for image %d\n", index , image ); |
---|
[723] | 492 | #endif |
---|
| 493 | |
---|
| 494 | // (re)initializes DC value for each image |
---|
| 495 | prev_dc = 0; |
---|
| 496 | |
---|
| 497 | // (re)align data bufio for each image |
---|
| 498 | mwmr_bufio_align( &bufio_in_data ); |
---|
| 499 | |
---|
| 500 | // (re)initializes bit-stream for each image |
---|
| 501 | bitreader_init( &stream, &bufio_in_data ); |
---|
| 502 | |
---|
| 503 | // loop on the blocks in current image |
---|
| 504 | for ( block = 0 ; block < nblocks ; block++ ) |
---|
| 505 | { |
---|
| 506 | |
---|
| 507 | #if (DEBUG_VLD > 1) |
---|
[736] | 508 | if ( (index == DEBUG_CLUSTER_INDEX) || (DEBUG_CLUSTER_INDEX == 0XFFFFFFFF) ) |
---|
[748] | 509 | PRINTF("\nVLD[%d] uncompress block %d/%d in image %d\n", index, block, nblocks, image ); |
---|
[723] | 510 | #endif |
---|
[736] | 511 | prev_dc = vld_unpack_block( index, |
---|
| 512 | image, |
---|
| 513 | block, |
---|
| 514 | &stream, |
---|
| 515 | mwmr_out, |
---|
| 516 | &huff, |
---|
| 517 | prev_dc ); |
---|
[723] | 518 | } // end for blocks |
---|
| 519 | |
---|
| 520 | #if DEBUG_VLD |
---|
[736] | 521 | if ( (index == DEBUG_CLUSTER_INDEX) || (DEBUG_CLUSTER_INDEX == 0XFFFFFFFF) ) |
---|
[748] | 522 | PRINTF("\nVLD[%d] completes image %d at cycle %d\n", index , image , giet_proctime() ); |
---|
[723] | 523 | #endif |
---|
| 524 | image = image + x_size*y_size; |
---|
| 525 | |
---|
| 526 | } // end while on images |
---|
| 527 | |
---|
[736] | 528 | giet_pthread_exit( "VLD completed" ); |
---|
[723] | 529 | |
---|
| 530 | } // end vld() |
---|
| 531 | |
---|