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