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