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