source: soft/giet_vm/applications/mjpeg/demux.c @ 736

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

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

File size: 14.4 KB
Line 
1////////////////////////////////////////////////////////////////////////////////////////
2// File   : demux.c 
3// Date   : octobre 2015
4// author : Alain Greiner
5////////////////////////////////////////////////////////////////////////////////////////
6// This file define the code of the DEMUX  thread for the MJPEG application.
7// This function makes the analysis of the MJPEG stream of bytes: For each
8// compressed image arriving on the <in> input MWMR channel, it dispathch the stream
9// on three output MWMR channels:
10// - the <out_quanti> channel receive the quantisation table segment.
11// - the <out_huff> channel receive the huffman tables.
12// - the <out_data> channel receive the compressed bit stream.
13// It uses four BUFIO local buffers, connected to the four MWMR channels.
14// It search specifically the following 16 bits markers :
15// - the SOI_MK : Start of Image marquer
16// - the DQT_MK : Quantization Table marker
17// - the DHT_MK : Huffman Table marker
18// - the SOS_MK : Start of Scan marker
19// - the EOI_MK : REnd of Image marker
20////////////////////////////////////////////////////////////////////////////////////////
21
22#include <stdio.h>
23#include <stdint.h>
24#include <mwmr_channel.h>
25#include "mjpeg.h"
26
27#define SOI_MK  0xFFD8          // start of image
28#define APP_MK  0xFFE0          // custom, up to FFEF
29#define COM_MK  0xFFFE          // commment segment
30#define SOF_MK  0xFFC0          // start of frame
31#define SOS_MK  0xFFDA          // start of scan
32#define DHT_MK  0xFFC4          // Huffman table
33#define DQT_MK  0xFFDB          // Quant. table
34#define EOI_MK  0xFFD9          // end of image         
35#define MK_MSK  0xFFF0
36
37// macro to use a shared TTY
38#define PRINTF(...)    lock_acquire( &tty_lock ); \
39                       giet_tty_printf(__VA_ARGS__);  \
40                       lock_release( &tty_lock );
41
42///////////////////////////////////////////////////////////
43// This function discard all bytes from an input <bufio>,
44// until it found a marker, and returns the marker value.
45///////////////////////////////////////////////////////////
46uint16_t get_next_marker( mwmr_bufio_t* bufio )
47{
48    uint16_t   marker;
49    uint8_t    byte;
50    uint8_t    ff_found = 0;
51
52    do 
53    {
54        byte = mwmr_bufio_read_byte( bufio );
55
56        if ( ff_found )
57        {
58            ff_found = 0;
59            marker = byte | 0xFF00;
60
61            return marker;
62        }
63        else if ( byte == 0xFF ) 
64        {
65            ff_found = 1;
66        }
67    } while (1);
68}
69     
70
71//////////////////////////////////////////////////////////////
72__attribute__ ((constructor)) void demux( uint32_t index )
73//////////////////////////////////////////////////////////////
74{
75    // get platform parameters
76    uint32_t  x_size;
77    uint32_t  y_size;
78    uint32_t  nprocs;
79    giet_procs_number( &x_size , &y_size , &nprocs );
80
81    // get processor coordinates
82    uint32_t x, y, p;
83    giet_proc_xyp( &x , &y , &p );
84 
85    // private TTY allocation
86    // giet_tty_alloc( 0 );
87
88    PRINTF("\n[MJPEG] thread DEMUX[%d] starts on P[%d,%d,%d] / trdid = %x\n", 
89           index , x , y , p, (uint32_t)trdid_demux[index] )
90
91    // initialise BUFIO for MWMR channel <in>
92    mwmr_channel_t*   mwmr_in = tg_2_demux[index];
93    mwmr_bufio_t      bufio_in;
94    uint8_t           in_buffer[64];
95    mwmr_bufio_init( &bufio_in , in_buffer , 64 , 1 , mwmr_in );
96
97#if (DEBUG_DEMUX > 1)
98if ( (index == DEBUG_CLUSTER_INDEX) || (DEBUG_CLUSTER_INDEX == 0XFFFFFFFF) )
99{ PRINTF("\nDEMUX[%d] <in> : &mwmr = %x / &bufio = %x\n", 
100         index , mwmr_in , &bufio_in ) }
101#endif
102
103    // initialise BUFIO for MWMR channel <out_quanti>
104    mwmr_channel_t*   mwmr_out_quanti = demux_2_iqzz[index];
105    mwmr_bufio_t      bufio_out_quanti;
106    uint8_t           out_quanti_buffer[64];
107    mwmr_bufio_init( &bufio_out_quanti , out_quanti_buffer , 64 , 0 , mwmr_out_quanti );
108
109#if (DEBUG_DEMUX > 1)
110if ( (index == DEBUG_CLUSTER_INDEX) || (DEBUG_CLUSTER_INDEX == 0XFFFFFFFF) )
111{ PRINTF("\nDEMUX[%d] : <out_quanti> : mwmr = %x / &bufio = %x\n",
112         index , mwmr_out_quanti , &bufio_out_quanti ) }
113#endif
114
115    // initialise BUFIO for MWMR channel <out_huff>
116    mwmr_channel_t*   mwmr_out_huff = demux_2_vld_huff[index];
117    mwmr_bufio_t      bufio_out_huff;
118    uint8_t           out_huff_buffer[64];
119    mwmr_bufio_init( &bufio_out_huff , out_huff_buffer , 64 , 0 , mwmr_out_huff );
120
121#if (DEBUG_DEMUX > 1)
122if ( (index == DEBUG_CLUSTER_INDEX) || (DEBUG_CLUSTER_INDEX == 0XFFFFFFFF) )
123{ PRINTF("\nDEMUX[%d] : <out_huff> : mwmr = %x / &bufio = %x\n",
124         index , mwmr_out_huff , &bufio_out_huff ) }
125#endif
126
127    // initialise BUFIO for MWMR channel <out_data>
128    mwmr_channel_t*   mwmr_out_data = demux_2_vld_data[index];
129    mwmr_bufio_t      bufio_out_data;
130    uint8_t           out_data_buffer[64];
131    mwmr_bufio_init( &bufio_out_data , out_data_buffer , 64 , 0 , mwmr_out_data );
132
133#if (DEBUG_DEMUX > 1)
134if ( (index == DEBUG_CLUSTER_INDEX) || (DEBUG_CLUSTER_INDEX == 0XFFFFFFFF) )
135{ PRINTF("\nDEMUX[%d] : <out_data> : mwmr = %x / &bufio = %x\n",
136         index , mwmr_out_data , &bufio_out_data ) }
137#endif
138
139    uint32_t   found_marker;
140    uint32_t   image_done;
141
142    uint16_t   marker;          // 16 bits marker read from bufio_in
143    uint32_t   word;            // 32 bits word read from bufio_in
144    uint8_t    byte;            // one byte read from bufio_in
145    uint32_t   byte_count;      // byte counter in a given compressed image
146   
147    uint32_t   image = index;
148
149    // infinite loop : one image per iteration
150    while ( image < MAX_IMAGES ) 
151    {
152        // search start of image marker
153        do 
154        {
155            marker = get_next_marker( &bufio_in );
156
157        } 
158        while ( marker != SOI_MK );
159
160#if (DEBUG_DEMUX > 1)
161if ( (index == DEBUG_CLUSTER_INDEX) || (DEBUG_CLUSTER_INDEX == 0XFFFFFFFF) )
162{ PRINTF("\nDEMUX[%x] found Start of Image marker\n", index ) }
163#endif
164
165        found_marker = 0;
166        image_done   = 0;
167
168        // analyse image
169        while ( !image_done ) 
170        {
171            // search next marker if required
172            if ( !found_marker ) 
173            {
174                marker = get_next_marker( &bufio_in );
175            }
176
177            ////////////////////////////////////////////
178            if ( marker == SOF_MK )   // start of frame
179            {
180
181#if (DEBUG_DEMUX > 1)
182if ( (index == DEBUG_CLUSTER_INDEX) || (DEBUG_CLUSTER_INDEX == 0XFFFFFFFF) )
183{ PRINTF("\nDEMUX[%x] found Start of Frame marker\n", index ) }
184#endif
185                // Only one component per image is supported
186                // we check the image size (must fit Frame Buffer),
187                // and skip the fixed length frame header
188
189                // skip 3 bytes (Lf , P) from bufio_in
190                mwmr_bufio_skip( &bufio_in , 3 );
191
192                // read width & height from bufio_in
193                uint32_t height = (uint32_t)mwmr_bufio_read_byte( &bufio_in );
194                height = (height<<8) | mwmr_bufio_read_byte( &bufio_in );
195
196                uint32_t width  = (uint32_t)mwmr_bufio_read_byte( &bufio_in );
197                width  = (width<<8)  | mwmr_bufio_read_byte( &bufio_in );
198
199                giet_pthread_assert( (fbf_width == width) && (fbf_height == height) ,
200                "ERROR in demux() : image size doesn't fit frame buffer size" );
201
202                // read one byte (number of components) from bufio_in
203                uint8_t nf  = mwmr_bufio_read_byte( &bufio_in );
204
205                giet_pthread_assert( (nf==1) ,
206                "ERROR in demux() : only one component supported" );
207
208                // skip 3 bytes (C0,H0,V0,TQ0)
209                mwmr_bufio_skip( &bufio_in , 3 );
210
211                found_marker = 0;
212            }
213            ///////////////////////////////////////////////////////////
214            else if ( marker == DQT_MK )   // quantization table marker
215            {
216
217#if (DEBUG_DEMUX > 1)
218if ( (index == DEBUG_CLUSTER_INDEX) || (DEBUG_CLUSTER_INDEX == 0XFFFFFFFF) )
219{ PRINTF("\nDEMUX[%x] found Quantization Table marker\n", index ) }
220#endif
221                // The  quantisation table segment being fixed length,
222                // we skip the header and write the 64 coefs to out_quanti channel.
223
224                uint32_t  n;
225
226                // skip three first bytes (Lq , PqTq) from bufio_in
227                mwmr_bufio_skip( &bufio_in , 3 );
228
229                // write 64 coefs (one byte each)
230                for ( n = 0 ; n < 64 ; n++ )
231                {
232                    uint8_t byte = mwmr_bufio_read_byte( &bufio_in );
233                    mwmr_bufio_write_byte( &bufio_out_quanti , byte );
234                }
235
236                // flush out_quanti buffer
237                mwmr_bufio_flush( &bufio_out_quanti );
238
239                found_marker = 0;
240            }
241            ///////////////////////////////////////////////////////
242            else if ( marker == DHT_MK )   // Huffman table marker
243            {
244
245#if (DEBUG_DEMUX > 1)
246if ( (index == DEBUG_CLUSTER_INDEX) || (DEBUG_CLUSTER_INDEX == 0XFFFFFFFF) )
247{ PRINTF("\nDEMUX[%x] found Huffman Table marker\n", index ) }
248#endif
249                // The Huffman Table segment being variable length,
250                // we search the next marker, and transfer the complete
251                // segment (without marker) to the out_huff channel.
252
253                found_marker = 0;
254
255                while ( !found_marker ) 
256                {
257                    // read one byte from bufio_in
258                    byte = mwmr_bufio_read_byte( &bufio_in );
259
260                    if ( byte == 0xFF )  // potential marker
261                    {
262                        // read another byte from bufio_in
263                        byte = mwmr_bufio_read_byte( &bufio_in );
264
265                        if (byte == 0)  // not a real marker
266                        {
267                            // write one byte to bufio_out_huff
268                            mwmr_bufio_write_byte( &bufio_out_huff, 0xFF );
269                        }
270                        else            // it's a marker
271                        {
272                            marker       = 0xFF00 | byte;
273                            found_marker = 1;
274                        }
275                    }
276                    else                // normal byte
277                    {
278                        // write one byte to bufio_out_huff
279                        mwmr_bufio_write_byte( &bufio_out_huff , byte );
280                    }
281                }
282
283                // flush out_huff bufio
284                mwmr_bufio_flush( &bufio_out_huff );
285            } 
286            ///////////////////////////////////////////////////////
287            else if ( marker == SOS_MK )    // start of scan marker
288            {
289
290#if (DEBUG_DEMUX > 1)
291if ( (index == DEBUG_CLUSTER_INDEX) || (DEBUG_CLUSTER_INDEX == 0XFFFFFFFF) )
292{ PRINTF("\nDEMUX[%x] found Start of Scan marker\n", index ) }
293#endif
294                // The scan segment has a variable length:
295                // we skip the header, and search the next marker,
296                // to transfer the segment (without header) to out_data channel.
297
298                // read 2 bytes (scan header length) from bufio_in
299                uint32_t length = (uint32_t)mwmr_bufio_read_byte( &bufio_in );
300                length = (length<<8) | mwmr_bufio_read_byte( &bufio_in );
301
302                // skip scan segment header
303                mwmr_bufio_skip( &bufio_in , length-2 );
304
305                found_marker = 0;
306                 
307                while ( !found_marker ) 
308                {
309                    // read one byte from bufio_in
310                    byte = mwmr_bufio_read_byte( &bufio_in );
311
312                    if ( byte == 0xFF )  // potential marker
313                    {
314                        // read another byte from bufio_in
315                        byte = mwmr_bufio_read_byte( &bufio_in );
316
317                        if ( byte == 0x00 )   // not a real marker
318                        {
319                            // write one byte to bufio_out_data
320                            mwmr_bufio_write_byte( &bufio_out_data, 0xFF);
321                        }
322                        else                  // it is a marker
323                        {
324                            marker       = 0xFF00 | byte;
325                            found_marker = 1;
326                        }
327                    }
328                    else   // normal byte
329                    {
330                        // write one byte to bufio_out_data
331                        mwmr_bufio_write_byte( &bufio_out_data , byte );
332                    }
333                }
334
335                // flush out_data bufio
336                mwmr_bufio_flush( &bufio_out_data );
337            }
338            //////////////////////////////////////////////////////
339            else if ( marker == EOI_MK )    // end of image marker
340            {
341
342#if (DEBUG_DEMUX > 1)
343if ( (index == DEBUG_CLUSTER_INDEX) || (DEBUG_CLUSTER_INDEX == 0XFFFFFFFF) )
344{ PRINTF("\nDEMUX[%x] found End of Image marker\n", index ) }
345#endif
346                mwmr_bufio_flush( &bufio_out_data );
347                image_done = 1;
348            }
349            ///////////////////////////////////////////////////////////////////////////
350            else if ( ((marker & MK_MSK) == APP_MK) ||   // application specific marker
351                      (marker == COM_MK)            )    // comment marker
352            {
353
354#if (DEBUG_DEMUX > 1)
355if ( (index == DEBUG_CLUSTER_INDEX) || (DEBUG_CLUSTER_INDEX == 0XFFFFFFFF) )
356{ PRINTF("\nDEMUX[%x] found Comment or Application marker\n", index ) }
357#endif
358                // read segment length from bufio_in
359                uint32_t length = (uint32_t)mwmr_bufio_read_byte( &bufio_in );
360                length = (length<<8) | mwmr_bufio_read_byte( &bufio_in );
361
362                // skip segment from bufio_in
363                mwmr_bufio_skip( &bufio_in , length - 2 );
364
365                found_marker = 0;
366            }
367            /////////////////////////////////////////////////////////////////////
368            else if ( marker & 0xFFF0 == 0xFFC0 )  // other Start of Frame marker
369            {
370                giet_pthread_assert( 0 ,
371                "ERROR in demux() : only baseline DCT supported");
372            }       
373            ///////////////////////////
374            else   // any other marker
375            {
376                giet_pthread_assert( 0 ,
377                "ERROR in demux() : unsupported marker in MJPEG stream");
378            }
379        }  // end while ( image_done )
380
381#if DEBUG_DEMUX
382if ( (index == DEBUG_CLUSTER_INDEX) || (DEBUG_CLUSTER_INDEX == 0XFFFFFFFF) )
383{ PRINTF("\nDEMUX[%d] completes image %d at cycle %d\n", index , image , giet_proctime() ) }
384#endif
385        image = image + x_size * y_size;
386
387    }  // end while on images
388
389    giet_pthread_exit( "DEMUX completed" );
390
391}  // end demux()
392
393
394
395
Note: See TracBrowser for help on using the repository browser.