]> git.sesse.net Git - vlc/blob - src/audio_output/audio_output.c
* ac3_decoder/ac3_decoder.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_start_frame] >= p_fifo->date[p_fifo->l_next_frame] )
508                 {
509                         fprintf( stderr, "aout debug: %lli >= %lli\n", p_fifo->date[p_fifo->l_start_frame], p_fifo->date[p_fifo->l_next_frame] );
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                 else if ( (p_fifo->date[p_fifo->l_next_frame] - p_fifo->date[p_fifo->l_start_frame]) > 1000000 )
514                 {
515                         fprintf( stderr, "aout debug: (%lli - %lli) > 1000000\n", p_fifo->date[p_fifo->l_next_frame], p_fifo->date[p_fifo->l_start_frame] );
516                         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));
517                 }
518
519                 p_fifo->b_next_frame = 1;
520                 break;
521
522 /*
523             }
524             else
525             {
526                 fprintf(stderr, "-");
527                 p_fifo->l_start_frame = p_fifo->l_next_frame;
528             }
529 */
530         }
531         p_fifo->l_next_frame = (p_fifo->l_next_frame + 1) & AOUT_FIFO_SIZE;
532     }
533     if ( p_fifo->l_next_frame == p_fifo->l_end_frame )
534     {
535         if ( (((p_fifo->l_end_frame + 1) - p_fifo->l_start_frame) & AOUT_FIFO_SIZE) == 0 )
536         {
537             p_fifo->l_start_frame = 0;
538             p_fifo->b_start_frame = 0;
539             /* p_fifo->l_next_frame = 0; */
540             /* p_fifo->b_next_frame = 0; */
541             p_fifo->l_end_frame = 0;
542         }
543         vlc_mutex_unlock( &p_fifo->data_lock );
544         return( -1 );
545     }
546
547     l_units = ((p_fifo->l_next_frame - p_fifo->l_start_frame) & AOUT_FIFO_SIZE) * (p_fifo->l_frame_size >> p_fifo->b_stereo);
548
549     l_rate = (long)( ((mtime_t)l_units * 1000000)
550         / (p_fifo->date[p_fifo->l_next_frame] - p_fifo->date[p_fifo->l_start_frame]) );
551 //    fprintf( stderr, "aout debug: l_rate == %li\n", l_rate );
552
553     InitializeIncrement( &p_fifo->unit_increment, l_rate, p_aout->dsp.l_rate );
554
555     p_fifo->l_units = (((l_units - (p_fifo->l_unit -
556         (p_fifo->l_start_frame * (p_fifo->l_frame_size >> p_fifo->b_stereo))))
557         * p_aout->dsp.l_rate) / l_rate) + 1;
558
559     /* We release the lock before leaving */
560     vlc_mutex_unlock( &p_fifo->data_lock );
561     return( 0 );
562 }
563
564 void aout_Thread_S8_Mono( aout_thread_t * p_aout )
565 {
566 }
567
568 void aout_Thread_S8_Stereo( aout_thread_t * p_aout )
569 {
570 }
571
572 void aout_Thread_U8_Mono( aout_thread_t * p_aout )
573 {
574 }
575
576 void aout_Thread_U8_Stereo( aout_thread_t * p_aout )
577 {
578 }
579
580 void aout_Thread_S16_Mono( aout_thread_t * p_aout )
581 {
582 }
583
584 void aout_Thread_S16_Stereo( aout_thread_t * p_aout )
585 {
586     int i_fifo;
587     long l_units;
588     long l_buffer, l_buffer_limit;
589
590     intf_DbgMsg("adec debug: running audio output thread (%p) (pid == %i)\n", p_aout, getpid());
591
592     /* As the s32_buffer was created with calloc(), we don't have to set this
593      * memory to zero and we can immediately jump into the thread's loop */
594     while ( !p_aout->b_die )
595     {
596         vlc_mutex_lock( &p_aout->fifos_lock );
597         for ( i_fifo = 0; i_fifo < AOUT_MAX_FIFOS; i_fifo++ )
598         {
599             switch ( p_aout->fifo[i_fifo].i_type )
600             {
601                 case AOUT_EMPTY_FIFO:
602                     break;
603
604                 case AOUT_INTF_MONO_FIFO:
605                     if ( p_aout->fifo[i_fifo].l_units > p_aout->l_units )
606                     {
607                         l_buffer = 0;
608                         while ( l_buffer < (p_aout->l_units << 1) ) /* p_aout->dsp.b_stereo == 1 */
609                         {
610                             p_aout->s32_buffer[l_buffer++] +=
611                                 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
612                             p_aout->s32_buffer[l_buffer++] +=
613                                 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
614                             UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
615                         }
616                         p_aout->fifo[i_fifo].l_units -= p_aout->l_units;
617                     }
618                     else
619                     {
620                         l_buffer = 0;
621                         while ( l_buffer < (p_aout->fifo[i_fifo].l_units << 1) ) /* p_aout->dsp.b_stereo == 1 */
622                         {
623                             p_aout->s32_buffer[l_buffer++] +=
624                                 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
625                             p_aout->s32_buffer[l_buffer++] +=
626                                 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
627                             UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
628                         }
629                         free( p_aout->fifo[i_fifo].buffer ); /* !! */
630                         p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
631                         intf_DbgMsg("aout debug: audio output fifo (%p) destroyed\n", &p_aout->fifo[i_fifo]); /* !! */
632                     }
633                     break;
634
635                 case AOUT_INTF_STEREO_FIFO:
636                     if ( p_aout->fifo[i_fifo].l_units > p_aout->l_units )
637                     {
638                         l_buffer = 0;
639                         while ( l_buffer < (p_aout->l_units << 1) ) /* p_aout->dsp.b_stereo == 1 */
640                         {
641                             p_aout->s32_buffer[l_buffer++] +=
642                                 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit] );
643                             p_aout->s32_buffer[l_buffer++] +=
644                                 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit+1] );
645                             UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
646                         }
647                         p_aout->fifo[i_fifo].l_units -= p_aout->l_units;
648                     }
649                     else
650                     {
651                         l_buffer = 0;
652                         while ( l_buffer < (p_aout->fifo[i_fifo].l_units << 1) ) /* p_aout->dsp.b_stereo */
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                         free( p_aout->fifo[i_fifo].buffer ); /* !! */
661                         p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
662                         intf_DbgMsg("aout debug: audio output fifo (%p) destroyed\n", &p_aout->fifo[i_fifo]); /* !! */
663                     }
664                     break;
665
666                 case AOUT_ADEC_MONO_FIFO:
667                     l_units = p_aout->l_units;
668                     l_buffer = 0;
669                     while ( l_units > 0 )
670                     {
671                         if ( !p_aout->fifo[i_fifo].b_next_frame )
672                         {
673                             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)*/) )
674                             {
675                                 break;
676                             }
677                         }
678
679                         if ( p_aout->fifo[i_fifo].l_units > l_units )
680                         {
681                             l_buffer_limit = p_aout->l_units << 1; /* p_aout->dsp.b_stereo == 1 */
682                             while ( l_buffer < l_buffer_limit )
683                             {
684                                 p_aout->s32_buffer[l_buffer++] +=
685                                     (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
686                                 p_aout->s32_buffer[l_buffer++] +=
687                                     (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
688
689                                 UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
690                                 if ( p_aout->fifo[i_fifo].l_unit >= /* p_aout->fifo[i_fifo].b_stereo == 0 */
691                                      ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 0)) )
692                                 {
693                                     p_aout->fifo[i_fifo].l_unit -= /* p_aout->fifo[i_fifo].b_stereo == 0 */
694                                         ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 0));
695                                 }
696                             }
697                             p_aout->fifo[i_fifo].l_units -= l_units;
698                             break;
699                         }
700                         else
701                         {
702                             l_buffer_limit = l_buffer + (p_aout->fifo[i_fifo].l_units << 1);
703                             /* 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                             l_units -= p_aout->fifo[i_fifo].l_units;
720
721                             vlc_mutex_lock( &p_aout->fifo[i_fifo].data_lock );
722                             p_aout->fifo[i_fifo].l_start_frame = p_aout->fifo[i_fifo].l_next_frame;
723                             vlc_cond_signal( &p_aout->fifo[i_fifo].data_wait );
724                             vlc_mutex_unlock( &p_aout->fifo[i_fifo].data_lock );
725
726                             /* p_aout->fifo[i_fifo].b_start_frame = 1; */
727                             p_aout->fifo[i_fifo].l_next_frame += 1;
728                             p_aout->fifo[i_fifo].l_next_frame &= AOUT_FIFO_SIZE;
729                             p_aout->fifo[i_fifo].b_next_frame = 0;
730                         }
731                     }
732                     break;
733
734                 case AOUT_ADEC_STEREO_FIFO:
735                     l_units = p_aout->l_units;
736                     l_buffer = 0;
737                     while ( l_units > 0 )
738                     {
739                         if ( !p_aout->fifo[i_fifo].b_next_frame )
740                         {
741                             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)*/) )
742                             {
743                                 break;
744                             }
745                         }
746
747                         if ( p_aout->fifo[i_fifo].l_units > l_units )
748                         {
749                             l_buffer_limit = p_aout->l_units << 1; /* p_aout->dsp.b_stereo == 1 */
750                             while ( l_buffer < l_buffer_limit )
751                             {
752                                 p_aout->s32_buffer[l_buffer++] +=
753                                     (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit] );
754                                 p_aout->s32_buffer[l_buffer++] +=
755                                     (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit+1] );
756
757                                 UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
758                                 if ( p_aout->fifo[i_fifo].l_unit >= /* p_aout->fifo[i_fifo].b_stereo == 1 */
759                                      ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 1)) )
760                                 {
761                                     p_aout->fifo[i_fifo].l_unit -= /* p_aout->fifo[i_fifo].b_stereo == 1 */
762                                         ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 1));
763                                 }
764                             }
765                             p_aout->fifo[i_fifo].l_units -= l_units;
766                             break;
767                         }
768                         else
769                         {
770                             l_buffer_limit = l_buffer + (p_aout->fifo[i_fifo].l_units << 1);
771                             /* p_aout->dsp.b_stereo == 1 */
772                             while ( l_buffer < l_buffer_limit )
773                             {
774                                 p_aout->s32_buffer[l_buffer++] +=
775                                     (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit] );
776                                 p_aout->s32_buffer[l_buffer++] +=
777                                     (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit+1] );
778
779                                 UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
780                                 if ( p_aout->fifo[i_fifo].l_unit >= /* p_aout->fifo[i_fifo].b_stereo == 1 */
781                                      ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 1)) )
782                                 {
783                                     p_aout->fifo[i_fifo].l_unit -= /* p_aout->fifo[i_fifo].b_stereo == 1 */
784                                         ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 1));
785                                 }
786                             }
787                             l_units -= p_aout->fifo[i_fifo].l_units;
788
789                             vlc_mutex_lock( &p_aout->fifo[i_fifo].data_lock );
790                             p_aout->fifo[i_fifo].l_start_frame = p_aout->fifo[i_fifo].l_next_frame;
791                             vlc_cond_signal( &p_aout->fifo[i_fifo].data_wait );
792                             vlc_mutex_unlock( &p_aout->fifo[i_fifo].data_lock );
793
794                             /* p_aout->fifo[i_fifo].b_start_frame = 1; */
795                             p_aout->fifo[i_fifo].l_next_frame += 1;
796                             p_aout->fifo[i_fifo].l_next_frame &= AOUT_FIFO_SIZE;
797                             p_aout->fifo[i_fifo].b_next_frame = 0;
798                         }
799                     }
800                     break;
801
802                 default:
803                     intf_DbgMsg("aout debug: unknown fifo type (%i)\n", p_aout->fifo[i_fifo].i_type);
804                     break;
805             }
806         }
807         vlc_mutex_unlock( &p_aout->fifos_lock );
808
809         l_buffer_limit = p_aout->l_units << 1; /* p_aout->dsp.b_stereo == 1 */
810
811         for ( l_buffer = 0; l_buffer < l_buffer_limit; l_buffer++ )
812         {
813             ((s16 *)p_aout->buffer)[l_buffer] = S32_TO_S16( p_aout->s32_buffer[l_buffer] / AOUT_MAX_FIFOS );
814             p_aout->s32_buffer[l_buffer] = 0;
815         }
816
817         aout_dspGetBufInfo( &p_aout->dsp );
818         if ( p_aout->dsp.buf_info.fragments == p_aout->dsp.buf_info.fragstotal ) /* ?? */
819         {
820             aout_dspPlaySamples( &p_aout->dsp, (byte_t *)p_aout->buffer, sizeof(s16) * l_buffer_limit );
821             p_aout->date = mdate();
822         }
823         else if ( p_aout->dsp.buf_info.bytes >=
824             ((p_aout->dsp.buf_info.fragsize * p_aout->dsp.buf_info.fragstotal) -
825             (sizeof(s16) * l_buffer_limit)) )
826         {
827             aout_dspPlaySamples( &p_aout->dsp, (byte_t *)p_aout->buffer, sizeof(s16) * l_buffer_limit );
828         }
829         else
830         {
831             aout_dspPlaySamples( &p_aout->dsp, (byte_t *)p_aout->buffer, sizeof(s16) * l_buffer_limit );
832             msleep( p_aout->date_increment.l_euclidean_integer );
833         }
834         UPDATE_INCREMENT( p_aout->date_increment, p_aout->date )
835     }
836
837     vlc_mutex_lock( &p_aout->fifos_lock );
838     for ( i_fifo = 0; i_fifo < AOUT_MAX_FIFOS; i_fifo++ )
839     {
840         switch ( p_aout->fifo[i_fifo].i_type )
841         {
842             case AOUT_EMPTY_FIFO:
843                 break;
844
845             case AOUT_INTF_MONO_FIFO:
846             case AOUT_INTF_STEREO_FIFO:
847                 free( p_aout->fifo[i_fifo].buffer ); /* !! */
848                 p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
849                 intf_DbgMsg("aout debug: audio output fifo (%p) destroyed\n", &p_aout->fifo[i_fifo]);
850                 break;
851
852             case AOUT_ADEC_MONO_FIFO:
853             case AOUT_ADEC_STEREO_FIFO:
854                 free( p_aout->fifo[i_fifo].buffer );
855                 free( p_aout->fifo[i_fifo].date );
856                 p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
857                 intf_DbgMsg("aout debug: audio output fifo (%p) destroyed\n", &p_aout->fifo[i_fifo]);
858                 break;
859
860             default:
861                 break;
862         }
863     }
864     vlc_mutex_unlock( &p_aout->fifos_lock );
865 }
866
867 void aout_Thread_U16_Mono( aout_thread_t * p_aout )
868 {
869 }
870
871 void aout_Thread_U16_Stereo( aout_thread_t * p_aout )
872 {
873 }