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