source: soft/giet_vm/applications/mjpeg/mjpeg.c @ 723

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

Introduce application mjpeg.

File size: 10.6 KB
Line 
1/////////////////////////////////////////////////////////////////////////////////////////
2// File   : mjpeg.c   
3// Date   : octobre 2015
4// author : Alain Greiner
5/////////////////////////////////////////////////////////////////////////////////////////
6// This multi-threaded application illustrates "pipe-line" parallelism, and message
7// passing programming model, on top of the POSIX threads API.
8// It makes the parallel decompression of a MJPEG bitstream contained in a file.
9// The application is described as a TCG (Task and Communication Graph), and all
10// communications between threads uses MWMR channels,.
11// It uses the chained buffer DMA component to display the images on the graphic display.
12// It contains 6 types of threads (plus the "main" thread, that makes initialisation)
13// and 7 types of MWMR communication channels:
14// - the TG thread is only mapped in cluster[0,0], but all other threads
15//   (DEMUX, VLD, IQZZ, IDCT, LIBU) are replicated in all clusters.
16// - all MWMR channels are replicated in all clusters.
17// The number of cluster cannot be larger than 16*16.
18// The number of processors per cluster is not constrained.
19// The frame buffer size must fit the decompressed images size.
20// It uses one TTY terminal shared by all tasks.
21/////////////////////////////////////////////////////////////////////////////////////////
22
23#include <stdio.h>
24#include <mwmr_channel.h>
25#include <malloc.h>
26#include <stdlib.h>
27#include "mjpeg.h"
28
29
30// macro to use a shared TTY
31#define PRINTF(...)    lock_acquire( &tty_lock ); \
32                       giet_tty_printf(__VA_ARGS__);  \
33                       lock_release( &tty_lock );
34
35///////////////////////////////////////////////
36//       Global variables
37///////////////////////////////////////////////
38
39uint32_t         fd;    // file descriptor for the file containing the MJPEG stream
40
41mwmr_channel_t*  tg_2_demux[256];         // one per cluster
42mwmr_channel_t*  demux_2_vld_data[256];   // one per cluster
43mwmr_channel_t*  demux_2_vld_huff[256];   // one per cluster
44mwmr_channel_t*  demux_2_iqzz[256];       // one per cluster
45mwmr_channel_t*  vld_2_iqzz[256];         // one per cluster
46mwmr_channel_t*  iqzz_2_idct[256];        // one per cluster
47mwmr_channel_t*  idct_2_libu[256];        // one per cluster
48
49user_lock_t      tty_lock;                // lock protecting shared TTY
50
51uint8_t*         cma_buf[256];            // CMA buffers (one per cluster)
52void*            cma_sts[256];            // CMA buffers status
53
54uint32_t         fbf_width;               // Frame Buffer width
55uint32_t         fbf_height;              // Frame Buffer height
56
57uint32_t         nblocks_h;               // number of blocks in a column
58uint32_t         nblocks_w;               // number of blocks in a row   
59
60uint32_t         date[MAX_IMAGES];        // date of libu completion
61
62////////////////////////////////////////////////
63// declare thread functions
64////////////////////////////////////////////////
65
66extern void tg( );
67extern void demux( uint32_t index );
68extern void vld( uint32_t index );
69extern void iqzz( uint32_t index );
70extern void idct( uint32_t index );
71extern void libu( uint32_t index );
72
73/////////////////////////////////////////
74__attribute__ ((constructor)) void main()
75/////////////////////////////////////////
76{
77    // get platform parameters
78    uint32_t  x_size;
79    uint32_t  y_size;
80    uint32_t  nprocs;
81    giet_procs_number( &x_size , &y_size , &nprocs );
82
83    // shared TTY allocation
84    giet_tty_alloc( 1 );
85    lock_init( &tty_lock );
86
87    // check platform parameters
88    giet_pthread_assert( (nprocs <= 6),
89                         "[MJPEG ERROR] nprocs cannot be larger than 4");
90
91    giet_pthread_assert( (x_size <= 16),
92                         "[MJPEG ERROR] x_size cannot be larger than 16");
93
94    giet_pthread_assert( (y_size <= 16),
95                         "[MJPEG ERROR] y_size cannot be larger than 16");
96
97    giet_pthread_assert( (MAX_IMAGES >= (x_size*y_size)),
98                         "MJPEG ERROR] number of images smaller than x_size * y_size");
99
100    // check frame buffer size
101    giet_fbf_size( &fbf_width , &fbf_height );
102
103    giet_pthread_assert( ((fbf_width & 0x7) == 0) && ((fbf_height & 0x7) == 0) ,
104                         "[MJPEG ERROR] image width and height must be multiple of 8");
105
106    // request frame buffer and CMA channel allocation
107    giet_fbf_alloc();
108    giet_fbf_cma_alloc( x_size * y_size );
109
110    // file name and image size acquisition
111    char          file_pathname[256];
112    uint32_t      image_width;
113    uint32_t      image_height;
114
115    PRINTF("\n[MJPEG] enter path for JPEG stream file\n> "); 
116    giet_tty_gets( file_pathname , 256 );
117
118    if ( file_pathname[0] == 0 )
119    {
120        strcpy( file_pathname , "/misc/plan_48.mjpg" );
121        image_width  = 48;
122        image_height = 48;
123        PRINTF("\n\n[MJPEG] use /misc/plan_48.mjpg\n" );
124    }
125    else
126    {
127        PRINTF("\n[MJPEG] enter image width\n> "); 
128        giet_tty_getw( &image_width );
129        PRINTF("\n[MJPEG] enter image height\n> "); 
130        giet_tty_getw( &image_height );
131        PRINTF("\n"); 
132    }
133
134    giet_pthread_assert( (image_width == fbf_width) && (image_height == fbf_height) ,
135                         "[MJPEG ERROR] image size doesn't fit frame buffer size");
136 
137    // compute nblocks_h & nblocks_w
138    nblocks_w = fbf_width / 8;
139    nblocks_h = fbf_height / 8;
140
141    // open file containing the MJPEG bit stream
142    int fd = giet_fat_open( file_pathname , 0 );
143
144    giet_pthread_assert( (fd >= 0),
145                         "[MJPEG ERROR] cannot open MJPEG stream file");
146
147    // index for loops
148    uint32_t x;
149    uint32_t y;
150    uint32_t n;
151
152    uint32_t*  buffer; 
153
154    // initialise distributed heap,
155    // allocate MWMR channels
156    // allocate buffers for CMA
157    for ( x = 0 ; x < x_size ; x++ ) 
158    {
159        for ( y = 0 ; y < y_size ; y++ ) 
160        {
161            uint32_t index = x*y_size + y;
162
163            // initialise heap[x][y]
164            heap_init( x , y );
165
166            // allocate MWMR channels in cluster[x][y]
167            tg_2_demux[index]       = remote_malloc( sizeof( mwmr_channel_t ) , x , y );
168            buffer                  = remote_malloc( 4 * TG_2_DEMUX_DEPTH , x , y );
169            mwmr_init( tg_2_demux[index] , buffer , 1 , TG_2_DEMUX_DEPTH );
170
171            demux_2_vld_data[index] = remote_malloc( sizeof( mwmr_channel_t ) , x , y );
172            buffer                  = remote_malloc( 4 * DEMUX_2_VLD_DATA_DEPTH , x , y );
173            mwmr_init( demux_2_vld_data[index] , buffer , 1 , DEMUX_2_VLD_DATA_DEPTH );
174
175            demux_2_vld_huff[index] = remote_malloc( sizeof( mwmr_channel_t ) , x , y );
176            buffer                  = remote_malloc( 4 * DEMUX_2_VLD_HUFF_DEPTH , x , y );
177            mwmr_init( demux_2_vld_huff[index] , buffer , 1 , DEMUX_2_VLD_HUFF_DEPTH );
178
179            demux_2_iqzz[index]     = remote_malloc( sizeof( mwmr_channel_t ) , x , y );
180            buffer                  = remote_malloc( 4 * DEMUX_2_IQZZ_DEPTH , x , y );
181            mwmr_init( demux_2_iqzz[index] , buffer , 1 , DEMUX_2_IQZZ_DEPTH );
182
183            vld_2_iqzz[index]       = remote_malloc( sizeof( mwmr_channel_t ) , x , y );
184            buffer                  = remote_malloc( 4 * VLD_2_IQZZ_DEPTH , x , y );
185            mwmr_init( vld_2_iqzz[index] , buffer , 1 , VLD_2_IQZZ_DEPTH );
186
187            iqzz_2_idct[index]      = remote_malloc( sizeof( mwmr_channel_t ) , x , y );
188            buffer                  = remote_malloc( 4 * IQZZ_2_IDCT_DEPTH , x , y );
189            mwmr_init( iqzz_2_idct[index] , buffer , 1 , IQZZ_2_IDCT_DEPTH );
190
191            idct_2_libu[index]      = remote_malloc( sizeof( mwmr_channel_t ) , x , y );
192            buffer                  = remote_malloc( 4 * IDCT_2_LIBU_DEPTH , x , y );
193            mwmr_init( idct_2_libu[index] , buffer , 1 , IDCT_2_LIBU_DEPTH );
194
195            // allocate and register CMA buffers in cluster[x][y]
196            cma_buf[index] = remote_malloc( fbf_width * fbf_height , x , y );
197            cma_sts[index] = remote_malloc( 64 , x , y );
198            giet_fbf_cma_init_buf( index , cma_buf[index] , cma_sts[index] );
199        }
200    }
201
202    // start CMA channel
203    giet_fbf_cma_start( );
204
205    PRINTF("\n[MJPEG] main thread completes initialisation for %d cores\n", 
206           x_size * y_size * nprocs )
207
208    // thread trdid for pthread_create() and pthread_join()
209    pthread_t   trdid_tg; 
210    pthread_t   trdid_demux[256]; 
211    pthread_t   trdid_vld[256]; 
212    pthread_t   trdid_iqzz[256]; 
213    pthread_t   trdid_idct[256]; 
214    pthread_t   trdid_libu[256]; 
215
216    uint32_t index;
217
218    // launch all threads : precise mapping is defined in the mjpeg.py file
219
220    if ( giet_pthread_create( &trdid_tg, NULL, &tg , NULL ) )
221    giet_pthread_exit( "error launching thread tg\n");
222
223    for ( index = 0 ; index < (x_size * y_size) ; index++ )
224    {
225        if ( giet_pthread_create( &trdid_demux[index], NULL, &demux , (void*)index ) )
226        giet_pthread_exit( "error launching thread demux\n");
227
228        if ( giet_pthread_create( &trdid_vld[index], NULL, &vld , (void*)index ) )
229        giet_pthread_exit( "error launching thread vld\n");
230
231        if ( giet_pthread_create( &trdid_iqzz[index], NULL, &iqzz , (void*)index ) )
232        giet_pthread_exit( "error launching thread iqzz");
233
234        if ( giet_pthread_create( &trdid_idct[index], NULL, &idct , (void*)index ) )
235        giet_pthread_exit( "error launching thread idct\n");
236
237        if ( giet_pthread_create( &trdid_libu[index], NULL, &libu , (void*)index ) )
238        giet_pthread_exit( "error launching thread libu\n");
239    }
240
241    // wait all threads completion
242
243    if ( giet_pthread_join( trdid_tg , NULL ) )
244    { PRINTF("\n[MJPEG ERROR] calling giet_pthread_join() for tg\n" ) }
245
246    for ( index = 0 ; index < (x_size * y_size) ; index++ )
247    {
248        if ( giet_pthread_join( trdid_demux[index] , NULL ) )
249        { PRINTF("\n[MJPEG ERROR] calling giet_pthread_join() for demux[%d]\n", index ) }
250
251        if ( giet_pthread_join( trdid_vld[index] , NULL ) )
252        { PRINTF("\n[MJPEG ERROR] calling giet_pthread_join() for vld[%d]\n", index ) }
253
254        if ( giet_pthread_join( trdid_iqzz[index] , NULL ) )
255        { PRINTF("\n[MJPEG ERROR] calling giet_pthread_join() for iqzz[%d]\n", index ) }
256
257        if ( giet_pthread_join( trdid_idct[index] , NULL ) )
258        { PRINTF("\n[MJPEG ERROR] calling giet_pthread_join() for idct[%d]\n", index ) }
259
260        if ( giet_pthread_join( trdid_libu[index] , NULL ) )
261        { PRINTF("\n[MJPEG ERROR] calling giet_pthread_join() for libu[%d]\n", index ) }
262    }
263
264    // instrumentation
265
266    uint32_t image;
267    PRINTF("\n[MJPEG] Instumentation Results\n" )
268    for ( image = 0 ; image < MAX_IMAGES ; image++ )
269    { PRINTF(" - Image %d : completed at cycle %d\n", image , date[image]) }
270
271    giet_pthread_exit( "main completed" );
272   
273} // end main()
274
Note: See TracBrowser for help on using the repository browser.