]> git.sesse.net Git - vlc/blob - src/audio_output/audio_output.c
* ac3_decoder/ac3_decoder.c, audio_output/audio_output.c :
[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  * - Rajouter des vlc_cond_signal ?
16  *
17  */
18
19 /******************************************************************************
20  * Preamble
21  ******************************************************************************/
22 #include <unistd.h>
23
24 #include <sys/soundcard.h>
25 #include <stdio.h>                                            /* "intf_msg.h" */
26 #include <stdlib.h>                             /* calloc(), malloc(), free() */
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 "audio_dsp.h"
37 #include "main.h"
38
39 /******************************************************************************
40  * Local prototypes
41  ******************************************************************************/
42
43
44 static int aout_SpawnThread( aout_thread_t * p_aout );
45
46 /* Creating as much aout_Thread functions as configurations is one solution,
47  * examining the different cases in the Thread loop of an unique function is
48  * another. I chose the first solution. */
49 void aout_Thread_S8_Mono        ( aout_thread_t * p_aout );
50 void aout_Thread_U8_Mono        ( aout_thread_t * p_aout );
51 void aout_Thread_S16_Mono       ( aout_thread_t * p_aout );
52 void aout_Thread_U16_Mono       ( aout_thread_t * p_aout );
53 void aout_Thread_S8_Stereo      ( aout_thread_t * p_aout );
54 void aout_Thread_U8_Stereo      ( aout_thread_t * p_aout );
55 void aout_Thread_S16_Stereo     ( aout_thread_t * p_aout );
56 void aout_Thread_U16_Stereo     ( aout_thread_t * p_aout );
57
58 static __inline__ void InitializeIncrement( aout_increment_t * p_increment, long l_numerator, long l_denominator );
59 static __inline__ int NextFrame( aout_thread_t * p_aout, aout_fifo_t * p_fifo/*, mtime_t aout_date*/ );
60
61 /******************************************************************************
62  * aout_CreateThread: initialize audio thread
63  ******************************************************************************/
64 aout_thread_t *aout_CreateThread( int *pi_status )
65 {
66     aout_thread_t * p_aout;                               /* thread descriptor */
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     //???? kludge to initialize some audio parameters - place this section somewhere
77     //???? else
78     p_aout->dsp.i_format = AOUT_DEFAULT_FORMAT;
79     p_aout->dsp.psz_device = main_GetPszVariable( AOUT_DSP_VAR, AOUT_DSP_DEFAULT );
80     p_aout->dsp.b_stereo   = main_GetIntVariable( AOUT_STEREO_VAR, AOUT_STEREO_DEFAULT );
81     p_aout->dsp.l_rate     = main_GetIntVariable( AOUT_RATE_VAR, AOUT_RATE_DEFAULT );    
82     // ???? end of kludge
83
84     /* 
85      * Initialize DSP 
86      */
87     if ( aout_dspOpen( &p_aout->dsp ) )
88     {
89         free( p_aout );
90         return( NULL );
91     }
92     if ( aout_dspReset( &p_aout->dsp ) )
93     {
94         aout_dspClose( &p_aout->dsp );
95         free( p_aout );
96         return( NULL );
97     }
98     if ( aout_dspSetFormat( &p_aout->dsp ) )
99     {
100         aout_dspClose( &p_aout->dsp );
101         free( p_aout );
102         return( NULL );
103     }
104     if ( aout_dspSetChannels( &p_aout->dsp ) )
105     {
106         aout_dspClose( &p_aout->dsp );
107         free( p_aout );
108         return( NULL );
109     }
110     if ( aout_dspSetRate( &p_aout->dsp ) )
111     {
112         aout_dspClose( &p_aout->dsp );
113         free( p_aout );
114         return( NULL );
115     }
116     intf_DbgMsg("aout debug: audio device (%s) opened (format=%i, stereo=%i, rate=%li)\n",
117         p_aout->dsp.psz_device,
118         p_aout->dsp.i_format,
119         p_aout->dsp.b_stereo, p_aout->dsp.l_rate);
120
121     //?? maybe it would be cleaner to change SpawnThread prototype
122     //?? see vout to handle status correctly - however, it is not critical since
123     //?? this thread is only called in main is all calls are blocking
124     if( aout_SpawnThread( p_aout ) )
125     {
126         aout_dspClose( &p_aout->dsp );
127         free( p_aout );
128         return( NULL );
129     }
130
131     return( p_aout );
132 }
133
134 /******************************************************************************
135  * aout_SpawnThread
136  ******************************************************************************/
137 static int aout_SpawnThread( aout_thread_t * p_aout )
138 {
139     int             i_fifo;
140     long            l_bytes;
141     s64             s64_numerator, s64_denominator;
142     void *          aout_thread = NULL;
143
144     intf_DbgMsg("aout debug: spawning audio output thread (%p)\n", p_aout);
145
146     /* We want the audio output thread to live */
147     p_aout->b_die = 0;
148
149     /* Initialize the fifos lock */
150     vlc_mutex_init( &p_aout->fifos_lock );
151     /* Initialize audio fifos : set all fifos as empty and initialize locks */
152     for ( i_fifo = 0; i_fifo < AOUT_MAX_FIFOS; i_fifo++ )
153     {
154         p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO;
155         vlc_mutex_init( &p_aout->fifo[i_fifo].data_lock );
156         vlc_cond_init( &p_aout->fifo[i_fifo].data_wait );
157     }
158
159     /* Compute the size (in audio units) of the audio output buffer. Although
160      * AOUT_BUFFER_DURATION is given in microseconds, the output rate is given
161      * in Hz, that's why we need to divide by 10^6 microseconds (1 second) */
162     p_aout->l_units = (long)( ((s64)p_aout->dsp.l_rate * AOUT_BUFFER_DURATION) / 1000000 );
163
164     /* Make aout_thread point to the right thread function, and compute the
165      * byte size of the audio output buffer */
166     switch ( p_aout->dsp.b_stereo )
167     {
168         /* Audio output is mono */
169         case 0:
170             switch ( p_aout->dsp.i_format )
171             {
172                 case AFMT_U8:
173                     l_bytes = 1 * sizeof(u8) * p_aout->l_units;
174                     aout_thread = (void *)aout_Thread_U8_Mono;
175                     break;
176
177                 case AFMT_S8:
178                     l_bytes = 1 * sizeof(s8) * p_aout->l_units;
179                     aout_thread = (void *)aout_Thread_S8_Mono;
180                     break;
181
182                 case AFMT_U16_LE:
183                 case AFMT_U16_BE:
184                     l_bytes = 1 * sizeof(u16) * p_aout->l_units;
185                     aout_thread = (void *)aout_Thread_U16_Mono;
186                     break;
187
188                 case AFMT_S16_LE:
189                 case AFMT_S16_BE:
190                     l_bytes = 1 * sizeof(s16) * p_aout->l_units;
191                     aout_thread = (void *)aout_Thread_S16_Mono;
192                     break;
193
194                 default:
195                     intf_ErrMsg("aout error: unknown audio output format (%i)\n",
196                         p_aout->dsp.i_format);
197                     return( -1 );
198             }
199             break;
200
201         /* Audio output is stereo */
202         case 1:
203             switch ( p_aout->dsp.i_format )
204             {
205                 case AFMT_U8:
206                     l_bytes = 2 * sizeof(u8) * p_aout->l_units;
207                     aout_thread = (void *)aout_Thread_U8_Stereo;
208                     break;
209
210                 case AFMT_S8:
211                     l_bytes = 2 * sizeof(s8) * p_aout->l_units;
212                     aout_thread = (void *)aout_Thread_S8_Stereo;
213                     break;
214
215                 case AFMT_U16_LE:
216                 case AFMT_U16_BE:
217                     l_bytes = 2 * sizeof(u16) * p_aout->l_units;
218                     aout_thread = (void *)aout_Thread_U16_Stereo;
219                     break;
220
221                 case AFMT_S16_LE:
222                 case AFMT_S16_BE:
223                     l_bytes = 2 * sizeof(s16) * p_aout->l_units;
224                     aout_thread = (void *)aout_Thread_S16_Stereo;
225                     break;
226
227                 default:
228                     intf_ErrMsg("aout error: unknown audio output format (%i)\n",
229                         p_aout->dsp.i_format);
230                     return( -1 );
231             }
232             break;
233
234         default:
235             intf_ErrMsg("aout error: unknown number of audio channels (%i)\n",
236                 p_aout->dsp.b_stereo + 1);
237             return( -1 );
238     }
239
240     /* Allocate the memory needed by the audio output buffers, and set to zero
241      * the s32 buffer's memory */
242     if ( (p_aout->buffer = malloc(l_bytes)) == NULL )
243     {
244         intf_ErrMsg("aout error: not enough memory to create the output buffer\n");
245         return( -1 );
246     }
247     if ( (p_aout->s32_buffer = (s32 *)calloc(p_aout->l_units, sizeof(s32) << p_aout->dsp.b_stereo)) == NULL )
248     {
249         intf_ErrMsg("aout error: not enough memory to create the s32 output buffer\n");
250         free( p_aout->buffer );
251         return( -1 );
252     }
253
254     /* Initialize the incremental structure that is used to work out the date
255      * of the first audio unit in the output buffer */
256     s64_numerator = (s64)p_aout->l_units * 1000000;
257     s64_denominator = (s64)p_aout->dsp.l_rate;
258
259     p_aout->date_increment.l_remainder = -(long)s64_denominator;
260
261     p_aout->date_increment.l_euclidean_integer = 0;
262     while ( s64_numerator >= s64_denominator )
263     {
264         p_aout->date_increment.l_euclidean_integer++;
265         s64_numerator -= s64_denominator;
266     }
267
268     p_aout->date_increment.l_euclidean_remainder = (long)s64_numerator;
269
270     p_aout->date_increment.l_euclidean_denominator = (long)s64_denominator;
271
272     /* Before launching the thread, we try to predict the date of the first
273      * audio unit in the first output buffer */
274     p_aout->date = mdate();
275
276     /* Launch the thread */
277     if ( vlc_thread_create( &p_aout->thread_id, "audio output", (vlc_thread_func_t)aout_thread, p_aout ) )
278     {
279         intf_ErrMsg("aout error: can't spawn audio output thread (%p)\n", p_aout);
280         free( p_aout->buffer );
281         free( p_aout->s32_buffer );
282         return( -1 );
283     }
284
285     intf_DbgMsg("aout debug: audio output thread (%p) spawned\n", p_aout);
286     return( 0 );
287 }
288
289 /******************************************************************************
290  * aout_DestroyThread
291  ******************************************************************************/
292 void aout_DestroyThread( aout_thread_t * p_aout, int *pi_status )
293 {
294     //???? pi_status is not handled correctly: check vout how to do! 
295
296     intf_DbgMsg("aout debug: requesting termination of audio output thread (%p)\n", p_aout);
297
298     /* Ask thread to kill itself and wait until it's done */
299     p_aout->b_die = 1;
300     vlc_thread_join( p_aout->thread_id ); // only if pi_status is NULL
301
302     /* Free the allocated memory */
303     free( p_aout->buffer );
304     free( p_aout->s32_buffer );
305
306     /* Free the structure */
307     aout_dspClose( &p_aout->dsp );
308     intf_DbgMsg("aout debug: audio device (%s) closed\n", p_aout->dsp.psz_device);
309     free( p_aout );
310 }
311
312 /******************************************************************************
313  * aout_CreateFifo
314  ******************************************************************************/
315 aout_fifo_t * aout_CreateFifo( aout_thread_t * p_aout, aout_fifo_t * p_fifo )
316 {
317     int i_fifo;
318
319     /* Take the fifos lock */
320     vlc_mutex_lock( &p_aout->fifos_lock );
321
322     /* Looking for a free fifo structure */
323     for ( i_fifo = 0; i_fifo < AOUT_MAX_FIFOS; i_fifo++ )
324     {
325         if ( p_aout->fifo[i_fifo].i_type == AOUT_EMPTY_FIFO)
326         {
327             break;
328         }
329     }
330     if ( i_fifo == AOUT_MAX_FIFOS )
331     {
332         intf_ErrMsg("aout error: no empty fifo available\n");
333         vlc_mutex_unlock( &p_aout->fifos_lock );
334         return( NULL );
335     }
336
337     /* Initialize the new fifo structure */
338     switch ( p_aout->fifo[i_fifo].i_type = p_fifo->i_type )
339     {
340         case AOUT_INTF_MONO_FIFO:
341         case AOUT_INTF_STEREO_FIFO:
342             p_aout->fifo[i_fifo].b_die = 0;
343
344             p_aout->fifo[i_fifo].b_stereo = p_fifo->b_stereo;
345             p_aout->fifo[i_fifo].l_rate = p_fifo->l_rate;
346
347             p_aout->fifo[i_fifo].buffer = p_fifo->buffer;
348
349             p_aout->fifo[i_fifo].l_unit = 0;
350             InitializeIncrement( &p_aout->fifo[i_fifo].unit_increment, p_fifo->l_rate, p_aout->dsp.l_rate );
351             p_aout->fifo[i_fifo].l_units = p_fifo->l_units;
352             break;
353
354         case AOUT_ADEC_MONO_FIFO:
355         case AOUT_ADEC_STEREO_FIFO:
356             p_aout->b_die = 0;
357
358             p_aout->fifo[i_fifo].b_stereo = p_fifo->b_stereo;
359             p_aout->fifo[i_fifo].l_rate = p_fifo->l_rate;
360
361             p_aout->fifo[i_fifo].l_frame_size = p_fifo->l_frame_size;
362             /* Allocate the memory needed to store the audio frames. As the
363              * fifo is a rotative fifo, we must be able to find out whether the
364              * fifo is full or empty, that's why we must in fact allocate memory
365              * for (AOUT_FIFO_SIZE+1) audio frames. */
366             if ( (p_aout->fifo[i_fifo].buffer = malloc( sizeof(s16)*(AOUT_FIFO_SIZE+1)*p_fifo->l_frame_size )) == NULL )
367             {
368                 intf_ErrMsg("aout error: not enough memory to create the frames buffer\n");
369                 p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO;
370                 vlc_mutex_unlock( &p_aout->fifos_lock );
371                 return( NULL );
372             }
373
374             /* Allocate the memory needed to store the dates of the frames */
375             if ( (p_aout->fifo[i_fifo].date = (mtime_t *)malloc( sizeof(mtime_t)*(AOUT_FIFO_SIZE+1) )) == NULL )
376             {
377                 intf_ErrMsg("aout error: not enough memory to create the dates buffer\n");
378                 free( p_aout->fifo[i_fifo].buffer );
379                 p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO;
380                 vlc_mutex_unlock( &p_aout->fifos_lock );
381                 return( NULL );
382             }
383
384             /* Set the fifo's buffer as empty (the first frame that is to be
385              * played is also the first frame that is not to be played) */
386             p_aout->fifo[i_fifo].l_start_frame = 0;
387             /* p_aout->fifo[i_fifo].l_next_frame = 0; */
388             p_aout->fifo[i_fifo].l_end_frame = 0;
389
390             /* Waiting for the audio decoder to compute enough frames to work
391              * out the fifo's current rate (as soon as the decoder has decoded
392              * enough frames, the members of the fifo structure that are not
393              * initialized now will be calculated) */
394             p_aout->fifo[i_fifo].l_unit = 0; /* !! */
395             p_aout->fifo[i_fifo].b_start_frame = 0;
396             p_aout->fifo[i_fifo].b_next_frame = 0;
397             break;
398
399         default:
400             intf_ErrMsg("aout error: unknown fifo type (%i)\n", p_aout->fifo[i_fifo].i_type);
401             p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO;
402             vlc_mutex_unlock( &p_aout->fifos_lock );
403             return( NULL );
404     }
405
406     /* Release the fifos lock */
407     vlc_mutex_unlock( &p_aout->fifos_lock );
408
409     /* Return the pointer to the fifo structure */
410     intf_DbgMsg("aout debug: audio output fifo (%p) allocated\n", &p_aout->fifo[i_fifo]);
411     return( &p_aout->fifo[i_fifo] );
412 }
413
414 /******************************************************************************
415  * aout_DestroyFifo
416  ******************************************************************************/
417 void aout_DestroyFifo( aout_fifo_t * p_fifo )
418 {
419     intf_DbgMsg("aout debug: requesting destruction of audio output fifo (%p)\n", p_fifo);
420     p_fifo->b_die = 1;
421 }
422
423 /* Here are the local macros */
424
425 #define S32_TO_S16( sample ) \
426     (s16)( (sample) )
427
428 #define UPDATE_INCREMENT( increment, integer ) \
429     if ( ((increment).l_remainder += (increment).l_euclidean_remainder) >= 0 ) \
430     { \
431         (integer) += (increment).l_euclidean_integer + 1; \
432         (increment).l_remainder -= (increment).l_euclidean_denominator; \
433     } \
434     else \
435     { \
436         (integer) += (increment).l_euclidean_integer; \
437     }
438
439 /* Following functions are local */
440
441 /******************************************************************************
442  * InitializeIncrement
443  ******************************************************************************/
444 static __inline__ void InitializeIncrement( aout_increment_t * p_increment, long l_numerator, long l_denominator )
445 {
446     p_increment->l_remainder = -l_denominator;
447
448     p_increment->l_euclidean_integer = 0;
449     while ( l_numerator >= l_denominator )
450     {
451         p_increment->l_euclidean_integer++;
452         l_numerator -= l_denominator;
453     }
454
455     p_increment->l_euclidean_remainder = l_numerator;
456
457     p_increment->l_euclidean_denominator = l_denominator;
458 }
459
460 /******************************************************************************
461  * NextFrame
462  ******************************************************************************/
463 static __inline__ int NextFrame( aout_thread_t * p_aout, aout_fifo_t * p_fifo/*, mtime_t aout_date*/ )
464 {
465     long l_units, l_rate;
466
467     /* We take the lock */
468     vlc_mutex_lock( &p_fifo->data_lock );
469
470     /* Are we looking for a dated start frame ? */
471     if ( !p_fifo->b_start_frame )
472     {
473         while ( p_fifo->l_start_frame != p_fifo->l_end_frame )
474         {
475             if ( p_fifo->date[p_fifo->l_start_frame] != LAST_MDATE )
476             {
477                 p_fifo->b_start_frame = 1;
478                 p_fifo->l_next_frame = (p_fifo->l_start_frame + 1) & AOUT_FIFO_SIZE;
479                 break;
480             }
481             p_fifo->l_start_frame = (p_fifo->l_start_frame + 1) & AOUT_FIFO_SIZE;
482         }
483         if ( p_fifo->l_start_frame == p_fifo->l_end_frame )
484         {
485             vlc_mutex_unlock( &p_fifo->data_lock );
486             return( -1 );
487         }
488     }
489 /*
490     if ( aout_date < p_fifo->date[p_fifo->l_start_frame] )
491     {
492         fprintf(stderr, "+");
493         vlc_mutex_unlock( &p_fifo->data_lock );
494         return( -1 );
495     }
496 */
497     /* We are looking for the next dated frame */
498     while ( p_fifo->l_next_frame != p_fifo->l_end_frame )
499     {
500         if ( p_fifo->date[p_fifo->l_next_frame] != LAST_MDATE )
501         {
502 /*
503             if ( aout_date < p_fifo->date[p_fifo->l_next_frame] )
504             {
505 */
506 /*
507             if ( (p_fifo->date[p_fifo->l_next_frame] - p_fifo->date[p_fifo->l_start_frame] > 1000000) || (p_fifo->date[p_fifo->l_next_frame] <= p_fifo->date[p_fifo->l_start_frame]) )
508             {
509                 fprintf( stderr, "aout debug: p_fifo->l_rate == %li\n", p_fifo->l_rate );
510                 p_fifo->date[p_fifo->l_start_frame] = p_fifo->date[p_fifo->l_next_frame] - ((1000000 * ((mtime_t)(p_fifo->l_frame_size * ((p_fifo->l_next_frame - p_fifo->l_start_frame) & AOUT_FIFO_SIZE))) >> p_fifo->b_stereo) / ((mtime_t)p_fifo->l_rate));
511             }
512 */
513             p_fifo->b_next_frame = 1;
514             break;
515 /*
516             }
517             else
518             {
519                 fprintf(stderr, "-");
520                 p_fifo->l_start_frame = p_fifo->l_next_frame;
521             }
522 */
523         }
524         p_fifo->l_next_frame = (p_fifo->l_next_frame + 1) & AOUT_FIFO_SIZE;
525     }
526     if ( p_fifo->l_next_frame == p_fifo->l_end_frame )
527     {
528         if ( (((p_fifo->l_end_frame + 1) - p_fifo->l_start_frame) & AOUT_FIFO_SIZE) == 0 )
529         {
530             p_fifo->l_start_frame = 0;
531             p_fifo->b_start_frame = 0;
532             /* p_fifo->l_next_frame = 0; */
533             /* p_fifo->b_next_frame = 0; */
534             p_fifo->l_end_frame = 0;
535         }
536         vlc_mutex_unlock( &p_fifo->data_lock );
537         return( -1 );
538     }
539
540     l_units = ((p_fifo->l_next_frame - p_fifo->l_start_frame) & AOUT_FIFO_SIZE) * (p_fifo->l_frame_size >> p_fifo->b_stereo);
541
542     l_rate = (long)( ((mtime_t)l_units * 1000000)
543         / (p_fifo->date[p_fifo->l_next_frame] - p_fifo->date[p_fifo->l_start_frame]) );
544 //    fprintf( stderr, "aout debug: l_rate == %li\n", l_rate );
545
546     InitializeIncrement( &p_fifo->unit_increment, l_rate, p_aout->dsp.l_rate );
547
548     p_fifo->l_units = (((l_units - (p_fifo->l_unit -
549         (p_fifo->l_start_frame * (p_fifo->l_frame_size >> p_fifo->b_stereo))))
550         * p_aout->dsp.l_rate) / l_rate) + 1;
551
552     /* We release the lock before leaving */
553     vlc_mutex_unlock( &p_fifo->data_lock );
554     return( 0 );
555 }
556
557 void aout_Thread_S8_Mono( aout_thread_t * p_aout )
558 {
559 }
560
561 void aout_Thread_S8_Stereo( aout_thread_t * p_aout )
562 {
563 }
564
565 void aout_Thread_U8_Mono( aout_thread_t * p_aout )
566 {
567 }
568
569 void aout_Thread_U8_Stereo( aout_thread_t * p_aout )
570 {
571 }
572
573 void aout_Thread_S16_Mono( aout_thread_t * p_aout )
574 {
575 }
576
577 void aout_Thread_S16_Stereo( aout_thread_t * p_aout )
578 {
579     int i_fifo;
580     long l_units;
581     long l_buffer, l_buffer_limit;
582
583     intf_DbgMsg("adec debug: running audio output thread (%p) (pid == %i)\n", p_aout, getpid());
584
585     /* As the s32_buffer was created with calloc(), we don't have to set this
586      * memory to zero and we can immediately jump into the thread's loop */
587     while ( !p_aout->b_die )
588     {
589         vlc_mutex_lock( &p_aout->fifos_lock );
590         for ( i_fifo = 0; i_fifo < AOUT_MAX_FIFOS; i_fifo++ )
591         {
592             switch ( p_aout->fifo[i_fifo].i_type )
593             {
594                 case AOUT_EMPTY_FIFO:
595                     break;
596
597                 case AOUT_INTF_MONO_FIFO:
598                     if ( p_aout->fifo[i_fifo].l_units > p_aout->l_units )
599                     {
600                         l_buffer = 0;
601                         while ( l_buffer < (p_aout->l_units << 1) ) /* p_aout->dsp.b_stereo == 1 */
602                         {
603                             p_aout->s32_buffer[l_buffer++] +=
604                                 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
605                             p_aout->s32_buffer[l_buffer++] +=
606                                 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
607                             UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
608                         }
609                         p_aout->fifo[i_fifo].l_units -= p_aout->l_units;
610                     }
611                     else
612                     {
613                         l_buffer = 0;
614                         while ( l_buffer < (p_aout->fifo[i_fifo].l_units << 1) ) /* p_aout->dsp.b_stereo == 1 */
615                         {
616                             p_aout->s32_buffer[l_buffer++] +=
617                                 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
618                             p_aout->s32_buffer[l_buffer++] +=
619                                 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
620                             UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
621                         }
622                         free( p_aout->fifo[i_fifo].buffer ); /* !! */
623                         p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
624                         intf_DbgMsg("aout debug: audio output fifo (%p) destroyed\n", &p_aout->fifo[i_fifo]); /* !! */
625                     }
626                     break;
627
628                 case AOUT_INTF_STEREO_FIFO:
629                     if ( p_aout->fifo[i_fifo].l_units > p_aout->l_units )
630                     {
631                         l_buffer = 0;
632                         while ( l_buffer < (p_aout->l_units << 1) ) /* p_aout->dsp.b_stereo == 1 */
633                         {
634                             p_aout->s32_buffer[l_buffer++] +=
635                                 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit] );
636                             p_aout->s32_buffer[l_buffer++] +=
637                                 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit+1] );
638                             UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
639                         }
640                         p_aout->fifo[i_fifo].l_units -= p_aout->l_units;
641                     }
642                     else
643                     {
644                         l_buffer = 0;
645                         while ( l_buffer < (p_aout->fifo[i_fifo].l_units << 1) ) /* p_aout->dsp.b_stereo */
646                         {
647                             p_aout->s32_buffer[l_buffer++] +=
648                                 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit] );
649                             p_aout->s32_buffer[l_buffer++] +=
650                                 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit+1] );
651                             UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
652                         }
653                         free( p_aout->fifo[i_fifo].buffer ); /* !! */
654                         p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
655                         intf_DbgMsg("aout debug: audio output fifo (%p) destroyed\n", &p_aout->fifo[i_fifo]); /* !! */
656                     }
657                     break;
658
659                 case AOUT_ADEC_MONO_FIFO:
660                     l_units = p_aout->l_units;
661                     l_buffer = 0;
662                     while ( l_units > 0 )
663                     {
664                         if ( !p_aout->fifo[i_fifo].b_next_frame )
665                         {
666                             if ( NextFrame(p_aout, &p_aout->fifo[i_fifo]/*, p_aout->date + (mtime_t)((l_buffer >> p_aout->dsp.b_stereo) / p_aout->dsp.l_rate)*/) )
667                             {
668                                 break;
669                             }
670                         }
671
672                         if ( p_aout->fifo[i_fifo].l_units > l_units )
673                         {
674                             l_buffer_limit = p_aout->l_units << 1; /* p_aout->dsp.b_stereo == 1 */
675                             while ( l_buffer < l_buffer_limit )
676                             {
677                                 p_aout->s32_buffer[l_buffer++] +=
678                                     (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
679                                 p_aout->s32_buffer[l_buffer++] +=
680                                     (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
681
682                                 UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
683                                 if ( p_aout->fifo[i_fifo].l_unit >= /* p_aout->fifo[i_fifo].b_stereo == 0 */
684                                      ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 0)) )
685                                 {
686                                     p_aout->fifo[i_fifo].l_unit -= /* p_aout->fifo[i_fifo].b_stereo == 0 */
687                                         ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 0));
688                                 }
689                             }
690                             p_aout->fifo[i_fifo].l_units -= l_units;
691                             break;
692                         }
693                         else
694                         {
695                             l_buffer_limit = l_buffer + (p_aout->fifo[i_fifo].l_units << 1);
696                             /* p_aout->dsp.b_stereo == 1 */
697                             while ( l_buffer < l_buffer_limit )
698                             {
699                                 p_aout->s32_buffer[l_buffer++] +=
700                                     (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
701                                 p_aout->s32_buffer[l_buffer++] +=
702                                     (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
703
704                                 UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
705                                 if ( p_aout->fifo[i_fifo].l_unit >= /* p_aout->fifo[i_fifo].b_stereo == 0 */
706                                      ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 0)) )
707                                 {
708                                     p_aout->fifo[i_fifo].l_unit -= /* p_aout->fifo[i_fifo].b_stereo == 0 */
709                                         ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 0));
710                                 }
711                             }
712                             l_units -= p_aout->fifo[i_fifo].l_units;
713
714                             vlc_mutex_lock( &p_aout->fifo[i_fifo].data_lock );
715                             p_aout->fifo[i_fifo].l_start_frame = p_aout->fifo[i_fifo].l_next_frame;
716                             vlc_cond_signal( &p_aout->fifo[i_fifo].data_wait );
717                             vlc_mutex_unlock( &p_aout->fifo[i_fifo].data_lock );
718
719                             /* p_aout->fifo[i_fifo].b_start_frame = 1; */
720                             p_aout->fifo[i_fifo].l_next_frame += 1;
721                             p_aout->fifo[i_fifo].l_next_frame &= AOUT_FIFO_SIZE;
722                             p_aout->fifo[i_fifo].b_next_frame = 0;
723                         }
724                     }
725                     break;
726
727                 case AOUT_ADEC_STEREO_FIFO:
728                     l_units = p_aout->l_units;
729                     l_buffer = 0;
730                     while ( l_units > 0 )
731                     {
732                         if ( !p_aout->fifo[i_fifo].b_next_frame )
733                         {
734                             if ( NextFrame(p_aout, &p_aout->fifo[i_fifo]/*, p_aout->date + (mtime_t)((l_buffer >> p_aout->dsp.b_stereo) / p_aout->dsp.l_rate)*/) )
735                             {
736                                 break;
737                             }
738                         }
739
740                         if ( p_aout->fifo[i_fifo].l_units > l_units )
741                         {
742                             l_buffer_limit = p_aout->l_units << 1; /* p_aout->dsp.b_stereo == 1 */
743                             while ( l_buffer < l_buffer_limit )
744                             {
745                                 p_aout->s32_buffer[l_buffer++] +=
746                                     (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit] );
747                                 p_aout->s32_buffer[l_buffer++] +=
748                                     (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit+1] );
749
750                                 UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
751                                 if ( 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                                     p_aout->fifo[i_fifo].l_unit -= /* p_aout->fifo[i_fifo].b_stereo == 1 */
755                                         ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 1));
756                                 }
757                             }
758                             p_aout->fifo[i_fifo].l_units -= l_units;
759                             break;
760                         }
761                         else
762                         {
763                             l_buffer_limit = l_buffer + (p_aout->fifo[i_fifo].l_units << 1);
764                             /* p_aout->dsp.b_stereo == 1 */
765                             while ( l_buffer < l_buffer_limit )
766                             {
767                                 p_aout->s32_buffer[l_buffer++] +=
768                                     (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit] );
769                                 p_aout->s32_buffer[l_buffer++] +=
770                                     (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit+1] );
771
772                                 UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
773                                 if ( 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                                     p_aout->fifo[i_fifo].l_unit -= /* p_aout->fifo[i_fifo].b_stereo == 1 */
777                                         ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 1));
778                                 }
779                             }
780                             l_units -= p_aout->fifo[i_fifo].l_units;
781
782                             vlc_mutex_lock( &p_aout->fifo[i_fifo].data_lock );
783                             p_aout->fifo[i_fifo].l_start_frame = p_aout->fifo[i_fifo].l_next_frame;
784                             vlc_cond_signal( &p_aout->fifo[i_fifo].data_wait );
785                             vlc_mutex_unlock( &p_aout->fifo[i_fifo].data_lock );
786
787                             /* p_aout->fifo[i_fifo].b_start_frame = 1; */
788                             p_aout->fifo[i_fifo].l_next_frame += 1;
789                             p_aout->fifo[i_fifo].l_next_frame &= AOUT_FIFO_SIZE;
790                             p_aout->fifo[i_fifo].b_next_frame = 0;
791                         }
792                     }
793                     break;
794
795                 default:
796                     intf_DbgMsg("aout debug: unknown fifo type (%i)\n", p_aout->fifo[i_fifo].i_type);
797                     break;
798             }
799         }
800         vlc_mutex_unlock( &p_aout->fifos_lock );
801
802         l_buffer_limit = p_aout->l_units << 1; /* p_aout->dsp.b_stereo == 1 */
803
804         for ( l_buffer = 0; l_buffer < l_buffer_limit; l_buffer++ )
805         {
806             ((s16 *)p_aout->buffer)[l_buffer] = S32_TO_S16( p_aout->s32_buffer[l_buffer] / AOUT_MAX_FIFOS );
807             p_aout->s32_buffer[l_buffer] = 0;
808         }
809
810         aout_dspGetBufInfo( &p_aout->dsp );
811         if ( p_aout->dsp.buf_info.fragments == p_aout->dsp.buf_info.fragstotal ) /* ?? */
812         {
813             aout_dspPlaySamples( &p_aout->dsp, (byte_t *)p_aout->buffer, sizeof(s16) * l_buffer_limit );
814             p_aout->date = mdate();
815         }
816         else if ( p_aout->dsp.buf_info.bytes >=
817             ((p_aout->dsp.buf_info.fragsize * p_aout->dsp.buf_info.fragstotal) -
818             (sizeof(s16) * l_buffer_limit)) )
819         {
820             aout_dspPlaySamples( &p_aout->dsp, (byte_t *)p_aout->buffer, sizeof(s16) * l_buffer_limit );
821         }
822         else
823         {
824             aout_dspPlaySamples( &p_aout->dsp, (byte_t *)p_aout->buffer, sizeof(s16) * l_buffer_limit );
825             msleep( p_aout->date_increment.l_euclidean_integer );
826         }
827         UPDATE_INCREMENT( p_aout->date_increment, p_aout->date )
828     }
829
830     vlc_mutex_lock( &p_aout->fifos_lock );
831     for ( i_fifo = 0; i_fifo < AOUT_MAX_FIFOS; i_fifo++ )
832     {
833         switch ( p_aout->fifo[i_fifo].i_type )
834         {
835             case AOUT_EMPTY_FIFO:
836                 break;
837
838             case AOUT_INTF_MONO_FIFO:
839             case AOUT_INTF_STEREO_FIFO:
840                 free( p_aout->fifo[i_fifo].buffer ); /* !! */
841                 p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
842                 intf_DbgMsg("aout debug: audio output fifo (%p) destroyed\n", &p_aout->fifo[i_fifo]);
843                 break;
844
845             case AOUT_ADEC_MONO_FIFO:
846             case AOUT_ADEC_STEREO_FIFO:
847                 free( p_aout->fifo[i_fifo].buffer );
848                 free( p_aout->fifo[i_fifo].date );
849                 p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
850                 intf_DbgMsg("aout debug: audio output fifo (%p) destroyed\n", &p_aout->fifo[i_fifo]);
851                 break;
852
853             default:
854                 break;
855         }
856     }
857     vlc_mutex_unlock( &p_aout->fifos_lock );
858 }
859
860 void aout_Thread_U16_Mono( aout_thread_t * p_aout )
861 {
862 }
863
864 void aout_Thread_U16_Stereo( aout_thread_t * p_aout )
865 {
866 }