]> git.sesse.net Git - vlc/blob - src/audio_output/audio_output.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->fifo[i_fifo].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 UPDATE_INCREMENT( increment, integer ) \
426     if ( ((increment).l_remainder += (increment).l_euclidean_remainder) >= 0 ) \
427     { \
428         (integer) += (increment).l_euclidean_integer + 1; \
429         (increment).l_remainder -= (increment).l_euclidean_denominator; \
430     } \
431     else \
432     { \
433         (integer) += (increment).l_euclidean_integer; \
434     }
435
436 /* Following functions are local */
437
438 /******************************************************************************
439  * InitializeIncrement
440  ******************************************************************************/
441 static __inline__ void InitializeIncrement( aout_increment_t * p_increment, long l_numerator, long l_denominator )
442 {
443     p_increment->l_remainder = -l_denominator;
444
445     p_increment->l_euclidean_integer = 0;
446     while ( l_numerator >= l_denominator )
447     {
448         p_increment->l_euclidean_integer++;
449         l_numerator -= l_denominator;
450     }
451
452     p_increment->l_euclidean_remainder = l_numerator;
453
454     p_increment->l_euclidean_denominator = l_denominator;
455 }
456
457 /******************************************************************************
458  * NextFrame
459  ******************************************************************************/
460 static __inline__ int NextFrame( aout_thread_t * p_aout, aout_fifo_t * p_fifo/*, mtime_t aout_date*/ )
461 {
462     long l_units, l_rate;
463
464     /* We take the lock */
465     vlc_mutex_lock( &p_fifo->data_lock );
466
467     /* Are we looking for a dated start frame ? */
468     if ( !p_fifo->b_start_frame )
469     {
470         while ( p_fifo->l_start_frame != p_fifo->l_end_frame )
471         {
472             if ( p_fifo->date[p_fifo->l_start_frame] != LAST_MDATE )
473             {
474                 p_fifo->b_start_frame = 1;
475                 p_fifo->l_next_frame = (p_fifo->l_start_frame + 1) & AOUT_FIFO_SIZE;
476                 break;
477             }
478             p_fifo->l_start_frame = (p_fifo->l_start_frame + 1) & AOUT_FIFO_SIZE;
479         }
480         if ( p_fifo->l_start_frame == p_fifo->l_end_frame )
481         {
482             vlc_mutex_unlock( &p_fifo->data_lock );
483             return( -1 );
484         }
485     }
486 /*
487     if ( aout_date < p_fifo->date[p_fifo->l_start_frame] )
488     {
489         fprintf(stderr, "+");
490         vlc_mutex_unlock( &p_fifo->data_lock );
491         return( -1 );
492     }
493 */
494     /* We are looking for the next dated frame */
495     while ( p_fifo->l_next_frame != p_fifo->l_end_frame )
496     {
497         if ( p_fifo->date[p_fifo->l_next_frame] != LAST_MDATE )
498         {
499 /*
500             if ( aout_date < p_fifo->date[p_fifo->l_next_frame] )
501             {
502 */
503
504                 if ( p_fifo->date[p_fifo->l_start_frame] >= p_fifo->date[p_fifo->l_next_frame] )
505                 {
506                         fprintf( stderr, "aout debug: %lli >= %lli\n", p_fifo->date[p_fifo->l_start_frame], p_fifo->date[p_fifo->l_next_frame] );
507                         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));
508                         
509                 }
510                 else if ( (p_fifo->date[p_fifo->l_next_frame] - p_fifo->date[p_fifo->l_start_frame]) > 1000000 )
511                 {
512                         fprintf( stderr, "aout debug: (%lli - %lli) > 1000000\n", p_fifo->date[p_fifo->l_next_frame], p_fifo->date[p_fifo->l_start_frame] );
513                         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));
514                 }
515
516                 p_fifo->b_next_frame = 1;
517                 break;
518
519 /*
520             }
521             else
522             {
523                 fprintf(stderr, "-");
524                 p_fifo->l_start_frame = p_fifo->l_next_frame;
525             }
526 */
527         }
528         p_fifo->l_next_frame = (p_fifo->l_next_frame + 1) & AOUT_FIFO_SIZE;
529     }
530     if ( p_fifo->l_next_frame == p_fifo->l_end_frame )
531     {
532         if ( (((p_fifo->l_end_frame + 1) - p_fifo->l_start_frame) & AOUT_FIFO_SIZE) == 0 )
533         {
534             p_fifo->l_start_frame = 0;
535             p_fifo->b_start_frame = 0;
536             /* p_fifo->l_next_frame = 0; */
537             /* p_fifo->b_next_frame = 0; */
538             p_fifo->l_end_frame = 0;
539         }
540         vlc_mutex_unlock( &p_fifo->data_lock );
541         return( -1 );
542     }
543
544     l_units = ((p_fifo->l_next_frame - p_fifo->l_start_frame) & AOUT_FIFO_SIZE) * (p_fifo->l_frame_size >> p_fifo->b_stereo);
545
546     l_rate = (long)( ((mtime_t)l_units * 1000000)
547         / (p_fifo->date[p_fifo->l_next_frame] - p_fifo->date[p_fifo->l_start_frame]) );
548 //    fprintf( stderr, "aout debug: l_rate == %li\n", l_rate );
549
550     InitializeIncrement( &p_fifo->unit_increment, l_rate, p_aout->dsp.l_rate );
551
552     p_fifo->l_units = (((l_units - (p_fifo->l_unit -
553         (p_fifo->l_start_frame * (p_fifo->l_frame_size >> p_fifo->b_stereo))))
554         * p_aout->dsp.l_rate) / l_rate) + 1;
555
556     /* We release the lock before leaving */
557     vlc_mutex_unlock( &p_fifo->data_lock );
558     return( 0 );
559 }
560
561 void aout_Thread_S8_Mono( aout_thread_t * p_aout )
562 {
563 }
564
565 void aout_Thread_S8_Stereo( aout_thread_t * p_aout )
566 {
567 }
568
569 void aout_Thread_U8_Mono( aout_thread_t * p_aout )
570 {
571 }
572
573 void aout_Thread_U8_Stereo( aout_thread_t * p_aout )
574 {
575 }
576
577 void aout_Thread_S16_Mono( aout_thread_t * p_aout )
578 {
579 }
580
581 void aout_Thread_S16_Stereo( aout_thread_t * p_aout )
582 {
583     int i_fifo;
584     long l_units;
585     long l_buffer, l_buffer_limit;
586
587     intf_DbgMsg("adec debug: running audio output thread (%p) (pid == %i)\n", p_aout, getpid());
588
589     /* As the s32_buffer was created with calloc(), we don't have to set this
590      * memory to zero and we can immediately jump into the thread's loop */
591     while ( !p_aout->b_die )
592     {
593         vlc_mutex_lock( &p_aout->fifos_lock );
594         for ( i_fifo = 0; i_fifo < AOUT_MAX_FIFOS; i_fifo++ )
595         {
596             switch ( p_aout->fifo[i_fifo].i_type )
597             {
598                 case AOUT_EMPTY_FIFO:
599                     break;
600
601                 case AOUT_INTF_MONO_FIFO:
602                     if ( p_aout->fifo[i_fifo].b_die )
603                     {
604                         free( p_aout->fifo[i_fifo].buffer ); /* !! */
605                         p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
606                         intf_DbgMsg("aout debug: audio output fifo (%p) destroyed\n", &p_aout->fifo[i_fifo]);
607                         continue;
608                     }
609
610                     if ( p_aout->fifo[i_fifo].l_units > p_aout->l_units )
611                     {
612                         l_buffer = 0;
613                         while ( l_buffer < (p_aout->l_units << 1) ) /* p_aout->dsp.b_stereo == 1 */
614                         {
615                             p_aout->s32_buffer[l_buffer++] +=
616                                 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
617                             p_aout->s32_buffer[l_buffer++] +=
618                                 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
619                             UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
620                         }
621                         p_aout->fifo[i_fifo].l_units -= p_aout->l_units;
622                     }
623                     else
624                     {
625                         l_buffer = 0;
626                         while ( l_buffer < (p_aout->fifo[i_fifo].l_units << 1) ) /* p_aout->dsp.b_stereo == 1 */
627                         {
628                             p_aout->s32_buffer[l_buffer++] +=
629                                 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
630                             p_aout->s32_buffer[l_buffer++] +=
631                                 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
632                             UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
633                         }
634                         free( p_aout->fifo[i_fifo].buffer ); /* !! */
635                         p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
636                         intf_DbgMsg("aout debug: audio output fifo (%p) destroyed\n", &p_aout->fifo[i_fifo]); /* !! */
637                     }
638                     break;
639
640                 case AOUT_INTF_STEREO_FIFO:
641                     if ( p_aout->fifo[i_fifo].b_die )
642                     {
643                         free( p_aout->fifo[i_fifo].buffer ); /* !! */
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                     if ( p_aout->fifo[i_fifo].l_units > p_aout->l_units )
650                     {
651                         l_buffer = 0;
652                         while ( l_buffer < (p_aout->l_units << 1) ) /* p_aout->dsp.b_stereo == 1 */
653                         {
654                             p_aout->s32_buffer[l_buffer++] +=
655                                 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit] );
656                             p_aout->s32_buffer[l_buffer++] +=
657                                 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit+1] );
658                             UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
659                         }
660                         p_aout->fifo[i_fifo].l_units -= p_aout->l_units;
661                     }
662                     else
663                     {
664                         l_buffer = 0;
665                         while ( l_buffer < (p_aout->fifo[i_fifo].l_units << 1) ) /* p_aout->dsp.b_stereo */
666                         {
667                             p_aout->s32_buffer[l_buffer++] +=
668                                 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit] );
669                             p_aout->s32_buffer[l_buffer++] +=
670                                 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit+1] );
671                             UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
672                         }
673                         free( p_aout->fifo[i_fifo].buffer ); /* !! */
674                         p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
675                         intf_DbgMsg("aout debug: audio output fifo (%p) destroyed\n", &p_aout->fifo[i_fifo]); /* !! */
676                     }
677                     break;
678
679                 case AOUT_ADEC_MONO_FIFO:
680                     if ( p_aout->fifo[i_fifo].b_die )
681                     {
682                         free( p_aout->fifo[i_fifo].buffer );
683                         free( p_aout->fifo[i_fifo].date );
684                         p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
685                         intf_DbgMsg("aout debug: audio output fifo (%p) destroyed\n", &p_aout->fifo[i_fifo]);
686                         continue;
687                     }
688
689                     l_units = p_aout->l_units;
690                     l_buffer = 0;
691                     while ( l_units > 0 )
692                     {
693                         if ( !p_aout->fifo[i_fifo].b_next_frame )
694                         {
695                             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)*/) )
696                             {
697                                 break;
698                             }
699                         }
700
701                         if ( p_aout->fifo[i_fifo].l_units > l_units )
702                         {
703                             l_buffer_limit = p_aout->l_units << 1; /* p_aout->dsp.b_stereo == 1 */
704                             while ( l_buffer < l_buffer_limit )
705                             {
706                                 p_aout->s32_buffer[l_buffer++] +=
707                                     (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
708                                 p_aout->s32_buffer[l_buffer++] +=
709                                     (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
710
711                                 UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
712                                 if ( p_aout->fifo[i_fifo].l_unit >= /* p_aout->fifo[i_fifo].b_stereo == 0 */
713                                      ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 0)) )
714                                 {
715                                     p_aout->fifo[i_fifo].l_unit -= /* p_aout->fifo[i_fifo].b_stereo == 0 */
716                                         ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 0));
717                                 }
718                             }
719                             p_aout->fifo[i_fifo].l_units -= l_units;
720                             break;
721                         }
722                         else
723                         {
724                             l_buffer_limit = l_buffer + (p_aout->fifo[i_fifo].l_units << 1);
725                             /* p_aout->dsp.b_stereo == 1 */
726                             while ( l_buffer < l_buffer_limit )
727                             {
728                                 p_aout->s32_buffer[l_buffer++] +=
729                                     (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
730                                 p_aout->s32_buffer[l_buffer++] +=
731                                     (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
732
733                                 UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
734                                 if ( p_aout->fifo[i_fifo].l_unit >= /* p_aout->fifo[i_fifo].b_stereo == 0 */
735                                      ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 0)) )
736                                 {
737                                     p_aout->fifo[i_fifo].l_unit -= /* p_aout->fifo[i_fifo].b_stereo == 0 */
738                                         ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 0));
739                                 }
740                             }
741                             l_units -= p_aout->fifo[i_fifo].l_units;
742
743                             vlc_mutex_lock( &p_aout->fifo[i_fifo].data_lock );
744                             p_aout->fifo[i_fifo].l_start_frame = p_aout->fifo[i_fifo].l_next_frame;
745                             vlc_cond_signal( &p_aout->fifo[i_fifo].data_wait );
746                             vlc_mutex_unlock( &p_aout->fifo[i_fifo].data_lock );
747
748                             /* p_aout->fifo[i_fifo].b_start_frame = 1; */
749                             p_aout->fifo[i_fifo].l_next_frame += 1;
750                             p_aout->fifo[i_fifo].l_next_frame &= AOUT_FIFO_SIZE;
751                             p_aout->fifo[i_fifo].b_next_frame = 0;
752                         }
753                     }
754                     break;
755
756                 case AOUT_ADEC_STEREO_FIFO:
757                     if ( p_aout->fifo[i_fifo].b_die )
758                     {
759                         free( p_aout->fifo[i_fifo].buffer );
760                         free( p_aout->fifo[i_fifo].date );
761                         p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
762                         intf_DbgMsg("aout debug: audio output fifo (%p) destroyed\n", &p_aout->fifo[i_fifo]);
763                         continue;
764                     }
765
766                     l_units = p_aout->l_units;
767                     l_buffer = 0;
768                     while ( l_units > 0 )
769                     {
770                         if ( !p_aout->fifo[i_fifo].b_next_frame )
771                         {
772                             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)*/) )
773                             {
774                                 break;
775                             }
776                         }
777
778                         if ( p_aout->fifo[i_fifo].l_units > l_units )
779                         {
780                             l_buffer_limit = p_aout->l_units << 1; /* p_aout->dsp.b_stereo == 1 */
781                             while ( l_buffer < l_buffer_limit )
782                             {
783                                 p_aout->s32_buffer[l_buffer++] +=
784                                     (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit] );
785                                 p_aout->s32_buffer[l_buffer++] +=
786                                     (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit+1] );
787
788                                 UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
789                                 if ( p_aout->fifo[i_fifo].l_unit >= /* p_aout->fifo[i_fifo].b_stereo == 1 */
790                                      ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 1)) )
791                                 {
792                                     p_aout->fifo[i_fifo].l_unit -= /* p_aout->fifo[i_fifo].b_stereo == 1 */
793                                         ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 1));
794                                 }
795                             }
796                             p_aout->fifo[i_fifo].l_units -= l_units;
797                             break;
798                         }
799                         else
800                         {
801                             l_buffer_limit = l_buffer + (p_aout->fifo[i_fifo].l_units << 1);
802                             /* p_aout->dsp.b_stereo == 1 */
803                             while ( l_buffer < l_buffer_limit )
804                             {
805                                 p_aout->s32_buffer[l_buffer++] +=
806                                     (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit] );
807                                 p_aout->s32_buffer[l_buffer++] +=
808                                     (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit+1] );
809
810                                 UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
811                                 if ( p_aout->fifo[i_fifo].l_unit >= /* p_aout->fifo[i_fifo].b_stereo == 1 */
812                                      ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 1)) )
813                                 {
814                                     p_aout->fifo[i_fifo].l_unit -= /* p_aout->fifo[i_fifo].b_stereo == 1 */
815                                         ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 1));
816                                 }
817                             }
818                             l_units -= p_aout->fifo[i_fifo].l_units;
819
820                             vlc_mutex_lock( &p_aout->fifo[i_fifo].data_lock );
821                             p_aout->fifo[i_fifo].l_start_frame = p_aout->fifo[i_fifo].l_next_frame;
822                             vlc_cond_signal( &p_aout->fifo[i_fifo].data_wait );
823                             vlc_mutex_unlock( &p_aout->fifo[i_fifo].data_lock );
824
825                             /* p_aout->fifo[i_fifo].b_start_frame = 1; */
826                             p_aout->fifo[i_fifo].l_next_frame += 1;
827                             p_aout->fifo[i_fifo].l_next_frame &= AOUT_FIFO_SIZE;
828                             p_aout->fifo[i_fifo].b_next_frame = 0;
829                         }
830                     }
831                     break;
832
833                 default:
834                     intf_DbgMsg("aout debug: unknown fifo type (%i)\n", p_aout->fifo[i_fifo].i_type);
835                     break;
836             }
837         }
838         vlc_mutex_unlock( &p_aout->fifos_lock );
839
840         l_buffer_limit = p_aout->l_units << 1; /* p_aout->dsp.b_stereo == 1 */
841
842         for ( l_buffer = 0; l_buffer < l_buffer_limit; l_buffer++ )
843         {
844             ((s16 *)p_aout->buffer)[l_buffer] = (s16)( p_aout->s32_buffer[l_buffer] / AOUT_MAX_FIFOS );
845             p_aout->s32_buffer[l_buffer] = 0;
846         }
847
848         aout_dspGetBufInfo( &p_aout->dsp );
849         if ( p_aout->dsp.buf_info.fragments == p_aout->dsp.buf_info.fragstotal ) /* ?? */
850         {
851             aout_dspPlaySamples( &p_aout->dsp, (byte_t *)p_aout->buffer, sizeof(s16) * l_buffer_limit );
852             p_aout->date = mdate();
853         }
854         else if ( p_aout->dsp.buf_info.bytes >=
855             ((p_aout->dsp.buf_info.fragsize * p_aout->dsp.buf_info.fragstotal) -
856             (sizeof(s16) * l_buffer_limit)) )
857         {
858             aout_dspPlaySamples( &p_aout->dsp, (byte_t *)p_aout->buffer, sizeof(s16) * l_buffer_limit );
859         }
860         else
861         {
862             aout_dspPlaySamples( &p_aout->dsp, (byte_t *)p_aout->buffer, sizeof(s16) * l_buffer_limit );
863             msleep( p_aout->date_increment.l_euclidean_integer );
864         }
865         UPDATE_INCREMENT( p_aout->date_increment, p_aout->date )
866     }
867
868     vlc_mutex_lock( &p_aout->fifos_lock );
869     for ( i_fifo = 0; i_fifo < AOUT_MAX_FIFOS; i_fifo++ )
870     {
871         switch ( p_aout->fifo[i_fifo].i_type )
872         {
873             case AOUT_EMPTY_FIFO:
874                 break;
875
876             case AOUT_INTF_MONO_FIFO:
877             case AOUT_INTF_STEREO_FIFO:
878                 free( p_aout->fifo[i_fifo].buffer ); /* !! */
879                 p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
880                 intf_DbgMsg("aout debug: audio output fifo (%p) destroyed\n", &p_aout->fifo[i_fifo]);
881                 break;
882
883             case AOUT_ADEC_MONO_FIFO:
884             case AOUT_ADEC_STEREO_FIFO:
885                 free( p_aout->fifo[i_fifo].buffer );
886                 free( p_aout->fifo[i_fifo].date );
887                 p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
888                 intf_DbgMsg("aout debug: audio output fifo (%p) destroyed\n", &p_aout->fifo[i_fifo]);
889                 break;
890
891             default:
892                 break;
893         }
894     }
895     vlc_mutex_unlock( &p_aout->fifos_lock );
896 }
897
898 void aout_Thread_U16_Mono( aout_thread_t * p_aout )
899 {
900 }
901
902 void aout_Thread_U16_Stereo( aout_thread_t * p_aout )
903 {
904 }