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