]> git.sesse.net Git - vlc/blob - src/audio_output/audio_output.c
o renommage arbitraire et totalitaire de idctmmx.S en vdec_idctmmx.S
[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     if ( p_aout->p_sys_reset( p_aout ) )
117     {
118         p_aout->p_sys_close( p_aout );
119         free( p_aout );
120         return( NULL );
121     }
122     if ( p_aout->p_sys_setformat( p_aout ) )
123     {
124         p_aout->p_sys_close( p_aout );
125         free( p_aout );
126         return( NULL );
127     }
128     if ( p_aout->p_sys_setchannels( p_aout ) )
129     {
130         p_aout->p_sys_close( p_aout );
131         free( p_aout );
132         return( NULL );
133     }
134     if ( p_aout->p_sys_setrate( p_aout ) )
135     {
136         p_aout->p_sys_close( p_aout );
137         free( p_aout );
138         return( NULL );
139     }
140
141     /* this code isn't very nice since some values might be uninitialized */
142 /*    intf_DbgMsg("aout debug: audio device (%s) opened (format=%i, channels=%i, rate=%li)\n",
143         p_aout->psz_device,
144         p_aout->i_format,
145         p_aout->i_channels, p_aout->l_rate); */
146
147     //?? maybe it would be cleaner to change SpawnThread prototype
148     //?? see vout to handle status correctly - however, it is not critical since
149     //?? this thread is only called in main and all calls are blocking
150     if( aout_SpawnThread( p_aout ) )
151     {
152         p_aout->p_sys_close( p_aout );
153         free( p_aout );
154         return( NULL );
155     }
156
157     return( p_aout );
158 }
159
160 /*****************************************************************************
161  * aout_SpawnThread
162  *****************************************************************************/
163 static int aout_SpawnThread( aout_thread_t * p_aout )
164 {
165     int             i_fifo;
166     long            l_bytes;
167     void *          aout_thread = NULL;
168
169     intf_DbgMsg("aout debug: spawning audio output thread (%p)\n", p_aout);
170
171     /* We want the audio output thread to live */
172     p_aout->b_die = 0;
173
174     /* Initialize the fifos lock */
175     vlc_mutex_init( &p_aout->fifos_lock );
176     /* Initialize audio fifos : set all fifos as empty and initialize locks */
177     for ( i_fifo = 0; i_fifo < AOUT_MAX_FIFOS; i_fifo++ )
178     {
179         p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO;
180         vlc_mutex_init( &p_aout->fifo[i_fifo].data_lock );
181         vlc_cond_init( &p_aout->fifo[i_fifo].data_wait );
182     }
183
184     /* Compute the size (in audio units) of the audio output buffer. Although
185      * AOUT_BUFFER_DURATION is given in microseconds, the output rate is given
186      * in Hz, that's why we need to divide by 10^6 microseconds (1 second) */
187     p_aout->l_units = (long)( ((s64)p_aout->l_rate * AOUT_BUFFER_DURATION) / 1000000 );
188     p_aout->l_msleep = (long)( ((s64)p_aout->l_units * 1000000) / (s64)p_aout->l_rate );
189
190     /* Make aout_thread point to the right thread function, and compute the
191      * byte size of the audio output buffer */
192     switch ( p_aout->i_channels )
193     {
194         /* Audio output is mono */
195         case 1:
196             switch ( p_aout->i_format )
197             {
198                 case AOUT_FMT_U8:
199                     l_bytes = 1 * sizeof(u8) * p_aout->l_units;
200                     aout_thread = (void *)aout_Thread_U8_Mono;
201                     break;
202
203                 case AOUT_FMT_S8:
204                     l_bytes = 1 * sizeof(s8) * p_aout->l_units;
205                     aout_thread = (void *)aout_Thread_S8_Mono;
206                     break;
207
208                 case AOUT_FMT_U16_LE:
209                 case AOUT_FMT_U16_BE:
210                     l_bytes = 1 * sizeof(u16) * p_aout->l_units;
211                     aout_thread = (void *)aout_Thread_U16_Mono;
212                     break;
213
214                 case AOUT_FMT_S16_LE:
215                 case AOUT_FMT_S16_BE:
216                     l_bytes = 1 * sizeof(s16) * p_aout->l_units;
217                     aout_thread = (void *)aout_Thread_S16_Mono;
218                     break;
219
220                 default:
221                     intf_ErrMsg("aout error: unknown audio output format (%i)\n",
222                         p_aout->i_format);
223                     return( -1 );
224             }
225             break;
226
227         /* Audio output is stereo */
228         case 2:
229             switch ( p_aout->i_format )
230             {
231                 case AOUT_FMT_U8:
232                     l_bytes = 2 * sizeof(u8) * p_aout->l_units;
233                     aout_thread = (void *)aout_Thread_U8_Stereo;
234                     break;
235
236                 case AOUT_FMT_S8:
237                     l_bytes = 2 * sizeof(s8) * p_aout->l_units;
238                     aout_thread = (void *)aout_Thread_S8_Stereo;
239                     break;
240
241                 case AOUT_FMT_U16_LE:
242                 case AOUT_FMT_U16_BE:
243                     l_bytes = 2 * sizeof(u16) * p_aout->l_units;
244                     aout_thread = (void *)aout_Thread_U16_Stereo;
245                     break;
246
247                 case AOUT_FMT_S16_LE:
248                 case AOUT_FMT_S16_BE:
249                     l_bytes = 2 * sizeof(s16) * p_aout->l_units;
250                     aout_thread = (void *)aout_Thread_S16_Stereo;
251                     break;
252
253                 default:
254                     intf_ErrMsg("aout error: unknown audio output format (%i)\n",
255                         p_aout->i_format);
256                     return( -1 );
257             }
258             break;
259
260         default:
261             intf_ErrMsg("aout error: unknown number of audio channels (%i)\n",
262                 p_aout->i_channels );
263             return( -1 );
264     }
265
266     /* Allocate the memory needed by the audio output buffers, and set to zero
267      * the s32 buffer's memory */
268     if ( (p_aout->buffer = malloc(l_bytes)) == NULL )
269     {
270         intf_ErrMsg("aout error: not enough memory to create the output buffer\n");
271         return( -1 );
272     }
273     if ( (p_aout->s32_buffer = (s32 *)calloc(p_aout->l_units, sizeof(s32) << ( p_aout->i_channels - 1))) == NULL )
274     {
275         intf_ErrMsg("aout error: not enough memory to create the s32 output buffer\n");
276         free( p_aout->buffer );
277         return( -1 );
278     }
279
280     /* Before launching the thread, we try to predict the date of the first
281      * audio unit in the first output buffer */
282     p_aout->date = mdate();
283
284     /* Launch the thread */
285     if ( vlc_thread_create( &p_aout->thread_id, "audio output", (vlc_thread_func_t)aout_thread, p_aout ) )
286     {
287         intf_ErrMsg("aout error: can't spawn audio output thread (%p)\n", p_aout);
288         free( p_aout->buffer );
289         free( p_aout->s32_buffer );
290         return( -1 );
291     }
292
293     intf_DbgMsg("aout debug: audio output thread (%p) spawned\n", p_aout);
294     return( 0 );
295 }
296
297 /*****************************************************************************
298  * aout_DestroyThread
299  *****************************************************************************/
300 void aout_DestroyThread( aout_thread_t * p_aout, int *pi_status )
301 {
302     //???? pi_status is not handled correctly: check vout how to do!
303
304     intf_DbgMsg("aout debug: requesting termination of audio output thread (%p)\n", p_aout);
305
306     /* Ask thread to kill itself and wait until it's done */
307     p_aout->b_die = 1;
308     vlc_thread_join( p_aout->thread_id ); // only if pi_status is NULL
309
310     /* Free the allocated memory */
311     free( p_aout->buffer );
312     free( p_aout->s32_buffer );
313
314     /* Free the structure */
315     p_aout->p_sys_close( p_aout );
316     intf_DbgMsg("aout debug: audio device (%s) closed\n", p_aout->psz_device);
317     free( p_aout );
318 }
319
320 /*****************************************************************************
321  * aout_CreateFifo
322  *****************************************************************************/
323 aout_fifo_t * aout_CreateFifo( aout_thread_t * p_aout, aout_fifo_t * p_fifo )
324 {
325     int i_fifo;
326
327     /* Take the fifos lock */
328     vlc_mutex_lock( &p_aout->fifos_lock );
329
330     /* Looking for a free fifo structure */
331     for ( i_fifo = 0; i_fifo < AOUT_MAX_FIFOS; i_fifo++ )
332     {
333         if ( p_aout->fifo[i_fifo].i_type == AOUT_EMPTY_FIFO)
334         {
335             break;
336         }
337     }
338     if ( i_fifo == AOUT_MAX_FIFOS )
339     {
340         intf_ErrMsg("aout error: no empty fifo available\n");
341         vlc_mutex_unlock( &p_aout->fifos_lock );
342         return( NULL );
343     }
344
345     /* Initialize the new fifo structure */
346     switch ( p_aout->fifo[i_fifo].i_type = p_fifo->i_type )
347     {
348         case AOUT_INTF_MONO_FIFO:
349         case AOUT_INTF_STEREO_FIFO:
350             p_aout->fifo[i_fifo].b_die = 0;
351
352             p_aout->fifo[i_fifo].i_channels = p_fifo->i_channels;
353             p_aout->fifo[i_fifo].l_rate = p_fifo->l_rate;
354
355             p_aout->fifo[i_fifo].buffer = p_fifo->buffer;
356
357             p_aout->fifo[i_fifo].l_unit = 0;
358             InitializeIncrement( &p_aout->fifo[i_fifo].unit_increment, p_fifo->l_rate, p_aout->l_rate );
359             p_aout->fifo[i_fifo].l_units = p_fifo->l_units;
360             break;
361
362         case AOUT_ADEC_MONO_FIFO:
363         case AOUT_ADEC_STEREO_FIFO:
364             p_aout->fifo[i_fifo].b_die = 0;
365
366             p_aout->fifo[i_fifo].i_channels = p_fifo->i_channels;
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->i_channels - 1));
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->i_channels - 1));
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->i_channels - 1)))))
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 }
552
553 void aout_Thread_S16_Mono( aout_thread_t * p_aout )
554 {
555 }
556
557 void aout_Thread_S16_Stereo( aout_thread_t * p_aout )
558 {
559     int i_fifo;
560     long l_buffer, l_buffer_limit;
561     long l_units, l_bytes;
562
563     intf_DbgMsg("adec debug: running audio output thread (%p) (pid == %i)\n", p_aout, getpid());
564
565     /* As the s32_buffer was created with calloc(), we don't have to set this
566      * memory to zero and we can immediately jump into the thread's loop */
567     while ( !p_aout->b_die )
568     {
569         vlc_mutex_lock( &p_aout->fifos_lock );
570         for ( i_fifo = 0; i_fifo < AOUT_MAX_FIFOS; i_fifo++ )
571         {
572             switch ( p_aout->fifo[i_fifo].i_type )
573             {
574                 case AOUT_EMPTY_FIFO:
575                     break;
576
577                 case AOUT_INTF_MONO_FIFO:
578                     if ( p_aout->fifo[i_fifo].l_units > p_aout->l_units )
579                     {
580                         l_buffer = 0;
581                         while ( l_buffer < (p_aout->l_units << 1) ) /* p_aout->i_channels - 1 == 1 */
582                         {
583                             p_aout->s32_buffer[l_buffer++] +=
584                                 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
585                             p_aout->s32_buffer[l_buffer++] +=
586                                 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
587                             UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
588                         }
589                         p_aout->fifo[i_fifo].l_units -= p_aout->l_units;
590                     }
591                     else
592                     {
593                         l_buffer = 0;
594                         while ( l_buffer < (p_aout->fifo[i_fifo].l_units << 1) ) /* p_aout->i_channels - 1 == 1 */
595                         {
596                             p_aout->s32_buffer[l_buffer++] +=
597                                 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
598                             p_aout->s32_buffer[l_buffer++] +=
599                                 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
600                             UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
601                         }
602                         free( p_aout->fifo[i_fifo].buffer ); /* !! */
603                         p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
604                         intf_DbgMsg("aout debug: audio output fifo (%p) destroyed\n", &p_aout->fifo[i_fifo]); /* !! */
605                     }
606                     break;
607
608                 case AOUT_INTF_STEREO_FIFO:
609                     if ( p_aout->fifo[i_fifo].l_units > p_aout->l_units )
610                     {
611                         l_buffer = 0;
612                         while ( l_buffer < (p_aout->l_units << 1) ) /* p_aout->i_channels - 1 == 1 */
613                         {
614                             p_aout->s32_buffer[l_buffer++] +=
615                                 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit] );
616                             p_aout->s32_buffer[l_buffer++] +=
617                                 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit+1] );
618                             UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
619                         }
620                         p_aout->fifo[i_fifo].l_units -= p_aout->l_units;
621                     }
622                     else
623                     {
624                         l_buffer = 0;
625                         while ( l_buffer < (p_aout->fifo[i_fifo].l_units << 1) ) /* p_aout->i_channels - 1 == 1 */
626                         {
627                             p_aout->s32_buffer[l_buffer++] +=
628                                 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit] );
629                             p_aout->s32_buffer[l_buffer++] +=
630                                 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit+1] );
631                             UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
632                         }
633                         free( p_aout->fifo[i_fifo].buffer ); /* !! */
634                         p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
635                         intf_DbgMsg("aout debug: audio output fifo (%p) destroyed\n", &p_aout->fifo[i_fifo]); /* !! */
636                     }
637                     break;
638
639                 case AOUT_ADEC_MONO_FIFO:
640                     if ( p_aout->fifo[i_fifo].b_die )
641                     {
642                         free( p_aout->fifo[i_fifo].buffer );
643                         free( p_aout->fifo[i_fifo].date );
644                         p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
645                         intf_DbgMsg("aout debug: audio output fifo (%p) destroyed\n", &p_aout->fifo[i_fifo]);
646                         continue;
647                     }
648
649                     l_units = p_aout->l_units;
650                     l_buffer = 0;
651                     while ( l_units > 0 )
652                     {
653                         if ( !p_aout->fifo[i_fifo].b_next_frame )
654                         {
655                             if ( NextFrame(p_aout, &p_aout->fifo[i_fifo], p_aout->date + ((((mtime_t)(l_buffer >> 1)) * 1000000) / ((mtime_t)p_aout->l_rate))) )
656                             {
657                                 break;
658                             }
659                         }
660
661                         if ( p_aout->fifo[i_fifo].l_units > l_units )
662                         {
663                             l_buffer_limit = p_aout->l_units << 1; /* p_aout->i_channels - 1 == 1 */
664                             while ( l_buffer < l_buffer_limit )
665                             {
666                                 p_aout->s32_buffer[l_buffer++] +=
667                                     (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
668                                 p_aout->s32_buffer[l_buffer++] +=
669                                     (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
670
671                                 UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
672                                 if ( p_aout->fifo[i_fifo].l_unit >= /* p_aout->fifo[i_fifo].i_channels - 1 == 0 */
673                                      ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 0)) )
674                                 {
675                                     p_aout->fifo[i_fifo].l_unit -= /* p_aout->fifo[i_fifo].i_channels - 1 == 0 */
676                                         ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 0));
677                                 }
678                             }
679                             p_aout->fifo[i_fifo].l_units -= l_units;
680                             break;
681                         }
682                         else
683                         {
684                             l_buffer_limit = l_buffer + (p_aout->fifo[i_fifo].l_units << 1);
685                             /* p_aout->i_channels - 1 == 1 */
686                             while ( l_buffer < l_buffer_limit )
687                             {
688                                 p_aout->s32_buffer[l_buffer++] +=
689                                     (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
690                                 p_aout->s32_buffer[l_buffer++] +=
691                                     (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
692
693                                 UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
694                                 if ( p_aout->fifo[i_fifo].l_unit >= /* p_aout->fifo[i_fifo].i_channels - 1 == 0 */
695                                      ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 0)) )
696                                 {
697                                     p_aout->fifo[i_fifo].l_unit -= /* p_aout->fifo[i_fifo].i_channels - 1 == 0 */
698                                         ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 0));
699                                 }
700                             }
701                             l_units -= p_aout->fifo[i_fifo].l_units;
702
703                             vlc_mutex_lock( &p_aout->fifo[i_fifo].data_lock );
704                             p_aout->fifo[i_fifo].l_start_frame = p_aout->fifo[i_fifo].l_next_frame;
705                             vlc_cond_signal( &p_aout->fifo[i_fifo].data_wait );
706                             vlc_mutex_unlock( &p_aout->fifo[i_fifo].data_lock );
707
708                             /* p_aout->fifo[i_fifo].b_start_frame = 1; */
709                             p_aout->fifo[i_fifo].l_next_frame += 1;
710                             p_aout->fifo[i_fifo].l_next_frame &= AOUT_FIFO_SIZE;
711                             p_aout->fifo[i_fifo].b_next_frame = 0;
712                         }
713                     }
714                     break;
715
716                 case AOUT_ADEC_STEREO_FIFO:
717                     if ( p_aout->fifo[i_fifo].b_die )
718                     {
719                         free( p_aout->fifo[i_fifo].buffer );
720                         free( p_aout->fifo[i_fifo].date );
721                         p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
722                         intf_DbgMsg("aout debug: audio output fifo (%p) destroyed\n", &p_aout->fifo[i_fifo]);
723                         continue;
724                     }
725
726                     l_units = p_aout->l_units;
727                     l_buffer = 0;
728                     while ( l_units > 0 )
729                     {
730                         if ( !p_aout->fifo[i_fifo].b_next_frame )
731                         {
732                             if ( NextFrame(p_aout, &p_aout->fifo[i_fifo], p_aout->date + ((((mtime_t)(l_buffer >> 1)) * 1000000) / ((mtime_t)p_aout->l_rate))) )
733                             {
734                                 break;
735                             }
736                         }
737
738                         if ( p_aout->fifo[i_fifo].l_units > l_units )
739                         {
740                             l_buffer_limit = p_aout->l_units << 1; /* p_aout->i_channels - 1 == 1 */
741                             while ( l_buffer < l_buffer_limit )
742                             {
743                                 p_aout->s32_buffer[l_buffer++] +=
744                                     (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit] );
745                                 p_aout->s32_buffer[l_buffer++] +=
746                                     (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit+1] );
747
748                                 UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
749                                 if ( p_aout->fifo[i_fifo].l_unit >= /* p_aout->fifo[i_fifo].i_channels - 1 == 1 */
750                                      ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 1)) )
751                                 {
752                                     p_aout->fifo[i_fifo].l_unit -= /* p_aout->fifo[i_fifo].i_channels - 1 == 1 */
753                                         ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 1));
754                                 }
755                             }
756                             p_aout->fifo[i_fifo].l_units -= l_units;
757                             break;
758                         }
759                         else
760                         {
761                             l_buffer_limit = l_buffer + (p_aout->fifo[i_fifo].l_units << 1);
762                             /* p_aout->i_channels - 1 == 1 */
763                             while ( l_buffer < l_buffer_limit )
764                             {
765                                 p_aout->s32_buffer[l_buffer++] +=
766                                     (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit] );
767                                 p_aout->s32_buffer[l_buffer++] +=
768                                     (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit+1] );
769
770                                 UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
771                                 if ( p_aout->fifo[i_fifo].l_unit >= /* p_aout->fifo[i_fifo].i_channels - 1 == 1 */
772                                      ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 1)) )
773                                 {
774                                     p_aout->fifo[i_fifo].l_unit -= /* p_aout->fifo[i_fifo].i_channels - 1 == 1 */
775                                         ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 1));
776                                 }
777                             }
778                             l_units -= p_aout->fifo[i_fifo].l_units;
779
780                             vlc_mutex_lock( &p_aout->fifo[i_fifo].data_lock );
781                             p_aout->fifo[i_fifo].l_start_frame = p_aout->fifo[i_fifo].l_next_frame;
782                             vlc_cond_signal( &p_aout->fifo[i_fifo].data_wait );
783                             vlc_mutex_unlock( &p_aout->fifo[i_fifo].data_lock );
784
785                             /* p_aout->fifo[i_fifo].b_start_frame = 1; */
786                             p_aout->fifo[i_fifo].l_next_frame += 1;
787                             p_aout->fifo[i_fifo].l_next_frame &= AOUT_FIFO_SIZE;
788                             p_aout->fifo[i_fifo].b_next_frame = 0;
789                         }
790                     }
791                     break;
792
793                 default:
794                     intf_DbgMsg("aout debug: unknown fifo type (%i)\n", p_aout->fifo[i_fifo].i_type);
795                     break;
796             }
797         }
798         vlc_mutex_unlock( &p_aout->fifos_lock );
799
800         l_buffer_limit = p_aout->l_units << 1; /* p_aout->i_channels - 1 == 1 */
801
802         for ( l_buffer = 0; l_buffer < l_buffer_limit; l_buffer++ )
803         {
804             ((s16 *)p_aout->buffer)[l_buffer] = (s16)( p_aout->s32_buffer[l_buffer] / AOUT_MAX_FIFOS );
805             p_aout->s32_buffer[l_buffer] = 0;
806         }
807
808         l_bytes = p_aout->p_sys_getbufinfo( p_aout );
809         p_aout->date = mdate() + ((((mtime_t)(l_bytes / 4)) * 1000000) / ((mtime_t)p_aout->l_rate)); /* sizeof(s16) << (p_aout->i_channels - 1) == 4 */
810         p_aout->p_sys_playsamples( p_aout, (byte_t *)p_aout->buffer, l_buffer_limit * sizeof(s16) );
811         if ( l_bytes > (l_buffer_limit * sizeof(s16)) )
812         {
813             msleep( p_aout->l_msleep );
814         }
815     }
816
817     vlc_mutex_lock( &p_aout->fifos_lock );
818     for ( i_fifo = 0; i_fifo < AOUT_MAX_FIFOS; i_fifo++ )
819     {
820         switch ( p_aout->fifo[i_fifo].i_type )
821         {
822             case AOUT_EMPTY_FIFO:
823                 break;
824
825             case AOUT_INTF_MONO_FIFO:
826             case AOUT_INTF_STEREO_FIFO:
827                 free( p_aout->fifo[i_fifo].buffer ); /* !! */
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             case AOUT_ADEC_MONO_FIFO:
833             case AOUT_ADEC_STEREO_FIFO:
834                 free( p_aout->fifo[i_fifo].buffer );
835                 free( p_aout->fifo[i_fifo].date );
836                 p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
837                 intf_DbgMsg("aout debug: audio output fifo (%p) destroyed\n", &p_aout->fifo[i_fifo]);
838                 break;
839
840             default:
841                 break;
842         }
843     }
844     vlc_mutex_unlock( &p_aout->fifos_lock );
845 }
846
847 void aout_Thread_U16_Mono( aout_thread_t * p_aout )
848 {
849 }
850
851 void aout_Thread_U16_Stereo( aout_thread_t * p_aout )
852 {
853 }