source: soft/giet_vm/applications/mjpeg/vld.c @ 778

Last change on this file since 778 was 748, checked in by alain, 9 years ago

Modify instrumentation to save results on virtual disk.

File size: 17.7 KB
RevLine 
[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
33typedef 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////////////////////////////////////////////////////
43uint32_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///////////////////////////////////////////////
89uint8_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/////////////////////////////////////////
107void 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
125typedef 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/////////////////////////////////////////////
136void 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////////////////////////////////////////////
159void 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/////////////////////////////////////////////
202void 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)
263if ( (index == DEBUG_CLUSTER_INDEX) || (DEBUG_CLUSTER_INDEX == 0XFFFFFFFF) )
[723]264huff_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/////////////////////////////////////////////////////////
273int8_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///////////////////////////////////////////////////////////////////////////
304static 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]322static 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)
349if ( (index == DEBUG_CLUSTER_INDEX) || (DEBUG_CLUSTER_INDEX == 0XFFFFFFFF) )
[748]350PRINTF("\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)
364if ( (index == DEBUG_CLUSTER_INDEX) || (DEBUG_CLUSTER_INDEX == 0XFFFFFFFF) )
[748]365PRINTF("\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]386if ( (index == DEBUG_CLUSTER_INDEX) || (DEBUG_CLUSTER_INDEX == 0XFFFFFFFF) )
[748]387PRINTF("\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]397if ( (index == DEBUG_CLUSTER_INDEX) || (DEBUG_CLUSTER_INDEX == 0XFFFFFFFF) )
[748]398PRINTF("\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]459if ( (index == DEBUG_CLUSTER_INDEX) || (DEBUG_CLUSTER_INDEX == 0XFFFFFFFF) )
[748]460PRINTF("\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]470if ( (index == DEBUG_CLUSTER_INDEX) || (DEBUG_CLUSTER_INDEX == 0XFFFFFFFF) )
[748]471PRINTF("\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]490if ( (index == DEBUG_CLUSTER_INDEX) || (DEBUG_CLUSTER_INDEX == 0XFFFFFFFF) )
[748]491PRINTF("\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]508if ( (index == DEBUG_CLUSTER_INDEX) || (DEBUG_CLUSTER_INDEX == 0XFFFFFFFF) )
[748]509PRINTF("\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]521if ( (index == DEBUG_CLUSTER_INDEX) || (DEBUG_CLUSTER_INDEX == 0XFFFFFFFF) )
[748]522PRINTF("\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
Note: See TracBrowser for help on using the repository browser.