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

Last change on this file since 747 was 736, checked in by alain, 9 years ago

Modify the mjpeg application to support an optional
DCT hardware coprocessor.

File size: 17.6 KB
Line 
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
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
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/////////////////////////////////////////////
196void 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)
257if ( (index == DEBUG_CLUSTER_INDEX) || (DEBUG_CLUSTER_INDEX == 0XFFFFFFFF) )
258huff_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/////////////////////////////////////////////////////////
267int8_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///////////////////////////////////////////////////////////////////////////
298static 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//////////////////////////////////////////////////////////
316static 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)
343if ( (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)
358if ( (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)
380if ( (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 )
391if ( (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)
453if ( (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)
464if ( (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)
484if ( (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)
502if ( (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
515if ( (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
Note: See TracBrowser for help on using the repository browser.