]> git.sesse.net Git - vlc/blob - src/audio_output/audio_output.c
267fb7568283b8c9284d3d0465cce0f57eebe7de
[vlc] / src / audio_output / audio_output.c
1 /*****************************************************************************
2  * audio_output.c : audio output thread
3  * (c)1999 VideoLAN
4  *****************************************************************************/
5
6 /* TODO:
7  *
8  * - Passer un certain nombre de "fonctions" (genre add_samples) en macro ou
9  *   inline
10  * - Faire les optimisations dans les fonctions threads :
11  *   = Stocker les "petits calculs" dans des variables au lieu de les refaire
12  *     à chaque boucle
13  *   = Utiliser des tables pour les gros calculs
14  * - Faire une structure différente pour intf/adec fifo
15  *
16  */
17
18 /*****************************************************************************
19  * Preamble
20  *****************************************************************************/
21 #include <unistd.h>
22
23 #include <stdio.h>                                           /* "intf_msg.h" */
24 #include <stdlib.h>                            /* calloc(), malloc(), free() */
25
26 #include <dlfcn.h>                                                /* plugins */
27
28 #include "common.h"
29 #include "config.h"
30 #include "mtime.h"                             /* mtime_t, mdate(), msleep() */
31 #include "vlc_thread.h"
32
33 #include "intf_msg.h"                        /* intf_DbgMsg(), intf_ErrMsg() */
34
35 #include "audio_output.h"
36 #include "main.h"
37
38 /*****************************************************************************
39  * Local prototypes
40  *****************************************************************************/
41
42 static int aout_SpawnThread( aout_thread_t * p_aout );
43
44 /* Creating as much aout_Thread functions as configurations is one solution,
45  * examining the different cases in the Thread loop of an unique function is
46  * another. I chose the first solution. */
47 void aout_Thread_S8_Mono        ( aout_thread_t * p_aout );
48 void aout_Thread_U8_Mono        ( aout_thread_t * p_aout );
49 void aout_Thread_S16_Mono       ( aout_thread_t * p_aout );
50 void aout_Thread_U16_Mono       ( aout_thread_t * p_aout );
51 void aout_Thread_S8_Stereo      ( aout_thread_t * p_aout );
52 void aout_Thread_U8_Stereo      ( aout_thread_t * p_aout );
53 void aout_Thread_S16_Stereo     ( aout_thread_t * p_aout );
54 void aout_Thread_U16_Stereo     ( aout_thread_t * p_aout );
55
56 static __inline__ void InitializeIncrement( aout_increment_t * p_increment, long l_numerator, long l_denominator );
57 static __inline__ int NextFrame( aout_thread_t * p_aout, aout_fifo_t * p_fifo, mtime_t aout_date );
58
59 /*****************************************************************************
60  * aout_CreateThread: initialize audio thread
61  *****************************************************************************/
62 aout_thread_t *aout_CreateThread( int *pi_status )
63 {
64     aout_thread_t * p_aout;                             /* thread descriptor */
65     char * psz_method;
66     char * psz_plugin;
67 #if 0
68     int             i_status;                                 /* thread status */
69 #endif
70
71     /* Allocate descriptor */
72     p_aout = (aout_thread_t *) malloc( sizeof(aout_thread_t) );
73     if( p_aout == NULL )
74     {
75         return( NULL );
76     }
77
78     /* Initialize method-dependent functions */
79     psz_method = main_GetPszVariable( AOUT_METHOD_VAR, AOUT_DEFAULT_METHOD );
80
81     psz_plugin = malloc( sizeof("./audio_output/aout_.so") + strlen(psz_method) );
82     sprintf( psz_plugin, "./audio_output/aout_%s.so", psz_method );
83
84     p_aout->p_aout_plugin = dlopen( psz_plugin, RTLD_NOW | RTLD_GLOBAL );
85
86     if( p_aout->p_aout_plugin == NULL )
87     {
88         intf_ErrMsg( "error: could not open audio plugin %s\n", psz_plugin );
89         free( psz_plugin );
90         free( p_aout );
91         return( NULL );
92     }
93     free( psz_plugin );
94
95     /* Get plugins */
96     p_aout->p_sys_open =         dlsym(p_aout->p_aout_plugin, "aout_SysOpen");
97     p_aout->p_sys_reset =        dlsym(p_aout->p_aout_plugin, "aout_SysReset");
98     p_aout->p_sys_setformat =    dlsym(p_aout->p_aout_plugin, "aout_SysSetFormat");
99     p_aout->p_sys_setchannels =  dlsym(p_aout->p_aout_plugin, "aout_SysSetChannels");
100     p_aout->p_sys_setrate =      dlsym(p_aout->p_aout_plugin, "aout_SysSetRate");
101     p_aout->p_sys_getbufinfo =   dlsym(p_aout->p_aout_plugin, "aout_SysGetBufInfo");
102     p_aout->p_sys_playsamples =  dlsym(p_aout->p_aout_plugin, "aout_SysPlaySamples");
103     p_aout->p_sys_close =        dlsym(p_aout->p_aout_plugin, "aout_SysClose");
104
105     /*
106      * Initialize audio device
107      */
108     if ( p_aout->p_sys_open( p_aout ) )
109     {
110         dlclose( p_aout->p_aout_plugin );
111         free( p_aout );
112         return( NULL );
113     }
114
115     p_aout->b_stereo = ( p_aout->i_channels == 2 ) ? 1 : 0; /* FIXME: only works
116                                                    for i_channels == 1 or 2 ??*/
117
118     if ( p_aout->p_sys_reset( p_aout ) )
119     {
120         p_aout->p_sys_close( p_aout );
121         dlclose( p_aout->p_aout_plugin );
122         free( p_aout );
123         return( NULL );
124     }
125     if ( p_aout->p_sys_setformat( p_aout ) )
126     {
127         p_aout->p_sys_close( p_aout );
128         dlclose( p_aout->p_aout_plugin );
129         free( p_aout );
130         return( NULL );
131     }
132     if ( p_aout->p_sys_setchannels( p_aout ) )
133     {
134         p_aout->p_sys_close( p_aout );
135         dlclose( p_aout->p_aout_plugin );
136         free( p_aout );
137         return( NULL );
138     }
139     if ( p_aout->p_sys_setrate( p_aout ) )
140     {
141         p_aout->p_sys_close( p_aout );
142         dlclose( p_aout->p_aout_plugin );
143         free( p_aout );
144         return( NULL );
145     }
146
147     /* FIXME: maybe it would be cleaner to change SpawnThread prototype
148      * see vout to handle status correctly ?? however, it is not critical since
149      * this thread is only called in main and all calls are blocking */
150     if( aout_SpawnThread( p_aout ) )
151     {
152         p_aout->p_sys_close( p_aout );
153         dlclose( p_aout->p_aout_plugin );
154         free( p_aout );
155         return( NULL );
156     }
157
158     return( p_aout );
159 }
160
161 /*****************************************************************************
162  * aout_SpawnThread
163  *****************************************************************************/
164 static int aout_SpawnThread( aout_thread_t * p_aout )
165 {
166     int             i_fifo;
167     long            l_bytes;
168     void *          aout_thread = NULL;
169
170     intf_DbgMsg("aout debug: spawning audio output thread (%p)\n", p_aout);
171
172     /* We want the audio output thread to live */
173     p_aout->b_die = 0;
174
175     /* Initialize the fifos lock */
176     vlc_mutex_init( &p_aout->fifos_lock );
177     /* Initialize audio fifos : set all fifos as empty and initialize locks */
178     for ( i_fifo = 0; i_fifo < AOUT_MAX_FIFOS; i_fifo++ )
179     {
180         p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO;
181         vlc_mutex_init( &p_aout->fifo[i_fifo].data_lock );
182         vlc_cond_init( &p_aout->fifo[i_fifo].data_wait );
183     }
184
185     /* Compute the size (in audio units) of the audio output buffer. Although
186      * AOUT_BUFFER_DURATION is given in microseconds, the output rate is given
187      * in Hz, that's why we need to divide by 10^6 microseconds (1 second) */
188     p_aout->l_units = (long)( ((s64)p_aout->l_rate * AOUT_BUFFER_DURATION) / 1000000 );
189     p_aout->l_msleep = (long)( ((s64)p_aout->l_units * 1000000) / (s64)p_aout->l_rate );
190
191     /* Make aout_thread point to the right thread function, and compute the
192      * byte size of the audio output buffer */
193     switch ( p_aout->i_channels )
194     {
195         /* Audio output is mono */
196         case 1:
197             switch ( p_aout->i_format )
198             {
199                 case AOUT_FMT_U8:
200                     l_bytes = 1 * sizeof(u8) * p_aout->l_units;
201                     aout_thread = (void *)aout_Thread_U8_Mono;
202                     break;
203
204                 case AOUT_FMT_S8:
205                     l_bytes = 1 * sizeof(s8) * p_aout->l_units;
206                     aout_thread = (void *)aout_Thread_S8_Mono;
207                     break;
208
209                 case AOUT_FMT_U16_LE:
210                 case AOUT_FMT_U16_BE:
211                     l_bytes = 1 * sizeof(u16) * p_aout->l_units;
212                     aout_thread = (void *)aout_Thread_U16_Mono;
213                     break;
214
215                 case AOUT_FMT_S16_LE:
216                 case AOUT_FMT_S16_BE:
217                     l_bytes = 1 * sizeof(s16) * p_aout->l_units;
218                     aout_thread = (void *)aout_Thread_S16_Mono;
219                     break;
220
221                 default:
222                     intf_ErrMsg( "aout error: unknown audio output format (%i)\n",
223                                  p_aout->i_format );
224                     return( -1 );
225             }
226             break;
227
228         /* Audio output is stereo */
229         case 2:
230             switch ( p_aout->i_format )
231             {
232                 case AOUT_FMT_U8:
233                     l_bytes = 2 * sizeof(u8) * p_aout->l_units;
234                     aout_thread = (void *)aout_Thread_U8_Stereo;
235                     break;
236
237                 case AOUT_FMT_S8:
238                     l_bytes = 2 * sizeof(s8) * p_aout->l_units;
239                     aout_thread = (void *)aout_Thread_S8_Stereo;
240                     break;
241
242                 case AOUT_FMT_U16_LE:
243                 case AOUT_FMT_U16_BE:
244                     l_bytes = 2 * sizeof(u16) * p_aout->l_units;
245                     aout_thread = (void *)aout_Thread_U16_Stereo;
246                     break;
247
248                 case AOUT_FMT_S16_LE:
249                 case AOUT_FMT_S16_BE:
250                     l_bytes = 2 * sizeof(s16) * p_aout->l_units;
251                     aout_thread = (void *)aout_Thread_S16_Stereo;
252                     break;
253
254                 default:
255                     intf_ErrMsg("aout error: unknown audio output format (%i)\n",
256                         p_aout->i_format);
257                     return( -1 );
258             }
259             break;
260
261         default:
262             intf_ErrMsg("aout error: unknown number of audio channels (%i)\n",
263                 p_aout->i_channels );
264             return( -1 );
265     }
266
267     /* Allocate the memory needed by the audio output buffers, and set to zero
268      * the s32 buffer's memory */
269     if ( (p_aout->buffer = malloc(l_bytes)) == NULL )
270     {
271         intf_ErrMsg("aout error: not enough memory to create the output buffer\n");
272         return( -1 );
273     }
274     if ( (p_aout->s32_buffer = (s32 *)calloc(p_aout->l_units, sizeof(s32) << ( p_aout->b_stereo))) == NULL )
275     {
276         intf_ErrMsg("aout error: not enough memory to create the s32 output buffer\n");
277         free( p_aout->buffer );
278         return( -1 );
279     }
280
281     /* Before launching the thread, we try to predict the date of the first
282      * audio unit in the first output buffer */
283     p_aout->date = mdate() - 1000000;
284
285     /* Launch the thread */
286     if ( vlc_thread_create( &p_aout->thread_id, "audio output", (vlc_thread_func_t)aout_thread, p_aout ) )
287     {
288         intf_ErrMsg("aout error: can't spawn audio output thread (%p)\n", p_aout);
289         free( p_aout->buffer );
290         free( p_aout->s32_buffer );
291         return( -1 );
292     }
293
294     intf_DbgMsg("aout debug: audio output thread (%p) spawned\n", p_aout);
295     return( 0 );
296 }
297
298 /*****************************************************************************
299  * aout_DestroyThread
300  *****************************************************************************/
301 void aout_DestroyThread( aout_thread_t * p_aout, int *pi_status )
302 {
303     /* FIXME: pi_status is not handled correctly: check vout how to do!?? */
304
305     intf_DbgMsg("aout debug: requesting termination of audio output thread (%p)\n", p_aout);
306
307     /* Ask thread to kill itself and wait until it's done */
308     p_aout->b_die = 1;
309     vlc_thread_join( p_aout->thread_id ); /* only if pi_status is NULL */
310
311     /* Free the allocated memory */
312     free( p_aout->buffer );
313     free( p_aout->s32_buffer );
314
315     /* Free the structure */
316     p_aout->p_sys_close( p_aout );
317     intf_DbgMsg("aout debug: audio device (%s) closed\n", p_aout->psz_device);
318
319     /* Close plugin */
320     dlclose( p_aout->p_aout_plugin );
321
322     /* Free structure */
323     free( p_aout );
324 }
325
326 /*****************************************************************************
327  * aout_CreateFifo
328  *****************************************************************************/
329 aout_fifo_t * aout_CreateFifo( aout_thread_t * p_aout, aout_fifo_t * p_fifo )
330 {
331     int i_fifo;
332
333     /* Take the fifos lock */
334     vlc_mutex_lock( &p_aout->fifos_lock );
335
336     /* Looking for a free fifo structure */
337     for ( i_fifo = 0; i_fifo < AOUT_MAX_FIFOS; i_fifo++ )
338     {
339         if ( p_aout->fifo[i_fifo].i_type == AOUT_EMPTY_FIFO)
340         {
341             break;
342         }
343     }
344     if ( i_fifo == AOUT_MAX_FIFOS )
345     {
346         intf_ErrMsg("aout error: no empty fifo available\n");
347         vlc_mutex_unlock( &p_aout->fifos_lock );
348         return( NULL );
349     }
350
351     /* Initialize the new fifo structure */
352     switch ( p_aout->fifo[i_fifo].i_type = p_fifo->i_type )
353     {
354         case AOUT_INTF_MONO_FIFO:
355         case AOUT_INTF_STEREO_FIFO:
356             p_aout->fifo[i_fifo].b_die = 0;
357
358             p_aout->fifo[i_fifo].i_channels = p_fifo->i_channels;
359             p_aout->fifo[i_fifo].b_stereo = p_fifo->b_stereo;
360             p_aout->fifo[i_fifo].l_rate = p_fifo->l_rate;
361
362             p_aout->fifo[i_fifo].buffer = p_fifo->buffer;
363
364             p_aout->fifo[i_fifo].l_unit = 0;
365             InitializeIncrement( &p_aout->fifo[i_fifo].unit_increment, p_fifo->l_rate, p_aout->l_rate );
366             p_aout->fifo[i_fifo].l_units = p_fifo->l_units;
367             break;
368
369         case AOUT_ADEC_MONO_FIFO:
370         case AOUT_ADEC_STEREO_FIFO:
371             p_aout->fifo[i_fifo].b_die = 0;
372
373             p_aout->fifo[i_fifo].i_channels = p_fifo->i_channels;
374             p_aout->fifo[i_fifo].b_stereo = p_fifo->b_stereo;
375             p_aout->fifo[i_fifo].l_rate = p_fifo->l_rate;
376
377             p_aout->fifo[i_fifo].l_frame_size = p_fifo->l_frame_size;
378             /* Allocate the memory needed to store the audio frames. As the
379              * fifo is a rotative fifo, we must be able to find out whether the
380              * fifo is full or empty, that's why we must in fact allocate memory
381              * for (AOUT_FIFO_SIZE+1) audio frames. */
382             if ( (p_aout->fifo[i_fifo].buffer = malloc( sizeof(s16)*(AOUT_FIFO_SIZE+1)*p_fifo->l_frame_size )) == NULL )
383             {
384                 intf_ErrMsg("aout error: not enough memory to create the frames buffer\n");
385                 p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO;
386                 vlc_mutex_unlock( &p_aout->fifos_lock );
387                 return( NULL );
388             }
389
390             /* Allocate the memory needed to store the dates of the frames */
391             if ( (p_aout->fifo[i_fifo].date = (mtime_t *)malloc( sizeof(mtime_t)*(AOUT_FIFO_SIZE+1) )) == NULL )
392             {
393                 intf_ErrMsg("aout error: not enough memory to create the dates buffer\n");
394                 free( p_aout->fifo[i_fifo].buffer );
395                 p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO;
396                 vlc_mutex_unlock( &p_aout->fifos_lock );
397                 return( NULL );
398             }
399
400             /* Set the fifo's buffer as empty (the first frame that is to be
401              * played is also the first frame that is not to be played) */
402             p_aout->fifo[i_fifo].l_start_frame = 0;
403             /* p_aout->fifo[i_fifo].l_next_frame = 0; */
404             p_aout->fifo[i_fifo].l_end_frame = 0;
405
406             /* Waiting for the audio decoder to compute enough frames to work
407              * out the fifo's current rate (as soon as the decoder has decoded
408              * enough frames, the members of the fifo structure that are not
409              * initialized now will be calculated) */
410             p_aout->fifo[i_fifo].b_start_frame = 0;
411             p_aout->fifo[i_fifo].b_next_frame = 0;
412             break;
413
414         default:
415             intf_ErrMsg("aout error: unknown fifo type (%i)\n", p_aout->fifo[i_fifo].i_type);
416             p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO;
417             vlc_mutex_unlock( &p_aout->fifos_lock );
418             return( NULL );
419     }
420
421     /* Release the fifos lock */
422     vlc_mutex_unlock( &p_aout->fifos_lock );
423
424     /* Return the pointer to the fifo structure */
425     intf_DbgMsg("aout debug: audio output fifo (%p) allocated\n", &p_aout->fifo[i_fifo]);
426     return( &p_aout->fifo[i_fifo] );
427 }
428
429 /*****************************************************************************
430  * aout_DestroyFifo
431  *****************************************************************************/
432 void aout_DestroyFifo( aout_fifo_t * p_fifo )
433 {
434     intf_DbgMsg("aout debug: requesting destruction of audio output fifo (%p)\n", p_fifo);
435     p_fifo->b_die = 1;
436 }
437
438 /* Here are the local macros */
439
440 #define UPDATE_INCREMENT( increment, integer ) \
441     if ( ((increment).l_remainder += (increment).l_euclidean_remainder) >= 0 )\
442     { \
443         (integer) += (increment).l_euclidean_integer + 1; \
444         (increment).l_remainder -= (increment).l_euclidean_denominator; \
445     } \
446     else \
447     { \
448         (integer) += (increment).l_euclidean_integer; \
449     }
450
451 /* Following functions are local */
452
453 /*****************************************************************************
454  * InitializeIncrement
455  *****************************************************************************/
456 static __inline__ void InitializeIncrement( aout_increment_t * p_increment, long l_numerator, long l_denominator )
457 {
458     p_increment->l_remainder = -l_denominator;
459
460     p_increment->l_euclidean_integer = 0;
461     while ( l_numerator >= l_denominator )
462     {
463         p_increment->l_euclidean_integer++;
464         l_numerator -= l_denominator;
465     }
466
467     p_increment->l_euclidean_remainder = l_numerator;
468
469     p_increment->l_euclidean_denominator = l_denominator;
470 }
471
472 /*****************************************************************************
473  * NextFrame
474  *****************************************************************************/
475 static __inline__ int NextFrame( aout_thread_t * p_aout, aout_fifo_t * p_fifo, mtime_t aout_date )
476 {
477     long l_units, l_rate;
478
479     /* We take the lock */
480     vlc_mutex_lock( &p_fifo->data_lock );
481
482     /* Are we looking for a dated start frame ? */
483     if ( !p_fifo->b_start_frame )
484     {
485         while ( p_fifo->l_start_frame != p_fifo->l_end_frame )
486         {
487             if ( p_fifo->date[p_fifo->l_start_frame] != LAST_MDATE )
488             {
489                 p_fifo->b_start_frame = 1;
490                 p_fifo->l_next_frame = (p_fifo->l_start_frame + 1) & AOUT_FIFO_SIZE;
491                 p_fifo->l_unit = p_fifo->l_start_frame * (p_fifo->l_frame_size >> (p_fifo->b_stereo));
492                 break;
493             }
494             p_fifo->l_start_frame = (p_fifo->l_start_frame + 1) & AOUT_FIFO_SIZE;
495         }
496
497         if ( p_fifo->l_start_frame == p_fifo->l_end_frame )
498         {
499             vlc_mutex_unlock( &p_fifo->data_lock );
500             return( -1 );
501         }
502     }
503
504     /* We are looking for the next dated frame */
505     /* FIXME : is the output fifo full ?? */
506     while ( !p_fifo->b_next_frame )
507     {
508         while ( p_fifo->l_next_frame != p_fifo->l_end_frame )
509         {
510             if ( p_fifo->date[p_fifo->l_next_frame] != LAST_MDATE )
511             {
512                 p_fifo->b_next_frame = 1;
513                 break;
514             }
515             p_fifo->l_next_frame = (p_fifo->l_next_frame + 1) & AOUT_FIFO_SIZE;
516         }
517
518         while ( p_fifo->l_next_frame == p_fifo->l_end_frame )
519         {
520             vlc_cond_wait( &p_fifo->data_wait, &p_fifo->data_lock );
521             if ( p_fifo->b_die )
522             {
523                 vlc_mutex_unlock( &p_fifo->data_lock );
524                 return( -1 );
525             }
526         }
527     }
528
529     l_units = ((p_fifo->l_next_frame - p_fifo->l_start_frame) & AOUT_FIFO_SIZE) * (p_fifo->l_frame_size >> (p_fifo->b_stereo));
530
531     l_rate = p_fifo->l_rate + ((aout_date - p_fifo->date[p_fifo->l_start_frame]) / 256);
532 //    fprintf( stderr, "aout debug: %lli (%li);\n", aout_date - p_fifo->date[p_fifo->l_start_frame], l_rate );
533
534     InitializeIncrement( &p_fifo->unit_increment, l_rate, p_aout->l_rate );
535
536     p_fifo->l_units = (((l_units - (p_fifo->l_unit -
537         (p_fifo->l_start_frame * (p_fifo->l_frame_size >> (p_fifo->b_stereo)))))
538         * p_aout->l_rate) / l_rate) + 1;
539
540     /* We release the lock before leaving */
541     vlc_mutex_unlock( &p_fifo->data_lock );
542     return( 0 );
543 }
544
545 void aout_Thread_S8_Mono( aout_thread_t * p_aout )
546 {
547 }
548
549 void aout_Thread_S8_Stereo( aout_thread_t * p_aout )
550 {
551 }
552
553 void aout_Thread_U8_Mono( aout_thread_t * p_aout )
554 {
555 }
556
557 void aout_Thread_U8_Stereo( aout_thread_t * p_aout )
558 {
559     int i_fifo;
560     long l_buffer, l_buffer_limit;
561     long l_units, l_bytes;
562
563     intf_DbgMsg("adec debug: ********aout_Thread_U8_Stereo********\n");
564     intf_DbgMsg("adec debug: running audio output thread (%p) (pid == %i)\n", p_aout, getpid());
565
566     /* As the s32_buffer was created with calloc(), we don't have to set this
567      * memory to zero and we can immediately jump into the thread's loop */
568     while ( !p_aout->b_die )
569     {
570         vlc_mutex_lock( &p_aout->fifos_lock );
571         for ( i_fifo = 0; i_fifo < AOUT_MAX_FIFOS; i_fifo++ )
572         {
573             switch ( p_aout->fifo[i_fifo].i_type )
574             {
575                 case AOUT_EMPTY_FIFO:
576                     break;
577
578                 case AOUT_INTF_MONO_FIFO:
579                     if ( p_aout->fifo[i_fifo].l_units > p_aout->l_units )
580                     {
581                         l_buffer = 0;
582                         while ( l_buffer < (p_aout->l_units << 1) ) /* p_aout->b_stereo == 1 */
583                         {
584                             p_aout->s32_buffer[l_buffer++] +=
585                                 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
586                             p_aout->s32_buffer[l_buffer++] +=
587                                 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
588                             UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
589                         }
590                         p_aout->fifo[i_fifo].l_units -= p_aout->l_units;
591                     }
592                     else
593                     {
594                         l_buffer = 0;
595                         while ( l_buffer < (p_aout->fifo[i_fifo].l_units << 1) ) /* p_aout->b_stereo == 1 */
596                         {
597                             p_aout->s32_buffer[l_buffer++] +=
598                                 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
599                             p_aout->s32_buffer[l_buffer++] +=
600                                 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
601                             UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
602                         }
603                         free( p_aout->fifo[i_fifo].buffer ); /* !! */
604                         p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
605                         intf_DbgMsg("aout debug: audio output fifo (%p) destroyed\n", &p_aout->fifo[i_fifo]); /* !! */
606                     }
607                     break;
608
609                 case AOUT_INTF_STEREO_FIFO:
610                     if ( p_aout->fifo[i_fifo].l_units > p_aout->l_units )
611                     {
612                         l_buffer = 0;
613                         while ( l_buffer < (p_aout->l_units << 1) ) /* p_aout->b_stereo == 1 */
614                         {
615                             p_aout->s32_buffer[l_buffer++] +=
616                                 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit] );
617                             p_aout->s32_buffer[l_buffer++] +=
618                                 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit+1] );
619                             UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
620                         }
621                         p_aout->fifo[i_fifo].l_units -= p_aout->l_units;
622                     }
623                     else
624                     {
625                         l_buffer = 0;
626                         while ( l_buffer < (p_aout->fifo[i_fifo].l_units << 1) ) /* p_aout->b_stereo == 1 */
627                         {
628                             p_aout->s32_buffer[l_buffer++] +=
629                                 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit] );
630                             p_aout->s32_buffer[l_buffer++] +=
631                                 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit+1] );
632                             UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
633                         }
634                         free( p_aout->fifo[i_fifo].buffer ); /* !! */
635                         p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
636                         intf_DbgMsg("aout debug: audio output fifo (%p) destroyed\n", &p_aout->fifo[i_fifo]); /* !! */
637                     }
638                     break;
639
640                 case AOUT_ADEC_MONO_FIFO:
641                     if ( p_aout->fifo[i_fifo].b_die )
642                     {
643                         free( p_aout->fifo[i_fifo].buffer );
644                         free( p_aout->fifo[i_fifo].date );
645                         p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
646                         intf_DbgMsg("aout debug: audio output fifo (%p) destroyed\n", &p_aout->fifo[i_fifo]);
647                         continue;
648                     }
649
650                     l_units = p_aout->l_units;
651                     l_buffer = 0;
652                     while ( l_units > 0 )
653                     {
654                         if ( !p_aout->fifo[i_fifo].b_next_frame )
655                         {
656                             if ( NextFrame(p_aout, &p_aout->fifo[i_fifo], p_aout->date + ((((mtime_t)(l_buffer >> 1)) * 1000000) / ((mtime_t)p_aout->l_rate))) )
657                             {
658                                 break;
659                             }
660                         }
661
662                         if ( p_aout->fifo[i_fifo].l_units > l_units )
663                         {
664                             l_buffer_limit = p_aout->l_units << 1; /* p_aout->b_stereo == 1 */
665                             while ( l_buffer < l_buffer_limit )
666                             {
667                                 p_aout->s32_buffer[l_buffer++] +=
668                                     (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
669                                 p_aout->s32_buffer[l_buffer++] +=
670                                     (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
671
672                                 UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
673                                 if ( p_aout->fifo[i_fifo].l_unit >= /* p_aout->fifo[i_fifo].b_stereo == 0 */
674                                      ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 0)) )
675                                 {
676                                     p_aout->fifo[i_fifo].l_unit -= /* p_aout->fifo[i_fifo].b_stereo == 0 */
677                                         ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 0));
678                                 }
679                             }
680                             p_aout->fifo[i_fifo].l_units -= l_units;
681                             break;
682                         }
683                         else
684                         {
685                             l_buffer_limit = l_buffer + (p_aout->fifo[i_fifo].l_units << 1);
686                             /* p_aout->b_stereo == 1 */
687                             while ( l_buffer < l_buffer_limit )
688                             {
689                                 p_aout->s32_buffer[l_buffer++] +=
690                                     (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
691                                 p_aout->s32_buffer[l_buffer++] +=
692                                     (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
693
694                                 UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
695                                 if ( p_aout->fifo[i_fifo].l_unit >= /* p_aout->fifo[i_fifo].b_stereo == 0 */
696                                      ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 0)) )
697                                 {
698                                     p_aout->fifo[i_fifo].l_unit -= /* p_aout->fifo[i_fifo].b_stereo == 0 */
699                                         ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 0));
700                                 }
701                             }
702                             l_units -= p_aout->fifo[i_fifo].l_units;
703
704                             vlc_mutex_lock( &p_aout->fifo[i_fifo].data_lock );
705                             p_aout->fifo[i_fifo].l_start_frame = p_aout->fifo[i_fifo].l_next_frame;
706                             vlc_cond_signal( &p_aout->fifo[i_fifo].data_wait );
707                             vlc_mutex_unlock( &p_aout->fifo[i_fifo].data_lock );
708
709                             /* p_aout->fifo[i_fifo].b_start_frame = 1; */
710                             p_aout->fifo[i_fifo].l_next_frame += 1;
711                             p_aout->fifo[i_fifo].l_next_frame &= AOUT_FIFO_SIZE;
712                             p_aout->fifo[i_fifo].b_next_frame = 0;
713                         }
714                     }
715                     break;
716
717                 case AOUT_ADEC_STEREO_FIFO:
718                     if ( p_aout->fifo[i_fifo].b_die )
719                     {
720                         free( p_aout->fifo[i_fifo].buffer );
721                         free( p_aout->fifo[i_fifo].date );
722                         p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
723                         intf_DbgMsg("aout debug: audio output fifo (%p) destroyed\n", &p_aout->fifo[i_fifo]);
724                         continue;
725                     }
726
727                     l_units = p_aout->l_units;
728                     l_buffer = 0;
729                     while ( l_units > 0 )
730                     {
731                         if ( !p_aout->fifo[i_fifo].b_next_frame )
732                         {
733                             if ( NextFrame(p_aout, &p_aout->fifo[i_fifo], p_aout->date + ((((mtime_t)(l_buffer >> 1)) * 1000000) / ((mtime_t)p_aout->l_rate))) )
734                             {
735                                 break;
736                             }
737                         }
738
739                         if ( p_aout->fifo[i_fifo].l_units > l_units )
740                         {
741                             l_buffer_limit = p_aout->l_units << 1; /* p_aout->b_stereo == 1 */
742                             while ( l_buffer < l_buffer_limit )
743                             {
744                                 p_aout->s32_buffer[l_buffer++] +=
745                                     (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit] );
746                                 p_aout->s32_buffer[l_buffer++] +=
747                                     (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit+1] );
748
749                                 UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
750                                 if ( p_aout->fifo[i_fifo].l_unit >= /* p_aout->fifo[i_fifo].b_stereo == 1 */
751                                      ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 1)) )
752                                 {
753                                     p_aout->fifo[i_fifo].l_unit -= /* p_aout->fifo[i_fifo].b_stereo == 1 */
754                                         ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 1));
755                                 }
756                             }
757                             p_aout->fifo[i_fifo].l_units -= l_units;
758                             break;
759                         }
760                         else
761                         {
762                             l_buffer_limit = l_buffer + (p_aout->fifo[i_fifo].l_units << 1);
763                             /* p_aout->b_stereo == 1 */
764                             while ( l_buffer < l_buffer_limit )
765                             {
766                                 p_aout->s32_buffer[l_buffer++] +=
767                                     (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit] );
768                                 p_aout->s32_buffer[l_buffer++] +=
769                                     (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit+1] );
770
771                                 UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
772                                 if ( p_aout->fifo[i_fifo].l_unit >= /* p_aout->fifo[i_fifo].b_stereo == 1 */
773                                      ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 1)) )
774                                 {
775                                     p_aout->fifo[i_fifo].l_unit -= /* p_aout->fifo[i_fifo].b_stereo == 1 */
776                                         ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 1));
777                                 }
778                             }
779                             l_units -= p_aout->fifo[i_fifo].l_units;
780
781                             vlc_mutex_lock( &p_aout->fifo[i_fifo].data_lock );
782                             p_aout->fifo[i_fifo].l_start_frame = p_aout->fifo[i_fifo].l_next_frame;
783                             vlc_cond_signal( &p_aout->fifo[i_fifo].data_wait );
784                             vlc_mutex_unlock( &p_aout->fifo[i_fifo].data_lock );
785
786                             /* p_aout->fifo[i_fifo].b_start_frame = 1; */
787                             p_aout->fifo[i_fifo].l_next_frame += 1;
788                             p_aout->fifo[i_fifo].l_next_frame &= AOUT_FIFO_SIZE;
789                             p_aout->fifo[i_fifo].b_next_frame = 0;
790                         }
791                     }
792                     break;
793
794             default:
795                     intf_DbgMsg("aout debug: unknown fifo type (%i)\n", p_aout->fifo[i_fifo].i_type);
796                     break;
797             }
798         }
799         vlc_mutex_unlock( &p_aout->fifos_lock );
800
801         l_buffer_limit = p_aout->l_units  << 1 ; /* p_aout->b_stereo == 1 */
802
803         for ( l_buffer = 0; l_buffer < l_buffer_limit; l_buffer++ )
804         {
805             ((u8 *)p_aout->buffer)[l_buffer] = (u8)( (p_aout->s32_buffer[l_buffer] / 256) + 128 );
806             p_aout->s32_buffer[l_buffer] = 0;
807         }
808         l_bytes = p_aout->p_sys_getbufinfo( p_aout, l_buffer_limit );
809         p_aout->date = mdate() + ((((mtime_t)(l_bytes / 2 )) * 1000000) / ((mtime_t)p_aout->l_rate)); /* sizeof(u8) << (p_aout->b_stereo) == 2 */
810         p_aout->p_sys_playsamples( p_aout, (byte_t *)p_aout->buffer, l_buffer_limit * sizeof(u8) );
811         if ( l_bytes > (l_buffer_limit * sizeof(u8)) )
812         {
813             msleep( p_aout->l_msleep );
814         }
815     }
816
817     vlc_mutex_lock( &p_aout->fifos_lock );
818     for ( i_fifo = 0; i_fifo < AOUT_MAX_FIFOS; i_fifo++ )
819     {
820         switch ( p_aout->fifo[i_fifo].i_type )
821         {
822             case AOUT_EMPTY_FIFO:
823                 break;
824
825             case AOUT_INTF_MONO_FIFO:
826             case AOUT_INTF_STEREO_FIFO:
827                 free( p_aout->fifo[i_fifo].buffer ); /* !! */
828                 p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
829                 intf_DbgMsg("aout debug: audio output fifo (%p) destroyed\n", &p_aout->fifo[i_fifo]);
830                 break;
831
832             case AOUT_ADEC_MONO_FIFO:
833             case AOUT_ADEC_STEREO_FIFO:
834                 free( p_aout->fifo[i_fifo].buffer );
835                 free( p_aout->fifo[i_fifo].date );
836                 p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
837                 intf_DbgMsg("aout debug: audio output fifo (%p) destroyed\n", &p_aout->fifo[i_fifo]);
838                 break;
839
840             default:
841                 break;
842         }
843     }
844     vlc_mutex_unlock( &p_aout->fifos_lock );
845
846 }
847
848 void aout_Thread_S16_Mono( aout_thread_t * p_aout )
849 {
850 }
851
852 void aout_Thread_S16_Stereo( aout_thread_t * p_aout )
853 {
854     int i_fifo;
855     long l_buffer, l_buffer_limit;
856     long l_units, l_bytes;
857
858     intf_DbgMsg("adec debug: ********aout_Thread_S16_Stereo********\n");
859     intf_DbgMsg("adec debug: running audio output thread (%p) (pid == %i)\n", p_aout, getpid());
860
861     /* As the s32_buffer was created with calloc(), we don't have to set this
862      * memory to zero and we can immediately jump into the thread's loop */
863     while ( !p_aout->b_die )
864     {
865         vlc_mutex_lock( &p_aout->fifos_lock );
866         for ( i_fifo = 0; i_fifo < AOUT_MAX_FIFOS; i_fifo++ )
867         {
868             switch ( p_aout->fifo[i_fifo].i_type )
869             {
870                 case AOUT_EMPTY_FIFO:
871                     break;
872
873                 case AOUT_INTF_MONO_FIFO:
874                     if ( p_aout->fifo[i_fifo].l_units > p_aout->l_units )
875                     {
876                         l_buffer = 0;
877                         while ( l_buffer < (p_aout->l_units << 1) ) /* p_aout->b_stereo == 1 */
878                         {
879                             p_aout->s32_buffer[l_buffer++] +=
880                                 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
881                             p_aout->s32_buffer[l_buffer++] +=
882                                 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
883                             UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
884                         }
885                         p_aout->fifo[i_fifo].l_units -= p_aout->l_units;
886                     }
887                     else
888                     {
889                         l_buffer = 0;
890                         while ( l_buffer < (p_aout->fifo[i_fifo].l_units << 1) ) /* p_aout->b_stereo == 1 */
891                         {
892                             p_aout->s32_buffer[l_buffer++] +=
893                                 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
894                             p_aout->s32_buffer[l_buffer++] +=
895                                 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
896                             UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
897                         }
898                         free( p_aout->fifo[i_fifo].buffer ); /* !! */
899                         p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
900                         intf_DbgMsg("aout debug: audio output fifo (%p) destroyed\n", &p_aout->fifo[i_fifo]); /* !! */
901                     }
902                     break;
903
904                 case AOUT_INTF_STEREO_FIFO:
905                     if ( p_aout->fifo[i_fifo].l_units > p_aout->l_units )
906                     {
907                         l_buffer = 0;
908                         while ( l_buffer < (p_aout->l_units << 1) ) /* p_aout->b_stereo == 1 */
909                         {
910                             p_aout->s32_buffer[l_buffer++] +=
911                                 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit] );
912                             p_aout->s32_buffer[l_buffer++] +=
913                                 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit+1] );
914                             UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
915                         }
916                         p_aout->fifo[i_fifo].l_units -= p_aout->l_units;
917                     }
918                     else
919                     {
920                         l_buffer = 0;
921                         while ( l_buffer < (p_aout->fifo[i_fifo].l_units << 1) ) /* p_aout->b_stereo == 1 */
922                         {
923                             p_aout->s32_buffer[l_buffer++] +=
924                                 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit] );
925                             p_aout->s32_buffer[l_buffer++] +=
926                                 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit+1] );
927                             UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
928                         }
929                         free( p_aout->fifo[i_fifo].buffer ); /* !! */
930                         p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
931                         intf_DbgMsg("aout debug: audio output fifo (%p) destroyed\n", &p_aout->fifo[i_fifo]); /* !! */
932                     }
933                     break;
934
935                 case AOUT_ADEC_MONO_FIFO:
936                     if ( p_aout->fifo[i_fifo].b_die )
937                     {
938                         free( p_aout->fifo[i_fifo].buffer );
939                         free( p_aout->fifo[i_fifo].date );
940                         p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
941                         intf_DbgMsg("aout debug: audio output fifo (%p) destroyed\n", &p_aout->fifo[i_fifo]);
942                         continue;
943                     }
944
945                     l_units = p_aout->l_units;
946                     l_buffer = 0;
947                     while ( l_units > 0 )
948                     {
949                         if ( !p_aout->fifo[i_fifo].b_next_frame )
950                         {
951                             if ( NextFrame(p_aout, &p_aout->fifo[i_fifo], p_aout->date + ((((mtime_t)(l_buffer >> 1)) * 1000000) / ((mtime_t)p_aout->l_rate))) )
952                             {
953                                 break;
954                             }
955                         }
956
957                         if ( p_aout->fifo[i_fifo].l_units > l_units )
958                         {
959                             l_buffer_limit = p_aout->l_units << 1; /* p_aout->b_stereo == 1 */
960                             while ( l_buffer < l_buffer_limit )
961                             {
962                                 p_aout->s32_buffer[l_buffer++] +=
963                                     (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
964                                 p_aout->s32_buffer[l_buffer++] +=
965                                     (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
966
967                                 UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
968                                 if ( p_aout->fifo[i_fifo].l_unit >= /* p_aout->fifo[i_fifo].b_stereo == 0 */
969                                      ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 0)) )
970                                 {
971                                     p_aout->fifo[i_fifo].l_unit -= /* p_aout->fifo[i_fifo].b_stereo == 0 */
972                                         ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 0));
973                                 }
974                             }
975                             p_aout->fifo[i_fifo].l_units -= l_units;
976                             break;
977                         }
978                         else
979                         {
980                             l_buffer_limit = l_buffer + (p_aout->fifo[i_fifo].l_units << 1);
981                             /* p_aout->b_stereo == 1 */
982                             while ( l_buffer < l_buffer_limit )
983                             {
984                                 p_aout->s32_buffer[l_buffer++] +=
985                                     (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
986                                 p_aout->s32_buffer[l_buffer++] +=
987                                     (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
988
989                                 UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
990                                 if ( p_aout->fifo[i_fifo].l_unit >= /* p_aout->fifo[i_fifo].b_stereo == 0 */
991                                      ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 0)) )
992                                 {
993                                     p_aout->fifo[i_fifo].l_unit -= /* p_aout->fifo[i_fifo].b_stereo == 0 */
994                                         ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 0));
995                                 }
996                             }
997                             l_units -= p_aout->fifo[i_fifo].l_units;
998
999                             vlc_mutex_lock( &p_aout->fifo[i_fifo].data_lock );
1000                             p_aout->fifo[i_fifo].l_start_frame = p_aout->fifo[i_fifo].l_next_frame;
1001                             vlc_cond_signal( &p_aout->fifo[i_fifo].data_wait );
1002                             vlc_mutex_unlock( &p_aout->fifo[i_fifo].data_lock );
1003
1004                             /* p_aout->fifo[i_fifo].b_start_frame = 1; */
1005                             p_aout->fifo[i_fifo].l_next_frame += 1;
1006                             p_aout->fifo[i_fifo].l_next_frame &= AOUT_FIFO_SIZE;
1007                             p_aout->fifo[i_fifo].b_next_frame = 0;
1008                         }
1009                     }
1010                     break;
1011
1012                 case AOUT_ADEC_STEREO_FIFO:
1013                     if ( p_aout->fifo[i_fifo].b_die )
1014                     {
1015                         free( p_aout->fifo[i_fifo].buffer );
1016                         free( p_aout->fifo[i_fifo].date );
1017                         p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
1018                         intf_DbgMsg("aout debug: audio output fifo (%p) destroyed\n", &p_aout->fifo[i_fifo]);
1019                         continue;
1020                     }
1021
1022                     l_units = p_aout->l_units;
1023                     l_buffer = 0;
1024                     while ( l_units > 0 )
1025                     {
1026                         if ( !p_aout->fifo[i_fifo].b_next_frame )
1027                         {
1028                             if ( NextFrame(p_aout, &p_aout->fifo[i_fifo], p_aout->date + ((((mtime_t)(l_buffer >> 1)) * 1000000) / ((mtime_t)p_aout->l_rate))) )
1029                             {
1030                                 break;
1031                             }
1032                         }
1033
1034                         if ( p_aout->fifo[i_fifo].l_units > l_units )
1035                         {
1036                             l_buffer_limit = p_aout->l_units << 1; /* p_aout->b_stereo == 1 */
1037                             while ( l_buffer < l_buffer_limit )
1038                             {
1039                                 p_aout->s32_buffer[l_buffer++] +=
1040                                     (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit] );
1041                                 p_aout->s32_buffer[l_buffer++] +=
1042                                     (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit+1] );
1043
1044                                 UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
1045                                 if ( p_aout->fifo[i_fifo].l_unit >= /* p_aout->fifo[i_fifo].b_stereo == 1 */
1046                                      ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 1)) )
1047                                 {
1048                                     p_aout->fifo[i_fifo].l_unit -= /* p_aout->fifo[i_fifo].b_stereo == 1 */
1049                                         ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 1));
1050                                 }
1051                             }
1052                             p_aout->fifo[i_fifo].l_units -= l_units;
1053                             break;
1054                         }
1055                         else
1056                         {
1057                             l_buffer_limit = l_buffer + (p_aout->fifo[i_fifo].l_units << 1);
1058                             /* p_aout->b_stereo == 1 */
1059                             while ( l_buffer < l_buffer_limit )
1060                             {
1061                                 p_aout->s32_buffer[l_buffer++] +=
1062                                     (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit] );
1063                                 p_aout->s32_buffer[l_buffer++] +=
1064                                     (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit+1] );
1065
1066                                 UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
1067                                 if ( p_aout->fifo[i_fifo].l_unit >= /* p_aout->fifo[i_fifo].b_stereo == 1 */
1068                                      ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 1)) )
1069                                 {
1070                                     p_aout->fifo[i_fifo].l_unit -= /* p_aout->fifo[i_fifo].b_stereo == 1 */
1071                                         ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 1));
1072                                 }
1073                             }
1074                             l_units -= p_aout->fifo[i_fifo].l_units;
1075
1076                             vlc_mutex_lock( &p_aout->fifo[i_fifo].data_lock );
1077                             p_aout->fifo[i_fifo].l_start_frame = p_aout->fifo[i_fifo].l_next_frame;
1078                             vlc_cond_signal( &p_aout->fifo[i_fifo].data_wait );
1079                             vlc_mutex_unlock( &p_aout->fifo[i_fifo].data_lock );
1080
1081                             /* p_aout->fifo[i_fifo].b_start_frame = 1; */
1082                             p_aout->fifo[i_fifo].l_next_frame += 1;
1083                             p_aout->fifo[i_fifo].l_next_frame &= AOUT_FIFO_SIZE;
1084                             p_aout->fifo[i_fifo].b_next_frame = 0;
1085                         }
1086                     }
1087                     break;
1088
1089             default:
1090                     intf_DbgMsg("aout debug: unknown fifo type (%i)\n", p_aout->fifo[i_fifo].i_type);
1091                     break;
1092             }
1093         }
1094         vlc_mutex_unlock( &p_aout->fifos_lock );
1095
1096         l_buffer_limit = p_aout->l_units << 1; /* p_aout->b_stereo == 1 */
1097
1098         for ( l_buffer = 0; l_buffer < l_buffer_limit; l_buffer++ )
1099         {
1100             ((s16 *)p_aout->buffer)[l_buffer] = (s16)( p_aout->s32_buffer[l_buffer] / AOUT_MAX_FIFOS );
1101             p_aout->s32_buffer[l_buffer] = 0;
1102         }
1103
1104         l_bytes = p_aout->p_sys_getbufinfo( p_aout, l_buffer_limit );
1105         p_aout->date = -1000000 + mdate() + ((((mtime_t)(l_bytes / 4)) * 1000000) / ((mtime_t)p_aout->l_rate)); /* sizeof(s16) << (p_aout->b_stereo) == 4 */
1106         p_aout->p_sys_playsamples( p_aout, (byte_t *)p_aout->buffer, l_buffer_limit * sizeof(s16) );
1107         if ( l_bytes > (l_buffer_limit * sizeof(s16)) )
1108         {
1109             msleep( p_aout->l_msleep );
1110         }
1111     }
1112
1113     vlc_mutex_lock( &p_aout->fifos_lock );
1114     for ( i_fifo = 0; i_fifo < AOUT_MAX_FIFOS; i_fifo++ )
1115     {
1116         switch ( p_aout->fifo[i_fifo].i_type )
1117         {
1118             case AOUT_EMPTY_FIFO:
1119                 break;
1120
1121             case AOUT_INTF_MONO_FIFO:
1122             case AOUT_INTF_STEREO_FIFO:
1123                 free( p_aout->fifo[i_fifo].buffer ); /* !! */
1124                 p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
1125                 intf_DbgMsg("aout debug: audio output fifo (%p) destroyed\n", &p_aout->fifo[i_fifo]);
1126                 break;
1127
1128             case AOUT_ADEC_MONO_FIFO:
1129             case AOUT_ADEC_STEREO_FIFO:
1130                 free( p_aout->fifo[i_fifo].buffer );
1131                 free( p_aout->fifo[i_fifo].date );
1132                 p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
1133                 intf_DbgMsg("aout debug: audio output fifo (%p) destroyed\n", &p_aout->fifo[i_fifo]);
1134                 break;
1135
1136             default:
1137                 break;
1138         }
1139     }
1140     vlc_mutex_unlock( &p_aout->fifos_lock );
1141 }
1142
1143 void aout_Thread_U16_Mono( aout_thread_t * p_aout )
1144 {
1145 }
1146
1147 void aout_Thread_U16_Stereo( aout_thread_t * p_aout )
1148 {
1149 }