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