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

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

Introduce application mjpeg.

File size: 13.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]\n", index, x, y, p )
89
90    // initialise BUFIO for MWMR channel <in>
91    mwmr_channel_t*   mwmr_in = tg_2_demux[index];
92    mwmr_bufio_t      bufio_in;
93    uint8_t           in_buffer[64];
94    mwmr_bufio_init( &bufio_in , in_buffer , 64 , 1 , mwmr_in );
95
96#if (DEBUG_DEMUX > 1)
97PRINTF("\nDEMUX[%d] <in> : &mwmr = %x / &bufio = %x\n", 
98       index , mwmr_in , &bufio_in )
99#endif
100
101    // initialise BUFIO for MWMR channel <out_quanti>
102    mwmr_channel_t*   mwmr_out_quanti = demux_2_iqzz[index];
103    mwmr_bufio_t      bufio_out_quanti;
104    uint8_t           out_quanti_buffer[64];
105    mwmr_bufio_init( &bufio_out_quanti , out_quanti_buffer , 64 , 0 , mwmr_out_quanti );
106
107#if (DEBUG_DEMUX > 1)
108PRINTF("\nDEMUX[%d] : <out_quanti> : mwmr = %x / &bufio = %x\n",
109       index , mwmr_out_quanti , &bufio_out_quanti )
110#endif
111
112    // initialise BUFIO for MWMR channel <out_huff>
113    mwmr_channel_t*   mwmr_out_huff = demux_2_vld_huff[index];
114    mwmr_bufio_t      bufio_out_huff;
115    uint8_t           out_huff_buffer[64];
116    mwmr_bufio_init( &bufio_out_huff , out_huff_buffer , 64 , 0 , mwmr_out_huff );
117
118#if (DEBUG_DEMUX > 1)
119PRINTF("\nDEMUX[%d] : <out_huff> : mwmr = %x / &bufio = %x\n",
120       index , mwmr_out_huff , &bufio_out_huff )
121#endif
122
123    // initialise BUFIO for MWMR channel <out_data>
124    mwmr_channel_t*   mwmr_out_data = demux_2_vld_data[index];
125    mwmr_bufio_t      bufio_out_data;
126    uint8_t           out_data_buffer[64];
127    mwmr_bufio_init( &bufio_out_data , out_data_buffer , 64 , 0 , mwmr_out_data );
128
129#if (DEBUG_DEMUX > 1)
130PRINTF("\nDEMUX[%d] : <out_data> : mwmr = %x / &bufio = %x\n",
131       index , mwmr_out_data , &bufio_out_data )
132#endif
133
134    uint32_t   found_marker;
135    uint32_t   image_done;
136
137    uint16_t   marker;          // 16 bits marker read from bufio_in
138    uint32_t   word;            // 32 bits word read from bufio_in
139    uint8_t    byte;            // one byte read from bufio_in
140    uint32_t   byte_count;      // byte counter in a given compressed image
141   
142    uint32_t   image = index;
143
144    // infinite loop : one image per iteration
145    while ( image < MAX_IMAGES ) 
146    {
147        // search start of image marker
148        do 
149        {
150            marker = get_next_marker( &bufio_in );
151
152#if (DEBUG_DEMUX > 1)
153if ( marker == SOI_MK ) PRINTF("\nDEMUX[%x] found Start of Image marker\n", index )
154#endif
155        } 
156        while ( marker != SOI_MK );
157
158        found_marker = 0;
159        image_done   = 0;
160
161        // analyse image
162        while ( !image_done ) 
163        {
164            // search next marker if required
165            if ( !found_marker ) 
166            {
167                marker = get_next_marker( &bufio_in );
168            }
169
170            ////////////////////////////////////////////
171            if ( marker == SOF_MK )   // start of frame
172            {
173
174#if (DEBUG_DEMUX > 1)
175PRINTF("\nDEMUX[%x] found Start of Frame marker\n", index )
176#endif
177                // Only one component per image is supported
178                // we check the image size (must fit Frame Buffer),
179                // and skip the fixed length frame header
180
181                // skip 3 bytes (Lf , P) from bufio_in
182                mwmr_bufio_skip( &bufio_in , 3 );
183
184                // read width & height from bufio_in
185                uint32_t height = (uint32_t)mwmr_bufio_read_byte( &bufio_in );
186                height = (height<<8) | mwmr_bufio_read_byte( &bufio_in );
187
188                uint32_t width  = (uint32_t)mwmr_bufio_read_byte( &bufio_in );
189                width  = (width<<8)  | mwmr_bufio_read_byte( &bufio_in );
190
191                giet_pthread_assert( (fbf_width == width) && (fbf_height == height) ,
192                "ERROR in demux() : image size doesn't fit frame buffer size" );
193
194                // read one byte (number of components) from bufio_in
195                uint8_t nf  = mwmr_bufio_read_byte( &bufio_in );
196
197                giet_pthread_assert( (nf==1) ,
198                "ERROR in demux() : only one component supported" );
199
200                // skip 3 bytes (C0,H0,V0,TQ0)
201                mwmr_bufio_skip( &bufio_in , 3 );
202
203                found_marker = 0;
204            }
205            ///////////////////////////////////////////////////////////
206            else if ( marker == DQT_MK )   // quantization table marker
207            {
208
209#if (DEBUG_DEMUX > 1)
210PRINTF("\nDEMUX[%x] found Quantization Table marker\n", index )
211#endif
212                // The  quantisation table segment being fixed length,
213                // we skip the header and write the 64 coefs to out_quanti channel.
214
215                uint32_t  n;
216
217                // skip three first bytes (Lq , PqTq) from bufio_in
218                mwmr_bufio_skip( &bufio_in , 3 );
219
220                // write 64 coefs (one byte each)
221                for ( n = 0 ; n < 64 ; n++ )
222                {
223                    uint8_t byte = mwmr_bufio_read_byte( &bufio_in );
224                    mwmr_bufio_write_byte( &bufio_out_quanti , byte );
225                }
226
227                // flush out_quanti buffer
228                mwmr_bufio_flush( &bufio_out_quanti );
229
230                found_marker = 0;
231            }
232            ///////////////////////////////////////////////////////
233            else if ( marker == DHT_MK )   // Huffman table marker
234            {
235
236#if (DEBUG_DEMUX > 1)
237PRINTF("\nDEMUX[%x] found Huffman Table marker\n", index )
238#endif
239                // The Huffman Table segment being variable length,
240                // we search the next marker, and transfer the complete
241                // segment (without marker) to the out_huff channel.
242
243                found_marker = 0;
244
245                while ( !found_marker ) 
246                {
247                    // read one byte from bufio_in
248                    byte = mwmr_bufio_read_byte( &bufio_in );
249
250                    if ( byte == 0xFF )  // potential marker
251                    {
252                        // read another byte from bufio_in
253                        byte = mwmr_bufio_read_byte( &bufio_in );
254
255                        if (byte == 0)  // not a real marker
256                        {
257                            // write one byte to bufio_out_huff
258                            mwmr_bufio_write_byte( &bufio_out_huff, 0xFF );
259                        }
260                        else            // it's a marker
261                        {
262                            marker       = 0xFF00 | byte;
263                            found_marker = 1;
264                        }
265                    }
266                    else                // normal byte
267                    {
268                        // write one byte to bufio_out_huff
269                        mwmr_bufio_write_byte( &bufio_out_huff , byte );
270                    }
271                }
272
273                // flush out_huff bufio
274                mwmr_bufio_flush( &bufio_out_huff );
275            } 
276            ///////////////////////////////////////////////////////
277            else if ( marker == SOS_MK )    // start of scan marker
278            {
279
280#if (DEBUG_DEMUX > 1)
281PRINTF("\nDEMUX[%x] found Start of Scan marker\n", index )
282#endif
283                // The scan segment has a variable length:
284                // we skip the header, and search the next marker,
285                // to transfer the segment (without header) to out_data channel.
286
287                // read 2 bytes (scan header length) from bufio_in
288                uint32_t length = (uint32_t)mwmr_bufio_read_byte( &bufio_in );
289                length = (length<<8) | mwmr_bufio_read_byte( &bufio_in );
290
291                // skip scan segment header
292                mwmr_bufio_skip( &bufio_in , length-2 );
293
294                found_marker = 0;
295                 
296                while ( !found_marker ) 
297                {
298                    // read one byte from bufio_in
299                    byte = mwmr_bufio_read_byte( &bufio_in );
300
301                    if ( byte == 0xFF )  // potential marker
302                    {
303                        // read another byte from bufio_in
304                        byte = mwmr_bufio_read_byte( &bufio_in );
305
306                        if ( byte == 0x00 )   // not a real marker
307                        {
308                            // write one byte to bufio_out_data
309                            mwmr_bufio_write_byte( &bufio_out_data, 0xFF);
310                        }
311                        else                  // it is a marker
312                        {
313                            marker       = 0xFF00 | byte;
314                            found_marker = 1;
315                        }
316                    }
317                    else   // normal byte
318                    {
319                        // write one byte to bufio_out_data
320                        mwmr_bufio_write_byte( &bufio_out_data , byte );
321                    }
322                }
323
324                // flush out_data bufio
325                mwmr_bufio_flush( &bufio_out_data );
326            }
327            //////////////////////////////////////////////////////
328            else if ( marker == EOI_MK )    // end of image marker
329            {
330
331#if (DEBUG_DEMUX > 1)
332PRINTF("\nDEMUX[%x] found End of Image marker\n", index )
333#endif
334                mwmr_bufio_flush( &bufio_out_data );
335                image_done = 1;
336            }
337            ///////////////////////////////////////////////////////////////////////////
338            else if ( ((marker & MK_MSK) == APP_MK) ||   // application specific marker
339                      (marker == COM_MK)            )    // comment marker
340            {
341
342#if (DEBUG_DEMUX > 1)
343PRINTF("\nDEMUX[%x] found Comment or Application marker\n", index )
344#endif
345                // read segment length from bufio_in
346                uint32_t length = (uint32_t)mwmr_bufio_read_byte( &bufio_in );
347                length = (length<<8) | mwmr_bufio_read_byte( &bufio_in );
348
349                // skip segment from bufio_in
350                mwmr_bufio_skip( &bufio_in , length - 2 );
351
352                found_marker = 0;
353            }
354            /////////////////////////////////////////////////////////////////////
355            else if ( marker & 0xFFF0 == 0xFFC0 )  // other Start of Frame marker
356            {
357                giet_pthread_assert( 0 ,
358                "ERROR in demux() : only baseline DCT supported");
359            }       
360            ///////////////////////////
361            else   // any other marker
362            {
363                giet_pthread_assert( 0 ,
364                "ERROR in demux() : unsupported marker in MJPEG stream");
365            }
366        }  // end while ( image_done )
367
368#if DEBUG_DEMUX
369PRINTF("\nDEMUX[%d] completes image %d at cycle %d\n", index , image , giet_proctime() )
370#endif
371        image = image + x_size * y_size;
372
373    }  // end while on images
374
375    giet_pthread_exit( "demux completed" );
376
377}  // end demux()
378
379
380
381
Note: See TracBrowser for help on using the repository browser.