]> git.sesse.net Git - vlc/blob - src/audio_output/audio_output.c
Beginning of Interface II
[vlc] / src / audio_output / audio_output.c
1 /*****************************************************************************
2  * audio_output.c : audio output thread
3  *****************************************************************************
4  * Copyright (C) 1999, 2000 VideoLAN
5  *
6  * Authors: Michel Kaempf <maxx@via.ecp.fr>
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  * 
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
21  *****************************************************************************/
22
23 /* TODO:
24  *
25  * - Passer un certain nombre de "fonctions" (genre add_samples) en macro ou
26  *   inline
27  * - Faire les optimisations dans les fonctions threads :
28  *   = Stocker les "petits calculs" dans des variables au lieu de les refaire
29  *     à chaque boucle
30  *   = Utiliser des tables pour les gros calculs
31  * - Faire une structure différente pour intf/adec fifo
32  *
33  */
34
35 /*****************************************************************************
36  * Preamble
37  *****************************************************************************/
38 #include "defs.h"
39
40 #include <unistd.h>                                              /* getpid() */
41
42 #include <stdio.h>                                           /* "intf_msg.h" */
43 #include <stdlib.h>                            /* calloc(), malloc(), free() */
44
45 #include "config.h"
46 #include "common.h"
47 #include "threads.h"
48 #include "mtime.h"                             /* mtime_t, mdate(), msleep() */
49 #include "modules.h"
50
51 #include "intf_msg.h"                        /* intf_DbgMsg(), intf_ErrMsg() */
52
53 #include "audio_output.h"
54 #include "main.h"
55
56 /*****************************************************************************
57  * Local prototypes
58  *****************************************************************************/
59
60 static int aout_SpawnThread( aout_thread_t * p_aout );
61
62 /* Creating as much aout_Thread functions as configurations is one solution,
63  * examining the different cases in the Thread loop of an unique function is
64  * another. I chose the first solution. */
65 void aout_Thread_S8_Mono        ( aout_thread_t * p_aout );
66 void aout_Thread_U8_Mono        ( aout_thread_t * p_aout );
67 void aout_Thread_S16_Mono       ( aout_thread_t * p_aout );
68 void aout_Thread_U16_Mono       ( aout_thread_t * p_aout );
69 void aout_Thread_S8_Stereo      ( aout_thread_t * p_aout );
70 void aout_Thread_U8_Stereo      ( aout_thread_t * p_aout );
71 void aout_Thread_S16_Stereo     ( aout_thread_t * p_aout );
72 void aout_Thread_U16_Stereo     ( aout_thread_t * p_aout );
73
74 static __inline__ void InitializeIncrement( aout_increment_t * p_increment, long l_numerator, long l_denominator );
75 static __inline__ int NextFrame( aout_thread_t * p_aout, aout_fifo_t * p_fifo, mtime_t aout_date );
76
77 /*****************************************************************************
78  * InitializeIncrement
79  *****************************************************************************/
80 static __inline__ void InitializeIncrement( aout_increment_t * p_increment, long l_numerator, long l_denominator )
81 {
82     p_increment->l_remainder = -l_denominator;
83
84     p_increment->l_euclidean_integer = 0;
85     while ( l_numerator >= l_denominator )
86     {
87         p_increment->l_euclidean_integer++;
88         l_numerator -= l_denominator;
89     }
90
91     p_increment->l_euclidean_remainder = l_numerator;
92
93     p_increment->l_euclidean_denominator = l_denominator;
94 }
95
96 /*****************************************************************************
97  * aout_CreateThread: initialize audio thread
98  *****************************************************************************/
99 aout_thread_t *aout_CreateThread( int *pi_status )
100 {
101     aout_thread_t * p_aout;                             /* thread descriptor */
102 #if 0
103     int             i_status;                               /* thread status */
104 #endif
105
106     /* Allocate descriptor */
107     p_aout = (aout_thread_t *) malloc( sizeof(aout_thread_t) );
108     if( p_aout == NULL )
109     {
110         return( NULL );
111     }
112
113     /* Choose the best module */
114     p_aout->p_module = module_Need( p_main->p_bank,
115                                     MODULE_CAPABILITY_AOUT, NULL );
116
117     if( p_aout->p_module == NULL )
118     {
119         intf_ErrMsg( "aout error: no suitable aout module" );
120         free( p_aout );
121         return( NULL );
122     }
123
124 #define aout_functions p_aout->p_module->p_functions->aout.functions.aout
125     p_aout->pf_open       = aout_functions.pf_open;
126     p_aout->pf_setformat  = aout_functions.pf_setformat;
127     p_aout->pf_getbufinfo = aout_functions.pf_getbufinfo;
128     p_aout->pf_play       = aout_functions.pf_play;
129     p_aout->pf_close      = aout_functions.pf_close;
130 #undef aout_functions
131
132     /*
133      * Initialize audio device
134      */
135     if ( p_aout->pf_open( p_aout ) )
136     {
137         module_Unneed( p_main->p_bank, p_aout->p_module );
138         free( p_aout );
139         return( NULL );
140     }
141
142     p_aout->b_stereo = ( p_aout->i_channels == 2 ) ? 1 : 0; /* FIXME: only works
143                                                    for i_channels == 1 or 2 ??*/
144
145     if ( p_aout->pf_setformat( p_aout ) )
146     {
147         p_aout->pf_close( p_aout );
148         module_Unneed( p_main->p_bank, p_aout->p_module );
149         free( p_aout );
150         return( NULL );
151     }
152
153     /* Initialize the volume level */
154     p_aout->vol = VOLUME_DEFAULT;
155     
156     /* FIXME: maybe it would be cleaner to change SpawnThread prototype
157      * see vout to handle status correctly ?? however, it is not critical since
158      * this thread is only called in main and all calls are blocking */
159     if( aout_SpawnThread( p_aout ) )
160     {
161         p_aout->pf_close( p_aout );
162         module_Unneed( p_main->p_bank, p_aout->p_module );
163         free( p_aout );
164         return( NULL );
165     }
166
167     return( p_aout );
168 }
169
170 /*****************************************************************************
171  * aout_SpawnThread
172  *****************************************************************************/
173 static int aout_SpawnThread( aout_thread_t * p_aout )
174 {
175     int             i_fifo;
176     long            l_bytes;
177     void *          aout_thread = NULL;
178
179     intf_DbgMsg("aout debug: spawning audio output thread (%p)", p_aout);
180
181     /* We want the audio output thread to live */
182     p_aout->b_die = 0;
183     p_aout->b_active = 1;
184
185     /* Initialize the fifos lock */
186     vlc_mutex_init( &p_aout->fifos_lock );
187     /* Initialize audio fifos : set all fifos as empty and initialize locks */
188     for ( i_fifo = 0; i_fifo < AOUT_MAX_FIFOS; i_fifo++ )
189     {
190         p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO;
191         vlc_mutex_init( &p_aout->fifo[i_fifo].data_lock );
192         vlc_cond_init( &p_aout->fifo[i_fifo].data_wait );
193     }
194
195     /* Compute the size (in audio units) of the audio output buffer. Although
196      * AOUT_BUFFER_DURATION is given in microseconds, the output rate is given
197      * in Hz, that's why we need to divide by 10^6 microseconds (1 second) */
198     p_aout->l_units = (long)( ((s64)p_aout->l_rate * AOUT_BUFFER_DURATION) / 1000000 );
199     p_aout->l_msleep = (long)( ((s64)p_aout->l_units * 1000000) / (s64)p_aout->l_rate );
200
201     /* Make aout_thread point to the right thread function, and compute the
202      * byte size of the audio output buffer */
203     switch ( p_aout->i_channels )
204     {
205         /* Audio output is mono */
206         case 1:
207             switch ( p_aout->i_format )
208             {
209                 case AOUT_FMT_U8:
210                     l_bytes = 1 * sizeof(u8) * p_aout->l_units;
211                     aout_thread = (void *)aout_Thread_U8_Mono;
212                     break;
213
214                 case AOUT_FMT_S8:
215                     l_bytes = 1 * sizeof(s8) * p_aout->l_units;
216                     aout_thread = (void *)aout_Thread_S8_Mono;
217                     break;
218
219                 case AOUT_FMT_U16_LE:
220                 case AOUT_FMT_U16_BE:
221                     l_bytes = 1 * sizeof(u16) * p_aout->l_units;
222                     aout_thread = (void *)aout_Thread_U16_Mono;
223                     break;
224
225                 case AOUT_FMT_S16_LE:
226                 case AOUT_FMT_S16_BE:
227                     l_bytes = 1 * sizeof(s16) * p_aout->l_units;
228                     aout_thread = (void *)aout_Thread_S16_Mono;
229                     break;
230
231                 default:
232                     intf_ErrMsg( "aout error: unknown audio output format (%i)",
233                                  p_aout->i_format );
234                     return( -1 );
235             }
236             break;
237
238         /* Audio output is stereo */
239         case 2:
240             switch ( p_aout->i_format )
241             {
242                 case AOUT_FMT_U8:
243                     l_bytes = 2 * sizeof(u8) * p_aout->l_units;
244                     aout_thread = (void *)aout_Thread_U8_Stereo;
245                     break;
246
247                 case AOUT_FMT_S8:
248                     l_bytes = 2 * sizeof(s8) * p_aout->l_units;
249                     aout_thread = (void *)aout_Thread_S8_Stereo;
250                     break;
251
252                 case AOUT_FMT_U16_LE:
253                 case AOUT_FMT_U16_BE:
254                     l_bytes = 2 * sizeof(u16) * p_aout->l_units;
255                     aout_thread = (void *)aout_Thread_U16_Stereo;
256                     break;
257
258                 case AOUT_FMT_S16_LE:
259                 case AOUT_FMT_S16_BE:
260                     l_bytes = 2 * sizeof(s16) * p_aout->l_units;
261                     aout_thread = (void *)aout_Thread_S16_Stereo;
262                     break;
263
264                 default:
265                     intf_ErrMsg("aout error: unknown audio output format (%i)",
266                         p_aout->i_format);
267                     return( -1 );
268             }
269             break;
270
271         default:
272             intf_ErrMsg("aout error: unknown number of audio channels (%i)",
273                 p_aout->i_channels );
274             return( -1 );
275     }
276
277     /* Allocate the memory needed by the audio output buffers, and set to zero
278      * the s32 buffer's memory */
279     if ( (p_aout->buffer = malloc(l_bytes)) == NULL )
280     {
281         intf_ErrMsg("aout error: not enough memory to create the output buffer");
282         return( -1 );
283     }
284     if ( (p_aout->s32_buffer = (s32 *)calloc(p_aout->l_units, sizeof(s32) << ( p_aout->b_stereo))) == NULL )
285     {
286         intf_ErrMsg("aout error: not enough memory to create the s32 output buffer");
287         free( p_aout->buffer );
288         return( -1 );
289     }
290
291     /* Before launching the thread, we try to predict the date of the first
292      * audio unit in the first output buffer */
293     p_aout->date = mdate() - 1000000;
294
295     /* Launch the thread */
296     if ( vlc_thread_create( &p_aout->thread_id, "audio output", (vlc_thread_func_t)aout_thread, p_aout ) )
297     {
298         intf_ErrMsg("aout error: can't spawn audio output thread (%p)", p_aout);
299         free( p_aout->buffer );
300         free( p_aout->s32_buffer );
301         return( -1 );
302     }
303
304     intf_DbgMsg("aout debug: audio output thread (%p) spawned", p_aout);
305     return( 0 );
306 }
307
308 /*****************************************************************************
309  * aout_DestroyThread
310  *****************************************************************************/
311 void aout_DestroyThread( aout_thread_t * p_aout, int *pi_status )
312 {
313
314     int i_fifo;
315     
316     /* FIXME: pi_status is not handled correctly: check vout how to do!?? */
317
318     intf_DbgMsg("aout debug: requesting termination of audio output thread (%p)", p_aout);
319
320     /* Ask thread to kill itself and wait until it's done */
321     p_aout->b_die = 1;
322     vlc_thread_join( p_aout->thread_id ); /* only if pi_status is NULL */
323
324     /* Free the allocated memory */
325     free( p_aout->buffer );
326     free( p_aout->s32_buffer );
327
328     /* Destroy the condition and mutex locks */
329     for ( i_fifo = 0; i_fifo < AOUT_MAX_FIFOS; i_fifo++ )
330     {
331         vlc_mutex_destroy( &p_aout->fifo[i_fifo].data_lock );
332         vlc_cond_destroy( &p_aout->fifo[i_fifo].data_wait );
333     }
334     vlc_mutex_destroy( &p_aout->fifos_lock );
335     
336     /* Free the plugin */
337     p_aout->pf_close( p_aout );
338
339     /* Release the aout module */
340     module_Unneed( p_main->p_bank, p_aout->p_module );
341
342     /* Free structure */
343     free( p_aout );
344 }
345
346 /*****************************************************************************
347  * aout_CreateFifo
348  *****************************************************************************/
349 aout_fifo_t * aout_CreateFifo( aout_thread_t * p_aout, aout_fifo_t * p_fifo )
350 {
351     int i_fifo;
352
353     /* Take the fifos lock */
354     vlc_mutex_lock( &p_aout->fifos_lock );
355
356     /* Looking for a free fifo structure */
357     for ( i_fifo = 0; i_fifo < AOUT_MAX_FIFOS; i_fifo++ )
358     {
359         if ( p_aout->fifo[i_fifo].i_type == AOUT_EMPTY_FIFO)
360         {
361             break;
362         }
363     }
364     if ( i_fifo == AOUT_MAX_FIFOS )
365     {
366         intf_ErrMsg("aout error: no empty fifo available");
367         vlc_mutex_unlock( &p_aout->fifos_lock );
368         return( NULL );
369     }
370
371     /* Initialize the new fifo structure */
372     switch ( p_aout->fifo[i_fifo].i_type = p_fifo->i_type )
373     {
374         case AOUT_INTF_MONO_FIFO:
375         case AOUT_INTF_STEREO_FIFO:
376             p_aout->fifo[i_fifo].b_die = 0;
377
378             p_aout->fifo[i_fifo].i_channels = p_fifo->i_channels;
379             p_aout->fifo[i_fifo].b_stereo = p_fifo->b_stereo;
380             p_aout->fifo[i_fifo].l_rate = p_fifo->l_rate;
381
382             p_aout->fifo[i_fifo].buffer = p_fifo->buffer;
383
384             p_aout->fifo[i_fifo].l_unit = 0;
385             InitializeIncrement( &p_aout->fifo[i_fifo].unit_increment, p_fifo->l_rate, p_aout->l_rate );
386             p_aout->fifo[i_fifo].l_units = p_fifo->l_units;
387             break;
388
389         case AOUT_ADEC_MONO_FIFO:
390         case AOUT_ADEC_STEREO_FIFO:
391             p_aout->fifo[i_fifo].b_die = 0;
392
393             p_aout->fifo[i_fifo].i_channels = p_fifo->i_channels;
394             p_aout->fifo[i_fifo].b_stereo = p_fifo->b_stereo;
395             p_aout->fifo[i_fifo].l_rate = p_fifo->l_rate;
396
397             p_aout->fifo[i_fifo].l_frame_size = p_fifo->l_frame_size;
398             /* Allocate the memory needed to store the audio frames. As the
399              * fifo is a rotative fifo, we must be able to find out whether the
400              * fifo is full or empty, that's why we must in fact allocate memory
401              * for (AOUT_FIFO_SIZE+1) audio frames. */
402             if ( (p_aout->fifo[i_fifo].buffer = malloc( sizeof(s16)*(AOUT_FIFO_SIZE+1)*p_fifo->l_frame_size )) == NULL )
403             {
404                 intf_ErrMsg("aout error: not enough memory to create the frames buffer");
405                 p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO;
406                 vlc_mutex_unlock( &p_aout->fifos_lock );
407                 return( NULL );
408             }
409
410             /* Allocate the memory needed to store the dates of the frames */
411             if ( (p_aout->fifo[i_fifo].date = (mtime_t *)malloc( sizeof(mtime_t)*(AOUT_FIFO_SIZE+1) )) == NULL )
412             {
413                 intf_ErrMsg("aout error: not enough memory to create the dates buffer");
414                 free( p_aout->fifo[i_fifo].buffer );
415                 p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO;
416                 vlc_mutex_unlock( &p_aout->fifos_lock );
417                 return( NULL );
418             }
419
420             /* Set the fifo's buffer as empty (the first frame that is to be
421              * played is also the first frame that is not to be played) */
422             p_aout->fifo[i_fifo].l_start_frame = 0;
423             /* p_aout->fifo[i_fifo].l_next_frame = 0; */
424             p_aout->fifo[i_fifo].l_end_frame = 0;
425
426             /* Waiting for the audio decoder to compute enough frames to work
427              * out the fifo's current rate (as soon as the decoder has decoded
428              * enough frames, the members of the fifo structure that are not
429              * initialized now will be calculated) */
430             p_aout->fifo[i_fifo].b_start_frame = 0;
431             p_aout->fifo[i_fifo].b_next_frame = 0;
432             break;
433
434         default:
435             intf_ErrMsg("aout error: unknown fifo type (%i)", p_aout->fifo[i_fifo].i_type);
436             p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO;
437             vlc_mutex_unlock( &p_aout->fifos_lock );
438             return( NULL );
439     }
440
441     /* Release the fifos lock */
442     vlc_mutex_unlock( &p_aout->fifos_lock );
443
444     /* Return the pointer to the fifo structure */
445     intf_DbgMsg("aout debug: audio output fifo (%p) allocated", &p_aout->fifo[i_fifo]);
446     return( &p_aout->fifo[i_fifo] );
447 }
448
449 /*****************************************************************************
450  * aout_DestroyFifo
451  *****************************************************************************/
452 void aout_DestroyFifo( aout_fifo_t * p_fifo )
453 {
454     intf_DbgMsg("aout debug: requesting destruction of audio output fifo (%p)", p_fifo);
455     p_fifo->b_die = 1;
456 }
457
458 /* Here are the local macros */
459
460 #define UPDATE_INCREMENT( increment, integer ) \
461     if ( ((increment).l_remainder += (increment).l_euclidean_remainder) >= 0 )\
462     { \
463         (integer) += (increment).l_euclidean_integer + 1; \
464         (increment).l_remainder -= (increment).l_euclidean_denominator; \
465     } \
466     else \
467     { \
468         (integer) += (increment).l_euclidean_integer; \
469     }
470
471 /* Following functions are local */
472
473 /*****************************************************************************
474  * NextFrame
475  *****************************************************************************/
476 static __inline__ int NextFrame( aout_thread_t * p_aout, aout_fifo_t * p_fifo, mtime_t aout_date )
477 {
478     long l_units, l_rate;
479
480     /* We take the lock */
481     vlc_mutex_lock( &p_fifo->data_lock );
482
483     /* Are we looking for a dated start frame ? */
484     if ( !p_fifo->b_start_frame )
485     {
486         while ( p_fifo->l_start_frame != p_fifo->l_end_frame )
487         {
488             if ( p_fifo->date[p_fifo->l_start_frame] != LAST_MDATE )
489             {
490                 p_fifo->b_start_frame = 1;
491                 p_fifo->l_next_frame = (p_fifo->l_start_frame + 1) & AOUT_FIFO_SIZE;
492                 p_fifo->l_unit = p_fifo->l_start_frame * (p_fifo->l_frame_size >> (p_fifo->b_stereo));
493                 break;
494             }
495             p_fifo->l_start_frame = (p_fifo->l_start_frame + 1) & AOUT_FIFO_SIZE;
496         }
497
498         if ( p_fifo->l_start_frame == p_fifo->l_end_frame )
499         {
500             vlc_mutex_unlock( &p_fifo->data_lock );
501             return( -1 );
502         }
503     }
504
505     /* We are looking for the next dated frame */
506     /* FIXME : is the output fifo full ?? */
507     while ( !p_fifo->b_next_frame )
508     {
509         while ( p_fifo->l_next_frame != p_fifo->l_end_frame )
510         {
511             if ( p_fifo->date[p_fifo->l_next_frame] != LAST_MDATE )
512             {
513                 p_fifo->b_next_frame = 1;
514                 break;
515             }
516             p_fifo->l_next_frame = (p_fifo->l_next_frame + 1) & AOUT_FIFO_SIZE;
517         }
518
519         while ( p_fifo->l_next_frame == p_fifo->l_end_frame )
520         {
521             vlc_cond_wait( &p_fifo->data_wait, &p_fifo->data_lock );
522             if ( p_fifo->b_die )
523             {
524                 vlc_mutex_unlock( &p_fifo->data_lock );
525                 return( -1 );
526             }
527         }
528     }
529
530     l_units = ((p_fifo->l_next_frame - p_fifo->l_start_frame) & AOUT_FIFO_SIZE) * (p_fifo->l_frame_size >> (p_fifo->b_stereo));
531
532     l_rate = p_fifo->l_rate + ((aout_date - p_fifo->date[p_fifo->l_start_frame]) / 256);
533     intf_DbgMsg( "aout debug: %lli (%li);", aout_date - p_fifo->date[p_fifo->l_start_frame], l_rate );
534
535     InitializeIncrement( &p_fifo->unit_increment, l_rate, p_aout->l_rate );
536
537     p_fifo->l_units = (((l_units - (p_fifo->l_unit -
538         (p_fifo->l_start_frame * (p_fifo->l_frame_size >> (p_fifo->b_stereo)))))
539         * p_aout->l_rate) / l_rate) + 1;
540
541     /* We release the lock before leaving */
542     vlc_mutex_unlock( &p_fifo->data_lock );
543     return( 0 );
544 }
545
546 void aout_Thread_S8_Mono( aout_thread_t * p_aout )
547 {
548 }
549
550 void aout_Thread_S8_Stereo( aout_thread_t * p_aout )
551 {
552 }
553
554 void aout_Thread_U8_Mono( aout_thread_t * p_aout )
555 {
556     int i_fifo;
557     long l_buffer, l_buffer_limit;
558     long l_units, l_bytes;
559
560     intf_DbgMsg("adec debug: running audio output U8_M_thread (%p) (pid == %i)", p_aout, getpid());
561
562     /* As the s32_buffer was created with calloc(), we don't have to set this
563      * memory to zero and we can immediately jump into the thread's loop */
564     while ( !p_aout->b_die )
565     {
566         vlc_mutex_lock( &p_aout->fifos_lock );
567         for ( i_fifo = 0; i_fifo < AOUT_MAX_FIFOS; i_fifo++ )
568         {
569             switch ( p_aout->fifo[i_fifo].i_type )
570             {
571                 case AOUT_EMPTY_FIFO:
572                     break;
573
574                 case AOUT_INTF_MONO_FIFO:
575                     if ( p_aout->fifo[i_fifo].l_units > p_aout->l_units )
576                     {
577                         l_buffer = 0;
578                         while ( l_buffer < (p_aout->l_units) ) /* p_aout->b_stereo == 0 */
579                         {
580                             p_aout->s32_buffer[l_buffer++] +=
581                                 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
582                             p_aout->s32_buffer[l_buffer++] +=
583                                 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
584                             UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
585                         }
586                         p_aout->fifo[i_fifo].l_units -= p_aout->l_units;
587                     }
588                     else
589                     {
590                         l_buffer = 0;
591                         while ( l_buffer < (p_aout->fifo[i_fifo].l_units) ) /* p_aout->b_stereo == 0 */
592                         {
593                             p_aout->s32_buffer[l_buffer++] +=
594                                 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
595                             UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
596                         }
597                         free( p_aout->fifo[i_fifo].buffer ); /* !! */
598                         p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
599                         intf_DbgMsg("aout debug: audio output fifo (%p) destroyed", &p_aout->fifo[i_fifo]); /* !! */
600                     }
601                     break;
602
603                 case AOUT_INTF_STEREO_FIFO:
604                     if ( p_aout->fifo[i_fifo].l_units > p_aout->l_units )
605                     {
606                         l_buffer = 0;
607                         while ( l_buffer < (p_aout->l_units) ) /* p_aout->b_stereo == 0 */
608                         {
609                             /* I mix half left - half right */
610                             p_aout->s32_buffer[l_buffer++] +=
611                                 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit] ) / 2 +
612                                 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit+1] ) / 2;
613                             UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
614                         }
615                         p_aout->fifo[i_fifo].l_units -= p_aout->l_units;
616                     }
617                     else
618                     {
619                         l_buffer = 0;
620                         while ( l_buffer < (p_aout->fifo[i_fifo].l_units) ) /* p_aout->b_stereo == 0 */
621                         {
622                             /* I mix half left - half right */
623                             p_aout->s32_buffer[l_buffer++] +=
624                                 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit] ) / 2 +
625                                 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit+1] ) / 2;
626                             UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
627                         }
628                         free( p_aout->fifo[i_fifo].buffer ); /* !! */
629                         p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
630                         intf_DbgMsg("aout debug: audio output fifo (%p) destroyed", &p_aout->fifo[i_fifo]); /* !! */
631                     }
632                     break;
633
634                 case AOUT_ADEC_MONO_FIFO:
635                     if ( p_aout->fifo[i_fifo].b_die )
636                     {
637                         free( p_aout->fifo[i_fifo].buffer );
638                         free( p_aout->fifo[i_fifo].date );
639                         p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
640                         intf_DbgMsg("aout debug: audio output fifo (%p) destroyed", &p_aout->fifo[i_fifo]);
641                         continue;
642                     }
643
644                     l_units = p_aout->l_units;
645                     l_buffer = 0;
646                     while ( l_units > 0 )
647                     {
648                         if ( !p_aout->fifo[i_fifo].b_next_frame )
649                         {
650                             if ( NextFrame(p_aout, &p_aout->fifo[i_fifo], p_aout->date + ((((mtime_t)(l_buffer >> 1)) * 1000000) / ((mtime_t)p_aout->l_rate))) )
651                             {
652                                 break;
653                             }
654                         }
655
656                         if ( p_aout->fifo[i_fifo].l_units > l_units )
657                         {
658                             l_buffer_limit = p_aout->l_units; /* p_aout->b_stereo == 0 */
659                             while ( l_buffer < l_buffer_limit )
660                             {
661                                 p_aout->s32_buffer[l_buffer++] +=
662                                     (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
663
664                                 UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
665                                 if ( p_aout->fifo[i_fifo].l_unit >= /* p_aout->fifo[i_fifo].b_stereo == 0 */
666                                      ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 0)) )
667                                 {
668                                     p_aout->fifo[i_fifo].l_unit -= /* p_aout->fifo[i_fifo].b_stereo == 0 */
669                                         ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 0));
670                                 }
671                             }
672                             p_aout->fifo[i_fifo].l_units -= l_units;
673                             break;
674                         }
675                         else
676                         {
677                             l_buffer_limit = l_buffer + (p_aout->fifo[i_fifo].l_units);
678                             /* p_aout->b_stereo == 0 */
679                             while ( l_buffer < l_buffer_limit )
680                             {
681                                 p_aout->s32_buffer[l_buffer++] +=
682                                     (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
683
684                                 UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
685                                 if ( p_aout->fifo[i_fifo].l_unit >= /* p_aout->fifo[i_fifo].b_stereo == 0 */
686                                      ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 0)) )
687                                 {
688                                     p_aout->fifo[i_fifo].l_unit -= /* p_aout->fifo[i_fifo].b_stereo == 0 */
689                                         ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 0));
690                                 }
691                             }
692                             l_units -= p_aout->fifo[i_fifo].l_units;
693
694                             vlc_mutex_lock( &p_aout->fifo[i_fifo].data_lock );
695                             p_aout->fifo[i_fifo].l_start_frame = p_aout->fifo[i_fifo].l_next_frame;
696                             vlc_cond_signal( &p_aout->fifo[i_fifo].data_wait );
697                             vlc_mutex_unlock( &p_aout->fifo[i_fifo].data_lock );
698
699                             /* p_aout->fifo[i_fifo].b_start_frame = 1; */
700                             p_aout->fifo[i_fifo].l_next_frame += 1;
701                             p_aout->fifo[i_fifo].l_next_frame &= AOUT_FIFO_SIZE;
702                             p_aout->fifo[i_fifo].b_next_frame = 0;
703                         }
704                     }
705                     break;
706
707                 case AOUT_ADEC_STEREO_FIFO:
708                     if ( p_aout->fifo[i_fifo].b_die )
709                     {
710                         free( p_aout->fifo[i_fifo].buffer );
711                         free( p_aout->fifo[i_fifo].date );
712                         p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
713                         intf_DbgMsg("aout debug: audio output fifo (%p) destroyed", &p_aout->fifo[i_fifo]);
714                         continue;
715                     }
716
717                     l_units = p_aout->l_units;
718                     l_buffer = 0;
719                     while ( l_units > 0 )
720                     {
721                         if ( !p_aout->fifo[i_fifo].b_next_frame )
722                         {
723                             if ( NextFrame(p_aout, &p_aout->fifo[i_fifo], p_aout->date + ((((mtime_t)(l_buffer >> 1)) * 1000000) / ((mtime_t)p_aout->l_rate))) )
724                             {
725                                 break;
726                             }
727                         }
728
729                         if ( p_aout->fifo[i_fifo].l_units > l_units )
730                         {
731                             l_buffer_limit = p_aout->l_units; /* p_aout->b_stereo == 0 */
732                             while ( l_buffer < l_buffer_limit )
733                             {
734                                 /* I mix half left - half right */
735                                 p_aout->s32_buffer[l_buffer++] +=
736                                     (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit] ) / 2 +
737                                     (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit+1] ) / 2;
738
739                                 UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
740                                 if ( p_aout->fifo[i_fifo].l_unit >= /* p_aout->fifo[i_fifo].b_stereo == 1 */
741                                      ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 1)) )
742                                 {
743                                     p_aout->fifo[i_fifo].l_unit -= /* p_aout->fifo[i_fifo].b_stereo == 1 */
744                                         ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 1));
745                                 }
746                             }
747                             p_aout->fifo[i_fifo].l_units -= l_units;
748                             break;
749                         }
750                         else
751                         {
752                             l_buffer_limit = l_buffer + (p_aout->fifo[i_fifo].l_units);
753                             /* p_aout->b_stereo == 0 */
754                             while ( l_buffer < l_buffer_limit )
755                             {
756                                 /* I mix half left - half right */
757                                 p_aout->s32_buffer[l_buffer++] +=
758                                     (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit] ) / 2 +
759                                     (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit+1] ) / 2;
760
761                                 UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
762                                 if ( p_aout->fifo[i_fifo].l_unit >= /* p_aout->fifo[i_fifo].b_stereo == 1 */
763                                      ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 1)) )
764                                 {
765                                     p_aout->fifo[i_fifo].l_unit -= /* p_aout->fifo[i_fifo].b_stereo == 1 */
766                                         ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 1));
767                                 }
768                             }
769                             l_units -= p_aout->fifo[i_fifo].l_units;
770
771                             vlc_mutex_lock( &p_aout->fifo[i_fifo].data_lock );
772                             p_aout->fifo[i_fifo].l_start_frame = p_aout->fifo[i_fifo].l_next_frame;
773                             vlc_cond_signal( &p_aout->fifo[i_fifo].data_wait );
774                             vlc_mutex_unlock( &p_aout->fifo[i_fifo].data_lock );
775
776                             /* p_aout->fifo[i_fifo].b_start_frame = 1; */
777                             p_aout->fifo[i_fifo].l_next_frame += 1;
778                             p_aout->fifo[i_fifo].l_next_frame &= AOUT_FIFO_SIZE;
779                             p_aout->fifo[i_fifo].b_next_frame = 0;
780                         }
781                     }
782                     break;
783
784             default:
785                     intf_DbgMsg("aout debug: unknown fifo type (%i)", p_aout->fifo[i_fifo].i_type);
786                     break;
787             }
788         }
789         vlc_mutex_unlock( &p_aout->fifos_lock );
790
791         l_buffer_limit = p_aout->l_units; /* p_aout->b_stereo == 0 */
792
793         for ( l_buffer = 0; l_buffer < l_buffer_limit; l_buffer++ )
794         {
795             ((u8 *)p_aout->buffer)[l_buffer] = (u8)( ( (p_aout->s32_buffer[l_buffer] / AOUT_MAX_FIFOS / 256 ) + 128 ) * p_aout->vol / 256 );
796             p_aout->s32_buffer[l_buffer] = 0;
797         }
798         l_bytes = p_aout->pf_getbufinfo( p_aout, l_buffer_limit );
799         p_aout->date = mdate() + ((((mtime_t)(l_bytes / 1 )) * 1000000) / ((mtime_t)p_aout->l_rate)); /* sizeof(u8) << (p_aout->b_stereo) == 1 */
800         p_aout->pf_play( p_aout, (byte_t *)p_aout->buffer, l_buffer_limit * sizeof(u8) );
801         if ( l_bytes > (l_buffer_limit * sizeof(u8) * 2) ) /* There are 2 channels (left & right) */
802         {
803             msleep( p_aout->l_msleep );
804         }
805     }
806
807     vlc_mutex_lock( &p_aout->fifos_lock );
808     for ( i_fifo = 0; i_fifo < AOUT_MAX_FIFOS; i_fifo++ )
809     {
810         switch ( p_aout->fifo[i_fifo].i_type )
811         {
812             case AOUT_EMPTY_FIFO:
813                 break;
814
815             case AOUT_INTF_MONO_FIFO:
816             case AOUT_INTF_STEREO_FIFO:
817                 free( p_aout->fifo[i_fifo].buffer ); /* !! */
818                 p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
819                 intf_DbgMsg("aout debug: audio output fifo (%p) destroyed", &p_aout->fifo[i_fifo]);
820                 break;
821
822             case AOUT_ADEC_MONO_FIFO:
823             case AOUT_ADEC_STEREO_FIFO:
824                 free( p_aout->fifo[i_fifo].buffer );
825                 free( p_aout->fifo[i_fifo].date );
826                 p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
827                 intf_DbgMsg("aout debug: audio output fifo (%p) destroyed", &p_aout->fifo[i_fifo]);
828                 break;
829
830             default:
831                 break;
832         }
833     }
834     vlc_mutex_unlock( &p_aout->fifos_lock );
835
836
837 }
838
839 void aout_Thread_U8_Stereo( aout_thread_t * p_aout )
840 {
841     int i_fifo;
842     long l_buffer, l_buffer_limit;
843     long l_units, l_bytes;
844
845     intf_DbgMsg("adec debug: running audio output U8_S_thread (%p) (pid == %i)", p_aout, getpid());
846
847     /* As the s32_buffer was created with calloc(), we don't have to set this
848      * memory to zero and we can immediately jump into the thread's loop */
849     while ( !p_aout->b_die )
850     {
851         vlc_mutex_lock( &p_aout->fifos_lock );
852         for ( i_fifo = 0; i_fifo < AOUT_MAX_FIFOS; i_fifo++ )
853         {
854             switch ( p_aout->fifo[i_fifo].i_type )
855             {
856                 case AOUT_EMPTY_FIFO:
857                     break;
858
859                 case AOUT_INTF_MONO_FIFO:
860                     if ( p_aout->fifo[i_fifo].l_units > p_aout->l_units )
861                     {
862                         l_buffer = 0;
863                         while ( l_buffer < (p_aout->l_units << 1) ) /* p_aout->b_stereo == 1 */
864                         {
865                             p_aout->s32_buffer[l_buffer++] +=
866                                 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
867                             p_aout->s32_buffer[l_buffer++] +=
868                                 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
869                             UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
870                         }
871                         p_aout->fifo[i_fifo].l_units -= p_aout->l_units;
872                     }
873                     else
874                     {
875                         l_buffer = 0;
876                         while ( l_buffer < (p_aout->fifo[i_fifo].l_units << 1) ) /* p_aout->b_stereo == 1 */
877                         {
878                             p_aout->s32_buffer[l_buffer++] +=
879                                 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
880                             p_aout->s32_buffer[l_buffer++] +=
881                                 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
882                             UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
883                         }
884                         free( p_aout->fifo[i_fifo].buffer ); /* !! */
885                         p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
886                         intf_DbgMsg("aout debug: audio output fifo (%p) destroyed", &p_aout->fifo[i_fifo]); /* !! */
887                     }
888                     break;
889
890                 case AOUT_INTF_STEREO_FIFO:
891                     if ( p_aout->fifo[i_fifo].l_units > p_aout->l_units )
892                     {
893                         l_buffer = 0;
894                         while ( l_buffer < (p_aout->l_units << 1) ) /* p_aout->b_stereo == 1 */
895                         {
896                             p_aout->s32_buffer[l_buffer++] +=
897                                 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit] );
898                             p_aout->s32_buffer[l_buffer++] +=
899                                 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit+1] );
900                             UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
901                         }
902                         p_aout->fifo[i_fifo].l_units -= p_aout->l_units;
903                     }
904                     else
905                     {
906                         l_buffer = 0;
907                         while ( l_buffer < (p_aout->fifo[i_fifo].l_units << 1) ) /* p_aout->b_stereo == 1 */
908                         {
909                             p_aout->s32_buffer[l_buffer++] +=
910                                 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit] );
911                             p_aout->s32_buffer[l_buffer++] +=
912                                 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit+1] );
913                             UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
914                         }
915                         free( p_aout->fifo[i_fifo].buffer ); /* !! */
916                         p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
917                         intf_DbgMsg("aout debug: audio output fifo (%p) destroyed", &p_aout->fifo[i_fifo]); /* !! */
918                     }
919                     break;
920
921                 case AOUT_ADEC_MONO_FIFO:
922                     if ( p_aout->fifo[i_fifo].b_die )
923                     {
924                         free( p_aout->fifo[i_fifo].buffer );
925                         free( p_aout->fifo[i_fifo].date );
926                         p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
927                         intf_DbgMsg("aout debug: audio output fifo (%p) destroyed", &p_aout->fifo[i_fifo]);
928                         continue;
929                     }
930
931                     l_units = p_aout->l_units;
932                     l_buffer = 0;
933                     while ( l_units > 0 )
934                     {
935                         if ( !p_aout->fifo[i_fifo].b_next_frame )
936                         {
937                             if ( NextFrame(p_aout, &p_aout->fifo[i_fifo], p_aout->date + ((((mtime_t)(l_buffer >> 1)) * 1000000) / ((mtime_t)p_aout->l_rate))) )
938                             {
939                                 break;
940                             }
941                         }
942
943                         if ( p_aout->fifo[i_fifo].l_units > l_units )
944                         {
945                             l_buffer_limit = p_aout->l_units << 1; /* p_aout->b_stereo == 1 */
946                             while ( l_buffer < l_buffer_limit )
947                             {
948                                 p_aout->s32_buffer[l_buffer++] +=
949                                     (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
950                                 p_aout->s32_buffer[l_buffer++] +=
951                                     (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
952
953                                 UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
954                                 if ( p_aout->fifo[i_fifo].l_unit >= /* p_aout->fifo[i_fifo].b_stereo == 0 */
955                                      ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 0)) )
956                                 {
957                                     p_aout->fifo[i_fifo].l_unit -= /* p_aout->fifo[i_fifo].b_stereo == 0 */
958                                         ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 0));
959                                 }
960                             }
961                             p_aout->fifo[i_fifo].l_units -= l_units;
962                             break;
963                         }
964                         else
965                         {
966                             l_buffer_limit = l_buffer + (p_aout->fifo[i_fifo].l_units << 1);
967                             /* p_aout->b_stereo == 1 */
968                             while ( l_buffer < l_buffer_limit )
969                             {
970                                 p_aout->s32_buffer[l_buffer++] +=
971                                     (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
972                                 p_aout->s32_buffer[l_buffer++] +=
973                                     (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
974
975                                 UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
976                                 if ( p_aout->fifo[i_fifo].l_unit >= /* p_aout->fifo[i_fifo].b_stereo == 0 */
977                                      ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 0)) )
978                                 {
979                                     p_aout->fifo[i_fifo].l_unit -= /* p_aout->fifo[i_fifo].b_stereo == 0 */
980                                         ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 0));
981                                 }
982                             }
983                             l_units -= p_aout->fifo[i_fifo].l_units;
984
985                             vlc_mutex_lock( &p_aout->fifo[i_fifo].data_lock );
986                             p_aout->fifo[i_fifo].l_start_frame = p_aout->fifo[i_fifo].l_next_frame;
987                             vlc_cond_signal( &p_aout->fifo[i_fifo].data_wait );
988                             vlc_mutex_unlock( &p_aout->fifo[i_fifo].data_lock );
989
990                             /* p_aout->fifo[i_fifo].b_start_frame = 1; */
991                             p_aout->fifo[i_fifo].l_next_frame += 1;
992                             p_aout->fifo[i_fifo].l_next_frame &= AOUT_FIFO_SIZE;
993                             p_aout->fifo[i_fifo].b_next_frame = 0;
994                         }
995                     }
996                     break;
997
998                 case AOUT_ADEC_STEREO_FIFO:
999                     if ( p_aout->fifo[i_fifo].b_die )
1000                     {
1001                         free( p_aout->fifo[i_fifo].buffer );
1002                         free( p_aout->fifo[i_fifo].date );
1003                         p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
1004                         intf_DbgMsg("aout debug: audio output fifo (%p) destroyed", &p_aout->fifo[i_fifo]);
1005                         continue;
1006                     }
1007
1008                     l_units = p_aout->l_units;
1009                     l_buffer = 0;
1010                     while ( l_units > 0 )
1011                     {
1012                         if ( !p_aout->fifo[i_fifo].b_next_frame )
1013                         {
1014                             if ( NextFrame(p_aout, &p_aout->fifo[i_fifo], p_aout->date + ((((mtime_t)(l_buffer >> 1)) * 1000000) / ((mtime_t)p_aout->l_rate))) )
1015                             {
1016                                 break;
1017                             }
1018                         }
1019
1020                         if ( p_aout->fifo[i_fifo].l_units > l_units )
1021                         {
1022                             l_buffer_limit = p_aout->l_units << 1; /* p_aout->b_stereo == 1 */
1023                             while ( l_buffer < l_buffer_limit )
1024                             {
1025                                 p_aout->s32_buffer[l_buffer++] +=
1026                                     (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit] );
1027                                 p_aout->s32_buffer[l_buffer++] +=
1028                                     (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit+1] );
1029
1030                                 UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
1031                                 if ( p_aout->fifo[i_fifo].l_unit >= /* p_aout->fifo[i_fifo].b_stereo == 1 */
1032                                      ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 1)) )
1033                                 {
1034                                     p_aout->fifo[i_fifo].l_unit -= /* p_aout->fifo[i_fifo].b_stereo == 1 */
1035                                         ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 1));
1036                                 }
1037                             }
1038                             p_aout->fifo[i_fifo].l_units -= l_units;
1039                             break;
1040                         }
1041                         else
1042                         {
1043                             l_buffer_limit = l_buffer + (p_aout->fifo[i_fifo].l_units << 1);
1044                             /* p_aout->b_stereo == 1 */
1045                             while ( l_buffer < l_buffer_limit )
1046                             {
1047                                 p_aout->s32_buffer[l_buffer++] +=
1048                                     (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit] );
1049                                 p_aout->s32_buffer[l_buffer++] +=
1050                                     (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit+1] );
1051
1052                                 UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
1053                                 if ( p_aout->fifo[i_fifo].l_unit >= /* p_aout->fifo[i_fifo].b_stereo == 1 */
1054                                      ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 1)) )
1055                                 {
1056                                     p_aout->fifo[i_fifo].l_unit -= /* p_aout->fifo[i_fifo].b_stereo == 1 */
1057                                         ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 1));
1058                                 }
1059                             }
1060                             l_units -= p_aout->fifo[i_fifo].l_units;
1061
1062                             vlc_mutex_lock( &p_aout->fifo[i_fifo].data_lock );
1063                             p_aout->fifo[i_fifo].l_start_frame = p_aout->fifo[i_fifo].l_next_frame;
1064                             vlc_cond_signal( &p_aout->fifo[i_fifo].data_wait );
1065                             vlc_mutex_unlock( &p_aout->fifo[i_fifo].data_lock );
1066
1067                             /* p_aout->fifo[i_fifo].b_start_frame = 1; */
1068                             p_aout->fifo[i_fifo].l_next_frame += 1;
1069                             p_aout->fifo[i_fifo].l_next_frame &= AOUT_FIFO_SIZE;
1070                             p_aout->fifo[i_fifo].b_next_frame = 0;
1071                         }
1072                     }
1073                     break;
1074
1075             default:
1076                     intf_DbgMsg("aout debug: unknown fifo type (%i)", p_aout->fifo[i_fifo].i_type);
1077                     break;
1078             }
1079         }
1080         vlc_mutex_unlock( &p_aout->fifos_lock );
1081
1082         l_buffer_limit = p_aout->l_units  << 1 ; /* p_aout->b_stereo == 1 */
1083
1084         for ( l_buffer = 0; l_buffer < l_buffer_limit; l_buffer++ )
1085         {
1086             ((u8 *)p_aout->buffer)[l_buffer] = (u8)( ( (p_aout->s32_buffer[l_buffer] / AOUT_MAX_FIFOS / 256) + 128 ) * p_aout->vol / 256 );
1087             p_aout->s32_buffer[l_buffer] = 0;
1088         }
1089         l_bytes = p_aout->pf_getbufinfo( p_aout, l_buffer_limit );
1090         p_aout->date = mdate() + ((((mtime_t)(l_bytes / 2 )) * 1000000) / ((mtime_t)p_aout->l_rate)); /* sizeof(u8) << (p_aout->b_stereo) == 2 */
1091         p_aout->pf_play( p_aout, (byte_t *)p_aout->buffer, l_buffer_limit * sizeof(u8) );
1092         if ( l_bytes > (l_buffer_limit * sizeof(u8)) )
1093         {
1094             msleep( p_aout->l_msleep );
1095         }
1096     }
1097
1098     vlc_mutex_lock( &p_aout->fifos_lock );
1099     for ( i_fifo = 0; i_fifo < AOUT_MAX_FIFOS; i_fifo++ )
1100     {
1101         switch ( p_aout->fifo[i_fifo].i_type )
1102         {
1103             case AOUT_EMPTY_FIFO:
1104                 break;
1105
1106             case AOUT_INTF_MONO_FIFO:
1107             case AOUT_INTF_STEREO_FIFO:
1108                 free( p_aout->fifo[i_fifo].buffer ); /* !! */
1109                 p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
1110                 intf_DbgMsg("aout debug: audio output fifo (%p) destroyed", &p_aout->fifo[i_fifo]);
1111                 break;
1112
1113             case AOUT_ADEC_MONO_FIFO:
1114             case AOUT_ADEC_STEREO_FIFO:
1115                 free( p_aout->fifo[i_fifo].buffer );
1116                 free( p_aout->fifo[i_fifo].date );
1117                 p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
1118                 intf_DbgMsg("aout debug: audio output fifo (%p) destroyed", &p_aout->fifo[i_fifo]);
1119                 break;
1120
1121             default:
1122                 break;
1123         }
1124     }
1125     vlc_mutex_unlock( &p_aout->fifos_lock );
1126
1127 }
1128
1129 void aout_Thread_S16_Mono( aout_thread_t * p_aout )
1130 {
1131 }
1132
1133 void aout_Thread_S16_Stereo( aout_thread_t * p_aout )
1134 {
1135     int i_fifo;
1136     long l_buffer, l_buffer_limit;
1137     long l_units, l_bytes;
1138
1139     intf_DbgMsg("adec debug: running audio output S16_S_thread (%p) (pid == %i)", p_aout, getpid());
1140
1141     /* As the s32_buffer was created with calloc(), we don't have to set this
1142      * memory to zero and we can immediately jump into the thread's loop */
1143     while ( !p_aout->b_die )
1144     {
1145         vlc_mutex_lock( &p_aout->fifos_lock );
1146         for ( i_fifo = 0; i_fifo < AOUT_MAX_FIFOS; i_fifo++ )
1147         {
1148             switch ( p_aout->fifo[i_fifo].i_type )
1149             {
1150                 case AOUT_EMPTY_FIFO:
1151                     break;
1152
1153                 case AOUT_INTF_MONO_FIFO:
1154                     if ( p_aout->fifo[i_fifo].l_units > p_aout->l_units )
1155                     {
1156                         l_buffer = 0;
1157                         while ( l_buffer < (p_aout->l_units << 1) ) /* p_aout->b_stereo == 1 */
1158                         {
1159                             p_aout->s32_buffer[l_buffer++] +=
1160                                 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
1161                             p_aout->s32_buffer[l_buffer++] +=
1162                                 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
1163                             UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
1164                         }
1165                         p_aout->fifo[i_fifo].l_units -= p_aout->l_units;
1166                     }
1167                     else
1168                     {
1169                         l_buffer = 0;
1170                         while ( l_buffer < (p_aout->fifo[i_fifo].l_units << 1) ) /* p_aout->b_stereo == 1 */
1171                         {
1172                             p_aout->s32_buffer[l_buffer++] +=
1173                                 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
1174                             p_aout->s32_buffer[l_buffer++] +=
1175                                 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
1176                             UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
1177                         }
1178                         free( p_aout->fifo[i_fifo].buffer ); /* !! */
1179                         p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
1180                         intf_DbgMsg("aout debug: audio output fifo (%p) destroyed", &p_aout->fifo[i_fifo]); /* !! */
1181                     }
1182                     break;
1183
1184                 case AOUT_INTF_STEREO_FIFO:
1185                     if ( p_aout->fifo[i_fifo].l_units > p_aout->l_units )
1186                     {
1187                         l_buffer = 0;
1188                         while ( l_buffer < (p_aout->l_units << 1) ) /* p_aout->b_stereo == 1 */
1189                         {
1190                             p_aout->s32_buffer[l_buffer++] +=
1191                                 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit] );
1192                             p_aout->s32_buffer[l_buffer++] +=
1193                                 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit+1] );
1194                             UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
1195                         }
1196                         p_aout->fifo[i_fifo].l_units -= p_aout->l_units;
1197                     }
1198                     else
1199                     {
1200                         l_buffer = 0;
1201                         while ( l_buffer < (p_aout->fifo[i_fifo].l_units << 1) ) /* p_aout->b_stereo == 1 */
1202                         {
1203                             p_aout->s32_buffer[l_buffer++] +=
1204                                 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit] );
1205                             p_aout->s32_buffer[l_buffer++] +=
1206                                 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit+1] );
1207                             UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
1208                         }
1209                         free( p_aout->fifo[i_fifo].buffer ); /* !! */
1210                         p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
1211                         intf_DbgMsg("aout debug: audio output fifo (%p) destroyed", &p_aout->fifo[i_fifo]); /* !! */
1212                     }
1213                     break;
1214
1215                 case AOUT_ADEC_MONO_FIFO:
1216                     if ( p_aout->fifo[i_fifo].b_die )
1217                     {
1218                         free( p_aout->fifo[i_fifo].buffer );
1219                         free( p_aout->fifo[i_fifo].date );
1220                         p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
1221                         intf_DbgMsg("aout debug: audio output fifo (%p) destroyed", &p_aout->fifo[i_fifo]);
1222                         continue;
1223                     }
1224
1225                     l_units = p_aout->l_units;
1226                     l_buffer = 0;
1227                     while ( l_units > 0 )
1228                     {
1229                         if ( !p_aout->fifo[i_fifo].b_next_frame )
1230                         {
1231                             if ( NextFrame(p_aout, &p_aout->fifo[i_fifo], p_aout->date + ((((mtime_t)(l_buffer >> 1)) * 1000000) / ((mtime_t)p_aout->l_rate))) )
1232                             {
1233                                 break;
1234                             }
1235                         }
1236
1237                         if ( p_aout->fifo[i_fifo].l_units > l_units )
1238                         {
1239                             l_buffer_limit = p_aout->l_units << 1; /* p_aout->b_stereo == 1 */
1240                             while ( l_buffer < l_buffer_limit )
1241                             {
1242                                 p_aout->s32_buffer[l_buffer++] +=
1243                                     (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
1244                                 p_aout->s32_buffer[l_buffer++] +=
1245                                     (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
1246
1247                                 UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
1248                                 if ( p_aout->fifo[i_fifo].l_unit >= /* p_aout->fifo[i_fifo].b_stereo == 0 */
1249                                      ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 0)) )
1250                                 {
1251                                     p_aout->fifo[i_fifo].l_unit -= /* p_aout->fifo[i_fifo].b_stereo == 0 */
1252                                         ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 0));
1253                                 }
1254                             }
1255                             p_aout->fifo[i_fifo].l_units -= l_units;
1256                             break;
1257                         }
1258                         else
1259                         {
1260                             l_buffer_limit = l_buffer + (p_aout->fifo[i_fifo].l_units << 1);
1261                             /* p_aout->b_stereo == 1 */
1262                             while ( l_buffer < l_buffer_limit )
1263                             {
1264                                 p_aout->s32_buffer[l_buffer++] +=
1265                                     (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
1266                                 p_aout->s32_buffer[l_buffer++] +=
1267                                     (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
1268
1269                                 UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
1270                                 if ( p_aout->fifo[i_fifo].l_unit >= /* p_aout->fifo[i_fifo].b_stereo == 0 */
1271                                      ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 0)) )
1272                                 {
1273                                     p_aout->fifo[i_fifo].l_unit -= /* p_aout->fifo[i_fifo].b_stereo == 0 */
1274                                         ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 0));
1275                                 }
1276                             }
1277                             l_units -= p_aout->fifo[i_fifo].l_units;
1278
1279                             vlc_mutex_lock( &p_aout->fifo[i_fifo].data_lock );
1280                             p_aout->fifo[i_fifo].l_start_frame = p_aout->fifo[i_fifo].l_next_frame;
1281                             vlc_cond_signal( &p_aout->fifo[i_fifo].data_wait );
1282                             vlc_mutex_unlock( &p_aout->fifo[i_fifo].data_lock );
1283
1284                             /* p_aout->fifo[i_fifo].b_start_frame = 1; */
1285                             p_aout->fifo[i_fifo].l_next_frame += 1;
1286                             p_aout->fifo[i_fifo].l_next_frame &= AOUT_FIFO_SIZE;
1287                             p_aout->fifo[i_fifo].b_next_frame = 0;
1288                         }
1289                     }
1290                     break;
1291
1292                 case AOUT_ADEC_STEREO_FIFO:
1293                     if ( p_aout->fifo[i_fifo].b_die )
1294                     {
1295                         free( p_aout->fifo[i_fifo].buffer );
1296                         free( p_aout->fifo[i_fifo].date );
1297                         p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
1298                         intf_DbgMsg("aout debug: audio output fifo (%p) destroyed", &p_aout->fifo[i_fifo]);
1299                         continue;
1300                     }
1301
1302                     l_units = p_aout->l_units;
1303                     l_buffer = 0;
1304                     while ( l_units > 0 )
1305                     {
1306                         if ( !p_aout->fifo[i_fifo].b_next_frame )
1307                         {
1308                             if ( NextFrame(p_aout, &p_aout->fifo[i_fifo], p_aout->date + ((((mtime_t)(l_buffer >> 1)) * 1000000) / ((mtime_t)p_aout->l_rate))) )
1309                             {
1310                                 break;
1311                             }
1312                         }
1313
1314                         if ( p_aout->fifo[i_fifo].l_units > l_units )
1315                         {
1316                             l_buffer_limit = p_aout->l_units << 1; /* p_aout->b_stereo == 1 */
1317                             while ( l_buffer < l_buffer_limit )
1318                             {
1319                                 p_aout->s32_buffer[l_buffer++] +=
1320                                     (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit] );
1321                                 p_aout->s32_buffer[l_buffer++] +=
1322                                     (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit+1] );
1323
1324                                 UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
1325                                 if ( p_aout->fifo[i_fifo].l_unit >= /* p_aout->fifo[i_fifo].b_stereo == 1 */
1326                                      ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 1)) )
1327                                 {
1328                                     p_aout->fifo[i_fifo].l_unit -= /* p_aout->fifo[i_fifo].b_stereo == 1 */
1329                                         ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 1));
1330                                 }
1331                             }
1332                             p_aout->fifo[i_fifo].l_units -= l_units;
1333                             break;
1334                         }
1335                         else
1336                         {
1337                             l_buffer_limit = l_buffer + (p_aout->fifo[i_fifo].l_units << 1);
1338                             /* p_aout->b_stereo == 1 */
1339                             while ( l_buffer < l_buffer_limit )
1340                             {
1341                                 p_aout->s32_buffer[l_buffer++] +=
1342                                     (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit] );
1343                                 p_aout->s32_buffer[l_buffer++] +=
1344                                     (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit+1] );
1345
1346                                 UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
1347                                 if ( p_aout->fifo[i_fifo].l_unit >= /* p_aout->fifo[i_fifo].b_stereo == 1 */
1348                                      ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 1)) )
1349                                 {
1350                                     p_aout->fifo[i_fifo].l_unit -= /* p_aout->fifo[i_fifo].b_stereo == 1 */
1351                                         ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 1));
1352                                 }
1353                             }
1354                             l_units -= p_aout->fifo[i_fifo].l_units;
1355
1356                             vlc_mutex_lock( &p_aout->fifo[i_fifo].data_lock );
1357                             p_aout->fifo[i_fifo].l_start_frame = p_aout->fifo[i_fifo].l_next_frame;
1358                             vlc_cond_signal( &p_aout->fifo[i_fifo].data_wait );
1359                             vlc_mutex_unlock( &p_aout->fifo[i_fifo].data_lock );
1360
1361                             /* p_aout->fifo[i_fifo].b_start_frame = 1; */
1362                             p_aout->fifo[i_fifo].l_next_frame += 1;
1363                             p_aout->fifo[i_fifo].l_next_frame &= AOUT_FIFO_SIZE;
1364                             p_aout->fifo[i_fifo].b_next_frame = 0;
1365                         }
1366                     }
1367                     break;
1368
1369             default:
1370                     intf_DbgMsg("aout debug: unknown fifo type (%i)", p_aout->fifo[i_fifo].i_type);
1371                     break;
1372             }
1373         }
1374         vlc_mutex_unlock( &p_aout->fifos_lock );
1375
1376         l_buffer_limit = p_aout->l_units << 1; /* p_aout->b_stereo == 1 */
1377
1378         for ( l_buffer = 0; l_buffer < l_buffer_limit; l_buffer++ )
1379         {
1380             ((s16 *)p_aout->buffer)[l_buffer] = (s16)( ( p_aout->s32_buffer[l_buffer] / AOUT_MAX_FIFOS ) * p_aout->vol / 256 ) ;
1381             p_aout->s32_buffer[l_buffer] = 0;
1382         }
1383
1384         l_bytes = p_aout->pf_getbufinfo( p_aout, l_buffer_limit );
1385         p_aout->date = mdate() + ((((mtime_t)(l_bytes / 4)) * 1000000) / ((mtime_t)p_aout->l_rate)); /* sizeof(s16) << (p_aout->b_stereo) == 4 */
1386         p_aout->pf_play( p_aout, (byte_t *)p_aout->buffer, l_buffer_limit * sizeof(s16) );
1387         if ( l_bytes > (l_buffer_limit * sizeof(s16)) )
1388         {
1389             msleep( p_aout->l_msleep );
1390         }
1391     }
1392
1393     vlc_mutex_lock( &p_aout->fifos_lock );
1394     for ( i_fifo = 0; i_fifo < AOUT_MAX_FIFOS; i_fifo++ )
1395     {
1396         switch ( p_aout->fifo[i_fifo].i_type )
1397         {
1398             case AOUT_EMPTY_FIFO:
1399                 break;
1400
1401             case AOUT_INTF_MONO_FIFO:
1402             case AOUT_INTF_STEREO_FIFO:
1403                 free( p_aout->fifo[i_fifo].buffer ); /* !! */
1404                 p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
1405                 intf_DbgMsg("aout debug: audio output fifo (%p) destroyed", &p_aout->fifo[i_fifo]);
1406                 break;
1407
1408             case AOUT_ADEC_MONO_FIFO:
1409             case AOUT_ADEC_STEREO_FIFO:
1410                 free( p_aout->fifo[i_fifo].buffer );
1411                 free( p_aout->fifo[i_fifo].date );
1412                 p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
1413                 intf_DbgMsg("aout debug: audio output fifo (%p) destroyed", &p_aout->fifo[i_fifo]);
1414                 break;
1415
1416             default:
1417                 break;
1418         }
1419     }
1420     vlc_mutex_unlock( &p_aout->fifos_lock );
1421 }
1422
1423 void aout_Thread_U16_Mono( aout_thread_t * p_aout )
1424 {
1425 }
1426
1427 void aout_Thread_U16_Stereo( aout_thread_t * p_aout )
1428 {
1429 }